xref: /illumos-gate/usr/src/cmd/mailx/util.c (revision 2a8bcb4efb45d99ac41c94a75c396b362c414f7f)
1*955eb5e1SGarrett D'Amore /*
2*955eb5e1SGarrett D'Amore  * CDDL HEADER START
3*955eb5e1SGarrett D'Amore  *
4*955eb5e1SGarrett D'Amore  * The contents of this file are subject to the terms of the
5*955eb5e1SGarrett D'Amore  * Common Development and Distribution License, Version 1.0 only
6*955eb5e1SGarrett D'Amore  * (the "License").  You may not use this file except in compliance
7*955eb5e1SGarrett D'Amore  * with the License.
8*955eb5e1SGarrett D'Amore  *
9*955eb5e1SGarrett D'Amore  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*955eb5e1SGarrett D'Amore  * or http://www.opensolaris.org/os/licensing.
11*955eb5e1SGarrett D'Amore  * See the License for the specific language governing permissions
12*955eb5e1SGarrett D'Amore  * and limitations under the License.
13*955eb5e1SGarrett D'Amore  *
14*955eb5e1SGarrett D'Amore  * When distributing Covered Code, include this CDDL HEADER in each
15*955eb5e1SGarrett D'Amore  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*955eb5e1SGarrett D'Amore  * If applicable, add the following below this CDDL HEADER, with the
17*955eb5e1SGarrett D'Amore  * fields enclosed by brackets "[]" replaced with your own identifying
18*955eb5e1SGarrett D'Amore  * information: Portions Copyright [yyyy] [name of copyright owner]
19*955eb5e1SGarrett D'Amore  *
20*955eb5e1SGarrett D'Amore  * CDDL HEADER END
21*955eb5e1SGarrett D'Amore  */
22*955eb5e1SGarrett D'Amore /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*955eb5e1SGarrett D'Amore /*	  All Rights Reserved  	*/
24*955eb5e1SGarrett D'Amore 
25*955eb5e1SGarrett D'Amore 
26*955eb5e1SGarrett D'Amore /*
27*955eb5e1SGarrett D'Amore  * Copyright 1985-2002 Sun Microsystems, Inc. All rights reserved.
28*955eb5e1SGarrett D'Amore  * Use is subject to license terms.
29*955eb5e1SGarrett D'Amore  */
30*955eb5e1SGarrett D'Amore 
31*955eb5e1SGarrett D'Amore /*
32*955eb5e1SGarrett D'Amore  * University Copyright- Copyright (c) 1982, 1986, 1988
33*955eb5e1SGarrett D'Amore  * The Regents of the University of California
34*955eb5e1SGarrett D'Amore  * All Rights Reserved
35*955eb5e1SGarrett D'Amore  *
36*955eb5e1SGarrett D'Amore  * University Acknowledgment- Portions of this document are derived from
37*955eb5e1SGarrett D'Amore  * software developed by the University of California, Berkeley, and its
38*955eb5e1SGarrett D'Amore  * contributors.
39*955eb5e1SGarrett D'Amore  */
40*955eb5e1SGarrett D'Amore 
41*955eb5e1SGarrett D'Amore #include "rcv.h"
42*955eb5e1SGarrett D'Amore #include <locale.h>
43*955eb5e1SGarrett D'Amore 
44*955eb5e1SGarrett D'Amore /*
45*955eb5e1SGarrett D'Amore  * mailx -- a modified version of a University of California at Berkeley
46*955eb5e1SGarrett D'Amore  *	mail program
47*955eb5e1SGarrett D'Amore  *
48*955eb5e1SGarrett D'Amore  * Auxiliary functions.
49*955eb5e1SGarrett D'Amore  */
50*955eb5e1SGarrett D'Amore 
51*955eb5e1SGarrett D'Amore static char	*phrase(char *name, int token, int comma);
52*955eb5e1SGarrett D'Amore static char	*ripoff(register char *buf);
53*955eb5e1SGarrett D'Amore 
54*955eb5e1SGarrett D'Amore /*
55*955eb5e1SGarrett D'Amore  * Return a pointer to a dynamic copy of the argument.
56*955eb5e1SGarrett D'Amore  */
57*955eb5e1SGarrett D'Amore 
58*955eb5e1SGarrett D'Amore char *
savestr(char * str)59*955eb5e1SGarrett D'Amore savestr(char *str)
60*955eb5e1SGarrett D'Amore {
61*955eb5e1SGarrett D'Amore 	register char *cp, *cp2, *top;
62*955eb5e1SGarrett D'Amore 
63*955eb5e1SGarrett D'Amore 	for (cp = str; *cp; cp++)
64*955eb5e1SGarrett D'Amore 		;
65*955eb5e1SGarrett D'Amore 	top = (char *)salloc((unsigned)(cp-str + 1));
66*955eb5e1SGarrett D'Amore 	if (top == NOSTR)
67*955eb5e1SGarrett D'Amore 		return(NOSTR);
68*955eb5e1SGarrett D'Amore 	for (cp = str, cp2 = top; *cp; cp++)
69*955eb5e1SGarrett D'Amore 		*cp2++ = *cp;
70*955eb5e1SGarrett D'Amore 	*cp2 = 0;
71*955eb5e1SGarrett D'Amore 	return(top);
72*955eb5e1SGarrett D'Amore }
73*955eb5e1SGarrett D'Amore 
74*955eb5e1SGarrett D'Amore /*
75*955eb5e1SGarrett D'Amore  * Announce a fatal error and die.
76*955eb5e1SGarrett D'Amore  */
77*955eb5e1SGarrett D'Amore 
78*955eb5e1SGarrett D'Amore void
panic(char * str)79*955eb5e1SGarrett D'Amore panic(char *str)
80*955eb5e1SGarrett D'Amore {
81*955eb5e1SGarrett D'Amore 	fprintf(stderr, gettext("mailx: Panic - %s\n"), str);
82*955eb5e1SGarrett D'Amore 	exit(1);
83*955eb5e1SGarrett D'Amore 	/* NOTREACHED */
84*955eb5e1SGarrett D'Amore }
85*955eb5e1SGarrett D'Amore 
86*955eb5e1SGarrett D'Amore /*
87*955eb5e1SGarrett D'Amore  * Touch the named message by setting its MTOUCH flag.
88*955eb5e1SGarrett D'Amore  * Touched messages have the effect of not being sent
89*955eb5e1SGarrett D'Amore  * back to the system mailbox on exit.
90*955eb5e1SGarrett D'Amore  */
91*955eb5e1SGarrett D'Amore 
92*955eb5e1SGarrett D'Amore void
touch(int mesg)93*955eb5e1SGarrett D'Amore touch(int mesg)
94*955eb5e1SGarrett D'Amore {
95*955eb5e1SGarrett D'Amore 	register struct message *mp;
96*955eb5e1SGarrett D'Amore 
97*955eb5e1SGarrett D'Amore 	if (mesg < 1 || mesg > msgCount)
98*955eb5e1SGarrett D'Amore 		return;
99*955eb5e1SGarrett D'Amore 	mp = &message[mesg-1];
100*955eb5e1SGarrett D'Amore 	mp->m_flag |= MTOUCH;
101*955eb5e1SGarrett D'Amore 	if ((mp->m_flag & MREAD) == 0)
102*955eb5e1SGarrett D'Amore 		mp->m_flag |= MREAD|MSTATUS;
103*955eb5e1SGarrett D'Amore }
104*955eb5e1SGarrett D'Amore 
105*955eb5e1SGarrett D'Amore /*
106*955eb5e1SGarrett D'Amore  * Test to see if the passed file name is a directory.
107*955eb5e1SGarrett D'Amore  * Return true if it is.
108*955eb5e1SGarrett D'Amore  */
109*955eb5e1SGarrett D'Amore 
110*955eb5e1SGarrett D'Amore int
isdir(char name[])111*955eb5e1SGarrett D'Amore isdir(char name[])
112*955eb5e1SGarrett D'Amore {
113*955eb5e1SGarrett D'Amore 	struct stat sbuf;
114*955eb5e1SGarrett D'Amore 
115*955eb5e1SGarrett D'Amore 	if (stat(name, &sbuf) < 0)
116*955eb5e1SGarrett D'Amore 		return(0);
117*955eb5e1SGarrett D'Amore 	return((sbuf.st_mode & S_IFMT) == S_IFDIR);
118*955eb5e1SGarrett D'Amore }
119*955eb5e1SGarrett D'Amore 
120*955eb5e1SGarrett D'Amore /*
121*955eb5e1SGarrett D'Amore  * Count the number of arguments in the given string raw list.
122*955eb5e1SGarrett D'Amore  */
123*955eb5e1SGarrett D'Amore 
124*955eb5e1SGarrett D'Amore int
argcount(char ** argv)125*955eb5e1SGarrett D'Amore argcount(char **argv)
126*955eb5e1SGarrett D'Amore {
127*955eb5e1SGarrett D'Amore 	register char **ap;
128*955eb5e1SGarrett D'Amore 
129*955eb5e1SGarrett D'Amore 	for (ap = argv; *ap != NOSTR; ap++)
130*955eb5e1SGarrett D'Amore 		;
131*955eb5e1SGarrett D'Amore 	return(ap-argv);
132*955eb5e1SGarrett D'Amore }
133*955eb5e1SGarrett D'Amore 
134*955eb5e1SGarrett D'Amore /*
135*955eb5e1SGarrett D'Amore  * Return the desired header line from the passed message
136*955eb5e1SGarrett D'Amore  * pointer (or NOSTR if the desired header field is not available).
137*955eb5e1SGarrett D'Amore  * Read all the header lines and concatenate multiple instances of
138*955eb5e1SGarrett D'Amore  * the requested header.
139*955eb5e1SGarrett D'Amore  */
140*955eb5e1SGarrett D'Amore 
141*955eb5e1SGarrett D'Amore char *
hfield(char field[],struct message * mp,char * (* add)(char *,char *))142*955eb5e1SGarrett D'Amore hfield(char field[], struct message *mp, char *(*add)(char *, char *))
143*955eb5e1SGarrett D'Amore {
144*955eb5e1SGarrett D'Amore 	register FILE *ibuf;
145*955eb5e1SGarrett D'Amore 	char linebuf[LINESIZE];
146*955eb5e1SGarrett D'Amore 	register long lc;
147*955eb5e1SGarrett D'Amore 	char *r = NOSTR;
148*955eb5e1SGarrett D'Amore 
149*955eb5e1SGarrett D'Amore 	ibuf = setinput(mp);
150*955eb5e1SGarrett D'Amore 	if ((lc = mp->m_lines) <= 0)
151*955eb5e1SGarrett D'Amore 		return(NOSTR);
152*955eb5e1SGarrett D'Amore 	if (readline(ibuf, linebuf) < 0)
153*955eb5e1SGarrett D'Amore 		return(NOSTR);
154*955eb5e1SGarrett D'Amore 	lc--;
155*955eb5e1SGarrett D'Amore 	while ((lc = gethfield(ibuf, linebuf, lc)) >= 0)
156*955eb5e1SGarrett D'Amore 		if (ishfield(linebuf, field))
157*955eb5e1SGarrett D'Amore 			r = (*add)(r, hcontents(linebuf));
158*955eb5e1SGarrett D'Amore 	return r;
159*955eb5e1SGarrett D'Amore }
160*955eb5e1SGarrett D'Amore 
161*955eb5e1SGarrett D'Amore /*
162*955eb5e1SGarrett D'Amore  * Return the next header field found in the given message.
163*955eb5e1SGarrett D'Amore  * Return > 0 if something found, <= 0 elsewise.
164*955eb5e1SGarrett D'Amore  * Must deal with \ continuations & other such fraud.
165*955eb5e1SGarrett D'Amore  */
166*955eb5e1SGarrett D'Amore 
167*955eb5e1SGarrett D'Amore int
gethfield(register FILE * f,char linebuf[],register long rem)168*955eb5e1SGarrett D'Amore gethfield(
169*955eb5e1SGarrett D'Amore 	register FILE *f,
170*955eb5e1SGarrett D'Amore 	char linebuf[],
171*955eb5e1SGarrett D'Amore 	register long rem)
172*955eb5e1SGarrett D'Amore {
173*955eb5e1SGarrett D'Amore 	char line2[LINESIZE];
174*955eb5e1SGarrett D'Amore 	register char *cp, *cp2;
175*955eb5e1SGarrett D'Amore 	register int c;
176*955eb5e1SGarrett D'Amore 
177*955eb5e1SGarrett D'Amore 	for (;;) {
178*955eb5e1SGarrett D'Amore 		if (rem <= 0)
179*955eb5e1SGarrett D'Amore 			return(-1);
180*955eb5e1SGarrett D'Amore 		if (readline(f, linebuf) < 0)
181*955eb5e1SGarrett D'Amore 			return(-1);
182*955eb5e1SGarrett D'Amore 		rem--;
183*955eb5e1SGarrett D'Amore 		if (strlen(linebuf) == 0)
184*955eb5e1SGarrett D'Amore 			return(-1);
185*955eb5e1SGarrett D'Amore 		if (isspace(linebuf[0]))
186*955eb5e1SGarrett D'Amore 			continue;
187*955eb5e1SGarrett D'Amore 		if (!headerp(linebuf))
188*955eb5e1SGarrett D'Amore 			return(-1);
189*955eb5e1SGarrett D'Amore 
190*955eb5e1SGarrett D'Amore 		/*
191*955eb5e1SGarrett D'Amore 		 * I guess we got a headline.
192*955eb5e1SGarrett D'Amore 		 * Handle wraparounding
193*955eb5e1SGarrett D'Amore 		 */
194*955eb5e1SGarrett D'Amore 
195*955eb5e1SGarrett D'Amore 		for (;;) {
196*955eb5e1SGarrett D'Amore 			if (rem <= 0)
197*955eb5e1SGarrett D'Amore 				break;
198*955eb5e1SGarrett D'Amore 			c = getc(f);
199*955eb5e1SGarrett D'Amore 			ungetc(c, f);
200*955eb5e1SGarrett D'Amore 			if (!isspace(c) || c == '\n')
201*955eb5e1SGarrett D'Amore 				break;
202*955eb5e1SGarrett D'Amore 			if (readline(f, line2) < 0)
203*955eb5e1SGarrett D'Amore 				break;
204*955eb5e1SGarrett D'Amore 			rem--;
205*955eb5e1SGarrett D'Amore 			cp2 = line2;
206*955eb5e1SGarrett D'Amore 			for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++)
207*955eb5e1SGarrett D'Amore 				;
208*955eb5e1SGarrett D'Amore 			if (strlen(linebuf) + strlen(cp2) >=
209*955eb5e1SGarrett D'Amore 			    (unsigned)LINESIZE-2)
210*955eb5e1SGarrett D'Amore 				break;
211*955eb5e1SGarrett D'Amore 			cp = &linebuf[strlen(linebuf)];
212*955eb5e1SGarrett D'Amore 			while (cp > linebuf &&
213*955eb5e1SGarrett D'Amore 			    (isspace(cp[-1]) || cp[-1] == '\\'))
214*955eb5e1SGarrett D'Amore 				cp--;
215*955eb5e1SGarrett D'Amore 			*cp++ = ' ';
216*955eb5e1SGarrett D'Amore 			for (cp2 = line2; *cp2 != 0 && isspace(*cp2); cp2++)
217*955eb5e1SGarrett D'Amore 				;
218*955eb5e1SGarrett D'Amore 			nstrcpy(cp, LINESIZE - (cp - linebuf), cp2);
219*955eb5e1SGarrett D'Amore 		}
220*955eb5e1SGarrett D'Amore 		if ((c = strlen(linebuf)) > 0) {
221*955eb5e1SGarrett D'Amore 			cp = &linebuf[c-1];
222*955eb5e1SGarrett D'Amore 			while (cp > linebuf && isspace(*cp))
223*955eb5e1SGarrett D'Amore 				cp--;
224*955eb5e1SGarrett D'Amore 			*++cp = 0;
225*955eb5e1SGarrett D'Amore 		}
226*955eb5e1SGarrett D'Amore 		return(rem);
227*955eb5e1SGarrett D'Amore 	}
228*955eb5e1SGarrett D'Amore 	/* NOTREACHED */
229*955eb5e1SGarrett D'Amore }
230*955eb5e1SGarrett D'Amore 
231*955eb5e1SGarrett D'Amore /*
232*955eb5e1SGarrett D'Amore  * Check whether the passed line is a header line of
233*955eb5e1SGarrett D'Amore  * the desired breed.
234*955eb5e1SGarrett D'Amore  */
235*955eb5e1SGarrett D'Amore 
236*955eb5e1SGarrett D'Amore int
ishfield(char linebuf[],char field[])237*955eb5e1SGarrett D'Amore ishfield(char linebuf[], char field[])
238*955eb5e1SGarrett D'Amore {
239*955eb5e1SGarrett D'Amore 	register char *cp;
240*955eb5e1SGarrett D'Amore 
241*955eb5e1SGarrett D'Amore 	if ((cp = strchr(linebuf, ':')) == NOSTR)
242*955eb5e1SGarrett D'Amore 		return(0);
243*955eb5e1SGarrett D'Amore 	if (cp == linebuf)
244*955eb5e1SGarrett D'Amore 		return(0);
245*955eb5e1SGarrett D'Amore 	*cp = 0;
246*955eb5e1SGarrett D'Amore 	if (icequal(linebuf, field)) {
247*955eb5e1SGarrett D'Amore 		*cp = ':';
248*955eb5e1SGarrett D'Amore 		return(1);
249*955eb5e1SGarrett D'Amore 	}
250*955eb5e1SGarrett D'Amore 	*cp = ':';
251*955eb5e1SGarrett D'Amore 	return(0);
252*955eb5e1SGarrett D'Amore }
253*955eb5e1SGarrett D'Amore 
254*955eb5e1SGarrett D'Amore /*
255*955eb5e1SGarrett D'Amore  * Extract the non label information from the given header field
256*955eb5e1SGarrett D'Amore  * and return it.
257*955eb5e1SGarrett D'Amore  */
258*955eb5e1SGarrett D'Amore 
259*955eb5e1SGarrett D'Amore char *
hcontents(char hfield[])260*955eb5e1SGarrett D'Amore hcontents(char hfield[])
261*955eb5e1SGarrett D'Amore {
262*955eb5e1SGarrett D'Amore 	register char *cp;
263*955eb5e1SGarrett D'Amore 
264*955eb5e1SGarrett D'Amore 	if ((cp = strchr(hfield, ':')) == NOSTR)
265*955eb5e1SGarrett D'Amore 		return(NOSTR);
266*955eb5e1SGarrett D'Amore 	cp++;
267*955eb5e1SGarrett D'Amore 	while (*cp && isspace(*cp))
268*955eb5e1SGarrett D'Amore 		cp++;
269*955eb5e1SGarrett D'Amore 	return(cp);
270*955eb5e1SGarrett D'Amore }
271*955eb5e1SGarrett D'Amore 
272*955eb5e1SGarrett D'Amore /*
273*955eb5e1SGarrett D'Amore  * Compare two strings, ignoring case.
274*955eb5e1SGarrett D'Amore  */
275*955eb5e1SGarrett D'Amore 
276*955eb5e1SGarrett D'Amore int
icequal(register char * s1,register char * s2)277*955eb5e1SGarrett D'Amore icequal(register char *s1, register char *s2)
278*955eb5e1SGarrett D'Amore {
279*955eb5e1SGarrett D'Amore 
280*955eb5e1SGarrett D'Amore 	while (toupper(*s1++) == toupper(*s2))
281*955eb5e1SGarrett D'Amore 		if (*s2++ == 0)
282*955eb5e1SGarrett D'Amore 			return(1);
283*955eb5e1SGarrett D'Amore 	return(0);
284*955eb5e1SGarrett D'Amore }
285*955eb5e1SGarrett D'Amore 
286*955eb5e1SGarrett D'Amore /*
287*955eb5e1SGarrett D'Amore  * Copy a string, lowercasing it as we go. Here dstsize is the size of
288*955eb5e1SGarrett D'Amore  * the destination buffer dst.
289*955eb5e1SGarrett D'Amore  */
290*955eb5e1SGarrett D'Amore void
istrcpy(char * dst,int dstsize,char * src)291*955eb5e1SGarrett D'Amore istrcpy(char *dst, int dstsize, char *src)
292*955eb5e1SGarrett D'Amore {
293*955eb5e1SGarrett D'Amore 	register char *cp, *cp2;
294*955eb5e1SGarrett D'Amore 
295*955eb5e1SGarrett D'Amore 	cp2 = dst;
296*955eb5e1SGarrett D'Amore 	cp = src;
297*955eb5e1SGarrett D'Amore 
298*955eb5e1SGarrett D'Amore 	while (--dstsize > 0 && *cp != '\0')
299*955eb5e1SGarrett D'Amore 		*cp2++ = tolower(*cp++);
300*955eb5e1SGarrett D'Amore 	*cp2 = '\0';
301*955eb5e1SGarrett D'Amore }
302*955eb5e1SGarrett D'Amore 
303*955eb5e1SGarrett D'Amore /*
304*955eb5e1SGarrett D'Amore  * The following code deals with input stacking to do source
305*955eb5e1SGarrett D'Amore  * commands.  All but the current file pointer are saved on
306*955eb5e1SGarrett D'Amore  * the stack.
307*955eb5e1SGarrett D'Amore  */
308*955eb5e1SGarrett D'Amore 
309*955eb5e1SGarrett D'Amore static	int	ssp = -1;		/* Top of file stack */
310*955eb5e1SGarrett D'Amore static struct sstack {
311*955eb5e1SGarrett D'Amore 	FILE	*s_file;		/* File we were in. */
312*955eb5e1SGarrett D'Amore 	int	s_cond;			/* Saved state of conditionals */
313*955eb5e1SGarrett D'Amore 	int	s_loading;		/* Loading .mailrc, etc. */
314*955eb5e1SGarrett D'Amore } *sstack;
315*955eb5e1SGarrett D'Amore 
316*955eb5e1SGarrett D'Amore /*
317*955eb5e1SGarrett D'Amore  * Pushdown current input file and switch to a new one.
318*955eb5e1SGarrett D'Amore  * Set the global flag "sourcing" so that others will realize
319*955eb5e1SGarrett D'Amore  * that they are no longer reading from a tty (in all probability).
320*955eb5e1SGarrett D'Amore  */
321*955eb5e1SGarrett D'Amore 
322*955eb5e1SGarrett D'Amore int
source(char name[])323*955eb5e1SGarrett D'Amore source(char name[])
324*955eb5e1SGarrett D'Amore {
325*955eb5e1SGarrett D'Amore 	register FILE *fi;
326*955eb5e1SGarrett D'Amore 	register char *cp;
327*955eb5e1SGarrett D'Amore 
328*955eb5e1SGarrett D'Amore 	if ((cp = expand(name)) == NOSTR)
329*955eb5e1SGarrett D'Amore 		return(1);
330*955eb5e1SGarrett D'Amore 	if ((fi = fopen(cp, "r")) == NULL) {
331*955eb5e1SGarrett D'Amore 		printf(gettext("Unable to open %s\n"), cp);
332*955eb5e1SGarrett D'Amore 		return(1);
333*955eb5e1SGarrett D'Amore 	}
334*955eb5e1SGarrett D'Amore 
335*955eb5e1SGarrett D'Amore 	if (!maxfiles) {
336*955eb5e1SGarrett D'Amore 		if ((maxfiles = (int)ulimit(4, 0)) < 0)
337*955eb5e1SGarrett D'Amore #ifndef _NFILE
338*955eb5e1SGarrett D'Amore # define _NFILE 20
339*955eb5e1SGarrett D'Amore #endif
340*955eb5e1SGarrett D'Amore 			maxfiles = _NFILE;
341*955eb5e1SGarrett D'Amore 		sstack = (struct sstack *)calloc(maxfiles, sizeof(struct sstack));
342*955eb5e1SGarrett D'Amore 		if (sstack == NULL) {
343*955eb5e1SGarrett D'Amore 			printf(gettext(
344*955eb5e1SGarrett D'Amore 			    "Couldn't allocate memory for sourcing stack\n"));
345*955eb5e1SGarrett D'Amore 			fclose(fi);
346*955eb5e1SGarrett D'Amore 			return(1);
347*955eb5e1SGarrett D'Amore 		}
348*955eb5e1SGarrett D'Amore 	}
349*955eb5e1SGarrett D'Amore 
350*955eb5e1SGarrett D'Amore 	sstack[++ssp].s_file = input;
351*955eb5e1SGarrett D'Amore 	sstack[ssp].s_cond = cond;
352*955eb5e1SGarrett D'Amore 	sstack[ssp].s_loading = loading;
353*955eb5e1SGarrett D'Amore 	loading = 0;
354*955eb5e1SGarrett D'Amore 	cond = CANY;
355*955eb5e1SGarrett D'Amore 	input = fi;
356*955eb5e1SGarrett D'Amore 	sourcing++;
357*955eb5e1SGarrett D'Amore 	return(0);
358*955eb5e1SGarrett D'Amore }
359*955eb5e1SGarrett D'Amore 
360*955eb5e1SGarrett D'Amore /*
361*955eb5e1SGarrett D'Amore  * Pop the current input back to the previous level.
362*955eb5e1SGarrett D'Amore  * Update the "sourcing" flag as appropriate.
363*955eb5e1SGarrett D'Amore  */
364*955eb5e1SGarrett D'Amore 
365*955eb5e1SGarrett D'Amore int
unstack(void)366*955eb5e1SGarrett D'Amore unstack(void)
367*955eb5e1SGarrett D'Amore {
368*955eb5e1SGarrett D'Amore 	if (ssp < 0) {
369*955eb5e1SGarrett D'Amore 		printf(gettext("\"Source\" stack over-pop.\n"));
370*955eb5e1SGarrett D'Amore 		sourcing = 0;
371*955eb5e1SGarrett D'Amore 		return(1);
372*955eb5e1SGarrett D'Amore 	}
373*955eb5e1SGarrett D'Amore 	fclose(input);
374*955eb5e1SGarrett D'Amore 	if (cond != CANY)
375*955eb5e1SGarrett D'Amore 		printf(gettext("Unmatched \"if\"\n"));
376*955eb5e1SGarrett D'Amore 	cond = sstack[ssp].s_cond;
377*955eb5e1SGarrett D'Amore 	loading = sstack[ssp].s_loading;
378*955eb5e1SGarrett D'Amore 	input = sstack[ssp--].s_file;
379*955eb5e1SGarrett D'Amore 	if (ssp < 0)
380*955eb5e1SGarrett D'Amore 		sourcing = loading;
381*955eb5e1SGarrett D'Amore 	return(0);
382*955eb5e1SGarrett D'Amore }
383*955eb5e1SGarrett D'Amore 
384*955eb5e1SGarrett D'Amore /*
385*955eb5e1SGarrett D'Amore  * Touch the indicated file.
386*955eb5e1SGarrett D'Amore  * This is nifty for the shell.
387*955eb5e1SGarrett D'Amore  * If we have the utime() system call, this is better served
388*955eb5e1SGarrett D'Amore  * by using that, since it will work for empty files.
389*955eb5e1SGarrett D'Amore  * On non-utime systems, we must sleep a second, then read.
390*955eb5e1SGarrett D'Amore  */
391*955eb5e1SGarrett D'Amore 
392*955eb5e1SGarrett D'Amore void
alter(char name[])393*955eb5e1SGarrett D'Amore alter(char name[])
394*955eb5e1SGarrett D'Amore {
395*955eb5e1SGarrett D'Amore 	int rc = utime(name, utimep);
396*955eb5e1SGarrett D'Amore 	extern int errno;
397*955eb5e1SGarrett D'Amore 
398*955eb5e1SGarrett D'Amore 	if (rc != 0) {
399*955eb5e1SGarrett D'Amore 		fprintf(stderr, gettext("Cannot utime %s in aux:alter\n"),
400*955eb5e1SGarrett D'Amore name);
401*955eb5e1SGarrett D'Amore 		fprintf(stderr, gettext("Errno: %d\n"), errno);
402*955eb5e1SGarrett D'Amore 	}
403*955eb5e1SGarrett D'Amore }
404*955eb5e1SGarrett D'Amore 
405*955eb5e1SGarrett D'Amore /*
406*955eb5e1SGarrett D'Amore  * Examine the passed line buffer and
407*955eb5e1SGarrett D'Amore  * return true if it is all blanks and tabs.
408*955eb5e1SGarrett D'Amore  */
409*955eb5e1SGarrett D'Amore 
410*955eb5e1SGarrett D'Amore int
blankline(const char linebuf[])411*955eb5e1SGarrett D'Amore blankline(const char linebuf[])
412*955eb5e1SGarrett D'Amore {
413*955eb5e1SGarrett D'Amore 	register const char *cp;
414*955eb5e1SGarrett D'Amore 
415*955eb5e1SGarrett D'Amore 	for (cp = linebuf; *cp; cp++)
416*955eb5e1SGarrett D'Amore 		if (!any(*cp, " \t"))
417*955eb5e1SGarrett D'Amore 			return(0);
418*955eb5e1SGarrett D'Amore 	return(1);
419*955eb5e1SGarrett D'Amore }
420*955eb5e1SGarrett D'Amore 
421*955eb5e1SGarrett D'Amore /*
422*955eb5e1SGarrett D'Amore  * Skin an arpa net address according to the RFC 822 interpretation
423*955eb5e1SGarrett D'Amore  * of "host-phrase."
424*955eb5e1SGarrett D'Amore  */
425*955eb5e1SGarrett D'Amore static char *
phrase(char * name,int token,int comma)426*955eb5e1SGarrett D'Amore phrase(char *name, int token, int comma)
427*955eb5e1SGarrett D'Amore {
428*955eb5e1SGarrett D'Amore 	register char c;
429*955eb5e1SGarrett D'Amore 	register char *cp, *cp2;
430*955eb5e1SGarrett D'Amore 	char *bufend, *nbufp;
431*955eb5e1SGarrett D'Amore 	int gotlt, lastsp, didq;
432*955eb5e1SGarrett D'Amore 	char nbuf[LINESIZE];
433*955eb5e1SGarrett D'Amore 	int nesting;
434*955eb5e1SGarrett D'Amore 
435*955eb5e1SGarrett D'Amore 	if (name == NOSTR)
436*955eb5e1SGarrett D'Amore 		return(NOSTR);
437*955eb5e1SGarrett D'Amore 	if (strlen(name) >= (unsigned)LINESIZE)
438*955eb5e1SGarrett D'Amore 		nbufp = (char *)salloc(strlen(name));
439*955eb5e1SGarrett D'Amore 	else
440*955eb5e1SGarrett D'Amore 		nbufp = nbuf;
441*955eb5e1SGarrett D'Amore 	gotlt = 0;
442*955eb5e1SGarrett D'Amore 	lastsp = 0;
443*955eb5e1SGarrett D'Amore 	bufend = nbufp;
444*955eb5e1SGarrett D'Amore 	for (cp = name, cp2 = bufend; (c = *cp++) != 0;) {
445*955eb5e1SGarrett D'Amore 		switch (c) {
446*955eb5e1SGarrett D'Amore 		case '(':
447*955eb5e1SGarrett D'Amore 			/*
448*955eb5e1SGarrett D'Amore 				Start of a comment, ignore it.
449*955eb5e1SGarrett D'Amore 			*/
450*955eb5e1SGarrett D'Amore 			nesting = 1;
451*955eb5e1SGarrett D'Amore 			while ((c = *cp) != 0) {
452*955eb5e1SGarrett D'Amore 				cp++;
453*955eb5e1SGarrett D'Amore 				switch(c) {
454*955eb5e1SGarrett D'Amore 				case '\\':
455*955eb5e1SGarrett D'Amore 					if (*cp == 0) goto outcm;
456*955eb5e1SGarrett D'Amore 					cp++;
457*955eb5e1SGarrett D'Amore 					break;
458*955eb5e1SGarrett D'Amore 				case '(':
459*955eb5e1SGarrett D'Amore 					nesting++;
460*955eb5e1SGarrett D'Amore 					break;
461*955eb5e1SGarrett D'Amore 				case ')':
462*955eb5e1SGarrett D'Amore 					--nesting;
463*955eb5e1SGarrett D'Amore 					break;
464*955eb5e1SGarrett D'Amore 				}
465*955eb5e1SGarrett D'Amore 				if (nesting <= 0) break;
466*955eb5e1SGarrett D'Amore 			}
467*955eb5e1SGarrett D'Amore 		outcm:
468*955eb5e1SGarrett D'Amore 			lastsp = 0;
469*955eb5e1SGarrett D'Amore 			break;
470*955eb5e1SGarrett D'Amore 		case '"':
471*955eb5e1SGarrett D'Amore 			/*
472*955eb5e1SGarrett D'Amore 				Start a quoted string.
473*955eb5e1SGarrett D'Amore 				Copy it in its entirety.
474*955eb5e1SGarrett D'Amore 			*/
475*955eb5e1SGarrett D'Amore 			didq = 0;
476*955eb5e1SGarrett D'Amore 			while ((c = *cp) != 0) {
477*955eb5e1SGarrett D'Amore 				cp++;
478*955eb5e1SGarrett D'Amore 				switch (c) {
479*955eb5e1SGarrett D'Amore 				case '\\':
480*955eb5e1SGarrett D'Amore 					if ((c = *cp) == 0) goto outqs;
481*955eb5e1SGarrett D'Amore 					cp++;
482*955eb5e1SGarrett D'Amore 					break;
483*955eb5e1SGarrett D'Amore 				case '"':
484*955eb5e1SGarrett D'Amore 					goto outqs;
485*955eb5e1SGarrett D'Amore 				}
486*955eb5e1SGarrett D'Amore 				if (gotlt == 0 || gotlt == '<') {
487*955eb5e1SGarrett D'Amore 					if (lastsp) {
488*955eb5e1SGarrett D'Amore 						lastsp = 0;
489*955eb5e1SGarrett D'Amore 						*cp2++ = ' ';
490*955eb5e1SGarrett D'Amore 					}
491*955eb5e1SGarrett D'Amore 					if (!didq) {
492*955eb5e1SGarrett D'Amore 						*cp2++ = '"';
493*955eb5e1SGarrett D'Amore 						didq++;
494*955eb5e1SGarrett D'Amore 					}
495*955eb5e1SGarrett D'Amore 					*cp2++ = c;
496*955eb5e1SGarrett D'Amore 				}
497*955eb5e1SGarrett D'Amore 			}
498*955eb5e1SGarrett D'Amore 		outqs:
499*955eb5e1SGarrett D'Amore 			if (didq)
500*955eb5e1SGarrett D'Amore 				*cp2++ = '"';
501*955eb5e1SGarrett D'Amore 			lastsp = 0;
502*955eb5e1SGarrett D'Amore 			break;
503*955eb5e1SGarrett D'Amore 
504*955eb5e1SGarrett D'Amore 		case ' ':
505*955eb5e1SGarrett D'Amore 		case '\t':
506*955eb5e1SGarrett D'Amore 		case '\n':
507*955eb5e1SGarrett D'Amore 			if (token && (!comma || c == '\n')) {
508*955eb5e1SGarrett D'Amore 			done:
509*955eb5e1SGarrett D'Amore 				cp[-1] = 0;
510*955eb5e1SGarrett D'Amore 				return cp;
511*955eb5e1SGarrett D'Amore 			}
512*955eb5e1SGarrett D'Amore 			lastsp = 1;
513*955eb5e1SGarrett D'Amore 			break;
514*955eb5e1SGarrett D'Amore 
515*955eb5e1SGarrett D'Amore 		case ',':
516*955eb5e1SGarrett D'Amore 			*cp2++ = c;
517*955eb5e1SGarrett D'Amore 			if (gotlt != '<') {
518*955eb5e1SGarrett D'Amore 				if (token)
519*955eb5e1SGarrett D'Amore 					goto done;
520*955eb5e1SGarrett D'Amore 				bufend = cp2;
521*955eb5e1SGarrett D'Amore 				gotlt = 0;
522*955eb5e1SGarrett D'Amore 			}
523*955eb5e1SGarrett D'Amore 			break;
524*955eb5e1SGarrett D'Amore 
525*955eb5e1SGarrett D'Amore 		case '<':
526*955eb5e1SGarrett D'Amore 			cp2 = bufend;
527*955eb5e1SGarrett D'Amore 			gotlt = c;
528*955eb5e1SGarrett D'Amore 			lastsp = 0;
529*955eb5e1SGarrett D'Amore 			break;
530*955eb5e1SGarrett D'Amore 
531*955eb5e1SGarrett D'Amore 		case '>':
532*955eb5e1SGarrett D'Amore 			if (gotlt == '<') {
533*955eb5e1SGarrett D'Amore 				gotlt = c;
534*955eb5e1SGarrett D'Amore 				break;
535*955eb5e1SGarrett D'Amore 			}
536*955eb5e1SGarrett D'Amore 
537*955eb5e1SGarrett D'Amore 			/* FALLTHROUGH . . . */
538*955eb5e1SGarrett D'Amore 
539*955eb5e1SGarrett D'Amore 		default:
540*955eb5e1SGarrett D'Amore 			if (gotlt == 0 || gotlt == '<') {
541*955eb5e1SGarrett D'Amore 				if (lastsp) {
542*955eb5e1SGarrett D'Amore 					lastsp = 0;
543*955eb5e1SGarrett D'Amore 					*cp2++ = ' ';
544*955eb5e1SGarrett D'Amore 				}
545*955eb5e1SGarrett D'Amore 				*cp2++ = c;
546*955eb5e1SGarrett D'Amore 			}
547*955eb5e1SGarrett D'Amore 			break;
548*955eb5e1SGarrett D'Amore 		}
549*955eb5e1SGarrett D'Amore 	}
550*955eb5e1SGarrett D'Amore 	*cp2 = 0;
551*955eb5e1SGarrett D'Amore 	return (token ? --cp : equal(name, nbufp) ? name :
552*955eb5e1SGarrett D'Amore 	    nbufp == nbuf ? savestr(nbuf) : nbufp);
553*955eb5e1SGarrett D'Amore }
554*955eb5e1SGarrett D'Amore 
555*955eb5e1SGarrett D'Amore char *
skin(char * name)556*955eb5e1SGarrett D'Amore skin(char *name)
557*955eb5e1SGarrett D'Amore {
558*955eb5e1SGarrett D'Amore 	return phrase(name, 0, 0);
559*955eb5e1SGarrett D'Amore }
560*955eb5e1SGarrett D'Amore 
561*955eb5e1SGarrett D'Amore /*
562*955eb5e1SGarrett D'Amore  * Here sz is the buffer size of word.
563*955eb5e1SGarrett D'Amore  */
564*955eb5e1SGarrett D'Amore char *
yankword(char * name,char * word,int sz,int comma)565*955eb5e1SGarrett D'Amore yankword(char *name, char *word, int sz, int comma)
566*955eb5e1SGarrett D'Amore {
567*955eb5e1SGarrett D'Amore 	char *cp;
568*955eb5e1SGarrett D'Amore 
569*955eb5e1SGarrett D'Amore 	if (name == 0)
570*955eb5e1SGarrett D'Amore 		return 0;
571*955eb5e1SGarrett D'Amore 	while (isspace(*name))
572*955eb5e1SGarrett D'Amore 		name++;
573*955eb5e1SGarrett D'Amore 	if (*name == 0)
574*955eb5e1SGarrett D'Amore 		return 0;
575*955eb5e1SGarrett D'Amore 	cp = phrase(name, 1, comma);
576*955eb5e1SGarrett D'Amore 	nstrcpy(word, sz, name);
577*955eb5e1SGarrett D'Amore 	return cp;
578*955eb5e1SGarrett D'Amore }
579*955eb5e1SGarrett D'Amore 
580*955eb5e1SGarrett D'Amore int
docomma(char * s)581*955eb5e1SGarrett D'Amore docomma(char *s)
582*955eb5e1SGarrett D'Amore {
583*955eb5e1SGarrett D'Amore 	return s && strpbrk(s, "(<,");
584*955eb5e1SGarrett D'Amore }
585*955eb5e1SGarrett D'Amore 
586*955eb5e1SGarrett D'Amore /*
587*955eb5e1SGarrett D'Amore  * Fetch the sender's name from the passed message.
588*955eb5e1SGarrett D'Amore  */
589*955eb5e1SGarrett D'Amore 
590*955eb5e1SGarrett D'Amore char *
nameof(register struct message * mp)591*955eb5e1SGarrett D'Amore nameof(register struct message *mp)
592*955eb5e1SGarrett D'Amore {
593*955eb5e1SGarrett D'Amore 	char namebuf[LINESIZE];
594*955eb5e1SGarrett D'Amore 	char linebuf[LINESIZE];
595*955eb5e1SGarrett D'Amore 	register char *cp, *cp2;
596*955eb5e1SGarrett D'Amore 	register FILE *ibuf;
597*955eb5e1SGarrett D'Amore 	int first = 1, wint = 0;
598*955eb5e1SGarrett D'Amore 	char	*tmp;
599*955eb5e1SGarrett D'Amore 
600*955eb5e1SGarrett D'Amore 	if (value("from") && (cp = hfield("from", mp, addto)) != NOSTR)
601*955eb5e1SGarrett D'Amore 		return ripoff(cp);
602*955eb5e1SGarrett D'Amore 	ibuf = setinput(mp);
603*955eb5e1SGarrett D'Amore 	copy("", namebuf);
604*955eb5e1SGarrett D'Amore 	if (readline(ibuf, linebuf) <= 0)
605*955eb5e1SGarrett D'Amore 		return(savestr(namebuf));
606*955eb5e1SGarrett D'Amore newname:
607*955eb5e1SGarrett D'Amore 	for (cp = linebuf; *cp != ' '; cp++)
608*955eb5e1SGarrett D'Amore 		;
609*955eb5e1SGarrett D'Amore 	while (any(*cp, " \t"))
610*955eb5e1SGarrett D'Amore 		cp++;
611*955eb5e1SGarrett D'Amore 	for (cp2 = &namebuf[strlen(namebuf)]; *cp && !any(*cp, " \t") &&
612*955eb5e1SGarrett D'Amore 	    cp2-namebuf < LINESIZE-1; *cp2++ = *cp++)
613*955eb5e1SGarrett D'Amore 		;
614*955eb5e1SGarrett D'Amore 	*cp2 = '\0';
615*955eb5e1SGarrett D'Amore 	for (;;) {
616*955eb5e1SGarrett D'Amore 		if (readline(ibuf, linebuf) <= 0)
617*955eb5e1SGarrett D'Amore 			break;
618*955eb5e1SGarrett D'Amore 		if (substr(linebuf,"forwarded by ") != -1)
619*955eb5e1SGarrett D'Amore 			continue;
620*955eb5e1SGarrett D'Amore 		if (linebuf[0] == 'F')
621*955eb5e1SGarrett D'Amore 			cp = linebuf;
622*955eb5e1SGarrett D'Amore 		else if (linebuf[0] == '>')
623*955eb5e1SGarrett D'Amore 			cp = linebuf + 1;
624*955eb5e1SGarrett D'Amore 		else
625*955eb5e1SGarrett D'Amore 			break;
626*955eb5e1SGarrett D'Amore 		if (strncmp(cp, "From ", 5) != 0)
627*955eb5e1SGarrett D'Amore 			break;
628*955eb5e1SGarrett D'Amore 		if ((wint = substr(cp, "remote from ")) != -1) {
629*955eb5e1SGarrett D'Amore 			cp += wint + 12;
630*955eb5e1SGarrett D'Amore 			if (first) {
631*955eb5e1SGarrett D'Amore 				copy(cp, namebuf);
632*955eb5e1SGarrett D'Amore 				first = 0;
633*955eb5e1SGarrett D'Amore 			} else {
634*955eb5e1SGarrett D'Amore 				tmp = strrchr(namebuf, '!') + 1;
635*955eb5e1SGarrett D'Amore 				nstrcpy(tmp,
636*955eb5e1SGarrett D'Amore 					sizeof (namebuf) - (tmp  - namebuf),
637*955eb5e1SGarrett D'Amore 					cp);
638*955eb5e1SGarrett D'Amore 			}
639*955eb5e1SGarrett D'Amore 			nstrcat(namebuf, sizeof (namebuf), "!");
640*955eb5e1SGarrett D'Amore 			goto newname;
641*955eb5e1SGarrett D'Amore 		} else
642*955eb5e1SGarrett D'Amore 			break;
643*955eb5e1SGarrett D'Amore 	}
644*955eb5e1SGarrett D'Amore 	for (cp = namebuf; *cp == '!'; cp++);
645*955eb5e1SGarrett D'Amore 	while (ishost(host, cp))
646*955eb5e1SGarrett D'Amore 		cp = strchr(cp, '!') + 1;
647*955eb5e1SGarrett D'Amore 	if (value("mustbang") && !strchr(cp, '!')) {
648*955eb5e1SGarrett D'Amore 		snprintf(linebuf, sizeof (linebuf), "%s!%s",
649*955eb5e1SGarrett D'Amore 			host, cp);
650*955eb5e1SGarrett D'Amore 		cp = linebuf;
651*955eb5e1SGarrett D'Amore 	}
652*955eb5e1SGarrett D'Amore 	if (cp2 = hfield("from", mp, addto))
653*955eb5e1SGarrett D'Amore 		return(splice(cp, cp2));
654*955eb5e1SGarrett D'Amore 	else
655*955eb5e1SGarrett D'Amore 		return(savestr(cp));
656*955eb5e1SGarrett D'Amore }
657*955eb5e1SGarrett D'Amore 
658*955eb5e1SGarrett D'Amore /*
659*955eb5e1SGarrett D'Amore  * Splice an address into a commented recipient header.
660*955eb5e1SGarrett D'Amore  */
661*955eb5e1SGarrett D'Amore char *
splice(char * addr,char * hdr)662*955eb5e1SGarrett D'Amore splice(char *addr, char *hdr)
663*955eb5e1SGarrett D'Amore {
664*955eb5e1SGarrett D'Amore 	char buf[LINESIZE];
665*955eb5e1SGarrett D'Amore 	char *cp, *cp2;
666*955eb5e1SGarrett D'Amore 
667*955eb5e1SGarrett D'Amore 	if (cp = strchr(hdr, '<')) {
668*955eb5e1SGarrett D'Amore 		cp2 = strchr(cp, '>');
669*955eb5e1SGarrett D'Amore 		if (cp2 == NULL) {
670*955eb5e1SGarrett D'Amore 			nstrcpy(buf, sizeof (buf), addr);
671*955eb5e1SGarrett D'Amore 		} else {
672*955eb5e1SGarrett D'Amore 			snprintf(buf, sizeof (buf), "%.*s%s%s",
673*955eb5e1SGarrett D'Amore 				cp - hdr + 1, hdr, addr, cp2);
674*955eb5e1SGarrett D'Amore 		}
675*955eb5e1SGarrett D'Amore 	} else if (cp = strchr(hdr, '(')) {
676*955eb5e1SGarrett D'Amore 		snprintf(buf, sizeof (buf), "%s %s",
677*955eb5e1SGarrett D'Amore 			addr, cp);
678*955eb5e1SGarrett D'Amore 	} else
679*955eb5e1SGarrett D'Amore 		nstrcpy(buf, sizeof (buf), addr);
680*955eb5e1SGarrett D'Amore 	return savestr(ripoff(buf));
681*955eb5e1SGarrett D'Amore }
682*955eb5e1SGarrett D'Amore 
683*955eb5e1SGarrett D'Amore static char *
ripoff(register char * buf)684*955eb5e1SGarrett D'Amore ripoff(register char *buf)
685*955eb5e1SGarrett D'Amore {
686*955eb5e1SGarrett D'Amore 	register char *cp;
687*955eb5e1SGarrett D'Amore 
688*955eb5e1SGarrett D'Amore 	cp = buf + strlen(buf);
689*955eb5e1SGarrett D'Amore 	while (--cp >= buf && isspace(*cp));
690*955eb5e1SGarrett D'Amore 	if (cp >= buf && *cp == ',')
691*955eb5e1SGarrett D'Amore 		cp--;
692*955eb5e1SGarrett D'Amore 	*++cp = 0;
693*955eb5e1SGarrett D'Amore 	return buf;
694*955eb5e1SGarrett D'Amore }
695*955eb5e1SGarrett D'Amore 
696*955eb5e1SGarrett D'Amore /*
697*955eb5e1SGarrett D'Amore  * Are any of the characters in the two strings the same?
698*955eb5e1SGarrett D'Amore  */
699*955eb5e1SGarrett D'Amore 
700*955eb5e1SGarrett D'Amore int
anyof(register char * s1,register char * s2)701*955eb5e1SGarrett D'Amore anyof(register char *s1, register char *s2)
702*955eb5e1SGarrett D'Amore {
703*955eb5e1SGarrett D'Amore 	register int c;
704*955eb5e1SGarrett D'Amore 
705*955eb5e1SGarrett D'Amore 	while ((c = *s1++) != 0)
706*955eb5e1SGarrett D'Amore 		if (any(c, s2))
707*955eb5e1SGarrett D'Amore 			return(1);
708*955eb5e1SGarrett D'Amore 	return(0);
709*955eb5e1SGarrett D'Amore }
710*955eb5e1SGarrett D'Amore 
711*955eb5e1SGarrett D'Amore /*
712*955eb5e1SGarrett D'Amore  * See if the given header field is supposed to be ignored.
713*955eb5e1SGarrett D'Amore  * Fields of the form "Content-*" can't be ignored when saving.
714*955eb5e1SGarrett D'Amore  */
715*955eb5e1SGarrett D'Amore int
isign(char * field,int saving)716*955eb5e1SGarrett D'Amore isign(char *field, int saving)
717*955eb5e1SGarrett D'Amore {
718*955eb5e1SGarrett D'Amore 	char realfld[BUFSIZ];
719*955eb5e1SGarrett D'Amore 
720*955eb5e1SGarrett D'Amore 	/*
721*955eb5e1SGarrett D'Amore 	 * Lower-case the string, so that "Status" and "status"
722*955eb5e1SGarrett D'Amore 	 * will hash to the same place.
723*955eb5e1SGarrett D'Amore 	 */
724*955eb5e1SGarrett D'Amore 	istrcpy(realfld, sizeof (realfld), field);
725*955eb5e1SGarrett D'Amore 
726*955eb5e1SGarrett D'Amore 	if (saving && strncmp(realfld, "content-", 8) == 0)
727*955eb5e1SGarrett D'Amore 		return (0);
728*955eb5e1SGarrett D'Amore 
729*955eb5e1SGarrett D'Amore 	if (nretained > 0)
730*955eb5e1SGarrett D'Amore 		return (!member(realfld, retain));
731*955eb5e1SGarrett D'Amore 	else
732*955eb5e1SGarrett D'Amore 		return (member(realfld, ignore));
733*955eb5e1SGarrett D'Amore }
734*955eb5e1SGarrett D'Amore 
735*955eb5e1SGarrett D'Amore int
member(register char * realfield,register struct ignore ** table)736*955eb5e1SGarrett D'Amore member(register char *realfield, register struct ignore **table)
737*955eb5e1SGarrett D'Amore {
738*955eb5e1SGarrett D'Amore 	register struct ignore *igp;
739*955eb5e1SGarrett D'Amore 
740*955eb5e1SGarrett D'Amore 	for (igp = table[hash(realfield)]; igp != 0; igp = igp->i_link)
741*955eb5e1SGarrett D'Amore 		if (equal(igp->i_field, realfield))
742*955eb5e1SGarrett D'Amore 			return (1);
743*955eb5e1SGarrett D'Amore 
744*955eb5e1SGarrett D'Amore 	return (0);
745*955eb5e1SGarrett D'Amore }
746*955eb5e1SGarrett D'Amore 
747*955eb5e1SGarrett D'Amore /*
748*955eb5e1SGarrett D'Amore  * This routine looks for string2 in string1.
749*955eb5e1SGarrett D'Amore  * If found, it returns the position string2 is found at,
750*955eb5e1SGarrett D'Amore  * otherwise it returns a -1.
751*955eb5e1SGarrett D'Amore  */
752*955eb5e1SGarrett D'Amore int
substr(char * string1,char * string2)753*955eb5e1SGarrett D'Amore substr(char *string1, char *string2)
754*955eb5e1SGarrett D'Amore {
755*955eb5e1SGarrett D'Amore 	int i, j, len1, len2;
756*955eb5e1SGarrett D'Amore 
757*955eb5e1SGarrett D'Amore 	len1 = strlen(string1);
758*955eb5e1SGarrett D'Amore 	len2 = strlen(string2);
759*955eb5e1SGarrett D'Amore 	for (i = 0; i < len1 - len2 + 1; i++) {
760*955eb5e1SGarrett D'Amore 		for (j = 0; j < len2 && string1[i+j] == string2[j]; j++)
761*955eb5e1SGarrett D'Amore 			;
762*955eb5e1SGarrett D'Amore 		if (j == len2)
763*955eb5e1SGarrett D'Amore 			return(i);
764*955eb5e1SGarrett D'Amore 	}
765*955eb5e1SGarrett D'Amore 	return(-1);
766*955eb5e1SGarrett D'Amore }
767*955eb5e1SGarrett D'Amore 
768*955eb5e1SGarrett D'Amore /*
769*955eb5e1SGarrett D'Amore  * Copies src to the dstsize buffer at dst. The copy will never
770*955eb5e1SGarrett D'Amore  * overflow the destination buffer and the buffer will always be null
771*955eb5e1SGarrett D'Amore  * terminated.
772*955eb5e1SGarrett D'Amore  */
773*955eb5e1SGarrett D'Amore char *
nstrcpy(char * dst,int dstsize,char * src)774*955eb5e1SGarrett D'Amore nstrcpy(char *dst, int dstsize, char *src)
775*955eb5e1SGarrett D'Amore {
776*955eb5e1SGarrett D'Amore 	char *cp, *cp2;
777*955eb5e1SGarrett D'Amore 
778*955eb5e1SGarrett D'Amore 	cp2 = dst;
779*955eb5e1SGarrett D'Amore 	cp = src;
780*955eb5e1SGarrett D'Amore 
781*955eb5e1SGarrett D'Amore 	while (--dstsize > 0 && *cp != '\0')
782*955eb5e1SGarrett D'Amore 		*cp2++ = *cp++;
783*955eb5e1SGarrett D'Amore 	*cp2 = '\0';
784*955eb5e1SGarrett D'Amore 	return(dst);
785*955eb5e1SGarrett D'Amore }
786*955eb5e1SGarrett D'Amore 
787*955eb5e1SGarrett D'Amore /*
788*955eb5e1SGarrett D'Amore  * Appends src to the dstsize buffer at dst. The append will never
789*955eb5e1SGarrett D'Amore  * overflow the destination buffer and the buffer will always be null
790*955eb5e1SGarrett D'Amore  * terminated.
791*955eb5e1SGarrett D'Amore  */
792*955eb5e1SGarrett D'Amore char *
nstrcat(char * dst,int dstsize,char * src)793*955eb5e1SGarrett D'Amore nstrcat(char *dst, int dstsize, char *src)
794*955eb5e1SGarrett D'Amore {
795*955eb5e1SGarrett D'Amore 	char *cp, *cp2;
796*955eb5e1SGarrett D'Amore 
797*955eb5e1SGarrett D'Amore 	cp2 = dst;
798*955eb5e1SGarrett D'Amore 	cp = src;
799*955eb5e1SGarrett D'Amore 
800*955eb5e1SGarrett D'Amore 	while (*cp2 != '\0') {
801*955eb5e1SGarrett D'Amore 		cp2++;
802*955eb5e1SGarrett D'Amore 		dstsize--;
803*955eb5e1SGarrett D'Amore 	}
804*955eb5e1SGarrett D'Amore 	while (--dstsize > 0 && *cp != '\0')
805*955eb5e1SGarrett D'Amore 		*cp2++ = *cp++;
806*955eb5e1SGarrett D'Amore 	*cp2 = '\0';
807*955eb5e1SGarrett D'Amore 	return(dst);
808*955eb5e1SGarrett D'Amore }
809