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
usage()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
main(argc,argv)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
addbib(fp,argv)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
trim(line)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
bibedit(fp,cmd,arg)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
instruct()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
rd_skel(arg)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