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