1 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 2 /* All Rights Reserved */ 3 4 5 /* 6 * Copyright (c) 1980 Regents of the University of California. 7 * All rights reserved. The Berkeley software License Agreement 8 * specifies the terms and conditions for redistribution. 9 */ 10 11 /* 12 * Copyright (c) 1983, 1984 1985, 1986, 1987, 1988, Sun Microsystems, Inc. 13 * All Rights Reserved. 14 */ 15 16 #pragma ident "%Z%%M% %I% %E% SMI" 17 18 19 #include <locale.h> 20 #include <stdio.h> 21 #include <ctype.h> 22 #include <signal.h> 23 #define MAXENT 50 24 25 struct skeleton { 26 char prompt[20]; /* prompt user for entry */ 27 char keylet[5]; /* key letter for database */ 28 } bibskel[MAXENT] = { 29 " Author:", "%A", 30 " Title:", "%T", 31 " Journal:", "%J", 32 " Volume:", "%V", 33 " Pages:", "%P", 34 "Publisher:", "%I", 35 " City:", "%C", 36 " Date:", "%D", 37 " Other:", "%O", 38 " Keywords:", "%K", }; 39 40 int entries = 10; /* total number of entries in bibskel */ 41 int abstract = 1; /* asking for abstracts is the default */ 42 43 usage() /* print proper usage and exit */ 44 { 45 puts(gettext("Usage: addbib [-p promptfile] [-a] database\n\ 46 \t-p: the promptfile defines alternate fields\n\ 47 \t-a: don't include prompting for the abstract\n")); 48 exit(1); 49 } 50 51 main(argc, argv) /* addbib: bibliography entry program */ 52 int argc; 53 char *argv[]; 54 { 55 FILE *fp, *fopen(); 56 int i; 57 58 (void) setlocale(LC_ALL, ""); 59 60 #if !defined(TEXT_DOMAIN) 61 #define TEXT_DOMAIN "SYS_TEST" 62 #endif 63 (void) textdomain(TEXT_DOMAIN); 64 65 if (argc == 1) 66 { 67 puts(gettext("You must specify a bibliography file (database).")); 68 usage(); 69 } 70 for (i = 1; argv[i][0] == '-'; i++) 71 { 72 if (argv[i][1] == 'p') 73 { 74 if (i >= argc - 2) 75 { 76 puts(gettext("Not enough arguments for -p option.")); 77 usage(); 78 } 79 rd_skel(argv[++i]); 80 } 81 else if (argv[i][1] == 'a') 82 { 83 if (i >= argc - 1) 84 { 85 puts(gettext("No bibliofile specified after -a.")); 86 usage(); 87 } 88 abstract = 0; 89 } 90 else /* neither -p nor -a */ 91 { 92 printf(gettext("Invalid command line flag: %s\n"), argv[i]); 93 usage(); 94 } 95 } 96 if (i < argc - 1) 97 { 98 puts(gettext("Too many arguments with no options.")); 99 usage(); 100 } 101 if ((fp = fopen(argv[i], "a")) == NULL) 102 { 103 perror(argv[i]); 104 exit(1); 105 } 106 addbib(fp, argv[i]); /* loop for input */ 107 exit(0); 108 /* NOTREACHED */ 109 } 110 111 addbib(fp, argv) /* add entries to a bibliographic database */ 112 FILE *fp; 113 char *argv; 114 { 115 char line[BUFSIZ]; 116 int i = 0, firstln, repeat = 0, escape = 0; 117 118 printf(gettext("Instructions? ")); 119 fgets(line, BUFSIZ, stdin); 120 if (line[0] == 'y' || line[0] == 'Y') 121 instruct(); 122 while (1) 123 { 124 putchar('\n'); 125 putc('\n', fp); 126 for (i = 0; i < entries; i++) 127 { 128 printf("%s\t", gettext(bibskel[i].prompt)); 129 if (fgets(line, BUFSIZ, stdin) == NULL) 130 { 131 clearerr(stdin); 132 break; 133 } 134 if (line[0] == '-' && line[1] == '\n') 135 { 136 i -= 2; 137 if (i < -1) 138 { 139 printf(gettext("Too far back.\n")); 140 i++; 141 } 142 continue; 143 } 144 else if (line[strlen(line)-2] == '\\') 145 { 146 if (line[0] != '\\') 147 { 148 line[strlen(line)-2] = '\n'; 149 line[strlen(line)-1] = NULL; 150 trim(line); 151 fprintf(fp, "%s %s", 152 bibskel[i].keylet, line); 153 } 154 printf("> "); 155 again: 156 fgets(line, BUFSIZ, stdin); 157 if (line[strlen(line)-2] == '\\') 158 { 159 line[strlen(line)-2] = '\n'; 160 line[strlen(line)-1] = NULL; 161 trim(line); 162 fputs(line, fp); 163 printf("> "); 164 goto again; 165 } 166 trim(line); 167 fputs(line, fp); 168 } 169 else if (line[0] != '\n') 170 { 171 trim(line); 172 fprintf(fp, "%s %s", bibskel[i].keylet, line); 173 } 174 } 175 if (abstract) 176 { 177 puts(gettext(" Abstract: (ctrl-d to end)")); 178 firstln = 1; 179 while (fgets(line, BUFSIZ, stdin)) 180 { 181 if (firstln && line[0] != '%') 182 { 183 fprintf(fp, "%%X "); 184 firstln = 0; 185 } 186 fputs(line, fp); 187 } 188 clearerr(stdin); 189 } 190 fflush(fp); /* write to file at end of each cycle */ 191 if (ferror(fp)) 192 { 193 perror(argv); 194 exit(1); 195 } 196 editloop: 197 printf(gettext("\nContinue? ")); 198 fgets(line, BUFSIZ, stdin); 199 if (line[0] == 'e' || line[0] == 'v') 200 { 201 bibedit(fp, line, argv); 202 goto editloop; 203 } 204 if (line[0] == 'q' || line[0] == 'n') 205 return; 206 } 207 } 208 209 trim(line) /* trim line of trailing white space */ 210 char line[]; 211 { 212 int n; 213 214 n = strlen(line); 215 while (--n >= 0) 216 { 217 if (!isspace(line[n])) 218 break; 219 } 220 line[++n] = '\n'; 221 line[++n] = NULL; 222 } 223 224 bibedit(fp, cmd, arg) /* edit database with edit, ex, or vi */ 225 FILE *fp; 226 char *cmd, *arg; 227 { 228 int i = 0, status; 229 230 fclose(fp); 231 while (!isspace(cmd[i])) 232 i++; 233 cmd[i] = NULL; 234 if (fork() == 0) 235 { 236 if (cmd[0] == 'v' && cmd[1] == 'i') 237 execlp(cmd, cmd, "+$", arg, NULL); 238 else /* either ed, ex, or edit */ 239 execlp(cmd, cmd, arg, NULL); 240 } 241 signal(SIGINT, SIG_IGN); 242 signal(SIGQUIT, SIG_IGN); 243 wait(&status); 244 signal(SIGINT, SIG_DFL); 245 signal(SIGQUIT, SIG_DFL); 246 if ((fp = fopen(arg, "a")) == NULL) 247 { 248 perror(arg); 249 exit(1); 250 } 251 } 252 253 instruct() /* give user elementary directions */ 254 { 255 putchar('\n'); 256 puts(gettext("Addbib will prompt you for various bibliographic fields.\n" 257 "If you don't need a particular field, just hit RETURN,\n" 258 "\tand that field will not appear in the output file.\n" 259 "If you want to return to previous fields in the skeleton,\n" 260 "\ta single minus sign will go back a field at a time.\n" 261 "\t(This is the best way to input multiple authors.)\n" 262 "If you have to continue a field or add an unusual field,\n" 263 "\ta trailing backslash will allow a temporary escape.\n" 264 "Finally, (without -a) you will be prompted for an abstract\n" 265 "Type in as many lines as you need, and end with a ctrl-d.\n" 266 "To quit, type `q' or `n' when asked if you want to continue.\n" 267 "To edit the database, type `edit', `vi', or `ex' instead.")); 268 269 } 270 271 rd_skel(arg) /* redo bibskel from user-supplied file */ 272 char *arg; 273 { 274 FILE *pfp, *fopen(); 275 char str[BUFSIZ]; 276 int entry, i, j; 277 278 if ((pfp = fopen(arg, "r")) == NULL) 279 { 280 fprintf(stderr, gettext("Promptfile ")); 281 perror(arg); 282 exit(1); 283 } 284 for (entry = 0; fgets(str, BUFSIZ, pfp); entry++) 285 { 286 for (i = 0; str[i] != '\t' && str[i] != '\n'; i++) 287 bibskel[entry].prompt[i] = str[i]; 288 bibskel[entry].prompt[i] = NULL; 289 if (str[i] == '\n') 290 { 291 fprintf(stderr, gettext("No tabs between promptfile fields.\n")); 292 fprintf(stderr, gettext("Format: prompt-string <TAB> %%key\n")); 293 exit(1); 294 } 295 for (i++, j = 0; str[i] != '\n'; i++, j++) 296 bibskel[entry].keylet[j] = str[i]; 297 bibskel[entry].keylet[j] = NULL; 298 299 if (entry >= MAXENT) 300 { 301 fprintf(stderr, gettext("Too many entries in promptfile.\n")); 302 exit(1); 303 } 304 } 305 entries = entry; 306 fclose(pfp); 307 } 308