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
21struct 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
36int entries = 10;	/* total number of entries in bibskel */
37int abstract = 1;	/* asking for abstracts is the default */
38
39static void addbib(FILE *, char *);
40void bibedit(FILE *, char *, char *);
41static void instruct(void);
42static void rd_skel(char *);
43static void trim(char []);
44
45static void
46usage(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
54int
55main(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
105static void
106addbib(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
186static void
187trim(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
200void
201bibedit(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
226static void
227instruct(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
246static void
247rd_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