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