1: #ifndef lint 2: static char *sccsid = "@(#)addbib.c 4.2 (Berkeley) 11/2/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: }