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