1 #ifndef lint 2 static char *sccsid = "@(#)addbib.c 4.1 (Berkeley) 05/06/83"; 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 fgets(line, BUFSIZ, stdin); 107 if (line[0] == '-' && line[1] == '\n') 108 { 109 i -= 2; 110 if (i < -1) 111 { 112 printf("Too far back.\n"); 113 i++; 114 } 115 continue; 116 } 117 else if (line[strlen(line)-2] == '\\') 118 { 119 if (line[0] != '\\') 120 { 121 line[strlen(line)-2] = '\n'; 122 line[strlen(line)-1] = NULL; 123 trim(line); 124 fprintf(fp, "%s %s", 125 bibskel[i].keylet, line); 126 } 127 printf("> "); 128 again: 129 fgets(line, BUFSIZ, stdin); 130 if (line[strlen(line)-2] == '\\') 131 { 132 line[strlen(line)-2] = '\n'; 133 line[strlen(line)-1] = NULL; 134 trim(line); 135 fputs(line, fp); 136 printf("> "); 137 goto again; 138 } 139 trim(line); 140 fputs(line, fp); 141 } 142 else if (line[0] != '\n') 143 { 144 trim(line); 145 fprintf(fp, "%s %s", bibskel[i].keylet, line); 146 } 147 } 148 if (abstract) 149 { 150 puts(" Abstract: (ctrl-d to end)"); 151 firstln = 1; 152 while (fgets(line, BUFSIZ, stdin)) 153 { 154 if (firstln && line[0] != '%') 155 { 156 fprintf(fp, "%%X "); 157 firstln = 0; 158 } 159 fputs(line, fp); 160 } 161 } 162 fflush(fp); /* write to file at end of each cycle */ 163 if (ferror(fp)) 164 { 165 perror(argv); 166 exit(1); 167 } 168 editloop: 169 printf("\nContinue? "); 170 fgets(line, BUFSIZ, stdin); 171 if (line[0] == 'e' || line[0] == 'v') 172 { 173 bibedit(fp, line, argv); 174 goto editloop; 175 } 176 if (line[0] == 'q' || line[0] == 'n') 177 return; 178 } 179 } 180 181 trim(line) /* trim line of trailing white space */ 182 char line[]; 183 { 184 int n; 185 186 n = strlen(line); 187 while (--n >= 0) 188 { 189 if (!isspace(line[n])) 190 break; 191 } 192 line[++n] = '\n'; 193 line[++n] = NULL; 194 } 195 196 bibedit(fp, cmd, arg) /* edit database with edit, ex, or vi */ 197 FILE *fp; 198 char *cmd, *arg; 199 { 200 int i = 0, status; 201 202 fclose(fp); 203 while (!isspace(cmd[i])) 204 i++; 205 cmd[i] = NULL; 206 if (fork() == 0) 207 { 208 if (cmd[0] == 'v' && cmd[1] == 'i') 209 execlp(cmd, cmd, "+$", arg, NULL); 210 else /* either ed, ex, or edit */ 211 execlp(cmd, cmd, arg, NULL); 212 } 213 signal(SIGINT, SIG_IGN); 214 signal(SIGQUIT, SIG_IGN); 215 wait(&status); 216 signal(SIGINT, SIG_DFL); 217 signal(SIGQUIT, SIG_DFL); 218 if ((fp = fopen(arg, "a")) == NULL) 219 { 220 perror(arg); 221 exit(1); 222 } 223 } 224 225 instruct() /* give user elementary directions */ 226 { 227 putchar('\n'); 228 puts("Addbib will prompt you for various bibliographic fields."); 229 puts("If you don't need a particular field, just hit RETURN,"); 230 puts("\tand that field will not appear in the output file."); 231 puts("If you want to return to previous fields in the skeleton,"); 232 puts("\ta single minus sign will go back a field at a time."); 233 puts("\t(This is the best way to input multiple authors.)"); 234 puts("If you have to continue a field or add an unusual field,"); 235 puts("\ta trailing backslash will allow a temporary escape."); 236 puts("Finally, (without -a) you will be prompted for an abstract."); 237 puts("Type in as many lines as you need, and end with a ctrl-d."); 238 puts("To quit, type `q' or `n' when asked if you want to continue."); 239 puts("To edit the database, type `edit', `vi', or `ex' instead."); 240 } 241 242 rd_skel(arg) /* redo bibskel from user-supplied file */ 243 char *arg; 244 { 245 FILE *pfp, *fopen(); 246 char str[BUFSIZ]; 247 int entry, i, j; 248 249 if ((pfp = fopen(arg, "r")) == NULL) 250 { 251 fprintf(stderr, "Promptfile "); 252 perror(arg); 253 exit(1); 254 } 255 for (entry = 0; fgets(str, BUFSIZ, pfp); entry++) 256 { 257 for (i = 0; str[i] != '\t' && str[i] != '\n'; i++) 258 bibskel[entry].prompt[i] = str[i]; 259 bibskel[entry].prompt[i] = NULL; 260 if (str[i] == '\n') 261 { 262 fprintf(stderr, "No tabs between promptfile fields.\n"); 263 fprintf(stderr, "Format: prompt-string <TAB> %%key\n"); 264 exit(1); 265 } 266 for (i++, j = 0; str[i] != '\n'; i++, j++) 267 bibskel[entry].keylet[j] = str[i]; 268 bibskel[entry].keylet[j] = NULL; 269 270 if (entry >= MAXENT) 271 { 272 fprintf(stderr, "Too many entries in promptfile.\n"); 273 exit(1); 274 } 275 } 276 entries = entry; 277 fclose(pfp); 278 } 279