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