xref: /csrg-svn/libexec/bugfiler/unixtomh.c (revision 30167)
1*30167Sbostic #ifndef lint
2*30167Sbostic static char sccsid[] = "@(#)unixtomh.c	5.1 86/11/25";
3*30167Sbostic #endif not lint
4*30167Sbostic 
5*30167Sbostic /*
6*30167Sbostic  * This program copies the mail file in standard unix format
7*30167Sbostic  * given as $1 to the file $2 in Rand Message Handler format.
8*30167Sbostic  * The change made is to bracket each message with a line
9*30167Sbostic  * containing 4 control-A's and to split the From line into
10*30167Sbostic  * a From: field and a Date: field, with the date in Arpanet
11*30167Sbostic  * standard format.
12*30167Sbostic  *
13*30167Sbostic  * This program is designed to be called from the rand mh program
14*30167Sbostic  * ``inc''
15*30167Sbostic  *
16*30167Sbostic  * Set SENDMAIL if you are running sendmail -- this guarantees that
17*30167Sbostic  * From: and Date: lines will appear already, and will put the info
18*30167Sbostic  * in the UNIX-From line into a Received-From: field.
19*30167Sbostic  */
20*30167Sbostic 
21*30167Sbostic #include <stdio.h>
22*30167Sbostic #include <sys/types.h>
23*30167Sbostic #include <sys/timeb.h>
24*30167Sbostic #include <ctype.h>
25*30167Sbostic 
26*30167Sbostic #define SENDMAIL
27*30167Sbostic 
28*30167Sbostic struct headline {
29*30167Sbostic 	char	*l_from;	/* The name of the sender */
30*30167Sbostic 	char	*l_tty;		/* His tty string (if any) */
31*30167Sbostic 	char	*l_date;	/* The entire date string */
32*30167Sbostic };
33*30167Sbostic 
34*30167Sbostic char *savestr(), *copyin(), *copy(), *nextword(), *calloc();
35*30167Sbostic char *index();
36*30167Sbostic 
37*30167Sbostic #define	NOSTR		((char *) 0)
38*30167Sbostic #define	UUCP			/* Undo strange uucp naming */
39*30167Sbostic 
main(argc,argv)40*30167Sbostic main(argc, argv)
41*30167Sbostic 	char **argv;
42*30167Sbostic {
43*30167Sbostic 	char linebuf[BUFSIZ];
44*30167Sbostic 	register int maybe;
45*30167Sbostic 	register FILE *inf, *outf;
46*30167Sbostic 	int inhdr, infld;
47*30167Sbostic 
48*30167Sbostic 	if (argc > 3) {
49*30167Sbostic 		fprintf(stderr, "Usage: unixtomh name1 name2\n");
50*30167Sbostic 		exit(1);
51*30167Sbostic 	}
52*30167Sbostic 	outf = inf = NULL;
53*30167Sbostic 	if (argc < 3)
54*30167Sbostic 		outf = stdout;
55*30167Sbostic 	if (argc < 2)
56*30167Sbostic 		inf = stdin;
57*30167Sbostic 	if (inf == NULL && (inf = fopen(argv[1], "r")) == NULL) {
58*30167Sbostic 		perror(argv[1]);
59*30167Sbostic 		exit(1);
60*30167Sbostic 	}
61*30167Sbostic 	if (outf == NULL && (outf = fopen(argv[2], "w")) == NULL) {
62*30167Sbostic 		perror(argv[2]);
63*30167Sbostic 		exit(1);
64*30167Sbostic 	}
65*30167Sbostic 	maybe = 1;
66*30167Sbostic 	inhdr = 0;
67*30167Sbostic 	infld = 0;
68*30167Sbostic 	while (nullgets(linebuf, BUFSIZ, inf) > 0) {
69*30167Sbostic 		if (maybe && ishead(linebuf)) {
70*30167Sbostic 			fputs("\1\1\1\1\n", outf);
71*30167Sbostic 			inhdr++;
72*30167Sbostic 			dohead(linebuf, inf, outf);
73*30167Sbostic 			continue;
74*30167Sbostic 		}
75*30167Sbostic 		if (strlen(linebuf) == 0) {
76*30167Sbostic 			maybe = 1;
77*30167Sbostic 			inhdr = 0;
78*30167Sbostic 			infld = 0;
79*30167Sbostic 			putc('\n', outf);
80*30167Sbostic 			continue;
81*30167Sbostic 		}
82*30167Sbostic 		else
83*30167Sbostic 			maybe = 0;
84*30167Sbostic #ifndef SENDMAIL
85*30167Sbostic 		if (inhdr && strcmpn(linebuf, "Date: ", 6) == 0)
86*30167Sbostic 			continue;
87*30167Sbostic 		if (inhdr && strcmpn(linebuf, "From: ", 6) == 0)
88*30167Sbostic 			continue;
89*30167Sbostic #endif SENDMAIL
90*30167Sbostic 		if (infld && isspace(linebuf[0])) {
91*30167Sbostic 			fputs(linebuf, outf);
92*30167Sbostic 			putc('\n', outf);
93*30167Sbostic 			continue;
94*30167Sbostic 		}
95*30167Sbostic 		if (inhdr && !isspace(linebuf[0])) {
96*30167Sbostic 			char *colp, *sp;
97*30167Sbostic 
98*30167Sbostic 			colp = index(linebuf, ':');
99*30167Sbostic 			sp = index(linebuf, ' ');
100*30167Sbostic 			if (colp == NOSTR || sp == NOSTR || sp < colp) {
101*30167Sbostic 				putc('\n', outf);
102*30167Sbostic 				inhdr = 0;
103*30167Sbostic 			}
104*30167Sbostic 			else
105*30167Sbostic 				infld = 1;
106*30167Sbostic 		}
107*30167Sbostic 		fputs(linebuf, outf);
108*30167Sbostic 		putc('\n', outf);
109*30167Sbostic 	}
110*30167Sbostic 	fputs("\1\1\1\1\n", outf);
111*30167Sbostic 	fflush(outf);
112*30167Sbostic 	if (ferror(outf)) {
113*30167Sbostic 		fprintf(stderr, "unixtomh: write: ");
114*30167Sbostic 		perror(argv[2]);
115*30167Sbostic 		exit(1);
116*30167Sbostic 	}
117*30167Sbostic 	exit(0);
118*30167Sbostic }
119*30167Sbostic 
120*30167Sbostic /*
121*30167Sbostic  * Get a line from the given file descriptor, don't return the
122*30167Sbostic  * terminating newline.
123*30167Sbostic  */
124*30167Sbostic 
nullgets(linebuf,sz,file)125*30167Sbostic nullgets(linebuf, sz, file)
126*30167Sbostic 	char linebuf[];
127*30167Sbostic 	register FILE *file;
128*30167Sbostic {
129*30167Sbostic 	register char *cp;
130*30167Sbostic 	register int c, cnt;
131*30167Sbostic 
132*30167Sbostic 	cp = linebuf;
133*30167Sbostic 	cnt = sz;
134*30167Sbostic 	do {
135*30167Sbostic 		if (--cnt <= 0) {
136*30167Sbostic 			*cp = 0;
137*30167Sbostic 			return(1);
138*30167Sbostic 		}
139*30167Sbostic 		c = getc(file);
140*30167Sbostic 		*cp++ = c;
141*30167Sbostic 	} while (c != EOF && c != '\n');
142*30167Sbostic 	if (c == EOF && cp == linebuf+1)
143*30167Sbostic 		return(0);
144*30167Sbostic 	*--cp = 0;
145*30167Sbostic 	return(1);
146*30167Sbostic }
147*30167Sbostic 
148*30167Sbostic /*
149*30167Sbostic  * Output the fields extracted from the From line --
150*30167Sbostic  * From: and Date:  Untangle UUCP stuff if appropriate.
151*30167Sbostic  */
152*30167Sbostic 
dohead(line,infile,outfile)153*30167Sbostic dohead(line, infile, outfile)
154*30167Sbostic 	char line[];
155*30167Sbostic 	register FILE *infile, *outfile;
156*30167Sbostic {
157*30167Sbostic 	register char *cp;
158*30167Sbostic 	struct headline hl;
159*30167Sbostic 	char parbuf[BUFSIZ];
160*30167Sbostic #ifdef UUCP
161*30167Sbostic 	char *word();
162*30167Sbostic 	char namebuf[BUFSIZ];
163*30167Sbostic 	char linebuf[BUFSIZ];
164*30167Sbostic 	int first;
165*30167Sbostic 	long curoff;
166*30167Sbostic #endif UUCP
167*30167Sbostic 
168*30167Sbostic 	parse(line, &hl, parbuf);
169*30167Sbostic #ifndef SENDMAIL
170*30167Sbostic 	putdate(hl.l_date, outfile);
171*30167Sbostic #endif SENDMAIL
172*30167Sbostic #ifdef UUCP
173*30167Sbostic 	if (strcmp(hl.l_from, "uucp") == 0) {
174*30167Sbostic 		strcpy(namebuf, "");
175*30167Sbostic 		first = 1;
176*30167Sbostic 		for (;;) {
177*30167Sbostic 			curoff = ftell(infile);
178*30167Sbostic 			if (fgets(linebuf, BUFSIZ, infile) == NULL)
179*30167Sbostic 				break;
180*30167Sbostic 			if (strcmp(word(1, linebuf), ">From") != 0)
181*30167Sbostic 				break;
182*30167Sbostic 			if (strcmp(word(-3, linebuf), "remote") != 0)
183*30167Sbostic 				break;
184*30167Sbostic 			if (strcmp(word(-2, linebuf), "from") != 0)
185*30167Sbostic 				break;
186*30167Sbostic 			if (first) {
187*30167Sbostic 				strcpy(namebuf, word(-1, linebuf));
188*30167Sbostic 				strcat(namebuf, "!");
189*30167Sbostic 				strcat(namebuf, word(2, linebuf));
190*30167Sbostic 				first = 0;
191*30167Sbostic 			}
192*30167Sbostic 			else {
193*30167Sbostic 				strcpy(rindex(namebuf, '!')+1,
194*30167Sbostic 				    word(-1, linebuf));
195*30167Sbostic 				strcat(namebuf, "!");
196*30167Sbostic 				strcat(namebuf, word(2, linebuf));
197*30167Sbostic 			}
198*30167Sbostic 		}
199*30167Sbostic 		fseek(infile, curoff, 0);
200*30167Sbostic #ifdef SENDMAIL
201*30167Sbostic 		if (!first)
202*30167Sbostic 			fprintf(outfile, "Return-Path: <%s>\n", namebuf);
203*30167Sbostic #else SENDMAIL
204*30167Sbostic 		if (first)
205*30167Sbostic 			fprintf(outfile, "From: uucp\n");
206*30167Sbostic 		else
207*30167Sbostic 			fprintf(outfile, "From: %s\n", namebuf);
208*30167Sbostic #endif SENDMAIL
209*30167Sbostic 		return;
210*30167Sbostic 	}
211*30167Sbostic #endif UUCP
212*30167Sbostic #ifdef SENDMAIL
213*30167Sbostic 	if (hl.l_from[0] == '<')
214*30167Sbostic 		fprintf(outfile, "Return-Path: %s\n", hl.l_from);
215*30167Sbostic 	else
216*30167Sbostic 		fprintf(outfile, "Return-Path: <%s>\n", hl.l_from);
217*30167Sbostic #else SENDMAIL
218*30167Sbostic 	fprintf(outfile, "From: %s\n", hl.l_from);
219*30167Sbostic #endif SENDMAIL
220*30167Sbostic }
221*30167Sbostic 
222*30167Sbostic #ifdef UUCP
223*30167Sbostic 
224*30167Sbostic /*
225*30167Sbostic  * Return liberal word i from the given string.
226*30167Sbostic  * The words are numbered 1, 2, 3, . . .  from the left
227*30167Sbostic  * and -1, -2, . . . from the right.
228*30167Sbostic  */
229*30167Sbostic 
230*30167Sbostic char *
word(index,str)231*30167Sbostic word(index, str)
232*30167Sbostic 	char str[];
233*30167Sbostic {
234*30167Sbostic 	register char *cp;
235*30167Sbostic 	char *secbuf;
236*30167Sbostic 	register int c;
237*30167Sbostic 	static char retbuf[100];
238*30167Sbostic 	char *gword();
239*30167Sbostic 
240*30167Sbostic 	cp = str;
241*30167Sbostic 	if ((c = index) > 0) {
242*30167Sbostic 		while (c-- > 0)
243*30167Sbostic 			cp = gword(cp, retbuf);
244*30167Sbostic 		return(retbuf);
245*30167Sbostic 	}
246*30167Sbostic 	if (c == 0)
247*30167Sbostic 		return("");
248*30167Sbostic 	secbuf = (char *) alloca(strlen(str) + 1);
249*30167Sbostic 	strcpy(secbuf, str);
250*30167Sbostic 	rev(secbuf);
251*30167Sbostic 	cp = word(-index, secbuf);
252*30167Sbostic 	rev(cp);
253*30167Sbostic 	return(cp);
254*30167Sbostic }
255*30167Sbostic 
256*30167Sbostic /*
257*30167Sbostic  * Skip leading blanks in the string, return
258*30167Sbostic  * first liberal word collected.
259*30167Sbostic  */
260*30167Sbostic 
261*30167Sbostic char *
gword(cp,buf)262*30167Sbostic gword(cp, buf)
263*30167Sbostic 	register char *cp;
264*30167Sbostic 	char buf[];
265*30167Sbostic {
266*30167Sbostic 	register char *cp2;
267*30167Sbostic 
268*30167Sbostic 	cp2 = buf;
269*30167Sbostic 	while (*cp && any(*cp, " \t\n"))
270*30167Sbostic 		cp++;
271*30167Sbostic 	while (*cp && !any(*cp, " \t\n"))
272*30167Sbostic 		*cp2++ = *cp++;
273*30167Sbostic 	*cp2 = 0;
274*30167Sbostic 	return(cp);
275*30167Sbostic }
276*30167Sbostic 
277*30167Sbostic /*
278*30167Sbostic  * Reverse the characters in the string in place
279*30167Sbostic  */
280*30167Sbostic 
rev(str)281*30167Sbostic rev(str)
282*30167Sbostic 	char str[];
283*30167Sbostic {
284*30167Sbostic 	register char *cpl, *cpr;
285*30167Sbostic 	register int s;
286*30167Sbostic 
287*30167Sbostic 	s = strlen(str);
288*30167Sbostic 	cpl = str;
289*30167Sbostic 	cpr = &str[s-1];
290*30167Sbostic 	while (cpl < cpr) {
291*30167Sbostic 		s = *cpl;
292*30167Sbostic 		*cpl++ = *cpr;
293*30167Sbostic 		*cpr-- = s;
294*30167Sbostic 	}
295*30167Sbostic }
296*30167Sbostic #endif UUCP
297*30167Sbostic 
298*30167Sbostic /*
299*30167Sbostic  * Save a string in dynamic space.
300*30167Sbostic  * This little goodie is needed for
301*30167Sbostic  * a headline detector in head.c
302*30167Sbostic  */
303*30167Sbostic 
304*30167Sbostic char *
savestr(str)305*30167Sbostic savestr(str)
306*30167Sbostic 	char str[];
307*30167Sbostic {
308*30167Sbostic 	register char *top;
309*30167Sbostic 
310*30167Sbostic 	top = calloc(strlen(str) + 1, 1);
311*30167Sbostic 	if (top == NOSTR) {
312*30167Sbostic 		fprintf(stderr, "unixtomh:  Ran out of memory\n");
313*30167Sbostic 		exit(1);
314*30167Sbostic 	}
315*30167Sbostic 	copy(str, top);
316*30167Sbostic 	return(top);
317*30167Sbostic }
318*30167Sbostic 
319*30167Sbostic /*
320*30167Sbostic  * See if the passed line buffer is a mail header.
321*30167Sbostic  * Return true if yes.  Note the extreme pains to
322*30167Sbostic  * accomodate all funny formats.
323*30167Sbostic  */
324*30167Sbostic 
ishead(linebuf)325*30167Sbostic ishead(linebuf)
326*30167Sbostic 	char linebuf[];
327*30167Sbostic {
328*30167Sbostic 	register char *cp;
329*30167Sbostic 	struct headline hl;
330*30167Sbostic 	char parbuf[BUFSIZ];
331*30167Sbostic 
332*30167Sbostic 	cp = linebuf;
333*30167Sbostic 	if (!isname("From ", cp, 5))
334*30167Sbostic 		return(0);
335*30167Sbostic 	parse(cp, &hl, parbuf);
336*30167Sbostic 	if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
337*30167Sbostic 		fail(linebuf, "No from or date field");
338*30167Sbostic 		return(0);
339*30167Sbostic 	}
340*30167Sbostic 	if (!isdate(hl.l_date)) {
341*30167Sbostic 		fail(linebuf, "Date field not legal date");
342*30167Sbostic 		return(0);
343*30167Sbostic 	}
344*30167Sbostic 
345*30167Sbostic 	/*
346*30167Sbostic 	 * I guess we got it!
347*30167Sbostic 	 */
348*30167Sbostic 
349*30167Sbostic 	return(1);
350*30167Sbostic }
351*30167Sbostic 
fail(linebuf,reason)352*30167Sbostic fail(linebuf, reason)
353*30167Sbostic 	char linebuf[], reason[];
354*30167Sbostic {
355*30167Sbostic 	return;
356*30167Sbostic }
357*30167Sbostic 
358*30167Sbostic /*
359*30167Sbostic  * Split a headline into its useful components.
360*30167Sbostic  * Copy the line into dynamic string space, then set
361*30167Sbostic  * pointers into the copied line in the passed headline
362*30167Sbostic  * structure.  Actually, it scans.
363*30167Sbostic  */
364*30167Sbostic 
parse(line,hl,pbuf)365*30167Sbostic parse(line, hl, pbuf)
366*30167Sbostic 	char line[], pbuf[];
367*30167Sbostic 	struct headline *hl;
368*30167Sbostic {
369*30167Sbostic 	register char *cp, *dp;
370*30167Sbostic 	char *sp;
371*30167Sbostic 	char word[BUFSIZ];
372*30167Sbostic 
373*30167Sbostic 	hl->l_from = NOSTR;
374*30167Sbostic 	hl->l_tty = NOSTR;
375*30167Sbostic 	hl->l_date = NOSTR;
376*30167Sbostic 	cp = line;
377*30167Sbostic 	sp = pbuf;
378*30167Sbostic 
379*30167Sbostic 	/*
380*30167Sbostic 	 * Skip the first "word" of the line, which should be "From"
381*30167Sbostic 	 * anyway.
382*30167Sbostic 	 */
383*30167Sbostic 
384*30167Sbostic 	cp = nextword(cp, word);
385*30167Sbostic 	dp = nextword(cp, word);
386*30167Sbostic 	if (word[0] != 0)
387*30167Sbostic 		hl->l_from = copyin(word, &sp);
388*30167Sbostic 	if (isname(dp, "tty", 3)) {
389*30167Sbostic 		cp = nextword(dp, word);
390*30167Sbostic 		hl->l_tty = copyin(word, &sp);
391*30167Sbostic 		if (cp != NOSTR)
392*30167Sbostic 			hl->l_date = copyin(cp, &sp);
393*30167Sbostic 	}
394*30167Sbostic 	else
395*30167Sbostic 		if (dp != NOSTR)
396*30167Sbostic 			hl->l_date = copyin(dp, &sp);
397*30167Sbostic }
398*30167Sbostic 
399*30167Sbostic /*
400*30167Sbostic  * Copy the string on the left into the string on the right
401*30167Sbostic  * and bump the right (reference) string pointer by the length.
402*30167Sbostic  * Thus, dynamically allocate space in the right string, copying
403*30167Sbostic  * the left string into it.
404*30167Sbostic  */
405*30167Sbostic 
406*30167Sbostic char *
copyin(src,space)407*30167Sbostic copyin(src, space)
408*30167Sbostic 	char src[];
409*30167Sbostic 	char **space;
410*30167Sbostic {
411*30167Sbostic 	register char *cp, *top;
412*30167Sbostic 	register int s;
413*30167Sbostic 
414*30167Sbostic 	s = strlen(src);
415*30167Sbostic 	cp = *space;
416*30167Sbostic 	top = cp;
417*30167Sbostic 	strcpy(cp, src);
418*30167Sbostic 	cp += s + 1;
419*30167Sbostic 	*space = cp;
420*30167Sbostic 	return(top);
421*30167Sbostic }
422*30167Sbostic 
423*30167Sbostic /*
424*30167Sbostic  * See if the two passed strings agree in the first n characters.
425*30167Sbostic  * Return true if they do, gnu.
426*30167Sbostic  */
427*30167Sbostic 
isname(as1,as2,acount)428*30167Sbostic isname(as1, as2, acount)
429*30167Sbostic 	char *as1, *as2;
430*30167Sbostic {
431*30167Sbostic 	register char *s1, *s2;
432*30167Sbostic 	register count;
433*30167Sbostic 
434*30167Sbostic 	s1 = as1;
435*30167Sbostic 	s2 = as2;
436*30167Sbostic 	count = acount;
437*30167Sbostic 	if (count > 0)
438*30167Sbostic 		do
439*30167Sbostic 			if (*s1++ != *s2++)
440*30167Sbostic 				return(0);
441*30167Sbostic 		while (--count);
442*30167Sbostic 	return(1);
443*30167Sbostic }
444*30167Sbostic 
445*30167Sbostic /*
446*30167Sbostic  * Test to see if the passed string is a ctime(3) generated
447*30167Sbostic  * date string as documented in the manual.  The template
448*30167Sbostic  * below is used as the criterion of correctness.
449*30167Sbostic  * Also, we check for a possible trailing time zone using
450*30167Sbostic  * the auxtype template.
451*30167Sbostic  */
452*30167Sbostic 
453*30167Sbostic #define	L	1		/* A lower case char */
454*30167Sbostic #define	S	2		/* A space */
455*30167Sbostic #define	D	3		/* A digit */
456*30167Sbostic #define	O	4		/* An optional digit or space */
457*30167Sbostic #define	C	5		/* A colon */
458*30167Sbostic #define	N	6		/* A new line */
459*30167Sbostic #define U	7		/* An upper case char */
460*30167Sbostic 
461*30167Sbostic char ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
462*30167Sbostic char tmztypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
463*30167Sbostic 
isdate(date)464*30167Sbostic isdate(date)
465*30167Sbostic 	char date[];
466*30167Sbostic {
467*30167Sbostic 	register char *cp;
468*30167Sbostic 
469*30167Sbostic 	cp = date;
470*30167Sbostic 	if (cmatch(cp, ctypes))
471*30167Sbostic 		return(1);
472*30167Sbostic 	return(cmatch(cp, tmztypes));
473*30167Sbostic }
474*30167Sbostic 
475*30167Sbostic /*
476*30167Sbostic  * Match the given string against the given template.
477*30167Sbostic  * Return 1 if they match, 0 if they don't
478*30167Sbostic  */
479*30167Sbostic 
cmatch(str,temp)480*30167Sbostic cmatch(str, temp)
481*30167Sbostic 	char str[], temp[];
482*30167Sbostic {
483*30167Sbostic 	register char *cp, *tp;
484*30167Sbostic 	register int c;
485*30167Sbostic 
486*30167Sbostic 	cp = str;
487*30167Sbostic 	tp = temp;
488*30167Sbostic 	while (*cp != '\0' && *tp != 0) {
489*30167Sbostic 		c = *cp++;
490*30167Sbostic 		switch (*tp++) {
491*30167Sbostic 		case L:
492*30167Sbostic 			if (!islower(c))
493*30167Sbostic 				return(0);
494*30167Sbostic 			break;
495*30167Sbostic 
496*30167Sbostic 		case S:
497*30167Sbostic 			if (c != ' ')
498*30167Sbostic 				return(0);
499*30167Sbostic 			break;
500*30167Sbostic 
501*30167Sbostic 		case D:
502*30167Sbostic 			if (!isdigit(c))
503*30167Sbostic 				return(0);
504*30167Sbostic 			break;
505*30167Sbostic 
506*30167Sbostic 		case O:
507*30167Sbostic 			if (c != ' ' && !isdigit(c))
508*30167Sbostic 				return(0);
509*30167Sbostic 			break;
510*30167Sbostic 
511*30167Sbostic 		case C:
512*30167Sbostic 			if (c != ':')
513*30167Sbostic 				return(0);
514*30167Sbostic 			break;
515*30167Sbostic 
516*30167Sbostic 		case N:
517*30167Sbostic 			if (c != '\n')
518*30167Sbostic 				return(0);
519*30167Sbostic 			break;
520*30167Sbostic 
521*30167Sbostic 		case U:
522*30167Sbostic 			if (!isupper(c))
523*30167Sbostic 				return(0);
524*30167Sbostic 			break;
525*30167Sbostic 		}
526*30167Sbostic 	}
527*30167Sbostic 	if (*cp != '\0' || *tp != 0)
528*30167Sbostic 		return(0);
529*30167Sbostic 	return(1);
530*30167Sbostic }
531*30167Sbostic 
532*30167Sbostic /*
533*30167Sbostic  * Collect a liberal (space, tab delimited) word into the word buffer
534*30167Sbostic  * passed.  Also, return a pointer to the next word following that,
535*30167Sbostic  * or NOSTR if none follow.
536*30167Sbostic  */
537*30167Sbostic 
538*30167Sbostic char *
nextword(wp,wbuf)539*30167Sbostic nextword(wp, wbuf)
540*30167Sbostic 	char wp[], wbuf[];
541*30167Sbostic {
542*30167Sbostic 	register char *cp, *cp2;
543*30167Sbostic 
544*30167Sbostic 	if ((cp = wp) == NOSTR) {
545*30167Sbostic 		copy("", wbuf);
546*30167Sbostic 		return(NOSTR);
547*30167Sbostic 	}
548*30167Sbostic 	cp2 = wbuf;
549*30167Sbostic 	while (!any(*cp, " \t") && *cp != '\0')
550*30167Sbostic 		if (*cp == '"') {
551*30167Sbostic  			*cp2++ = *cp++;
552*30167Sbostic  			while (*cp != '\0' && *cp != '"')
553*30167Sbostic  				*cp2++ = *cp++;
554*30167Sbostic  			if (*cp == '"')
555*30167Sbostic  				*cp2++ = *cp++;
556*30167Sbostic  		} else
557*30167Sbostic  			*cp2++ = *cp++;
558*30167Sbostic 	*cp2 = '\0';
559*30167Sbostic 	while (any(*cp, " \t"))
560*30167Sbostic 		cp++;
561*30167Sbostic 	if (*cp == '\0')
562*30167Sbostic 		return(NOSTR);
563*30167Sbostic 	return(cp);
564*30167Sbostic }
565*30167Sbostic 
566*30167Sbostic /*
567*30167Sbostic  * Copy str1 to str2, return pointer to null in str2.
568*30167Sbostic  */
569*30167Sbostic 
570*30167Sbostic char *
copy(str1,str2)571*30167Sbostic copy(str1, str2)
572*30167Sbostic 	char *str1, *str2;
573*30167Sbostic {
574*30167Sbostic 	register char *s1, *s2;
575*30167Sbostic 
576*30167Sbostic 	s1 = str1;
577*30167Sbostic 	s2 = str2;
578*30167Sbostic 	while (*s1)
579*30167Sbostic 		*s2++ = *s1++;
580*30167Sbostic 	*s2 = 0;
581*30167Sbostic 	return(s2);
582*30167Sbostic }
583*30167Sbostic 
584*30167Sbostic /*
585*30167Sbostic  * Is ch any of the characters in str?
586*30167Sbostic  */
587*30167Sbostic 
any(ch,str)588*30167Sbostic any(ch, str)
589*30167Sbostic 	char *str;
590*30167Sbostic {
591*30167Sbostic 	register char *f;
592*30167Sbostic 	register c;
593*30167Sbostic 
594*30167Sbostic 	f = str;
595*30167Sbostic 	c = ch;
596*30167Sbostic 	while (*f)
597*30167Sbostic 		if (c == *f++)
598*30167Sbostic 			return(1);
599*30167Sbostic 	return(0);
600*30167Sbostic }
601*30167Sbostic 
602*30167Sbostic /*
603*30167Sbostic  * Convert lower case letters to upper case.
604*30167Sbostic  */
605*30167Sbostic 
raise(c)606*30167Sbostic raise(c)
607*30167Sbostic 	register int c;
608*30167Sbostic {
609*30167Sbostic 	if (c >= 'a' && c <= 'z')
610*30167Sbostic 		c += 'A' - 'a';
611*30167Sbostic 	return(c);
612*30167Sbostic }
613