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