xref: /freebsd/contrib/sendmail/src/util.c (revision 13058a916175518dfbac6ce66b9b8e22ecf43155)
1c2aa98e2SPeter Wemm /*
2602a2b1bSGregory Neil Shapiro  * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5c2aa98e2SPeter Wemm  * Copyright (c) 1988, 1993
6c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
7c2aa98e2SPeter Wemm  *
8c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm  * the sendmail distribution.
11c2aa98e2SPeter Wemm  *
12c2aa98e2SPeter Wemm  */
13c2aa98e2SPeter Wemm 
14c2aa98e2SPeter Wemm #ifndef lint
1513058a91SGregory Neil Shapiro static char id[] = "@(#)$Id: util.c,v 8.225.2.1.2.26 2001/06/01 08:23:25 gshapiro Exp $";
1606f25ae9SGregory Neil Shapiro #endif /* ! lint */
17c2aa98e2SPeter Wemm 
1806f25ae9SGregory Neil Shapiro #include <sendmail.h>
19c2aa98e2SPeter Wemm #include <sysexits.h>
2006f25ae9SGregory Neil Shapiro 
2106f25ae9SGregory Neil Shapiro 
2206f25ae9SGregory Neil Shapiro static void	readtimeout __P((time_t));
2306f25ae9SGregory Neil Shapiro 
24c2aa98e2SPeter Wemm /*
25c2aa98e2SPeter Wemm **  STRIPQUOTES -- Strip quotes & quote bits from a string.
26c2aa98e2SPeter Wemm **
27c2aa98e2SPeter Wemm **	Runs through a string and strips off unquoted quote
28c2aa98e2SPeter Wemm **	characters and quote bits.  This is done in place.
29c2aa98e2SPeter Wemm **
30c2aa98e2SPeter Wemm **	Parameters:
31c2aa98e2SPeter Wemm **		s -- the string to strip.
32c2aa98e2SPeter Wemm **
33c2aa98e2SPeter Wemm **	Returns:
34c2aa98e2SPeter Wemm **		none.
35c2aa98e2SPeter Wemm **
36c2aa98e2SPeter Wemm **	Side Effects:
37c2aa98e2SPeter Wemm **		none.
38c2aa98e2SPeter Wemm */
39c2aa98e2SPeter Wemm 
40c2aa98e2SPeter Wemm void
41c2aa98e2SPeter Wemm stripquotes(s)
42c2aa98e2SPeter Wemm 	char *s;
43c2aa98e2SPeter Wemm {
44c2aa98e2SPeter Wemm 	register char *p;
45c2aa98e2SPeter Wemm 	register char *q;
46c2aa98e2SPeter Wemm 	register char c;
47c2aa98e2SPeter Wemm 
48c2aa98e2SPeter Wemm 	if (s == NULL)
49c2aa98e2SPeter Wemm 		return;
50c2aa98e2SPeter Wemm 
51c2aa98e2SPeter Wemm 	p = q = s;
52c2aa98e2SPeter Wemm 	do
53c2aa98e2SPeter Wemm 	{
54c2aa98e2SPeter Wemm 		c = *p++;
55c2aa98e2SPeter Wemm 		if (c == '\\')
56c2aa98e2SPeter Wemm 			c = *p++;
57c2aa98e2SPeter Wemm 		else if (c == '"')
58c2aa98e2SPeter Wemm 			continue;
59c2aa98e2SPeter Wemm 		*q++ = c;
60c2aa98e2SPeter Wemm 	} while (c != '\0');
61c2aa98e2SPeter Wemm }
62c2aa98e2SPeter Wemm /*
63c2aa98e2SPeter Wemm **  ADDQUOTES -- Adds quotes & quote bits to a string.
64c2aa98e2SPeter Wemm **
65c2aa98e2SPeter Wemm **	Runs through a string and adds characters and quote bits.
66c2aa98e2SPeter Wemm **
67c2aa98e2SPeter Wemm **	Parameters:
68c2aa98e2SPeter Wemm **		s -- the string to modify.
69c2aa98e2SPeter Wemm **
70c2aa98e2SPeter Wemm **	Returns:
71c2aa98e2SPeter Wemm **		pointer to quoted string.
72c2aa98e2SPeter Wemm **
73c2aa98e2SPeter Wemm **	Side Effects:
74c2aa98e2SPeter Wemm **		none.
75c2aa98e2SPeter Wemm **
76c2aa98e2SPeter Wemm */
77c2aa98e2SPeter Wemm 
78c2aa98e2SPeter Wemm char *
79c2aa98e2SPeter Wemm addquotes(s)
80c2aa98e2SPeter Wemm 	char *s;
81c2aa98e2SPeter Wemm {
82c2aa98e2SPeter Wemm 	int len = 0;
83c2aa98e2SPeter Wemm 	char c;
84c2aa98e2SPeter Wemm 	char *p = s, *q, *r;
85c2aa98e2SPeter Wemm 
86c2aa98e2SPeter Wemm 	if (s == NULL)
87c2aa98e2SPeter Wemm 		return NULL;
88c2aa98e2SPeter Wemm 
89c2aa98e2SPeter Wemm 	/* Find length of quoted string */
90c2aa98e2SPeter Wemm 	while ((c = *p++) != '\0')
91c2aa98e2SPeter Wemm 	{
92c2aa98e2SPeter Wemm 		len++;
93c2aa98e2SPeter Wemm 		if (c == '\\' || c == '"')
94c2aa98e2SPeter Wemm 			len++;
95c2aa98e2SPeter Wemm 	}
96c2aa98e2SPeter Wemm 
97c2aa98e2SPeter Wemm 	q = r = xalloc(len + 3);
98c2aa98e2SPeter Wemm 	p = s;
99c2aa98e2SPeter Wemm 
100c2aa98e2SPeter Wemm 	/* add leading quote */
101c2aa98e2SPeter Wemm 	*q++ = '"';
102c2aa98e2SPeter Wemm 	while ((c = *p++) != '\0')
103c2aa98e2SPeter Wemm 	{
104c2aa98e2SPeter Wemm 		/* quote \ or " */
105c2aa98e2SPeter Wemm 		if (c == '\\' || c == '"')
106c2aa98e2SPeter Wemm 			*q++ = '\\';
107c2aa98e2SPeter Wemm 		*q++ = c;
108c2aa98e2SPeter Wemm 	}
109c2aa98e2SPeter Wemm 	*q++ = '"';
110c2aa98e2SPeter Wemm 	*q = '\0';
111c2aa98e2SPeter Wemm 	return r;
112c2aa98e2SPeter Wemm }
113c2aa98e2SPeter Wemm /*
114c2aa98e2SPeter Wemm **  RFC822_STRING -- Checks string for proper RFC822 string quoting.
115c2aa98e2SPeter Wemm **
116c2aa98e2SPeter Wemm **	Runs through a string and verifies RFC822 special characters
117c2aa98e2SPeter Wemm **	are only found inside comments, quoted strings, or backslash
118c2aa98e2SPeter Wemm **	escaped.  Also verified balanced quotes and parenthesis.
119c2aa98e2SPeter Wemm **
120c2aa98e2SPeter Wemm **	Parameters:
121c2aa98e2SPeter Wemm **		s -- the string to modify.
122c2aa98e2SPeter Wemm **
123c2aa98e2SPeter Wemm **	Returns:
124c2aa98e2SPeter Wemm **		TRUE -- if the string is RFC822 compliant.
125c2aa98e2SPeter Wemm **		FALSE -- if the string is not RFC822 compliant.
126c2aa98e2SPeter Wemm **
127c2aa98e2SPeter Wemm **	Side Effects:
128c2aa98e2SPeter Wemm **		none.
129c2aa98e2SPeter Wemm **
130c2aa98e2SPeter Wemm */
131c2aa98e2SPeter Wemm 
132c2aa98e2SPeter Wemm bool
133c2aa98e2SPeter Wemm rfc822_string(s)
134c2aa98e2SPeter Wemm 	char *s;
135c2aa98e2SPeter Wemm {
136c2aa98e2SPeter Wemm 	bool quoted = FALSE;
137c2aa98e2SPeter Wemm 	int commentlev = 0;
138c2aa98e2SPeter Wemm 	char *c = s;
139c2aa98e2SPeter Wemm 
140c2aa98e2SPeter Wemm 	if (s == NULL)
141c2aa98e2SPeter Wemm 		return FALSE;
142c2aa98e2SPeter Wemm 
143c2aa98e2SPeter Wemm 	while (*c != '\0')
144c2aa98e2SPeter Wemm 	{
145c2aa98e2SPeter Wemm 		/* escaped character */
146c2aa98e2SPeter Wemm 		if (*c == '\\')
147c2aa98e2SPeter Wemm 		{
148c2aa98e2SPeter Wemm 			c++;
149c2aa98e2SPeter Wemm 			if (*c == '\0')
150c2aa98e2SPeter Wemm 				return FALSE;
151c2aa98e2SPeter Wemm 		}
152c2aa98e2SPeter Wemm 		else if (commentlev == 0 && *c == '"')
153c2aa98e2SPeter Wemm 			quoted = !quoted;
154c2aa98e2SPeter Wemm 		else if (!quoted)
155c2aa98e2SPeter Wemm 		{
156c2aa98e2SPeter Wemm 			if (*c == ')')
157c2aa98e2SPeter Wemm 			{
158c2aa98e2SPeter Wemm 				/* unbalanced ')' */
159c2aa98e2SPeter Wemm 				if (commentlev == 0)
160c2aa98e2SPeter Wemm 					return FALSE;
161c2aa98e2SPeter Wemm 				else
162c2aa98e2SPeter Wemm 					commentlev--;
163c2aa98e2SPeter Wemm 			}
164c2aa98e2SPeter Wemm 			else if (*c == '(')
165c2aa98e2SPeter Wemm 				commentlev++;
166c2aa98e2SPeter Wemm 			else if (commentlev == 0 &&
167c2aa98e2SPeter Wemm 				 strchr(MustQuoteChars, *c) != NULL)
168c2aa98e2SPeter Wemm 				return FALSE;
169c2aa98e2SPeter Wemm 		}
170c2aa98e2SPeter Wemm 		c++;
171c2aa98e2SPeter Wemm 	}
172c2aa98e2SPeter Wemm 	/* unbalanced '"' or '(' */
173c2aa98e2SPeter Wemm 	if (quoted || commentlev != 0)
174c2aa98e2SPeter Wemm 		return FALSE;
175c2aa98e2SPeter Wemm 	else
176c2aa98e2SPeter Wemm 		return TRUE;
177c2aa98e2SPeter Wemm }
178c2aa98e2SPeter Wemm /*
179065a643dSPeter Wemm **  SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string
180065a643dSPeter Wemm **
18106f25ae9SGregory Neil Shapiro **	Arbitrarily shorten (in place) an RFC822 string and rebalance
182065a643dSPeter Wemm **	comments and quotes.
183065a643dSPeter Wemm **
184065a643dSPeter Wemm **	Parameters:
185065a643dSPeter Wemm **		string -- the string to shorten
186065a643dSPeter Wemm **		length -- the maximum size, 0 if no maximum
187065a643dSPeter Wemm **
188065a643dSPeter Wemm **	Returns:
189065a643dSPeter Wemm **		TRUE if string is changed, FALSE otherwise
190065a643dSPeter Wemm **
191065a643dSPeter Wemm **	Side Effects:
192065a643dSPeter Wemm **		Changes string in place, possibly resulting
193065a643dSPeter Wemm **		in a shorter string.
194065a643dSPeter Wemm */
195065a643dSPeter Wemm 
196065a643dSPeter Wemm bool
197065a643dSPeter Wemm shorten_rfc822_string(string, length)
198065a643dSPeter Wemm 	char *string;
199065a643dSPeter Wemm 	size_t length;
200065a643dSPeter Wemm {
201065a643dSPeter Wemm 	bool backslash = FALSE;
202065a643dSPeter Wemm 	bool modified = FALSE;
203065a643dSPeter Wemm 	bool quoted = FALSE;
204065a643dSPeter Wemm 	size_t slen;
205065a643dSPeter Wemm 	int parencount = 0;
206065a643dSPeter Wemm 	char *ptr = string;
207065a643dSPeter Wemm 
208065a643dSPeter Wemm 	/*
209065a643dSPeter Wemm 	**  If have to rebalance an already short enough string,
210065a643dSPeter Wemm 	**  need to do it within allocated space.
211065a643dSPeter Wemm 	*/
212193538b7SGregory Neil Shapiro 
213065a643dSPeter Wemm 	slen = strlen(string);
214065a643dSPeter Wemm 	if (length == 0 || slen < length)
215065a643dSPeter Wemm 		length = slen;
216065a643dSPeter Wemm 
217065a643dSPeter Wemm 	while (*ptr != '\0')
218065a643dSPeter Wemm 	{
219065a643dSPeter Wemm 		if (backslash)
220065a643dSPeter Wemm 		{
221065a643dSPeter Wemm 			backslash = FALSE;
222065a643dSPeter Wemm 			goto increment;
223065a643dSPeter Wemm 		}
224065a643dSPeter Wemm 
225065a643dSPeter Wemm 		if (*ptr == '\\')
226065a643dSPeter Wemm 			backslash = TRUE;
227065a643dSPeter Wemm 		else if (*ptr == '(')
228065a643dSPeter Wemm 		{
229065a643dSPeter Wemm 			if (!quoted)
230065a643dSPeter Wemm 				parencount++;
231065a643dSPeter Wemm 		}
232065a643dSPeter Wemm 		else if (*ptr == ')')
233065a643dSPeter Wemm 		{
234065a643dSPeter Wemm 			if (--parencount < 0)
235065a643dSPeter Wemm 				parencount = 0;
236065a643dSPeter Wemm 		}
237065a643dSPeter Wemm 
238065a643dSPeter Wemm 		/* Inside a comment, quotes don't matter */
239065a643dSPeter Wemm 		if (parencount <= 0 && *ptr == '"')
240065a643dSPeter Wemm 			quoted = !quoted;
241065a643dSPeter Wemm 
242065a643dSPeter Wemm increment:
243065a643dSPeter Wemm 		/* Check for sufficient space for next character */
24406f25ae9SGregory Neil Shapiro 		if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) +
245065a643dSPeter Wemm 						parencount +
246065a643dSPeter Wemm 						(quoted ? 1 : 0)))
247065a643dSPeter Wemm 		{
248065a643dSPeter Wemm 			/* Not enough, backtrack */
249065a643dSPeter Wemm 			if (*ptr == '\\')
250065a643dSPeter Wemm 				backslash = FALSE;
251065a643dSPeter Wemm 			else if (*ptr == '(' && !quoted)
252065a643dSPeter Wemm 				parencount--;
253065a643dSPeter Wemm 			else if (*ptr == '"' && parencount == 0)
254065a643dSPeter Wemm 				quoted = FALSE;
255065a643dSPeter Wemm 			break;
256065a643dSPeter Wemm 		}
257065a643dSPeter Wemm 		ptr++;
258065a643dSPeter Wemm 	}
259065a643dSPeter Wemm 
260065a643dSPeter Wemm 	/* Rebalance */
261065a643dSPeter Wemm 	while (parencount-- > 0)
262065a643dSPeter Wemm 	{
263065a643dSPeter Wemm 		if (*ptr != ')')
264065a643dSPeter Wemm 		{
265065a643dSPeter Wemm 			modified = TRUE;
266065a643dSPeter Wemm 			*ptr = ')';
267065a643dSPeter Wemm 		}
268065a643dSPeter Wemm 		ptr++;
269065a643dSPeter Wemm 	}
270065a643dSPeter Wemm 	if (quoted)
271065a643dSPeter Wemm 	{
272065a643dSPeter Wemm 		if (*ptr != '"')
273065a643dSPeter Wemm 		{
274065a643dSPeter Wemm 			modified = TRUE;
275065a643dSPeter Wemm 			*ptr = '"';
276065a643dSPeter Wemm 		}
277065a643dSPeter Wemm 		ptr++;
278065a643dSPeter Wemm 	}
279065a643dSPeter Wemm 	if (*ptr != '\0')
280065a643dSPeter Wemm 	{
281065a643dSPeter Wemm 		modified = TRUE;
282065a643dSPeter Wemm 		*ptr = '\0';
283065a643dSPeter Wemm 	}
284065a643dSPeter Wemm 	return modified;
285065a643dSPeter Wemm }
286065a643dSPeter Wemm /*
287065a643dSPeter Wemm **  FIND_CHARACTER -- find an unquoted character in an RFC822 string
288065a643dSPeter Wemm **
289065a643dSPeter Wemm **	Find an unquoted, non-commented character in an RFC822
290065a643dSPeter Wemm **	string and return a pointer to its location in the
291065a643dSPeter Wemm **	string.
292065a643dSPeter Wemm **
293065a643dSPeter Wemm **	Parameters:
294065a643dSPeter Wemm **		string -- the string to search
295065a643dSPeter Wemm **		character -- the character to find
296065a643dSPeter Wemm **
297065a643dSPeter Wemm **	Returns:
298065a643dSPeter Wemm **		pointer to the character, or
299065a643dSPeter Wemm **		a pointer to the end of the line if character is not found
300065a643dSPeter Wemm */
301065a643dSPeter Wemm 
302065a643dSPeter Wemm char *
303065a643dSPeter Wemm find_character(string, character)
304065a643dSPeter Wemm 	char *string;
30506f25ae9SGregory Neil Shapiro 	int character;
306065a643dSPeter Wemm {
307065a643dSPeter Wemm 	bool backslash = FALSE;
308065a643dSPeter Wemm 	bool quoted = FALSE;
309065a643dSPeter Wemm 	int parencount = 0;
310065a643dSPeter Wemm 
311065a643dSPeter Wemm 	while (string != NULL && *string != '\0')
312065a643dSPeter Wemm 	{
313065a643dSPeter Wemm 		if (backslash)
314065a643dSPeter Wemm 		{
315065a643dSPeter Wemm 			backslash = FALSE;
316065a643dSPeter Wemm 			if (!quoted && character == '\\' && *string == '\\')
317065a643dSPeter Wemm 				break;
318065a643dSPeter Wemm 			string++;
319065a643dSPeter Wemm 			continue;
320065a643dSPeter Wemm 		}
321065a643dSPeter Wemm 		switch (*string)
322065a643dSPeter Wemm 		{
323065a643dSPeter Wemm 		  case '\\':
324065a643dSPeter Wemm 			backslash = TRUE;
325065a643dSPeter Wemm 			break;
326065a643dSPeter Wemm 
327065a643dSPeter Wemm 		  case '(':
328065a643dSPeter Wemm 			if (!quoted)
329065a643dSPeter Wemm 				parencount++;
330065a643dSPeter Wemm 			break;
331065a643dSPeter Wemm 
332065a643dSPeter Wemm 		  case ')':
333065a643dSPeter Wemm 			if (--parencount < 0)
334065a643dSPeter Wemm 				parencount = 0;
335065a643dSPeter Wemm 			break;
336065a643dSPeter Wemm 		}
337065a643dSPeter Wemm 
338065a643dSPeter Wemm 		/* Inside a comment, nothing matters */
339065a643dSPeter Wemm 		if (parencount > 0)
340065a643dSPeter Wemm 		{
341065a643dSPeter Wemm 			string++;
342065a643dSPeter Wemm 			continue;
343065a643dSPeter Wemm 		}
344065a643dSPeter Wemm 
345065a643dSPeter Wemm 		if (*string == '"')
346065a643dSPeter Wemm 			quoted = !quoted;
347065a643dSPeter Wemm 		else if (*string == character && !quoted)
348065a643dSPeter Wemm 			break;
349065a643dSPeter Wemm 		string++;
350065a643dSPeter Wemm 	}
351065a643dSPeter Wemm 
352065a643dSPeter Wemm 	/* Return pointer to the character */
353065a643dSPeter Wemm 	return string;
354065a643dSPeter Wemm }
355065a643dSPeter Wemm /*
356c2aa98e2SPeter Wemm **  XALLOC -- Allocate memory and bitch wildly on failure.
357c2aa98e2SPeter Wemm **
358c2aa98e2SPeter Wemm **	THIS IS A CLUDGE.  This should be made to give a proper
359c2aa98e2SPeter Wemm **	error -- but after all, what can we do?
360c2aa98e2SPeter Wemm **
361c2aa98e2SPeter Wemm **	Parameters:
362c2aa98e2SPeter Wemm **		sz -- size of area to allocate.
363c2aa98e2SPeter Wemm **
364c2aa98e2SPeter Wemm **	Returns:
365c2aa98e2SPeter Wemm **		pointer to data region.
366c2aa98e2SPeter Wemm **
367c2aa98e2SPeter Wemm **	Side Effects:
368c2aa98e2SPeter Wemm **		Memory is allocated.
369c2aa98e2SPeter Wemm */
370c2aa98e2SPeter Wemm 
371c2aa98e2SPeter Wemm char *
372c2aa98e2SPeter Wemm xalloc(sz)
373c2aa98e2SPeter Wemm 	register int sz;
374c2aa98e2SPeter Wemm {
375c2aa98e2SPeter Wemm 	register char *p;
376c2aa98e2SPeter Wemm 
377c2aa98e2SPeter Wemm 	/* some systems can't handle size zero mallocs */
378c2aa98e2SPeter Wemm 	if (sz <= 0)
379c2aa98e2SPeter Wemm 		sz = 1;
380c2aa98e2SPeter Wemm 
3818774250cSGregory Neil Shapiro 	ENTER_CRITICAL();
382c2aa98e2SPeter Wemm 	p = malloc((unsigned) sz);
3838774250cSGregory Neil Shapiro 	LEAVE_CRITICAL();
384c2aa98e2SPeter Wemm 	if (p == NULL)
385c2aa98e2SPeter Wemm 	{
386c2aa98e2SPeter Wemm 		syserr("!Out of memory!!");
3878774250cSGregory Neil Shapiro 
3888774250cSGregory Neil Shapiro 		/* NOTREACHED */
3898774250cSGregory Neil Shapiro 		exit(EX_UNAVAILABLE);
390c2aa98e2SPeter Wemm 	}
39106f25ae9SGregory Neil Shapiro 	return p;
392c2aa98e2SPeter Wemm }
393c2aa98e2SPeter Wemm /*
3948774250cSGregory Neil Shapiro **  XREALLOC -- Reallocate memory and bitch wildly on failure.
3958774250cSGregory Neil Shapiro **
3968774250cSGregory Neil Shapiro **	THIS IS A CLUDGE.  This should be made to give a proper
3978774250cSGregory Neil Shapiro **	error -- but after all, what can we do?
3988774250cSGregory Neil Shapiro **
3998774250cSGregory Neil Shapiro **	Parameters:
4008774250cSGregory Neil Shapiro **		ptr -- original area.
4018774250cSGregory Neil Shapiro **		sz -- size of new area to allocate.
4028774250cSGregory Neil Shapiro **
4038774250cSGregory Neil Shapiro **	Returns:
4048774250cSGregory Neil Shapiro **		pointer to data region.
4058774250cSGregory Neil Shapiro **
4068774250cSGregory Neil Shapiro **	Side Effects:
4078774250cSGregory Neil Shapiro **		Memory is allocated.
4088774250cSGregory Neil Shapiro */
4098774250cSGregory Neil Shapiro 
4108774250cSGregory Neil Shapiro char *
4118774250cSGregory Neil Shapiro xrealloc(ptr, sz)
4128774250cSGregory Neil Shapiro 	void *ptr;
4138774250cSGregory Neil Shapiro 	size_t sz;
4148774250cSGregory Neil Shapiro {
4158774250cSGregory Neil Shapiro 	register char *p;
4168774250cSGregory Neil Shapiro 
4178774250cSGregory Neil Shapiro 	/* some systems can't handle size zero mallocs */
4188774250cSGregory Neil Shapiro 	if (sz <= 0)
4198774250cSGregory Neil Shapiro 		sz = 1;
4208774250cSGregory Neil Shapiro 
4218774250cSGregory Neil Shapiro 	ENTER_CRITICAL();
4228774250cSGregory Neil Shapiro 	p = realloc(ptr, (unsigned) sz);
4238774250cSGregory Neil Shapiro 	LEAVE_CRITICAL();
4248774250cSGregory Neil Shapiro 	if (p == NULL)
4258774250cSGregory Neil Shapiro 	{
4268774250cSGregory Neil Shapiro 		syserr("!Out of memory!!");
4278774250cSGregory Neil Shapiro 
4288774250cSGregory Neil Shapiro 		/* NOTREACHED */
4298774250cSGregory Neil Shapiro 		exit(EX_UNAVAILABLE);
4308774250cSGregory Neil Shapiro 	}
4318774250cSGregory Neil Shapiro 	return p;
4328774250cSGregory Neil Shapiro }
4338774250cSGregory Neil Shapiro /*
4348774250cSGregory Neil Shapiro **  XCALLOC -- Allocate memory and bitch wildly on failure.
4358774250cSGregory Neil Shapiro **
4368774250cSGregory Neil Shapiro **	THIS IS A CLUDGE.  This should be made to give a proper
4378774250cSGregory Neil Shapiro **	error -- but after all, what can we do?
4388774250cSGregory Neil Shapiro **
4398774250cSGregory Neil Shapiro **	Parameters:
4408774250cSGregory Neil Shapiro **		num -- number of items to allocate
4418774250cSGregory Neil Shapiro **		sz -- size of new area to allocate.
4428774250cSGregory Neil Shapiro **
4438774250cSGregory Neil Shapiro **	Returns:
4448774250cSGregory Neil Shapiro **		pointer to data region.
4458774250cSGregory Neil Shapiro **
4468774250cSGregory Neil Shapiro **	Side Effects:
4478774250cSGregory Neil Shapiro **		Memory is allocated.
4488774250cSGregory Neil Shapiro */
4498774250cSGregory Neil Shapiro 
4508774250cSGregory Neil Shapiro char *
4518774250cSGregory Neil Shapiro xcalloc(num, sz)
4528774250cSGregory Neil Shapiro 	size_t num;
4538774250cSGregory Neil Shapiro 	size_t sz;
4548774250cSGregory Neil Shapiro {
4558774250cSGregory Neil Shapiro 	register char *p;
4568774250cSGregory Neil Shapiro 
4578774250cSGregory Neil Shapiro 	/* some systems can't handle size zero mallocs */
4588774250cSGregory Neil Shapiro 	if (num <= 0)
4598774250cSGregory Neil Shapiro 		num = 1;
4608774250cSGregory Neil Shapiro 	if (sz <= 0)
4618774250cSGregory Neil Shapiro 		sz = 1;
4628774250cSGregory Neil Shapiro 
4638774250cSGregory Neil Shapiro 	ENTER_CRITICAL();
4648774250cSGregory Neil Shapiro 	p = calloc((unsigned) num, (unsigned) sz);
4658774250cSGregory Neil Shapiro 	LEAVE_CRITICAL();
4668774250cSGregory Neil Shapiro 	if (p == NULL)
4678774250cSGregory Neil Shapiro 	{
4688774250cSGregory Neil Shapiro 		syserr("!Out of memory!!");
4698774250cSGregory Neil Shapiro 
4708774250cSGregory Neil Shapiro 		/* NOTREACHED */
4718774250cSGregory Neil Shapiro 		exit(EX_UNAVAILABLE);
4728774250cSGregory Neil Shapiro 	}
4738774250cSGregory Neil Shapiro 	return p;
4748774250cSGregory Neil Shapiro }
4758774250cSGregory Neil Shapiro /*
4768774250cSGregory Neil Shapiro **  SM_FREE -- Free memory safely.
4778774250cSGregory Neil Shapiro **
4788774250cSGregory Neil Shapiro **	Parameters:
4798774250cSGregory Neil Shapiro **		ptr -- area to free
4808774250cSGregory Neil Shapiro **
4818774250cSGregory Neil Shapiro **	Returns:
4828774250cSGregory Neil Shapiro **		none.
4838774250cSGregory Neil Shapiro **
4848774250cSGregory Neil Shapiro **	Side Effects:
4858774250cSGregory Neil Shapiro **		Memory is freed.
4868774250cSGregory Neil Shapiro */
4878774250cSGregory Neil Shapiro 
4888774250cSGregory Neil Shapiro void
4898774250cSGregory Neil Shapiro sm_free(ptr)
4908774250cSGregory Neil Shapiro 	void *ptr;
4918774250cSGregory Neil Shapiro {
4928774250cSGregory Neil Shapiro 	ENTER_CRITICAL();
4938774250cSGregory Neil Shapiro 	free(ptr);
4948774250cSGregory Neil Shapiro 	LEAVE_CRITICAL();
4958774250cSGregory Neil Shapiro }
4968774250cSGregory Neil Shapiro /*
497c2aa98e2SPeter Wemm **  COPYPLIST -- copy list of pointers.
498c2aa98e2SPeter Wemm **
499c2aa98e2SPeter Wemm **	This routine is the equivalent of newstr for lists of
500c2aa98e2SPeter Wemm **	pointers.
501c2aa98e2SPeter Wemm **
502c2aa98e2SPeter Wemm **	Parameters:
503c2aa98e2SPeter Wemm **		list -- list of pointers to copy.
504c2aa98e2SPeter Wemm **			Must be NULL terminated.
505c2aa98e2SPeter Wemm **		copycont -- if TRUE, copy the contents of the vector
506c2aa98e2SPeter Wemm **			(which must be a string) also.
507c2aa98e2SPeter Wemm **
508c2aa98e2SPeter Wemm **	Returns:
509c2aa98e2SPeter Wemm **		a copy of 'list'.
510c2aa98e2SPeter Wemm **
511c2aa98e2SPeter Wemm **	Side Effects:
512c2aa98e2SPeter Wemm **		none.
513c2aa98e2SPeter Wemm */
514c2aa98e2SPeter Wemm 
515c2aa98e2SPeter Wemm char **
516c2aa98e2SPeter Wemm copyplist(list, copycont)
517c2aa98e2SPeter Wemm 	char **list;
518c2aa98e2SPeter Wemm 	bool copycont;
519c2aa98e2SPeter Wemm {
520c2aa98e2SPeter Wemm 	register char **vp;
521c2aa98e2SPeter Wemm 	register char **newvp;
522c2aa98e2SPeter Wemm 
523c2aa98e2SPeter Wemm 	for (vp = list; *vp != NULL; vp++)
524c2aa98e2SPeter Wemm 		continue;
525c2aa98e2SPeter Wemm 
526c2aa98e2SPeter Wemm 	vp++;
527c2aa98e2SPeter Wemm 
528c2aa98e2SPeter Wemm 	newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
52906f25ae9SGregory Neil Shapiro 	memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp);
530c2aa98e2SPeter Wemm 
531c2aa98e2SPeter Wemm 	if (copycont)
532c2aa98e2SPeter Wemm 	{
533c2aa98e2SPeter Wemm 		for (vp = newvp; *vp != NULL; vp++)
534c2aa98e2SPeter Wemm 			*vp = newstr(*vp);
535c2aa98e2SPeter Wemm 	}
536c2aa98e2SPeter Wemm 
53706f25ae9SGregory Neil Shapiro 	return newvp;
538c2aa98e2SPeter Wemm }
539c2aa98e2SPeter Wemm /*
540c2aa98e2SPeter Wemm **  COPYQUEUE -- copy address queue.
541c2aa98e2SPeter Wemm **
542c2aa98e2SPeter Wemm **	This routine is the equivalent of newstr for address queues
54306f25ae9SGregory Neil Shapiro **	addresses marked as QS_IS_DEAD() aren't copied
544c2aa98e2SPeter Wemm **
545c2aa98e2SPeter Wemm **	Parameters:
546c2aa98e2SPeter Wemm **		addr -- list of address structures to copy.
547c2aa98e2SPeter Wemm **
548c2aa98e2SPeter Wemm **	Returns:
549c2aa98e2SPeter Wemm **		a copy of 'addr'.
550c2aa98e2SPeter Wemm **
551c2aa98e2SPeter Wemm **	Side Effects:
552c2aa98e2SPeter Wemm **		none.
553c2aa98e2SPeter Wemm */
554c2aa98e2SPeter Wemm 
555c2aa98e2SPeter Wemm ADDRESS *
556c2aa98e2SPeter Wemm copyqueue(addr)
557c2aa98e2SPeter Wemm 	ADDRESS *addr;
558c2aa98e2SPeter Wemm {
559c2aa98e2SPeter Wemm 	register ADDRESS *newaddr;
560c2aa98e2SPeter Wemm 	ADDRESS *ret;
561c2aa98e2SPeter Wemm 	register ADDRESS **tail = &ret;
562c2aa98e2SPeter Wemm 
563c2aa98e2SPeter Wemm 	while (addr != NULL)
564c2aa98e2SPeter Wemm 	{
56506f25ae9SGregory Neil Shapiro 		if (!QS_IS_DEAD(addr->q_state))
566c2aa98e2SPeter Wemm 		{
56706f25ae9SGregory Neil Shapiro 			newaddr = (ADDRESS *) xalloc(sizeof *newaddr);
568c2aa98e2SPeter Wemm 			STRUCTCOPY(*addr, *newaddr);
569c2aa98e2SPeter Wemm 			*tail = newaddr;
570c2aa98e2SPeter Wemm 			tail = &newaddr->q_next;
571c2aa98e2SPeter Wemm 		}
572c2aa98e2SPeter Wemm 		addr = addr->q_next;
573c2aa98e2SPeter Wemm 	}
574c2aa98e2SPeter Wemm 	*tail = NULL;
575c2aa98e2SPeter Wemm 
576c2aa98e2SPeter Wemm 	return ret;
577c2aa98e2SPeter Wemm }
578c2aa98e2SPeter Wemm /*
57906f25ae9SGregory Neil Shapiro **  LOG_SENDMAIL_PID -- record sendmail pid and command line.
58006f25ae9SGregory Neil Shapiro **
58106f25ae9SGregory Neil Shapiro **	Parameters:
58206f25ae9SGregory Neil Shapiro **		e -- the current envelope.
58306f25ae9SGregory Neil Shapiro **
58406f25ae9SGregory Neil Shapiro **	Returns:
58506f25ae9SGregory Neil Shapiro **		none.
58606f25ae9SGregory Neil Shapiro **
58706f25ae9SGregory Neil Shapiro **	Side Effects:
58806f25ae9SGregory Neil Shapiro **		writes pidfile.
58906f25ae9SGregory Neil Shapiro */
59006f25ae9SGregory Neil Shapiro 
59106f25ae9SGregory Neil Shapiro void
59206f25ae9SGregory Neil Shapiro log_sendmail_pid(e)
59306f25ae9SGregory Neil Shapiro 	ENVELOPE *e;
59406f25ae9SGregory Neil Shapiro {
59506f25ae9SGregory Neil Shapiro 	long sff;
59606f25ae9SGregory Neil Shapiro 	FILE *pidf;
59706f25ae9SGregory Neil Shapiro 	char pidpath[MAXPATHLEN + 1];
59806f25ae9SGregory Neil Shapiro 
59906f25ae9SGregory Neil Shapiro 	/* write the pid to the log file for posterity */
60006f25ae9SGregory Neil Shapiro 	sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
60106f25ae9SGregory Neil Shapiro 	if (TrustedUid != 0 && RealUid == TrustedUid)
60206f25ae9SGregory Neil Shapiro 		sff |= SFF_OPENASROOT;
60306f25ae9SGregory Neil Shapiro 	expand(PidFile, pidpath, sizeof pidpath, e);
60406f25ae9SGregory Neil Shapiro 	pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, 0644, sff);
60506f25ae9SGregory Neil Shapiro 	if (pidf == NULL)
60606f25ae9SGregory Neil Shapiro 	{
607602a2b1bSGregory Neil Shapiro 		sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s",
608602a2b1bSGregory Neil Shapiro 			  pidpath, errstring(errno));
60906f25ae9SGregory Neil Shapiro 	}
61006f25ae9SGregory Neil Shapiro 	else
61106f25ae9SGregory Neil Shapiro 	{
6128774250cSGregory Neil Shapiro 		pid_t pid;
61306f25ae9SGregory Neil Shapiro 		extern char *CommandLineArgs;
61406f25ae9SGregory Neil Shapiro 
6158774250cSGregory Neil Shapiro 		pid = getpid();
616193538b7SGregory Neil Shapiro 
61706f25ae9SGregory Neil Shapiro 		/* write the process id on line 1 */
6188774250cSGregory Neil Shapiro 		fprintf(pidf, "%ld\n", (long) pid);
61906f25ae9SGregory Neil Shapiro 
62006f25ae9SGregory Neil Shapiro 		/* line 2 contains all command line flags */
62106f25ae9SGregory Neil Shapiro 		fprintf(pidf, "%s\n", CommandLineArgs);
62206f25ae9SGregory Neil Shapiro 
62306f25ae9SGregory Neil Shapiro 		/* flush and close */
62406f25ae9SGregory Neil Shapiro 		(void) fclose(pidf);
62506f25ae9SGregory Neil Shapiro 	}
62606f25ae9SGregory Neil Shapiro }
62706f25ae9SGregory Neil Shapiro /*
62806f25ae9SGregory Neil Shapiro **  SET_DELIVERY_MODE -- set and record the delivery mode
62906f25ae9SGregory Neil Shapiro **
63006f25ae9SGregory Neil Shapiro **	Parameters:
63106f25ae9SGregory Neil Shapiro **		mode -- delivery mode
63206f25ae9SGregory Neil Shapiro **		e -- the current envelope.
63306f25ae9SGregory Neil Shapiro **
63406f25ae9SGregory Neil Shapiro **	Returns:
63506f25ae9SGregory Neil Shapiro **		none.
63606f25ae9SGregory Neil Shapiro **
63706f25ae9SGregory Neil Shapiro **	Side Effects:
63806f25ae9SGregory Neil Shapiro **		sets $&{deliveryMode} macro
63906f25ae9SGregory Neil Shapiro */
64006f25ae9SGregory Neil Shapiro 
64106f25ae9SGregory Neil Shapiro void
64206f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e)
64306f25ae9SGregory Neil Shapiro 	int mode;
64406f25ae9SGregory Neil Shapiro 	ENVELOPE *e;
64506f25ae9SGregory Neil Shapiro {
64606f25ae9SGregory Neil Shapiro 	char buf[2];
64706f25ae9SGregory Neil Shapiro 
64806f25ae9SGregory Neil Shapiro 	e->e_sendmode = (char)mode;
64906f25ae9SGregory Neil Shapiro 	buf[0] = (char)mode;
65006f25ae9SGregory Neil Shapiro 	buf[1] = '\0';
65106f25ae9SGregory Neil Shapiro 	define(macid("{deliveryMode}", NULL), newstr(buf), e);
65206f25ae9SGregory Neil Shapiro }
65306f25ae9SGregory Neil Shapiro /*
654c2aa98e2SPeter Wemm **  PRINTAV -- print argument vector.
655c2aa98e2SPeter Wemm **
656c2aa98e2SPeter Wemm **	Parameters:
657c2aa98e2SPeter Wemm **		av -- argument vector.
658c2aa98e2SPeter Wemm **
659c2aa98e2SPeter Wemm **	Returns:
660c2aa98e2SPeter Wemm **		none.
661c2aa98e2SPeter Wemm **
662c2aa98e2SPeter Wemm **	Side Effects:
663c2aa98e2SPeter Wemm **		prints av.
664c2aa98e2SPeter Wemm */
665c2aa98e2SPeter Wemm 
666c2aa98e2SPeter Wemm void
667c2aa98e2SPeter Wemm printav(av)
668c2aa98e2SPeter Wemm 	register char **av;
669c2aa98e2SPeter Wemm {
670c2aa98e2SPeter Wemm 	while (*av != NULL)
671c2aa98e2SPeter Wemm 	{
672c2aa98e2SPeter Wemm 		if (tTd(0, 44))
67306f25ae9SGregory Neil Shapiro 			dprintf("\n\t%08lx=", (u_long) *av);
674c2aa98e2SPeter Wemm 		else
675c2aa98e2SPeter Wemm 			(void) putchar(' ');
676c2aa98e2SPeter Wemm 		xputs(*av++);
677c2aa98e2SPeter Wemm 	}
678c2aa98e2SPeter Wemm 	(void) putchar('\n');
679c2aa98e2SPeter Wemm }
680c2aa98e2SPeter Wemm /*
681c2aa98e2SPeter Wemm **  LOWER -- turn letter into lower case.
682c2aa98e2SPeter Wemm **
683c2aa98e2SPeter Wemm **	Parameters:
684c2aa98e2SPeter Wemm **		c -- character to turn into lower case.
685c2aa98e2SPeter Wemm **
686c2aa98e2SPeter Wemm **	Returns:
687c2aa98e2SPeter Wemm **		c, in lower case.
688c2aa98e2SPeter Wemm **
689c2aa98e2SPeter Wemm **	Side Effects:
690c2aa98e2SPeter Wemm **		none.
691c2aa98e2SPeter Wemm */
692c2aa98e2SPeter Wemm 
693c2aa98e2SPeter Wemm char
694c2aa98e2SPeter Wemm lower(c)
69506f25ae9SGregory Neil Shapiro 	register int c;
696c2aa98e2SPeter Wemm {
697c2aa98e2SPeter Wemm 	return ((isascii(c) && isupper(c)) ? tolower(c) : c);
698c2aa98e2SPeter Wemm }
699c2aa98e2SPeter Wemm /*
700c2aa98e2SPeter Wemm **  XPUTS -- put string doing control escapes.
701c2aa98e2SPeter Wemm **
702c2aa98e2SPeter Wemm **	Parameters:
703c2aa98e2SPeter Wemm **		s -- string to put.
704c2aa98e2SPeter Wemm **
705c2aa98e2SPeter Wemm **	Returns:
706c2aa98e2SPeter Wemm **		none.
707c2aa98e2SPeter Wemm **
708c2aa98e2SPeter Wemm **	Side Effects:
709c2aa98e2SPeter Wemm **		output to stdout
710c2aa98e2SPeter Wemm */
711c2aa98e2SPeter Wemm 
712c2aa98e2SPeter Wemm void
713c2aa98e2SPeter Wemm xputs(s)
714c2aa98e2SPeter Wemm 	register const char *s;
715c2aa98e2SPeter Wemm {
716c2aa98e2SPeter Wemm 	register int c;
717c2aa98e2SPeter Wemm 	register struct metamac *mp;
718c2aa98e2SPeter Wemm 	bool shiftout = FALSE;
719c2aa98e2SPeter Wemm 	extern struct metamac MetaMacros[];
720c2aa98e2SPeter Wemm 
721c2aa98e2SPeter Wemm 	if (s == NULL)
722c2aa98e2SPeter Wemm 	{
723c2aa98e2SPeter Wemm 		printf("%s<null>%s", TermEscape.te_rv_on, TermEscape.te_rv_off);
724c2aa98e2SPeter Wemm 		return;
725c2aa98e2SPeter Wemm 	}
726c2aa98e2SPeter Wemm 	while ((c = (*s++ & 0377)) != '\0')
727c2aa98e2SPeter Wemm 	{
728c2aa98e2SPeter Wemm 		if (shiftout)
729c2aa98e2SPeter Wemm 		{
730c2aa98e2SPeter Wemm 			printf("%s", TermEscape.te_rv_off);
731c2aa98e2SPeter Wemm 			shiftout = FALSE;
732c2aa98e2SPeter Wemm 		}
733c2aa98e2SPeter Wemm 		if (!isascii(c))
734c2aa98e2SPeter Wemm 		{
735c2aa98e2SPeter Wemm 			if (c == MATCHREPL)
736c2aa98e2SPeter Wemm 			{
737c2aa98e2SPeter Wemm 				printf("%s$", TermEscape.te_rv_on);
738c2aa98e2SPeter Wemm 				shiftout = TRUE;
739c2aa98e2SPeter Wemm 				if (*s == '\0')
740c2aa98e2SPeter Wemm 					continue;
741c2aa98e2SPeter Wemm 				c = *s++ & 0377;
742c2aa98e2SPeter Wemm 				goto printchar;
743c2aa98e2SPeter Wemm 			}
744c2aa98e2SPeter Wemm 			if (c == MACROEXPAND || c == MACRODEXPAND)
745c2aa98e2SPeter Wemm 			{
746c2aa98e2SPeter Wemm 				printf("%s$", TermEscape.te_rv_on);
747c2aa98e2SPeter Wemm 				if (c == MACRODEXPAND)
74806f25ae9SGregory Neil Shapiro 					(void) putchar('&');
749c2aa98e2SPeter Wemm 				shiftout = TRUE;
750c2aa98e2SPeter Wemm 				if (*s == '\0')
751c2aa98e2SPeter Wemm 					continue;
752c2aa98e2SPeter Wemm 				if (strchr("=~&?", *s) != NULL)
75306f25ae9SGregory Neil Shapiro 					(void) putchar(*s++);
754c2aa98e2SPeter Wemm 				if (bitset(0200, *s))
755193538b7SGregory Neil Shapiro 					printf("{%s}", macname(bitidx(*s++)));
756c2aa98e2SPeter Wemm 				else
757c2aa98e2SPeter Wemm 					printf("%c", *s++);
758c2aa98e2SPeter Wemm 				continue;
759c2aa98e2SPeter Wemm 			}
760c2aa98e2SPeter Wemm 			for (mp = MetaMacros; mp->metaname != '\0'; mp++)
761c2aa98e2SPeter Wemm 			{
762c2aa98e2SPeter Wemm 				if ((mp->metaval & 0377) == c)
763c2aa98e2SPeter Wemm 				{
764c2aa98e2SPeter Wemm 					printf("%s$%c",
765c2aa98e2SPeter Wemm 						TermEscape.te_rv_on,
766c2aa98e2SPeter Wemm 						mp->metaname);
767c2aa98e2SPeter Wemm 					shiftout = TRUE;
768c2aa98e2SPeter Wemm 					break;
769c2aa98e2SPeter Wemm 				}
770c2aa98e2SPeter Wemm 			}
771c2aa98e2SPeter Wemm 			if (c == MATCHCLASS || c == MATCHNCLASS)
772c2aa98e2SPeter Wemm 			{
773c2aa98e2SPeter Wemm 				if (bitset(0200, *s))
774c2aa98e2SPeter Wemm 					printf("{%s}", macname(*s++ & 0377));
775c2aa98e2SPeter Wemm 				else if (*s != '\0')
776c2aa98e2SPeter Wemm 					printf("%c", *s++);
777c2aa98e2SPeter Wemm 			}
778c2aa98e2SPeter Wemm 			if (mp->metaname != '\0')
779c2aa98e2SPeter Wemm 				continue;
780c2aa98e2SPeter Wemm 
781c2aa98e2SPeter Wemm 			/* unrecognized meta character */
782c2aa98e2SPeter Wemm 			printf("%sM-", TermEscape.te_rv_on);
783c2aa98e2SPeter Wemm 			shiftout = TRUE;
784c2aa98e2SPeter Wemm 			c &= 0177;
785c2aa98e2SPeter Wemm 		}
786c2aa98e2SPeter Wemm   printchar:
787c2aa98e2SPeter Wemm 		if (isprint(c))
788c2aa98e2SPeter Wemm 		{
78906f25ae9SGregory Neil Shapiro 			(void) putchar(c);
790c2aa98e2SPeter Wemm 			continue;
791c2aa98e2SPeter Wemm 		}
792c2aa98e2SPeter Wemm 
793c2aa98e2SPeter Wemm 		/* wasn't a meta-macro -- find another way to print it */
794c2aa98e2SPeter Wemm 		switch (c)
795c2aa98e2SPeter Wemm 		{
796c2aa98e2SPeter Wemm 		  case '\n':
797c2aa98e2SPeter Wemm 			c = 'n';
798c2aa98e2SPeter Wemm 			break;
799c2aa98e2SPeter Wemm 
800c2aa98e2SPeter Wemm 		  case '\r':
801c2aa98e2SPeter Wemm 			c = 'r';
802c2aa98e2SPeter Wemm 			break;
803c2aa98e2SPeter Wemm 
804c2aa98e2SPeter Wemm 		  case '\t':
805c2aa98e2SPeter Wemm 			c = 't';
806c2aa98e2SPeter Wemm 			break;
807c2aa98e2SPeter Wemm 		}
808c2aa98e2SPeter Wemm 		if (!shiftout)
809c2aa98e2SPeter Wemm 		{
810c2aa98e2SPeter Wemm 			printf("%s", TermEscape.te_rv_on);
811c2aa98e2SPeter Wemm 			shiftout = TRUE;
812c2aa98e2SPeter Wemm 		}
813c2aa98e2SPeter Wemm 		if (isprint(c))
814c2aa98e2SPeter Wemm 		{
815c2aa98e2SPeter Wemm 			(void) putchar('\\');
816c2aa98e2SPeter Wemm 			(void) putchar(c);
817c2aa98e2SPeter Wemm 		}
818c2aa98e2SPeter Wemm 		else
819c2aa98e2SPeter Wemm 		{
820c2aa98e2SPeter Wemm 			(void) putchar('^');
821c2aa98e2SPeter Wemm 			(void) putchar(c ^ 0100);
822c2aa98e2SPeter Wemm 		}
823c2aa98e2SPeter Wemm 	}
824c2aa98e2SPeter Wemm 	if (shiftout)
825c2aa98e2SPeter Wemm 		printf("%s", TermEscape.te_rv_off);
826c2aa98e2SPeter Wemm 	(void) fflush(stdout);
827c2aa98e2SPeter Wemm }
828c2aa98e2SPeter Wemm /*
829c2aa98e2SPeter Wemm **  MAKELOWER -- Translate a line into lower case
830c2aa98e2SPeter Wemm **
831c2aa98e2SPeter Wemm **	Parameters:
832c2aa98e2SPeter Wemm **		p -- the string to translate.  If NULL, return is
833c2aa98e2SPeter Wemm **			immediate.
834c2aa98e2SPeter Wemm **
835c2aa98e2SPeter Wemm **	Returns:
836c2aa98e2SPeter Wemm **		none.
837c2aa98e2SPeter Wemm **
838c2aa98e2SPeter Wemm **	Side Effects:
839c2aa98e2SPeter Wemm **		String pointed to by p is translated to lower case.
840c2aa98e2SPeter Wemm */
841c2aa98e2SPeter Wemm 
842c2aa98e2SPeter Wemm void
843c2aa98e2SPeter Wemm makelower(p)
844c2aa98e2SPeter Wemm 	register char *p;
845c2aa98e2SPeter Wemm {
846c2aa98e2SPeter Wemm 	register char c;
847c2aa98e2SPeter Wemm 
848c2aa98e2SPeter Wemm 	if (p == NULL)
849c2aa98e2SPeter Wemm 		return;
850c2aa98e2SPeter Wemm 	for (; (c = *p) != '\0'; p++)
851c2aa98e2SPeter Wemm 		if (isascii(c) && isupper(c))
852c2aa98e2SPeter Wemm 			*p = tolower(c);
853c2aa98e2SPeter Wemm }
854c2aa98e2SPeter Wemm /*
855c2aa98e2SPeter Wemm **  BUILDFNAME -- build full name from gecos style entry.
856c2aa98e2SPeter Wemm **
857c2aa98e2SPeter Wemm **	This routine interprets the strange entry that would appear
858c2aa98e2SPeter Wemm **	in the GECOS field of the password file.
859c2aa98e2SPeter Wemm **
860c2aa98e2SPeter Wemm **	Parameters:
861c2aa98e2SPeter Wemm **		p -- name to build.
86206f25ae9SGregory Neil Shapiro **		user -- the login name of this user (for &).
863c2aa98e2SPeter Wemm **		buf -- place to put the result.
864c2aa98e2SPeter Wemm **		buflen -- length of buf.
865c2aa98e2SPeter Wemm **
866c2aa98e2SPeter Wemm **	Returns:
867c2aa98e2SPeter Wemm **		none.
868c2aa98e2SPeter Wemm **
869c2aa98e2SPeter Wemm **	Side Effects:
870c2aa98e2SPeter Wemm **		none.
871c2aa98e2SPeter Wemm */
872c2aa98e2SPeter Wemm 
873c2aa98e2SPeter Wemm void
87406f25ae9SGregory Neil Shapiro buildfname(gecos, user, buf, buflen)
875c2aa98e2SPeter Wemm 	register char *gecos;
87606f25ae9SGregory Neil Shapiro 	char *user;
877c2aa98e2SPeter Wemm 	char *buf;
878c2aa98e2SPeter Wemm 	int buflen;
879c2aa98e2SPeter Wemm {
880c2aa98e2SPeter Wemm 	register char *p;
881c2aa98e2SPeter Wemm 	register char *bp = buf;
882c2aa98e2SPeter Wemm 
883c2aa98e2SPeter Wemm 	if (*gecos == '*')
884c2aa98e2SPeter Wemm 		gecos++;
885c2aa98e2SPeter Wemm 
886c2aa98e2SPeter Wemm 	/* copy gecos, interpolating & to be full name */
887c2aa98e2SPeter Wemm 	for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
888c2aa98e2SPeter Wemm 	{
889c2aa98e2SPeter Wemm 		if (bp >= &buf[buflen - 1])
890c2aa98e2SPeter Wemm 		{
891c2aa98e2SPeter Wemm 			/* buffer overflow -- just use login name */
89206f25ae9SGregory Neil Shapiro 			snprintf(buf, buflen, "%s", user);
893c2aa98e2SPeter Wemm 			return;
894c2aa98e2SPeter Wemm 		}
895c2aa98e2SPeter Wemm 		if (*p == '&')
896c2aa98e2SPeter Wemm 		{
897c2aa98e2SPeter Wemm 			/* interpolate full name */
89806f25ae9SGregory Neil Shapiro 			snprintf(bp, buflen - (bp - buf), "%s", user);
899c2aa98e2SPeter Wemm 			*bp = toupper(*bp);
900c2aa98e2SPeter Wemm 			bp += strlen(bp);
901c2aa98e2SPeter Wemm 		}
902c2aa98e2SPeter Wemm 		else
903c2aa98e2SPeter Wemm 			*bp++ = *p;
904c2aa98e2SPeter Wemm 	}
905c2aa98e2SPeter Wemm 	*bp = '\0';
906c2aa98e2SPeter Wemm }
907c2aa98e2SPeter Wemm /*
908c2aa98e2SPeter Wemm **  FIXCRLF -- fix <CR><LF> in line.
909c2aa98e2SPeter Wemm **
910c2aa98e2SPeter Wemm **	Looks for the <CR><LF> combination and turns it into the
911c2aa98e2SPeter Wemm **	UNIX canonical <NL> character.  It only takes one line,
912c2aa98e2SPeter Wemm **	i.e., it is assumed that the first <NL> found is the end
913c2aa98e2SPeter Wemm **	of the line.
914c2aa98e2SPeter Wemm **
915c2aa98e2SPeter Wemm **	Parameters:
916c2aa98e2SPeter Wemm **		line -- the line to fix.
917c2aa98e2SPeter Wemm **		stripnl -- if true, strip the newline also.
918c2aa98e2SPeter Wemm **
919c2aa98e2SPeter Wemm **	Returns:
920c2aa98e2SPeter Wemm **		none.
921c2aa98e2SPeter Wemm **
922c2aa98e2SPeter Wemm **	Side Effects:
923c2aa98e2SPeter Wemm **		line is changed in place.
924c2aa98e2SPeter Wemm */
925c2aa98e2SPeter Wemm 
926c2aa98e2SPeter Wemm void
927c2aa98e2SPeter Wemm fixcrlf(line, stripnl)
928c2aa98e2SPeter Wemm 	char *line;
929c2aa98e2SPeter Wemm 	bool stripnl;
930c2aa98e2SPeter Wemm {
931c2aa98e2SPeter Wemm 	register char *p;
932c2aa98e2SPeter Wemm 
933c2aa98e2SPeter Wemm 	p = strchr(line, '\n');
934c2aa98e2SPeter Wemm 	if (p == NULL)
935c2aa98e2SPeter Wemm 		return;
936c2aa98e2SPeter Wemm 	if (p > line && p[-1] == '\r')
937c2aa98e2SPeter Wemm 		p--;
938c2aa98e2SPeter Wemm 	if (!stripnl)
939c2aa98e2SPeter Wemm 		*p++ = '\n';
940c2aa98e2SPeter Wemm 	*p = '\0';
941c2aa98e2SPeter Wemm }
942c2aa98e2SPeter Wemm /*
943c2aa98e2SPeter Wemm **  PUTLINE -- put a line like fputs obeying SMTP conventions
944c2aa98e2SPeter Wemm **
945c2aa98e2SPeter Wemm **	This routine always guarantees outputing a newline (or CRLF,
946c2aa98e2SPeter Wemm **	as appropriate) at the end of the string.
947c2aa98e2SPeter Wemm **
948c2aa98e2SPeter Wemm **	Parameters:
949c2aa98e2SPeter Wemm **		l -- line to put.
950c2aa98e2SPeter Wemm **		mci -- the mailer connection information.
951c2aa98e2SPeter Wemm **
952c2aa98e2SPeter Wemm **	Returns:
953c2aa98e2SPeter Wemm **		none
954c2aa98e2SPeter Wemm **
955c2aa98e2SPeter Wemm **	Side Effects:
956c2aa98e2SPeter Wemm **		output of l to fp.
957c2aa98e2SPeter Wemm */
958c2aa98e2SPeter Wemm 
959c2aa98e2SPeter Wemm void
960c2aa98e2SPeter Wemm putline(l, mci)
961c2aa98e2SPeter Wemm 	register char *l;
962c2aa98e2SPeter Wemm 	register MCI *mci;
963c2aa98e2SPeter Wemm {
964c2aa98e2SPeter Wemm 	putxline(l, strlen(l), mci, PXLF_MAPFROM);
965c2aa98e2SPeter Wemm }
966c2aa98e2SPeter Wemm /*
967c2aa98e2SPeter Wemm **  PUTXLINE -- putline with flags bits.
968c2aa98e2SPeter Wemm **
969c2aa98e2SPeter Wemm **	This routine always guarantees outputing a newline (or CRLF,
970c2aa98e2SPeter Wemm **	as appropriate) at the end of the string.
971c2aa98e2SPeter Wemm **
972c2aa98e2SPeter Wemm **	Parameters:
973c2aa98e2SPeter Wemm **		l -- line to put.
974c2aa98e2SPeter Wemm **		len -- the length of the line.
975c2aa98e2SPeter Wemm **		mci -- the mailer connection information.
976c2aa98e2SPeter Wemm **		pxflags -- flag bits:
977c2aa98e2SPeter Wemm **		    PXLF_MAPFROM -- map From_ to >From_.
978c2aa98e2SPeter Wemm **		    PXLF_STRIP8BIT -- strip 8th bit.
979c2aa98e2SPeter Wemm **		    PXLF_HEADER -- map bare newline in header to newline space.
980c2aa98e2SPeter Wemm **
981c2aa98e2SPeter Wemm **	Returns:
982c2aa98e2SPeter Wemm **		none
983c2aa98e2SPeter Wemm **
984c2aa98e2SPeter Wemm **	Side Effects:
985c2aa98e2SPeter Wemm **		output of l to fp.
986c2aa98e2SPeter Wemm */
987c2aa98e2SPeter Wemm 
988c2aa98e2SPeter Wemm void
989c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags)
990c2aa98e2SPeter Wemm 	register char *l;
991c2aa98e2SPeter Wemm 	size_t len;
992c2aa98e2SPeter Wemm 	register MCI *mci;
993c2aa98e2SPeter Wemm 	int pxflags;
994c2aa98e2SPeter Wemm {
99506f25ae9SGregory Neil Shapiro 	bool dead = FALSE;
996c2aa98e2SPeter Wemm 	register char *p, *end;
997c2aa98e2SPeter Wemm 	int slop = 0;
998c2aa98e2SPeter Wemm 
999c2aa98e2SPeter Wemm 	/* strip out 0200 bits -- these can look like TELNET protocol */
1000c2aa98e2SPeter Wemm 	if (bitset(MCIF_7BIT, mci->mci_flags) ||
1001c2aa98e2SPeter Wemm 	    bitset(PXLF_STRIP8BIT, pxflags))
1002c2aa98e2SPeter Wemm 	{
1003c2aa98e2SPeter Wemm 		register char svchar;
1004c2aa98e2SPeter Wemm 
1005c2aa98e2SPeter Wemm 		for (p = l; (svchar = *p) != '\0'; ++p)
1006c2aa98e2SPeter Wemm 			if (bitset(0200, svchar))
1007c2aa98e2SPeter Wemm 				*p = svchar &~ 0200;
1008c2aa98e2SPeter Wemm 	}
1009c2aa98e2SPeter Wemm 
1010c2aa98e2SPeter Wemm 	end = l + len;
1011c2aa98e2SPeter Wemm 	do
1012c2aa98e2SPeter Wemm 	{
1013c2aa98e2SPeter Wemm 		/* find the end of the line */
1014c2aa98e2SPeter Wemm 		p = memchr(l, '\n', end - l);
1015c2aa98e2SPeter Wemm 		if (p == NULL)
1016c2aa98e2SPeter Wemm 			p = end;
1017c2aa98e2SPeter Wemm 
1018c2aa98e2SPeter Wemm 		if (TrafficLogFile != NULL)
1019c2aa98e2SPeter Wemm 			fprintf(TrafficLogFile, "%05d >>> ", (int) getpid());
1020c2aa98e2SPeter Wemm 
1021c2aa98e2SPeter Wemm 		/* check for line overflow */
1022c2aa98e2SPeter Wemm 		while (mci->mci_mailer->m_linelimit > 0 &&
1023c2aa98e2SPeter Wemm 		       (p - l + slop) > mci->mci_mailer->m_linelimit)
1024c2aa98e2SPeter Wemm 		{
1025c2aa98e2SPeter Wemm 			char *l_base = l;
1026c2aa98e2SPeter Wemm 			register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1];
1027c2aa98e2SPeter Wemm 
1028c2aa98e2SPeter Wemm 			if (l[0] == '.' && slop == 0 &&
1029c2aa98e2SPeter Wemm 			    bitnset(M_XDOT, mci->mci_mailer->m_flags))
1030c2aa98e2SPeter Wemm 			{
103106f25ae9SGregory Neil Shapiro 				if (putc('.', mci->mci_out) == EOF)
103206f25ae9SGregory Neil Shapiro 					dead = TRUE;
1033193538b7SGregory Neil Shapiro 				else
1034193538b7SGregory Neil Shapiro 				{
1035193538b7SGregory Neil Shapiro 					/* record progress for DATA timeout */
1036193538b7SGregory Neil Shapiro 					DataProgress = TRUE;
1037193538b7SGregory Neil Shapiro 				}
1038c2aa98e2SPeter Wemm 				if (TrafficLogFile != NULL)
1039c2aa98e2SPeter Wemm 					(void) putc('.', TrafficLogFile);
1040c2aa98e2SPeter Wemm 			}
1041c2aa98e2SPeter Wemm 			else if (l[0] == 'F' && slop == 0 &&
1042c2aa98e2SPeter Wemm 				 bitset(PXLF_MAPFROM, pxflags) &&
1043c2aa98e2SPeter Wemm 				 strncmp(l, "From ", 5) == 0 &&
1044c2aa98e2SPeter Wemm 				 bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
1045c2aa98e2SPeter Wemm 			{
104606f25ae9SGregory Neil Shapiro 				if (putc('>', mci->mci_out) == EOF)
104706f25ae9SGregory Neil Shapiro 					dead = TRUE;
1048193538b7SGregory Neil Shapiro 				else
1049193538b7SGregory Neil Shapiro 				{
1050193538b7SGregory Neil Shapiro 					/* record progress for DATA timeout */
1051193538b7SGregory Neil Shapiro 					DataProgress = TRUE;
1052193538b7SGregory Neil Shapiro 				}
1053c2aa98e2SPeter Wemm 				if (TrafficLogFile != NULL)
1054c2aa98e2SPeter Wemm 					(void) putc('>', TrafficLogFile);
1055c2aa98e2SPeter Wemm 			}
105606f25ae9SGregory Neil Shapiro 			if (dead)
105706f25ae9SGregory Neil Shapiro 				break;
105806f25ae9SGregory Neil Shapiro 
1059c2aa98e2SPeter Wemm 			while (l < q)
1060c2aa98e2SPeter Wemm 			{
106106f25ae9SGregory Neil Shapiro 				if (putc((unsigned char) *l++, mci->mci_out) ==
106206f25ae9SGregory Neil Shapiro 				    EOF)
106306f25ae9SGregory Neil Shapiro 				{
106406f25ae9SGregory Neil Shapiro 					dead = TRUE;
106506f25ae9SGregory Neil Shapiro 					break;
1066c2aa98e2SPeter Wemm 				}
1067193538b7SGregory Neil Shapiro 				else
1068193538b7SGregory Neil Shapiro 				{
106906f25ae9SGregory Neil Shapiro 					/* record progress for DATA timeout */
107006f25ae9SGregory Neil Shapiro 					DataProgress = TRUE;
107106f25ae9SGregory Neil Shapiro 				}
1072193538b7SGregory Neil Shapiro 			}
107306f25ae9SGregory Neil Shapiro 			if (dead)
107406f25ae9SGregory Neil Shapiro 				break;
107506f25ae9SGregory Neil Shapiro 
107606f25ae9SGregory Neil Shapiro 			if (putc('!', mci->mci_out) == EOF ||
107706f25ae9SGregory Neil Shapiro 			    fputs(mci->mci_mailer->m_eol,
107806f25ae9SGregory Neil Shapiro 				  mci->mci_out) == EOF ||
107906f25ae9SGregory Neil Shapiro 			    putc(' ', mci->mci_out) == EOF)
108006f25ae9SGregory Neil Shapiro 			{
108106f25ae9SGregory Neil Shapiro 				dead = TRUE;
108206f25ae9SGregory Neil Shapiro 				break;
108306f25ae9SGregory Neil Shapiro 			}
1084193538b7SGregory Neil Shapiro 			else
1085193538b7SGregory Neil Shapiro 			{
108606f25ae9SGregory Neil Shapiro 				/* record progress for DATA timeout */
108706f25ae9SGregory Neil Shapiro 				DataProgress = TRUE;
1088193538b7SGregory Neil Shapiro 			}
1089c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
1090c2aa98e2SPeter Wemm 			{
1091c2aa98e2SPeter Wemm 				for (l = l_base; l < q; l++)
109206f25ae9SGregory Neil Shapiro 					(void) putc((unsigned char)*l,
109306f25ae9SGregory Neil Shapiro 						    TrafficLogFile);
1094c2aa98e2SPeter Wemm 				fprintf(TrafficLogFile, "!\n%05d >>>  ",
1095c2aa98e2SPeter Wemm 					(int) getpid());
1096c2aa98e2SPeter Wemm 			}
1097c2aa98e2SPeter Wemm 			slop = 1;
1098c2aa98e2SPeter Wemm 		}
1099c2aa98e2SPeter Wemm 
110006f25ae9SGregory Neil Shapiro 		if (dead)
110106f25ae9SGregory Neil Shapiro 			break;
110206f25ae9SGregory Neil Shapiro 
1103c2aa98e2SPeter Wemm 		/* output last part */
1104c2aa98e2SPeter Wemm 		if (l[0] == '.' && slop == 0 &&
1105c2aa98e2SPeter Wemm 		    bitnset(M_XDOT, mci->mci_mailer->m_flags))
1106c2aa98e2SPeter Wemm 		{
110706f25ae9SGregory Neil Shapiro 			if (putc('.', mci->mci_out) == EOF)
110806f25ae9SGregory Neil Shapiro 				break;
1109193538b7SGregory Neil Shapiro 			else
1110193538b7SGregory Neil Shapiro 			{
1111193538b7SGregory Neil Shapiro 				/* record progress for DATA timeout */
1112193538b7SGregory Neil Shapiro 				DataProgress = TRUE;
1113193538b7SGregory Neil Shapiro 			}
1114c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
1115c2aa98e2SPeter Wemm 				(void) putc('.', TrafficLogFile);
1116c2aa98e2SPeter Wemm 		}
1117c2aa98e2SPeter Wemm 		else if (l[0] == 'F' && slop == 0 &&
1118c2aa98e2SPeter Wemm 			 bitset(PXLF_MAPFROM, pxflags) &&
1119c2aa98e2SPeter Wemm 			 strncmp(l, "From ", 5) == 0 &&
1120c2aa98e2SPeter Wemm 			 bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
1121c2aa98e2SPeter Wemm 		{
112206f25ae9SGregory Neil Shapiro 			if (putc('>', mci->mci_out) == EOF)
112306f25ae9SGregory Neil Shapiro 				break;
1124193538b7SGregory Neil Shapiro 			else
1125193538b7SGregory Neil Shapiro 			{
1126193538b7SGregory Neil Shapiro 				/* record progress for DATA timeout */
1127193538b7SGregory Neil Shapiro 				DataProgress = TRUE;
1128193538b7SGregory Neil Shapiro 			}
1129c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
1130c2aa98e2SPeter Wemm 				(void) putc('>', TrafficLogFile);
1131c2aa98e2SPeter Wemm 		}
1132c2aa98e2SPeter Wemm 		for ( ; l < p; ++l)
1133c2aa98e2SPeter Wemm 		{
1134c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
113506f25ae9SGregory Neil Shapiro 				(void) putc((unsigned char)*l, TrafficLogFile);
113606f25ae9SGregory Neil Shapiro 			if (putc((unsigned char) *l, mci->mci_out) == EOF)
113706f25ae9SGregory Neil Shapiro 			{
113806f25ae9SGregory Neil Shapiro 				dead = TRUE;
113906f25ae9SGregory Neil Shapiro 				break;
1140c2aa98e2SPeter Wemm 			}
1141193538b7SGregory Neil Shapiro 			else
1142193538b7SGregory Neil Shapiro 			{
114306f25ae9SGregory Neil Shapiro 				/* record progress for DATA timeout */
114406f25ae9SGregory Neil Shapiro 				DataProgress = TRUE;
114506f25ae9SGregory Neil Shapiro 			}
1146193538b7SGregory Neil Shapiro 		}
114706f25ae9SGregory Neil Shapiro 		if (dead)
114806f25ae9SGregory Neil Shapiro 			break;
114906f25ae9SGregory Neil Shapiro 
1150c2aa98e2SPeter Wemm 		if (TrafficLogFile != NULL)
1151c2aa98e2SPeter Wemm 			(void) putc('\n', TrafficLogFile);
115206f25ae9SGregory Neil Shapiro 		if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF)
115306f25ae9SGregory Neil Shapiro 			break;
1154193538b7SGregory Neil Shapiro 		else
1155193538b7SGregory Neil Shapiro 		{
1156193538b7SGregory Neil Shapiro 			/* record progress for DATA timeout */
1157193538b7SGregory Neil Shapiro 			DataProgress = TRUE;
1158193538b7SGregory Neil Shapiro 		}
1159c2aa98e2SPeter Wemm 		if (l < end && *l == '\n')
1160c2aa98e2SPeter Wemm 		{
1161c2aa98e2SPeter Wemm 			if (*++l != ' ' && *l != '\t' && *l != '\0' &&
1162c2aa98e2SPeter Wemm 			    bitset(PXLF_HEADER, pxflags))
1163c2aa98e2SPeter Wemm 			{
116406f25ae9SGregory Neil Shapiro 				if (putc(' ', mci->mci_out) == EOF)
116506f25ae9SGregory Neil Shapiro 					break;
1166193538b7SGregory Neil Shapiro 				else
1167193538b7SGregory Neil Shapiro 				{
1168193538b7SGregory Neil Shapiro 					/* record progress for DATA timeout */
1169193538b7SGregory Neil Shapiro 					DataProgress = TRUE;
1170193538b7SGregory Neil Shapiro 				}
1171c2aa98e2SPeter Wemm 				if (TrafficLogFile != NULL)
1172c2aa98e2SPeter Wemm 					(void) putc(' ', TrafficLogFile);
1173c2aa98e2SPeter Wemm 			}
1174c2aa98e2SPeter Wemm 		}
1175c2aa98e2SPeter Wemm 	} while (l < end);
1176c2aa98e2SPeter Wemm }
1177c2aa98e2SPeter Wemm /*
1178c2aa98e2SPeter Wemm **  XUNLINK -- unlink a file, doing logging as appropriate.
1179c2aa98e2SPeter Wemm **
1180c2aa98e2SPeter Wemm **	Parameters:
1181c2aa98e2SPeter Wemm **		f -- name of file to unlink.
1182c2aa98e2SPeter Wemm **
1183c2aa98e2SPeter Wemm **	Returns:
1184c2aa98e2SPeter Wemm **		none.
1185c2aa98e2SPeter Wemm **
1186c2aa98e2SPeter Wemm **	Side Effects:
1187c2aa98e2SPeter Wemm **		f is unlinked.
1188c2aa98e2SPeter Wemm */
1189c2aa98e2SPeter Wemm 
1190c2aa98e2SPeter Wemm void
1191c2aa98e2SPeter Wemm xunlink(f)
1192c2aa98e2SPeter Wemm 	char *f;
1193c2aa98e2SPeter Wemm {
1194c2aa98e2SPeter Wemm 	register int i;
1195c2aa98e2SPeter Wemm 
1196c2aa98e2SPeter Wemm 	if (LogLevel > 98)
1197c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, CurEnv->e_id,
1198c2aa98e2SPeter Wemm 			  "unlink %s",
1199c2aa98e2SPeter Wemm 			  f);
1200c2aa98e2SPeter Wemm 
1201c2aa98e2SPeter Wemm 	i = unlink(f);
1202c2aa98e2SPeter Wemm 	if (i < 0 && LogLevel > 97)
1203c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, CurEnv->e_id,
1204c2aa98e2SPeter Wemm 			  "%s: unlink-fail %d",
1205c2aa98e2SPeter Wemm 			  f, errno);
1206c2aa98e2SPeter Wemm }
1207c2aa98e2SPeter Wemm /*
1208c2aa98e2SPeter Wemm **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
1209c2aa98e2SPeter Wemm **
1210c2aa98e2SPeter Wemm **	Parameters:
1211c2aa98e2SPeter Wemm **		buf -- place to put the input line.
1212c2aa98e2SPeter Wemm **		siz -- size of buf.
1213c2aa98e2SPeter Wemm **		fp -- file to read from.
1214c2aa98e2SPeter Wemm **		timeout -- the timeout before error occurs.
1215c2aa98e2SPeter Wemm **		during -- what we are trying to read (for error messages).
1216c2aa98e2SPeter Wemm **
1217c2aa98e2SPeter Wemm **	Returns:
1218c2aa98e2SPeter Wemm **		NULL on error (including timeout).  This will also leave
1219c2aa98e2SPeter Wemm **			buf containing a null string.
1220c2aa98e2SPeter Wemm **		buf otherwise.
1221c2aa98e2SPeter Wemm **
1222c2aa98e2SPeter Wemm **	Side Effects:
1223c2aa98e2SPeter Wemm **		none.
1224c2aa98e2SPeter Wemm */
1225c2aa98e2SPeter Wemm 
122606f25ae9SGregory Neil Shapiro 
1227c2aa98e2SPeter Wemm static jmp_buf	CtxReadTimeout;
1228c2aa98e2SPeter Wemm 
1229c2aa98e2SPeter Wemm char *
1230c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during)
1231c2aa98e2SPeter Wemm 	char *buf;
1232c2aa98e2SPeter Wemm 	int siz;
1233c2aa98e2SPeter Wemm 	FILE *fp;
1234c2aa98e2SPeter Wemm 	time_t timeout;
1235c2aa98e2SPeter Wemm 	char *during;
1236c2aa98e2SPeter Wemm {
1237c2aa98e2SPeter Wemm 	register EVENT *ev = NULL;
1238c2aa98e2SPeter Wemm 	register char *p;
12392e43090eSPeter Wemm 	int save_errno;
1240c2aa98e2SPeter Wemm 
1241c2aa98e2SPeter Wemm 	if (fp == NULL)
1242c2aa98e2SPeter Wemm 	{
1243c2aa98e2SPeter Wemm 		buf[0] = '\0';
1244c2aa98e2SPeter Wemm 		return NULL;
1245c2aa98e2SPeter Wemm 	}
1246c2aa98e2SPeter Wemm 
1247c2aa98e2SPeter Wemm 	/* set the timeout */
1248c2aa98e2SPeter Wemm 	if (timeout != 0)
1249c2aa98e2SPeter Wemm 	{
1250c2aa98e2SPeter Wemm 		if (setjmp(CtxReadTimeout) != 0)
1251c2aa98e2SPeter Wemm 		{
1252c2aa98e2SPeter Wemm 			if (LogLevel > 1)
1253c2aa98e2SPeter Wemm 				sm_syslog(LOG_NOTICE, CurEnv->e_id,
1254c2aa98e2SPeter Wemm 					  "timeout waiting for input from %.100s during %s",
1255c2aa98e2SPeter Wemm 					  CurHostName ? CurHostName : "local",
1256c2aa98e2SPeter Wemm 					  during);
1257c2aa98e2SPeter Wemm 			buf[0] = '\0';
1258c2aa98e2SPeter Wemm #if XDEBUG
1259c2aa98e2SPeter Wemm 			checkfd012(during);
126006f25ae9SGregory Neil Shapiro #endif /* XDEBUG */
1261c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
1262c2aa98e2SPeter Wemm 				fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n",
1263c2aa98e2SPeter Wemm 					(int) getpid());
12642e43090eSPeter Wemm 			errno = 0;
126506f25ae9SGregory Neil Shapiro 			return NULL;
1266c2aa98e2SPeter Wemm 		}
1267c2aa98e2SPeter Wemm 		ev = setevent(timeout, readtimeout, 0);
1268c2aa98e2SPeter Wemm 	}
1269c2aa98e2SPeter Wemm 
1270c2aa98e2SPeter Wemm 	/* try to read */
1271c2aa98e2SPeter Wemm 	p = NULL;
12722e43090eSPeter Wemm 	errno = 0;
1273c2aa98e2SPeter Wemm 	while (!feof(fp) && !ferror(fp))
1274c2aa98e2SPeter Wemm 	{
1275c2aa98e2SPeter Wemm 		errno = 0;
1276c2aa98e2SPeter Wemm 		p = fgets(buf, siz, fp);
1277c2aa98e2SPeter Wemm 		if (p != NULL || errno != EINTR)
1278c2aa98e2SPeter Wemm 			break;
1279c2aa98e2SPeter Wemm 		clearerr(fp);
1280c2aa98e2SPeter Wemm 	}
12812e43090eSPeter Wemm 	save_errno = errno;
1282c2aa98e2SPeter Wemm 
1283c2aa98e2SPeter Wemm 	/* clear the event if it has not sprung */
1284c2aa98e2SPeter Wemm 	clrevent(ev);
1285c2aa98e2SPeter Wemm 
1286c2aa98e2SPeter Wemm 	/* clean up the books and exit */
1287c2aa98e2SPeter Wemm 	LineNumber++;
1288c2aa98e2SPeter Wemm 	if (p == NULL)
1289c2aa98e2SPeter Wemm 	{
1290c2aa98e2SPeter Wemm 		buf[0] = '\0';
1291c2aa98e2SPeter Wemm 		if (TrafficLogFile != NULL)
1292c2aa98e2SPeter Wemm 			fprintf(TrafficLogFile, "%05d <<< [EOF]\n", (int) getpid());
12932e43090eSPeter Wemm 		errno = save_errno;
129406f25ae9SGregory Neil Shapiro 		return NULL;
1295c2aa98e2SPeter Wemm 	}
1296c2aa98e2SPeter Wemm 	if (TrafficLogFile != NULL)
1297c2aa98e2SPeter Wemm 		fprintf(TrafficLogFile, "%05d <<< %s", (int) getpid(), buf);
1298c2aa98e2SPeter Wemm 	if (SevenBitInput)
1299c2aa98e2SPeter Wemm 	{
1300c2aa98e2SPeter Wemm 		for (p = buf; *p != '\0'; p++)
1301c2aa98e2SPeter Wemm 			*p &= ~0200;
1302c2aa98e2SPeter Wemm 	}
1303c2aa98e2SPeter Wemm 	else if (!HasEightBits)
1304c2aa98e2SPeter Wemm 	{
1305c2aa98e2SPeter Wemm 		for (p = buf; *p != '\0'; p++)
1306c2aa98e2SPeter Wemm 		{
1307c2aa98e2SPeter Wemm 			if (bitset(0200, *p))
1308c2aa98e2SPeter Wemm 			{
1309c2aa98e2SPeter Wemm 				HasEightBits = TRUE;
1310c2aa98e2SPeter Wemm 				break;
1311c2aa98e2SPeter Wemm 			}
1312c2aa98e2SPeter Wemm 		}
1313c2aa98e2SPeter Wemm 	}
131406f25ae9SGregory Neil Shapiro 	return buf;
1315c2aa98e2SPeter Wemm }
1316c2aa98e2SPeter Wemm 
1317c2aa98e2SPeter Wemm /* ARGSUSED */
1318c2aa98e2SPeter Wemm static void
1319c2aa98e2SPeter Wemm readtimeout(timeout)
1320c2aa98e2SPeter Wemm 	time_t timeout;
1321c2aa98e2SPeter Wemm {
13228774250cSGregory Neil Shapiro 	/*
13238774250cSGregory Neil Shapiro 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
13248774250cSGregory Neil Shapiro 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
13258774250cSGregory Neil Shapiro 	**	DOING.
13268774250cSGregory Neil Shapiro 	*/
13278774250cSGregory Neil Shapiro 
13288774250cSGregory Neil Shapiro 	errno = ETIMEDOUT;
1329c2aa98e2SPeter Wemm 	longjmp(CtxReadTimeout, 1);
1330c2aa98e2SPeter Wemm }
1331c2aa98e2SPeter Wemm /*
1332c2aa98e2SPeter Wemm **  FGETFOLDED -- like fgets, but know about folded lines.
1333c2aa98e2SPeter Wemm **
1334c2aa98e2SPeter Wemm **	Parameters:
1335c2aa98e2SPeter Wemm **		buf -- place to put result.
1336c2aa98e2SPeter Wemm **		n -- bytes available.
1337c2aa98e2SPeter Wemm **		f -- file to read from.
1338c2aa98e2SPeter Wemm **
1339c2aa98e2SPeter Wemm **	Returns:
1340c2aa98e2SPeter Wemm **		input line(s) on success, NULL on error or EOF.
1341c2aa98e2SPeter Wemm **		This will normally be buf -- unless the line is too
1342c2aa98e2SPeter Wemm **			long, when it will be xalloc()ed.
1343c2aa98e2SPeter Wemm **
1344c2aa98e2SPeter Wemm **	Side Effects:
1345c2aa98e2SPeter Wemm **		buf gets lines from f, with continuation lines (lines
1346c2aa98e2SPeter Wemm **		with leading white space) appended.  CRLF's are mapped
1347c2aa98e2SPeter Wemm **		into single newlines.  Any trailing NL is stripped.
1348c2aa98e2SPeter Wemm */
1349c2aa98e2SPeter Wemm 
1350c2aa98e2SPeter Wemm char *
1351c2aa98e2SPeter Wemm fgetfolded(buf, n, f)
1352c2aa98e2SPeter Wemm 	char *buf;
1353c2aa98e2SPeter Wemm 	register int n;
1354c2aa98e2SPeter Wemm 	FILE *f;
1355c2aa98e2SPeter Wemm {
1356c2aa98e2SPeter Wemm 	register char *p = buf;
1357c2aa98e2SPeter Wemm 	char *bp = buf;
1358c2aa98e2SPeter Wemm 	register int i;
1359c2aa98e2SPeter Wemm 
1360c2aa98e2SPeter Wemm 	n--;
1361c2aa98e2SPeter Wemm 	while ((i = getc(f)) != EOF)
1362c2aa98e2SPeter Wemm 	{
1363c2aa98e2SPeter Wemm 		if (i == '\r')
1364c2aa98e2SPeter Wemm 		{
1365c2aa98e2SPeter Wemm 			i = getc(f);
1366c2aa98e2SPeter Wemm 			if (i != '\n')
1367c2aa98e2SPeter Wemm 			{
1368c2aa98e2SPeter Wemm 				if (i != EOF)
1369c2aa98e2SPeter Wemm 					(void) ungetc(i, f);
1370c2aa98e2SPeter Wemm 				i = '\r';
1371c2aa98e2SPeter Wemm 			}
1372c2aa98e2SPeter Wemm 		}
1373c2aa98e2SPeter Wemm 		if (--n <= 0)
1374c2aa98e2SPeter Wemm 		{
1375c2aa98e2SPeter Wemm 			/* allocate new space */
1376c2aa98e2SPeter Wemm 			char *nbp;
1377c2aa98e2SPeter Wemm 			int nn;
1378c2aa98e2SPeter Wemm 
1379c2aa98e2SPeter Wemm 			nn = (p - bp);
1380c2aa98e2SPeter Wemm 			if (nn < MEMCHUNKSIZE)
1381c2aa98e2SPeter Wemm 				nn *= 2;
1382c2aa98e2SPeter Wemm 			else
1383c2aa98e2SPeter Wemm 				nn += MEMCHUNKSIZE;
1384c2aa98e2SPeter Wemm 			nbp = xalloc(nn);
138506f25ae9SGregory Neil Shapiro 			memmove(nbp, bp, p - bp);
1386c2aa98e2SPeter Wemm 			p = &nbp[p - bp];
1387c2aa98e2SPeter Wemm 			if (bp != buf)
13888774250cSGregory Neil Shapiro 				sm_free(bp);
1389c2aa98e2SPeter Wemm 			bp = nbp;
1390c2aa98e2SPeter Wemm 			n = nn - (p - bp);
1391c2aa98e2SPeter Wemm 		}
1392c2aa98e2SPeter Wemm 		*p++ = i;
1393c2aa98e2SPeter Wemm 		if (i == '\n')
1394c2aa98e2SPeter Wemm 		{
1395c2aa98e2SPeter Wemm 			LineNumber++;
1396c2aa98e2SPeter Wemm 			i = getc(f);
1397c2aa98e2SPeter Wemm 			if (i != EOF)
1398c2aa98e2SPeter Wemm 				(void) ungetc(i, f);
1399c2aa98e2SPeter Wemm 			if (i != ' ' && i != '\t')
1400c2aa98e2SPeter Wemm 				break;
1401c2aa98e2SPeter Wemm 		}
1402c2aa98e2SPeter Wemm 	}
1403c2aa98e2SPeter Wemm 	if (p == bp)
140406f25ae9SGregory Neil Shapiro 		return NULL;
1405c2aa98e2SPeter Wemm 	if (p[-1] == '\n')
1406c2aa98e2SPeter Wemm 		p--;
1407c2aa98e2SPeter Wemm 	*p = '\0';
140806f25ae9SGregory Neil Shapiro 	return bp;
1409c2aa98e2SPeter Wemm }
1410c2aa98e2SPeter Wemm /*
1411c2aa98e2SPeter Wemm **  CURTIME -- return current time.
1412c2aa98e2SPeter Wemm **
1413c2aa98e2SPeter Wemm **	Parameters:
1414c2aa98e2SPeter Wemm **		none.
1415c2aa98e2SPeter Wemm **
1416c2aa98e2SPeter Wemm **	Returns:
1417c2aa98e2SPeter Wemm **		the current time.
1418c2aa98e2SPeter Wemm **
1419c2aa98e2SPeter Wemm **	Side Effects:
1420c2aa98e2SPeter Wemm **		none.
1421c2aa98e2SPeter Wemm */
1422c2aa98e2SPeter Wemm 
1423c2aa98e2SPeter Wemm time_t
1424c2aa98e2SPeter Wemm curtime()
1425c2aa98e2SPeter Wemm {
1426c2aa98e2SPeter Wemm 	auto time_t t;
1427c2aa98e2SPeter Wemm 
1428c2aa98e2SPeter Wemm 	(void) time(&t);
142906f25ae9SGregory Neil Shapiro 	return t;
1430c2aa98e2SPeter Wemm }
1431c2aa98e2SPeter Wemm /*
1432c2aa98e2SPeter Wemm **  ATOBOOL -- convert a string representation to boolean.
1433c2aa98e2SPeter Wemm **
1434c2aa98e2SPeter Wemm **	Defaults to "TRUE"
1435c2aa98e2SPeter Wemm **
1436c2aa98e2SPeter Wemm **	Parameters:
1437c2aa98e2SPeter Wemm **		s -- string to convert.  Takes "tTyY" as true,
1438c2aa98e2SPeter Wemm **			others as false.
1439c2aa98e2SPeter Wemm **
1440c2aa98e2SPeter Wemm **	Returns:
1441c2aa98e2SPeter Wemm **		A boolean representation of the string.
1442c2aa98e2SPeter Wemm **
1443c2aa98e2SPeter Wemm **	Side Effects:
1444c2aa98e2SPeter Wemm **		none.
1445c2aa98e2SPeter Wemm */
1446c2aa98e2SPeter Wemm 
1447c2aa98e2SPeter Wemm bool
1448c2aa98e2SPeter Wemm atobool(s)
1449c2aa98e2SPeter Wemm 	register char *s;
1450c2aa98e2SPeter Wemm {
1451c2aa98e2SPeter Wemm 	if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL)
145206f25ae9SGregory Neil Shapiro 		return TRUE;
145306f25ae9SGregory Neil Shapiro 	return FALSE;
1454c2aa98e2SPeter Wemm }
1455c2aa98e2SPeter Wemm /*
1456c2aa98e2SPeter Wemm **  ATOOCT -- convert a string representation to octal.
1457c2aa98e2SPeter Wemm **
1458c2aa98e2SPeter Wemm **	Parameters:
1459c2aa98e2SPeter Wemm **		s -- string to convert.
1460c2aa98e2SPeter Wemm **
1461c2aa98e2SPeter Wemm **	Returns:
1462c2aa98e2SPeter Wemm **		An integer representing the string interpreted as an
1463c2aa98e2SPeter Wemm **		octal number.
1464c2aa98e2SPeter Wemm **
1465c2aa98e2SPeter Wemm **	Side Effects:
1466c2aa98e2SPeter Wemm **		none.
1467c2aa98e2SPeter Wemm */
1468c2aa98e2SPeter Wemm 
1469c2aa98e2SPeter Wemm int
1470c2aa98e2SPeter Wemm atooct(s)
1471c2aa98e2SPeter Wemm 	register char *s;
1472c2aa98e2SPeter Wemm {
1473c2aa98e2SPeter Wemm 	register int i = 0;
1474c2aa98e2SPeter Wemm 
1475c2aa98e2SPeter Wemm 	while (*s >= '0' && *s <= '7')
1476c2aa98e2SPeter Wemm 		i = (i << 3) | (*s++ - '0');
147706f25ae9SGregory Neil Shapiro 	return i;
1478c2aa98e2SPeter Wemm }
1479c2aa98e2SPeter Wemm /*
1480c2aa98e2SPeter Wemm **  BITINTERSECT -- tell if two bitmaps intersect
1481c2aa98e2SPeter Wemm **
1482c2aa98e2SPeter Wemm **	Parameters:
1483c2aa98e2SPeter Wemm **		a, b -- the bitmaps in question
1484c2aa98e2SPeter Wemm **
1485c2aa98e2SPeter Wemm **	Returns:
1486c2aa98e2SPeter Wemm **		TRUE if they have a non-null intersection
1487c2aa98e2SPeter Wemm **		FALSE otherwise
1488c2aa98e2SPeter Wemm **
1489c2aa98e2SPeter Wemm **	Side Effects:
1490c2aa98e2SPeter Wemm **		none.
1491c2aa98e2SPeter Wemm */
1492c2aa98e2SPeter Wemm 
1493c2aa98e2SPeter Wemm bool
1494c2aa98e2SPeter Wemm bitintersect(a, b)
149506f25ae9SGregory Neil Shapiro 	BITMAP256 a;
149606f25ae9SGregory Neil Shapiro 	BITMAP256 b;
1497c2aa98e2SPeter Wemm {
1498c2aa98e2SPeter Wemm 	int i;
1499c2aa98e2SPeter Wemm 
1500c2aa98e2SPeter Wemm 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
1501193538b7SGregory Neil Shapiro 	{
1502c2aa98e2SPeter Wemm 		if ((a[i] & b[i]) != 0)
150306f25ae9SGregory Neil Shapiro 			return TRUE;
1504193538b7SGregory Neil Shapiro 	}
150506f25ae9SGregory Neil Shapiro 	return FALSE;
1506c2aa98e2SPeter Wemm }
1507c2aa98e2SPeter Wemm /*
1508c2aa98e2SPeter Wemm **  BITZEROP -- tell if a bitmap is all zero
1509c2aa98e2SPeter Wemm **
1510c2aa98e2SPeter Wemm **	Parameters:
1511c2aa98e2SPeter Wemm **		map -- the bit map to check
1512c2aa98e2SPeter Wemm **
1513c2aa98e2SPeter Wemm **	Returns:
1514c2aa98e2SPeter Wemm **		TRUE if map is all zero.
1515c2aa98e2SPeter Wemm **		FALSE if there are any bits set in map.
1516c2aa98e2SPeter Wemm **
1517c2aa98e2SPeter Wemm **	Side Effects:
1518c2aa98e2SPeter Wemm **		none.
1519c2aa98e2SPeter Wemm */
1520c2aa98e2SPeter Wemm 
1521c2aa98e2SPeter Wemm bool
1522c2aa98e2SPeter Wemm bitzerop(map)
152306f25ae9SGregory Neil Shapiro 	BITMAP256 map;
1524c2aa98e2SPeter Wemm {
1525c2aa98e2SPeter Wemm 	int i;
1526c2aa98e2SPeter Wemm 
1527c2aa98e2SPeter Wemm 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
1528193538b7SGregory Neil Shapiro 	{
1529c2aa98e2SPeter Wemm 		if (map[i] != 0)
153006f25ae9SGregory Neil Shapiro 			return FALSE;
1531193538b7SGregory Neil Shapiro 	}
153206f25ae9SGregory Neil Shapiro 	return TRUE;
1533c2aa98e2SPeter Wemm }
1534c2aa98e2SPeter Wemm /*
1535c2aa98e2SPeter Wemm **  STRCONTAINEDIN -- tell if one string is contained in another
1536c2aa98e2SPeter Wemm **
1537c2aa98e2SPeter Wemm **	Parameters:
1538c2aa98e2SPeter Wemm **		a -- possible substring.
1539c2aa98e2SPeter Wemm **		b -- possible superstring.
1540c2aa98e2SPeter Wemm **
1541c2aa98e2SPeter Wemm **	Returns:
1542c2aa98e2SPeter Wemm **		TRUE if a is contained in b.
1543c2aa98e2SPeter Wemm **		FALSE otherwise.
1544c2aa98e2SPeter Wemm */
1545c2aa98e2SPeter Wemm 
1546c2aa98e2SPeter Wemm bool
1547c2aa98e2SPeter Wemm strcontainedin(a, b)
1548c2aa98e2SPeter Wemm 	register char *a;
1549c2aa98e2SPeter Wemm 	register char *b;
1550c2aa98e2SPeter Wemm {
1551c2aa98e2SPeter Wemm 	int la;
1552c2aa98e2SPeter Wemm 	int lb;
1553c2aa98e2SPeter Wemm 	int c;
1554c2aa98e2SPeter Wemm 
1555c2aa98e2SPeter Wemm 	la = strlen(a);
1556c2aa98e2SPeter Wemm 	lb = strlen(b);
1557c2aa98e2SPeter Wemm 	c = *a;
1558c2aa98e2SPeter Wemm 	if (isascii(c) && isupper(c))
1559c2aa98e2SPeter Wemm 		c = tolower(c);
1560c2aa98e2SPeter Wemm 	for (; lb-- >= la; b++)
1561c2aa98e2SPeter Wemm 	{
1562c2aa98e2SPeter Wemm 		if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c)
1563c2aa98e2SPeter Wemm 			continue;
1564c2aa98e2SPeter Wemm 		if (strncasecmp(a, b, la) == 0)
1565c2aa98e2SPeter Wemm 			return TRUE;
1566c2aa98e2SPeter Wemm 	}
1567c2aa98e2SPeter Wemm 	return FALSE;
1568c2aa98e2SPeter Wemm }
1569c2aa98e2SPeter Wemm /*
1570c2aa98e2SPeter Wemm **  CHECKFD012 -- check low numbered file descriptors
1571c2aa98e2SPeter Wemm **
1572c2aa98e2SPeter Wemm **	File descriptors 0, 1, and 2 should be open at all times.
1573c2aa98e2SPeter Wemm **	This routine verifies that, and fixes it if not true.
1574c2aa98e2SPeter Wemm **
1575c2aa98e2SPeter Wemm **	Parameters:
1576c2aa98e2SPeter Wemm **		where -- a tag printed if the assertion failed
1577c2aa98e2SPeter Wemm **
1578c2aa98e2SPeter Wemm **	Returns:
1579c2aa98e2SPeter Wemm **		none
1580c2aa98e2SPeter Wemm */
1581c2aa98e2SPeter Wemm 
1582c2aa98e2SPeter Wemm void
1583c2aa98e2SPeter Wemm checkfd012(where)
1584c2aa98e2SPeter Wemm 	char *where;
1585c2aa98e2SPeter Wemm {
1586c2aa98e2SPeter Wemm #if XDEBUG
1587c2aa98e2SPeter Wemm 	register int i;
1588c2aa98e2SPeter Wemm 
1589c2aa98e2SPeter Wemm 	for (i = 0; i < 3; i++)
1590c2aa98e2SPeter Wemm 		fill_fd(i, where);
1591c2aa98e2SPeter Wemm #endif /* XDEBUG */
1592c2aa98e2SPeter Wemm }
1593c2aa98e2SPeter Wemm /*
1594c2aa98e2SPeter Wemm **  CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging
1595c2aa98e2SPeter Wemm **
1596c2aa98e2SPeter Wemm **	Parameters:
1597c2aa98e2SPeter Wemm **		fd -- file descriptor to check.
1598c2aa98e2SPeter Wemm **		where -- tag to print on failure.
1599c2aa98e2SPeter Wemm **
1600c2aa98e2SPeter Wemm **	Returns:
1601c2aa98e2SPeter Wemm **		none.
1602c2aa98e2SPeter Wemm */
1603c2aa98e2SPeter Wemm 
1604c2aa98e2SPeter Wemm void
1605c2aa98e2SPeter Wemm checkfdopen(fd, where)
1606c2aa98e2SPeter Wemm 	int fd;
1607c2aa98e2SPeter Wemm 	char *where;
1608c2aa98e2SPeter Wemm {
1609c2aa98e2SPeter Wemm #if XDEBUG
1610c2aa98e2SPeter Wemm 	struct stat st;
1611c2aa98e2SPeter Wemm 
1612c2aa98e2SPeter Wemm 	if (fstat(fd, &st) < 0 && errno == EBADF)
1613c2aa98e2SPeter Wemm 	{
1614c2aa98e2SPeter Wemm 		syserr("checkfdopen(%d): %s not open as expected!", fd, where);
1615c2aa98e2SPeter Wemm 		printopenfds(TRUE);
1616c2aa98e2SPeter Wemm 	}
161706f25ae9SGregory Neil Shapiro #endif /* XDEBUG */
1618c2aa98e2SPeter Wemm }
1619c2aa98e2SPeter Wemm /*
1620c2aa98e2SPeter Wemm **  CHECKFDS -- check for new or missing file descriptors
1621c2aa98e2SPeter Wemm **
1622c2aa98e2SPeter Wemm **	Parameters:
1623c2aa98e2SPeter Wemm **		where -- tag for printing.  If null, take a base line.
1624c2aa98e2SPeter Wemm **
1625c2aa98e2SPeter Wemm **	Returns:
1626c2aa98e2SPeter Wemm **		none
1627c2aa98e2SPeter Wemm **
1628c2aa98e2SPeter Wemm **	Side Effects:
1629c2aa98e2SPeter Wemm **		If where is set, shows changes since the last call.
1630c2aa98e2SPeter Wemm */
1631c2aa98e2SPeter Wemm 
1632c2aa98e2SPeter Wemm void
1633c2aa98e2SPeter Wemm checkfds(where)
1634c2aa98e2SPeter Wemm 	char *where;
1635c2aa98e2SPeter Wemm {
1636c2aa98e2SPeter Wemm 	int maxfd;
1637c2aa98e2SPeter Wemm 	register int fd;
1638c2aa98e2SPeter Wemm 	bool printhdr = TRUE;
1639c2aa98e2SPeter Wemm 	int save_errno = errno;
164006f25ae9SGregory Neil Shapiro 	static BITMAP256 baseline;
1641c2aa98e2SPeter Wemm 	extern int DtableSize;
1642c2aa98e2SPeter Wemm 
1643193538b7SGregory Neil Shapiro 	if (DtableSize > BITMAPBITS)
1644193538b7SGregory Neil Shapiro 		maxfd = BITMAPBITS;
1645c2aa98e2SPeter Wemm 	else
1646c2aa98e2SPeter Wemm 		maxfd = DtableSize;
1647c2aa98e2SPeter Wemm 	if (where == NULL)
1648c2aa98e2SPeter Wemm 		clrbitmap(baseline);
1649c2aa98e2SPeter Wemm 
1650c2aa98e2SPeter Wemm 	for (fd = 0; fd < maxfd; fd++)
1651c2aa98e2SPeter Wemm 	{
1652c2aa98e2SPeter Wemm 		struct stat stbuf;
1653c2aa98e2SPeter Wemm 
1654c2aa98e2SPeter Wemm 		if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP)
1655c2aa98e2SPeter Wemm 		{
1656c2aa98e2SPeter Wemm 			if (!bitnset(fd, baseline))
1657c2aa98e2SPeter Wemm 				continue;
1658c2aa98e2SPeter Wemm 			clrbitn(fd, baseline);
1659c2aa98e2SPeter Wemm 		}
1660c2aa98e2SPeter Wemm 		else if (!bitnset(fd, baseline))
1661c2aa98e2SPeter Wemm 			setbitn(fd, baseline);
1662c2aa98e2SPeter Wemm 		else
1663c2aa98e2SPeter Wemm 			continue;
1664c2aa98e2SPeter Wemm 
1665c2aa98e2SPeter Wemm 		/* file state has changed */
1666c2aa98e2SPeter Wemm 		if (where == NULL)
1667c2aa98e2SPeter Wemm 			continue;
1668c2aa98e2SPeter Wemm 		if (printhdr)
1669c2aa98e2SPeter Wemm 		{
1670c2aa98e2SPeter Wemm 			sm_syslog(LOG_DEBUG, CurEnv->e_id,
1671c2aa98e2SPeter Wemm 				  "%s: changed fds:",
1672c2aa98e2SPeter Wemm 				  where);
1673c2aa98e2SPeter Wemm 			printhdr = FALSE;
1674c2aa98e2SPeter Wemm 		}
1675c2aa98e2SPeter Wemm 		dumpfd(fd, TRUE, TRUE);
1676c2aa98e2SPeter Wemm 	}
1677c2aa98e2SPeter Wemm 	errno = save_errno;
1678c2aa98e2SPeter Wemm }
1679c2aa98e2SPeter Wemm /*
1680c2aa98e2SPeter Wemm **  PRINTOPENFDS -- print the open file descriptors (for debugging)
1681c2aa98e2SPeter Wemm **
1682c2aa98e2SPeter Wemm **	Parameters:
1683c2aa98e2SPeter Wemm **		logit -- if set, send output to syslog; otherwise
1684c2aa98e2SPeter Wemm **			print for debugging.
1685c2aa98e2SPeter Wemm **
1686c2aa98e2SPeter Wemm **	Returns:
1687c2aa98e2SPeter Wemm **		none.
1688c2aa98e2SPeter Wemm */
1689c2aa98e2SPeter Wemm 
169006f25ae9SGregory Neil Shapiro #if NETINET || NETINET6
1691c2aa98e2SPeter Wemm # include <arpa/inet.h>
169206f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */
1693c2aa98e2SPeter Wemm 
1694c2aa98e2SPeter Wemm void
1695c2aa98e2SPeter Wemm printopenfds(logit)
1696c2aa98e2SPeter Wemm 	bool logit;
1697c2aa98e2SPeter Wemm {
1698c2aa98e2SPeter Wemm 	register int fd;
1699c2aa98e2SPeter Wemm 	extern int DtableSize;
1700c2aa98e2SPeter Wemm 
1701c2aa98e2SPeter Wemm 	for (fd = 0; fd < DtableSize; fd++)
1702c2aa98e2SPeter Wemm 		dumpfd(fd, FALSE, logit);
1703c2aa98e2SPeter Wemm }
1704c2aa98e2SPeter Wemm /*
1705c2aa98e2SPeter Wemm **  DUMPFD -- dump a file descriptor
1706c2aa98e2SPeter Wemm **
1707c2aa98e2SPeter Wemm **	Parameters:
1708c2aa98e2SPeter Wemm **		fd -- the file descriptor to dump.
1709c2aa98e2SPeter Wemm **		printclosed -- if set, print a notification even if
1710c2aa98e2SPeter Wemm **			it is closed; otherwise print nothing.
1711c2aa98e2SPeter Wemm **		logit -- if set, send output to syslog instead of stdout.
1712c2aa98e2SPeter Wemm */
1713c2aa98e2SPeter Wemm 
1714c2aa98e2SPeter Wemm void
1715c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit)
1716c2aa98e2SPeter Wemm 	int fd;
1717c2aa98e2SPeter Wemm 	bool printclosed;
1718c2aa98e2SPeter Wemm 	bool logit;
1719c2aa98e2SPeter Wemm {
1720c2aa98e2SPeter Wemm 	register char *p;
1721c2aa98e2SPeter Wemm 	char *hp;
1722c2aa98e2SPeter Wemm #ifdef S_IFSOCK
1723c2aa98e2SPeter Wemm 	SOCKADDR sa;
172406f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */
1725c2aa98e2SPeter Wemm 	auto SOCKADDR_LEN_T slen;
1726c2aa98e2SPeter Wemm 	int i;
1727c2aa98e2SPeter Wemm #if STAT64 > 0
1728c2aa98e2SPeter Wemm 	struct stat64 st;
172906f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */
1730c2aa98e2SPeter Wemm 	struct stat st;
173106f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */
1732c2aa98e2SPeter Wemm 	char buf[200];
1733c2aa98e2SPeter Wemm 
1734c2aa98e2SPeter Wemm 	p = buf;
1735c2aa98e2SPeter Wemm 	snprintf(p, SPACELEFT(buf, p), "%3d: ", fd);
1736c2aa98e2SPeter Wemm 	p += strlen(p);
1737c2aa98e2SPeter Wemm 
1738c2aa98e2SPeter Wemm 	if (
1739c2aa98e2SPeter Wemm #if STAT64 > 0
1740c2aa98e2SPeter Wemm 	    fstat64(fd, &st)
174106f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */
1742c2aa98e2SPeter Wemm 	    fstat(fd, &st)
174306f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */
1744c2aa98e2SPeter Wemm 	    < 0)
1745c2aa98e2SPeter Wemm 	{
1746c2aa98e2SPeter Wemm 		if (errno != EBADF)
1747c2aa98e2SPeter Wemm 		{
1748c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)",
1749c2aa98e2SPeter Wemm 				errstring(errno));
1750c2aa98e2SPeter Wemm 			goto printit;
1751c2aa98e2SPeter Wemm 		}
1752c2aa98e2SPeter Wemm 		else if (printclosed)
1753c2aa98e2SPeter Wemm 		{
1754c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "CLOSED");
1755c2aa98e2SPeter Wemm 			goto printit;
1756c2aa98e2SPeter Wemm 		}
1757c2aa98e2SPeter Wemm 		return;
1758c2aa98e2SPeter Wemm 	}
1759c2aa98e2SPeter Wemm 
1760c2aa98e2SPeter Wemm 	i = fcntl(fd, F_GETFL, NULL);
1761c2aa98e2SPeter Wemm 	if (i != -1)
1762c2aa98e2SPeter Wemm 	{
1763c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i);
1764c2aa98e2SPeter Wemm 		p += strlen(p);
1765c2aa98e2SPeter Wemm 	}
1766c2aa98e2SPeter Wemm 
176706f25ae9SGregory Neil Shapiro 	snprintf(p, SPACELEFT(buf, p), "mode=%o: ", (int) st.st_mode);
1768c2aa98e2SPeter Wemm 	p += strlen(p);
1769c2aa98e2SPeter Wemm 	switch (st.st_mode & S_IFMT)
1770c2aa98e2SPeter Wemm 	{
1771c2aa98e2SPeter Wemm #ifdef S_IFSOCK
1772c2aa98e2SPeter Wemm 	  case S_IFSOCK:
1773c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "SOCK ");
1774c2aa98e2SPeter Wemm 		p += strlen(p);
177506f25ae9SGregory Neil Shapiro 		memset(&sa, '\0', sizeof sa);
1776c2aa98e2SPeter Wemm 		slen = sizeof sa;
1777c2aa98e2SPeter Wemm 		if (getsockname(fd, &sa.sa, &slen) < 0)
177806f25ae9SGregory Neil Shapiro 			snprintf(p, SPACELEFT(buf, p), "(%s)",
177906f25ae9SGregory Neil Shapiro 				 errstring(errno));
1780c2aa98e2SPeter Wemm 		else
1781c2aa98e2SPeter Wemm 		{
1782c2aa98e2SPeter Wemm 			hp = hostnamebyanyaddr(&sa);
178306f25ae9SGregory Neil Shapiro 			if (hp == NULL)
178406f25ae9SGregory Neil Shapiro 			{
178506f25ae9SGregory Neil Shapiro 				/* EMPTY */
178606f25ae9SGregory Neil Shapiro 				/* do nothing */
178706f25ae9SGregory Neil Shapiro 			}
178806f25ae9SGregory Neil Shapiro # if NETINET
178906f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET)
1790c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
1791c2aa98e2SPeter Wemm 					 hp, ntohs(sa.sin.sin_port));
179206f25ae9SGregory Neil Shapiro # endif /* NETINET */
179306f25ae9SGregory Neil Shapiro # if NETINET6
179406f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET6)
179506f25ae9SGregory Neil Shapiro 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
179606f25ae9SGregory Neil Shapiro 					 hp, ntohs(sa.sin6.sin6_port));
179706f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1798c2aa98e2SPeter Wemm 			else
1799c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s", hp);
1800c2aa98e2SPeter Wemm 		}
1801c2aa98e2SPeter Wemm 		p += strlen(p);
1802c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "->");
1803c2aa98e2SPeter Wemm 		p += strlen(p);
1804c2aa98e2SPeter Wemm 		slen = sizeof sa;
1805c2aa98e2SPeter Wemm 		if (getpeername(fd, &sa.sa, &slen) < 0)
1806c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno));
1807c2aa98e2SPeter Wemm 		else
1808c2aa98e2SPeter Wemm 		{
1809c2aa98e2SPeter Wemm 			hp = hostnamebyanyaddr(&sa);
181006f25ae9SGregory Neil Shapiro 			if (hp == NULL)
181106f25ae9SGregory Neil Shapiro 			{
181206f25ae9SGregory Neil Shapiro 				/* EMPTY */
181306f25ae9SGregory Neil Shapiro 				/* do nothing */
181406f25ae9SGregory Neil Shapiro 			}
181506f25ae9SGregory Neil Shapiro # if NETINET
181606f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET)
1817c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
1818c2aa98e2SPeter Wemm 					 hp, ntohs(sa.sin.sin_port));
181906f25ae9SGregory Neil Shapiro # endif /* NETINET */
182006f25ae9SGregory Neil Shapiro # if NETINET6
182106f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET6)
182206f25ae9SGregory Neil Shapiro 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
182306f25ae9SGregory Neil Shapiro 					 hp, ntohs(sa.sin6.sin6_port));
182406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1825c2aa98e2SPeter Wemm 			else
1826c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s", hp);
1827c2aa98e2SPeter Wemm 		}
1828c2aa98e2SPeter Wemm 		break;
182906f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */
1830c2aa98e2SPeter Wemm 
1831c2aa98e2SPeter Wemm 	  case S_IFCHR:
1832c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "CHR: ");
1833c2aa98e2SPeter Wemm 		p += strlen(p);
1834c2aa98e2SPeter Wemm 		goto defprint;
1835c2aa98e2SPeter Wemm 
1836c2aa98e2SPeter Wemm 	  case S_IFBLK:
1837c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "BLK: ");
1838c2aa98e2SPeter Wemm 		p += strlen(p);
1839c2aa98e2SPeter Wemm 		goto defprint;
1840c2aa98e2SPeter Wemm 
1841c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK)
1842c2aa98e2SPeter Wemm 	  case S_IFIFO:
1843c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "FIFO: ");
1844c2aa98e2SPeter Wemm 		p += strlen(p);
1845c2aa98e2SPeter Wemm 		goto defprint;
184606f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */
1847c2aa98e2SPeter Wemm 
1848c2aa98e2SPeter Wemm #ifdef S_IFDIR
1849c2aa98e2SPeter Wemm 	  case S_IFDIR:
1850c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "DIR: ");
1851c2aa98e2SPeter Wemm 		p += strlen(p);
1852c2aa98e2SPeter Wemm 		goto defprint;
185306f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */
1854c2aa98e2SPeter Wemm 
1855c2aa98e2SPeter Wemm #ifdef S_IFLNK
1856c2aa98e2SPeter Wemm 	  case S_IFLNK:
1857c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "LNK: ");
1858c2aa98e2SPeter Wemm 		p += strlen(p);
1859c2aa98e2SPeter Wemm 		goto defprint;
186006f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */
1861c2aa98e2SPeter Wemm 
1862c2aa98e2SPeter Wemm 	  default:
1863c2aa98e2SPeter Wemm defprint:
186406f25ae9SGregory Neil Shapiro 		/*CONSTCOND*/
1865c2aa98e2SPeter Wemm 		if (sizeof st.st_ino > sizeof (long))
1866c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p),
1867c2aa98e2SPeter Wemm 				 "dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ",
1868c2aa98e2SPeter Wemm 				 major(st.st_dev), minor(st.st_dev),
1869c2aa98e2SPeter Wemm 				 quad_to_string(st.st_ino),
187006f25ae9SGregory Neil Shapiro 				 (int) st.st_nlink, (int) st.st_uid,
187106f25ae9SGregory Neil Shapiro 				 (int) st.st_gid);
1872c2aa98e2SPeter Wemm 		else
1873c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p),
1874c2aa98e2SPeter Wemm 				 "dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ",
1875c2aa98e2SPeter Wemm 				 major(st.st_dev), minor(st.st_dev),
1876c2aa98e2SPeter Wemm 				 (unsigned long) st.st_ino,
187706f25ae9SGregory Neil Shapiro 				 (int) st.st_nlink, (int) st.st_uid,
187806f25ae9SGregory Neil Shapiro 				 (int) st.st_gid);
187906f25ae9SGregory Neil Shapiro 		/*CONSTCOND*/
1880c2aa98e2SPeter Wemm 		if (sizeof st.st_size > sizeof (long))
1881c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "size=%s",
1882c2aa98e2SPeter Wemm 				 quad_to_string(st.st_size));
1883c2aa98e2SPeter Wemm 		else
1884c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "size=%lu",
1885c2aa98e2SPeter Wemm 				 (unsigned long) st.st_size);
1886c2aa98e2SPeter Wemm 		break;
1887c2aa98e2SPeter Wemm 	}
1888c2aa98e2SPeter Wemm 
1889c2aa98e2SPeter Wemm printit:
1890c2aa98e2SPeter Wemm 	if (logit)
1891c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL,
1892c2aa98e2SPeter Wemm 			  "%.800s", buf);
1893c2aa98e2SPeter Wemm 	else
1894c2aa98e2SPeter Wemm 		printf("%s\n", buf);
1895c2aa98e2SPeter Wemm }
1896c2aa98e2SPeter Wemm /*
1897c2aa98e2SPeter Wemm **  SHORTEN_HOSTNAME -- strip local domain information off of hostname.
1898c2aa98e2SPeter Wemm **
1899c2aa98e2SPeter Wemm **	Parameters:
1900c2aa98e2SPeter Wemm **		host -- the host to shorten (stripped in place).
1901c2aa98e2SPeter Wemm **
1902c2aa98e2SPeter Wemm **	Returns:
1903602a2b1bSGregory Neil Shapiro **		place where string was trunacted, NULL if not truncated.
1904c2aa98e2SPeter Wemm */
1905c2aa98e2SPeter Wemm 
1906602a2b1bSGregory Neil Shapiro char *
1907c2aa98e2SPeter Wemm shorten_hostname(host)
1908c2aa98e2SPeter Wemm 	char host[];
1909c2aa98e2SPeter Wemm {
1910c2aa98e2SPeter Wemm 	register char *p;
1911c2aa98e2SPeter Wemm 	char *mydom;
1912c2aa98e2SPeter Wemm 	int i;
1913c2aa98e2SPeter Wemm 	bool canon = FALSE;
1914c2aa98e2SPeter Wemm 
1915c2aa98e2SPeter Wemm 	/* strip off final dot */
1916c2aa98e2SPeter Wemm 	p = &host[strlen(host) - 1];
1917c2aa98e2SPeter Wemm 	if (*p == '.')
1918c2aa98e2SPeter Wemm 	{
1919c2aa98e2SPeter Wemm 		*p = '\0';
1920c2aa98e2SPeter Wemm 		canon = TRUE;
1921c2aa98e2SPeter Wemm 	}
1922c2aa98e2SPeter Wemm 
1923c2aa98e2SPeter Wemm 	/* see if there is any domain at all -- if not, we are done */
1924c2aa98e2SPeter Wemm 	p = strchr(host, '.');
1925c2aa98e2SPeter Wemm 	if (p == NULL)
1926602a2b1bSGregory Neil Shapiro 		return NULL;
1927c2aa98e2SPeter Wemm 
1928c2aa98e2SPeter Wemm 	/* yes, we have a domain -- see if it looks like us */
1929c2aa98e2SPeter Wemm 	mydom = macvalue('m', CurEnv);
1930c2aa98e2SPeter Wemm 	if (mydom == NULL)
1931c2aa98e2SPeter Wemm 		mydom = "";
1932c2aa98e2SPeter Wemm 	i = strlen(++p);
1933c2aa98e2SPeter Wemm 	if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 &&
1934c2aa98e2SPeter Wemm 	    (mydom[i] == '.' || mydom[i] == '\0'))
1935602a2b1bSGregory Neil Shapiro 	{
1936c2aa98e2SPeter Wemm 		*--p = '\0';
1937602a2b1bSGregory Neil Shapiro 		return p;
1938602a2b1bSGregory Neil Shapiro 	}
1939602a2b1bSGregory Neil Shapiro 	return NULL;
1940c2aa98e2SPeter Wemm }
1941c2aa98e2SPeter Wemm /*
1942c2aa98e2SPeter Wemm **  PROG_OPEN -- open a program for reading
1943c2aa98e2SPeter Wemm **
1944c2aa98e2SPeter Wemm **	Parameters:
1945c2aa98e2SPeter Wemm **		argv -- the argument list.
1946c2aa98e2SPeter Wemm **		pfd -- pointer to a place to store the file descriptor.
1947c2aa98e2SPeter Wemm **		e -- the current envelope.
1948c2aa98e2SPeter Wemm **
1949c2aa98e2SPeter Wemm **	Returns:
1950c2aa98e2SPeter Wemm **		pid of the process -- -1 if it failed.
1951c2aa98e2SPeter Wemm */
1952c2aa98e2SPeter Wemm 
19538774250cSGregory Neil Shapiro pid_t
1954c2aa98e2SPeter Wemm prog_open(argv, pfd, e)
1955c2aa98e2SPeter Wemm 	char **argv;
1956c2aa98e2SPeter Wemm 	int *pfd;
1957c2aa98e2SPeter Wemm 	ENVELOPE *e;
1958c2aa98e2SPeter Wemm {
19598774250cSGregory Neil Shapiro 	pid_t pid;
1960c2aa98e2SPeter Wemm 	int i;
196106f25ae9SGregory Neil Shapiro 	int save_errno;
1962c2aa98e2SPeter Wemm 	int fdv[2];
1963c2aa98e2SPeter Wemm 	char *p, *q;
1964c2aa98e2SPeter Wemm 	char buf[MAXLINE + 1];
1965c2aa98e2SPeter Wemm 	extern int DtableSize;
1966c2aa98e2SPeter Wemm 
1967c2aa98e2SPeter Wemm 	if (pipe(fdv) < 0)
1968c2aa98e2SPeter Wemm 	{
1969c2aa98e2SPeter Wemm 		syserr("%s: cannot create pipe for stdout", argv[0]);
1970c2aa98e2SPeter Wemm 		return -1;
1971c2aa98e2SPeter Wemm 	}
1972c2aa98e2SPeter Wemm 	pid = fork();
1973c2aa98e2SPeter Wemm 	if (pid < 0)
1974c2aa98e2SPeter Wemm 	{
1975c2aa98e2SPeter Wemm 		syserr("%s: cannot fork", argv[0]);
197606f25ae9SGregory Neil Shapiro 		(void) close(fdv[0]);
197706f25ae9SGregory Neil Shapiro 		(void) close(fdv[1]);
1978c2aa98e2SPeter Wemm 		return -1;
1979c2aa98e2SPeter Wemm 	}
1980c2aa98e2SPeter Wemm 	if (pid > 0)
1981c2aa98e2SPeter Wemm 	{
1982c2aa98e2SPeter Wemm 		/* parent */
198306f25ae9SGregory Neil Shapiro 		(void) close(fdv[1]);
1984c2aa98e2SPeter Wemm 		*pfd = fdv[0];
1985c2aa98e2SPeter Wemm 		return pid;
1986c2aa98e2SPeter Wemm 	}
1987c2aa98e2SPeter Wemm 
1988c2aa98e2SPeter Wemm 	/* child -- close stdin */
198906f25ae9SGregory Neil Shapiro 	(void) close(0);
1990c2aa98e2SPeter Wemm 
19918774250cSGregory Neil Shapiro 	/* Reset global flags */
19928774250cSGregory Neil Shapiro 	RestartRequest = NULL;
19938774250cSGregory Neil Shapiro 	ShutdownRequest = NULL;
19948774250cSGregory Neil Shapiro 	PendingSignal = 0;
19958774250cSGregory Neil Shapiro 
1996c2aa98e2SPeter Wemm 	/* stdout goes back to parent */
199706f25ae9SGregory Neil Shapiro 	(void) close(fdv[0]);
1998c2aa98e2SPeter Wemm 	if (dup2(fdv[1], 1) < 0)
1999c2aa98e2SPeter Wemm 	{
2000c2aa98e2SPeter Wemm 		syserr("%s: cannot dup2 for stdout", argv[0]);
2001c2aa98e2SPeter Wemm 		_exit(EX_OSERR);
2002c2aa98e2SPeter Wemm 	}
200306f25ae9SGregory Neil Shapiro 	(void) close(fdv[1]);
2004c2aa98e2SPeter Wemm 
2005c2aa98e2SPeter Wemm 	/* stderr goes to transcript if available */
2006c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
2007c2aa98e2SPeter Wemm 	{
200806f25ae9SGregory Neil Shapiro 		int xfd;
200906f25ae9SGregory Neil Shapiro 
201006f25ae9SGregory Neil Shapiro 		xfd = fileno(e->e_xfp);
201106f25ae9SGregory Neil Shapiro 		if (xfd >= 0 && dup2(xfd, 2) < 0)
2012c2aa98e2SPeter Wemm 		{
2013c2aa98e2SPeter Wemm 			syserr("%s: cannot dup2 for stderr", argv[0]);
2014c2aa98e2SPeter Wemm 			_exit(EX_OSERR);
2015c2aa98e2SPeter Wemm 		}
2016c2aa98e2SPeter Wemm 	}
2017c2aa98e2SPeter Wemm 
2018c2aa98e2SPeter Wemm 	/* this process has no right to the queue file */
2019c2aa98e2SPeter Wemm 	if (e->e_lockfp != NULL)
202006f25ae9SGregory Neil Shapiro 		(void) close(fileno(e->e_lockfp));
202106f25ae9SGregory Neil Shapiro 
202206f25ae9SGregory Neil Shapiro 	/* chroot to the program mailer directory, if defined */
202306f25ae9SGregory Neil Shapiro 	if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL)
202406f25ae9SGregory Neil Shapiro 	{
202506f25ae9SGregory Neil Shapiro 		expand(ProgMailer->m_rootdir, buf, sizeof buf, e);
202606f25ae9SGregory Neil Shapiro 		if (chroot(buf) < 0)
202706f25ae9SGregory Neil Shapiro 		{
202806f25ae9SGregory Neil Shapiro 			syserr("prog_open: cannot chroot(%s)", buf);
202906f25ae9SGregory Neil Shapiro 			exit(EX_TEMPFAIL);
203006f25ae9SGregory Neil Shapiro 		}
203106f25ae9SGregory Neil Shapiro 		if (chdir("/") < 0)
203206f25ae9SGregory Neil Shapiro 		{
203306f25ae9SGregory Neil Shapiro 			syserr("prog_open: cannot chdir(/)");
203406f25ae9SGregory Neil Shapiro 			exit(EX_TEMPFAIL);
203506f25ae9SGregory Neil Shapiro 		}
203606f25ae9SGregory Neil Shapiro 	}
2037c2aa98e2SPeter Wemm 
2038c2aa98e2SPeter Wemm 	/* run as default user */
2039c2aa98e2SPeter Wemm 	endpwent();
2040c2aa98e2SPeter Wemm 	if (setgid(DefGid) < 0 && geteuid() == 0)
204106f25ae9SGregory Neil Shapiro 	{
2042c2aa98e2SPeter Wemm 		syserr("prog_open: setgid(%ld) failed", (long) DefGid);
204306f25ae9SGregory Neil Shapiro 		exit(EX_TEMPFAIL);
204406f25ae9SGregory Neil Shapiro 	}
2045c2aa98e2SPeter Wemm 	if (setuid(DefUid) < 0 && geteuid() == 0)
204606f25ae9SGregory Neil Shapiro 	{
2047c2aa98e2SPeter Wemm 		syserr("prog_open: setuid(%ld) failed", (long) DefUid);
204806f25ae9SGregory Neil Shapiro 		exit(EX_TEMPFAIL);
204906f25ae9SGregory Neil Shapiro 	}
2050c2aa98e2SPeter Wemm 
2051c2aa98e2SPeter Wemm 	/* run in some directory */
2052c2aa98e2SPeter Wemm 	if (ProgMailer != NULL)
2053c2aa98e2SPeter Wemm 		p = ProgMailer->m_execdir;
2054c2aa98e2SPeter Wemm 	else
2055c2aa98e2SPeter Wemm 		p = NULL;
2056c2aa98e2SPeter Wemm 	for (; p != NULL; p = q)
2057c2aa98e2SPeter Wemm 	{
2058c2aa98e2SPeter Wemm 		q = strchr(p, ':');
2059c2aa98e2SPeter Wemm 		if (q != NULL)
2060c2aa98e2SPeter Wemm 			*q = '\0';
2061c2aa98e2SPeter Wemm 		expand(p, buf, sizeof buf, e);
2062c2aa98e2SPeter Wemm 		if (q != NULL)
2063c2aa98e2SPeter Wemm 			*q++ = ':';
2064c2aa98e2SPeter Wemm 		if (buf[0] != '\0' && chdir(buf) >= 0)
2065c2aa98e2SPeter Wemm 			break;
2066c2aa98e2SPeter Wemm 	}
2067c2aa98e2SPeter Wemm 	if (p == NULL)
2068c2aa98e2SPeter Wemm 	{
2069c2aa98e2SPeter Wemm 		/* backup directories */
2070c2aa98e2SPeter Wemm 		if (chdir("/tmp") < 0)
2071c2aa98e2SPeter Wemm 			(void) chdir("/");
2072c2aa98e2SPeter Wemm 	}
2073c2aa98e2SPeter Wemm 
2074c2aa98e2SPeter Wemm 	/* arrange for all the files to be closed */
2075c2aa98e2SPeter Wemm 	for (i = 3; i < DtableSize; i++)
2076c2aa98e2SPeter Wemm 	{
2077c2aa98e2SPeter Wemm 		register int j;
2078c2aa98e2SPeter Wemm 
2079c2aa98e2SPeter Wemm 		if ((j = fcntl(i, F_GETFD, 0)) != -1)
208006f25ae9SGregory Neil Shapiro 			(void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
2081c2aa98e2SPeter Wemm 	}
2082c2aa98e2SPeter Wemm 
2083c2aa98e2SPeter Wemm 	/* now exec the process */
208406f25ae9SGregory Neil Shapiro 	(void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron);
2085c2aa98e2SPeter Wemm 
2086c2aa98e2SPeter Wemm 	/* woops!  failed */
208706f25ae9SGregory Neil Shapiro 	save_errno = errno;
2088c2aa98e2SPeter Wemm 	syserr("%s: cannot exec", argv[0]);
208906f25ae9SGregory Neil Shapiro 	if (transienterror(save_errno))
2090c2aa98e2SPeter Wemm 		_exit(EX_OSERR);
2091c2aa98e2SPeter Wemm 	_exit(EX_CONFIG);
2092c2aa98e2SPeter Wemm 	return -1;	/* avoid compiler warning on IRIX */
2093c2aa98e2SPeter Wemm }
2094c2aa98e2SPeter Wemm /*
2095c2aa98e2SPeter Wemm **  GET_COLUMN -- look up a Column in a line buffer
2096c2aa98e2SPeter Wemm **
2097c2aa98e2SPeter Wemm **	Parameters:
2098c2aa98e2SPeter Wemm **		line -- the raw text line to search.
2099c2aa98e2SPeter Wemm **		col -- the column number to fetch.
2100c2aa98e2SPeter Wemm **		delim -- the delimiter between columns.  If null,
2101c2aa98e2SPeter Wemm **			use white space.
2102c2aa98e2SPeter Wemm **		buf -- the output buffer.
2103c2aa98e2SPeter Wemm **		buflen -- the length of buf.
2104c2aa98e2SPeter Wemm **
2105c2aa98e2SPeter Wemm **	Returns:
2106c2aa98e2SPeter Wemm **		buf if successful.
2107c2aa98e2SPeter Wemm **		NULL otherwise.
2108c2aa98e2SPeter Wemm */
2109c2aa98e2SPeter Wemm 
2110c2aa98e2SPeter Wemm char *
2111c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen)
2112c2aa98e2SPeter Wemm 	char line[];
2113c2aa98e2SPeter Wemm 	int col;
211406f25ae9SGregory Neil Shapiro 	int delim;
2115c2aa98e2SPeter Wemm 	char buf[];
2116c2aa98e2SPeter Wemm 	int buflen;
2117c2aa98e2SPeter Wemm {
2118c2aa98e2SPeter Wemm 	char *p;
2119c2aa98e2SPeter Wemm 	char *begin, *end;
2120c2aa98e2SPeter Wemm 	int i;
2121c2aa98e2SPeter Wemm 	char delimbuf[4];
2122c2aa98e2SPeter Wemm 
212306f25ae9SGregory Neil Shapiro 	if ((char)delim == '\0')
212406f25ae9SGregory Neil Shapiro 		(void) strlcpy(delimbuf, "\n\t ", sizeof delimbuf);
2125c2aa98e2SPeter Wemm 	else
2126c2aa98e2SPeter Wemm 	{
212706f25ae9SGregory Neil Shapiro 		delimbuf[0] = (char)delim;
2128c2aa98e2SPeter Wemm 		delimbuf[1] = '\0';
2129c2aa98e2SPeter Wemm 	}
2130c2aa98e2SPeter Wemm 
2131c2aa98e2SPeter Wemm 	p = line;
2132c2aa98e2SPeter Wemm 	if (*p == '\0')
2133c2aa98e2SPeter Wemm 		return NULL;			/* line empty */
213406f25ae9SGregory Neil Shapiro 	if (*p == (char)delim && col == 0)
2135c2aa98e2SPeter Wemm 		return NULL;			/* first column empty */
2136c2aa98e2SPeter Wemm 
2137c2aa98e2SPeter Wemm 	begin = line;
2138c2aa98e2SPeter Wemm 
213906f25ae9SGregory Neil Shapiro 	if (col == 0 && (char)delim == '\0')
2140c2aa98e2SPeter Wemm 	{
2141c2aa98e2SPeter Wemm 		while (*begin != '\0' && isascii(*begin) && isspace(*begin))
2142c2aa98e2SPeter Wemm 			begin++;
2143c2aa98e2SPeter Wemm 	}
2144c2aa98e2SPeter Wemm 
2145c2aa98e2SPeter Wemm 	for (i = 0; i < col; i++)
2146c2aa98e2SPeter Wemm 	{
2147c2aa98e2SPeter Wemm 		if ((begin = strpbrk(begin, delimbuf)) == NULL)
2148c2aa98e2SPeter Wemm 			return NULL;		/* no such column */
2149c2aa98e2SPeter Wemm 		begin++;
215006f25ae9SGregory Neil Shapiro 		if ((char)delim == '\0')
2151c2aa98e2SPeter Wemm 		{
2152c2aa98e2SPeter Wemm 			while (*begin != '\0' && isascii(*begin) && isspace(*begin))
2153c2aa98e2SPeter Wemm 				begin++;
2154c2aa98e2SPeter Wemm 		}
2155c2aa98e2SPeter Wemm 	}
2156c2aa98e2SPeter Wemm 
2157c2aa98e2SPeter Wemm 	end = strpbrk(begin, delimbuf);
2158c2aa98e2SPeter Wemm 	if (end == NULL)
2159c2aa98e2SPeter Wemm 		i = strlen(begin);
2160c2aa98e2SPeter Wemm 	else
2161c2aa98e2SPeter Wemm 		i = end - begin;
2162c2aa98e2SPeter Wemm 	if (i >= buflen)
2163c2aa98e2SPeter Wemm 		i = buflen - 1;
216406f25ae9SGregory Neil Shapiro 	(void) strlcpy(buf, begin, i + 1);
2165c2aa98e2SPeter Wemm 	return buf;
2166c2aa98e2SPeter Wemm }
2167c2aa98e2SPeter Wemm /*
2168c2aa98e2SPeter Wemm **  CLEANSTRCPY -- copy string keeping out bogus characters
2169c2aa98e2SPeter Wemm **
2170c2aa98e2SPeter Wemm **	Parameters:
2171c2aa98e2SPeter Wemm **		t -- "to" string.
2172c2aa98e2SPeter Wemm **		f -- "from" string.
2173c2aa98e2SPeter Wemm **		l -- length of space available in "to" string.
2174c2aa98e2SPeter Wemm **
2175c2aa98e2SPeter Wemm **	Returns:
2176c2aa98e2SPeter Wemm **		none.
2177c2aa98e2SPeter Wemm */
2178c2aa98e2SPeter Wemm 
2179c2aa98e2SPeter Wemm void
2180c2aa98e2SPeter Wemm cleanstrcpy(t, f, l)
2181c2aa98e2SPeter Wemm 	register char *t;
2182c2aa98e2SPeter Wemm 	register char *f;
2183c2aa98e2SPeter Wemm 	int l;
2184c2aa98e2SPeter Wemm {
2185c2aa98e2SPeter Wemm 	/* check for newlines and log if necessary */
2186c2aa98e2SPeter Wemm 	(void) denlstring(f, TRUE, TRUE);
2187c2aa98e2SPeter Wemm 
218806f25ae9SGregory Neil Shapiro 	if (l <= 0)
218906f25ae9SGregory Neil Shapiro 		syserr("!cleanstrcpy: length == 0");
219006f25ae9SGregory Neil Shapiro 
2191c2aa98e2SPeter Wemm 	l--;
2192c2aa98e2SPeter Wemm 	while (l > 0 && *f != '\0')
2193c2aa98e2SPeter Wemm 	{
2194c2aa98e2SPeter Wemm 		if (isascii(*f) &&
2195c2aa98e2SPeter Wemm 		    (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL))
2196c2aa98e2SPeter Wemm 		{
2197c2aa98e2SPeter Wemm 			l--;
2198c2aa98e2SPeter Wemm 			*t++ = *f;
2199c2aa98e2SPeter Wemm 		}
2200c2aa98e2SPeter Wemm 		f++;
2201c2aa98e2SPeter Wemm 	}
2202c2aa98e2SPeter Wemm 	*t = '\0';
2203c2aa98e2SPeter Wemm }
220406f25ae9SGregory Neil Shapiro 
2205c2aa98e2SPeter Wemm /*
2206c2aa98e2SPeter Wemm **  DENLSTRING -- convert newlines in a string to spaces
2207c2aa98e2SPeter Wemm **
2208c2aa98e2SPeter Wemm **	Parameters:
2209c2aa98e2SPeter Wemm **		s -- the input string
2210c2aa98e2SPeter Wemm **		strict -- if set, don't permit continuation lines.
2211c2aa98e2SPeter Wemm **		logattacks -- if set, log attempted attacks.
2212c2aa98e2SPeter Wemm **
2213c2aa98e2SPeter Wemm **	Returns:
2214c2aa98e2SPeter Wemm **		A pointer to a version of the string with newlines
2215c2aa98e2SPeter Wemm **		mapped to spaces.  This should be copied.
2216c2aa98e2SPeter Wemm */
2217c2aa98e2SPeter Wemm 
2218c2aa98e2SPeter Wemm char *
2219c2aa98e2SPeter Wemm denlstring(s, strict, logattacks)
2220c2aa98e2SPeter Wemm 	char *s;
2221c2aa98e2SPeter Wemm 	bool strict;
2222c2aa98e2SPeter Wemm 	bool logattacks;
2223c2aa98e2SPeter Wemm {
2224c2aa98e2SPeter Wemm 	register char *p;
2225c2aa98e2SPeter Wemm 	int l;
2226c2aa98e2SPeter Wemm 	static char *bp = NULL;
2227c2aa98e2SPeter Wemm 	static int bl = 0;
2228c2aa98e2SPeter Wemm 
2229c2aa98e2SPeter Wemm 	p = s;
2230c2aa98e2SPeter Wemm 	while ((p = strchr(p, '\n')) != NULL)
2231c2aa98e2SPeter Wemm 		if (strict || (*++p != ' ' && *p != '\t'))
2232c2aa98e2SPeter Wemm 			break;
2233c2aa98e2SPeter Wemm 	if (p == NULL)
2234c2aa98e2SPeter Wemm 		return s;
2235c2aa98e2SPeter Wemm 
2236c2aa98e2SPeter Wemm 	l = strlen(s) + 1;
2237c2aa98e2SPeter Wemm 	if (bl < l)
2238c2aa98e2SPeter Wemm 	{
2239c2aa98e2SPeter Wemm 		/* allocate more space */
2240c2aa98e2SPeter Wemm 		if (bp != NULL)
22418774250cSGregory Neil Shapiro 			sm_free(bp);
2242c2aa98e2SPeter Wemm 		bp = xalloc(l);
2243c2aa98e2SPeter Wemm 		bl = l;
2244c2aa98e2SPeter Wemm 	}
224506f25ae9SGregory Neil Shapiro 	(void) strlcpy(bp, s, l);
2246c2aa98e2SPeter Wemm 	for (p = bp; (p = strchr(p, '\n')) != NULL; )
2247c2aa98e2SPeter Wemm 		*p++ = ' ';
2248c2aa98e2SPeter Wemm 
2249c2aa98e2SPeter Wemm 	if (logattacks)
2250c2aa98e2SPeter Wemm 	{
2251c2aa98e2SPeter Wemm 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
2252c2aa98e2SPeter Wemm 			  "POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
2253c2aa98e2SPeter Wemm 			  RealHostName == NULL ? "[UNKNOWN]" : RealHostName,
2254c2aa98e2SPeter Wemm 			  shortenstring(bp, MAXSHORTSTR));
2255c2aa98e2SPeter Wemm 	}
2256c2aa98e2SPeter Wemm 
2257c2aa98e2SPeter Wemm 	return bp;
2258c2aa98e2SPeter Wemm }
2259c2aa98e2SPeter Wemm /*
2260c2aa98e2SPeter Wemm **  PATH_IS_DIR -- check to see if file exists and is a directory.
2261c2aa98e2SPeter Wemm **
2262c2aa98e2SPeter Wemm **	There are some additional checks for security violations in
2263c2aa98e2SPeter Wemm **	here.  This routine is intended to be used for the host status
2264c2aa98e2SPeter Wemm **	support.
2265c2aa98e2SPeter Wemm **
2266c2aa98e2SPeter Wemm **	Parameters:
2267c2aa98e2SPeter Wemm **		pathname -- pathname to check for directory-ness.
2268c2aa98e2SPeter Wemm **		createflag -- if set, create directory if needed.
2269c2aa98e2SPeter Wemm **
2270c2aa98e2SPeter Wemm **	Returns:
2271c2aa98e2SPeter Wemm **		TRUE -- if the indicated pathname is a directory
2272c2aa98e2SPeter Wemm **		FALSE -- otherwise
2273c2aa98e2SPeter Wemm */
2274c2aa98e2SPeter Wemm 
2275c2aa98e2SPeter Wemm int
2276c2aa98e2SPeter Wemm path_is_dir(pathname, createflag)
2277c2aa98e2SPeter Wemm 	char *pathname;
2278c2aa98e2SPeter Wemm 	bool createflag;
2279c2aa98e2SPeter Wemm {
2280c2aa98e2SPeter Wemm 	struct stat statbuf;
2281c2aa98e2SPeter Wemm 
2282c2aa98e2SPeter Wemm #if HASLSTAT
2283c2aa98e2SPeter Wemm 	if (lstat(pathname, &statbuf) < 0)
228406f25ae9SGregory Neil Shapiro #else /* HASLSTAT */
2285c2aa98e2SPeter Wemm 	if (stat(pathname, &statbuf) < 0)
228606f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */
2287c2aa98e2SPeter Wemm 	{
2288c2aa98e2SPeter Wemm 		if (errno != ENOENT || !createflag)
2289c2aa98e2SPeter Wemm 			return FALSE;
2290c2aa98e2SPeter Wemm 		if (mkdir(pathname, 0755) < 0)
2291c2aa98e2SPeter Wemm 			return FALSE;
2292c2aa98e2SPeter Wemm 		return TRUE;
2293c2aa98e2SPeter Wemm 	}
2294c2aa98e2SPeter Wemm 	if (!S_ISDIR(statbuf.st_mode))
2295c2aa98e2SPeter Wemm 	{
2296c2aa98e2SPeter Wemm 		errno = ENOTDIR;
2297c2aa98e2SPeter Wemm 		return FALSE;
2298c2aa98e2SPeter Wemm 	}
2299c2aa98e2SPeter Wemm 
2300c2aa98e2SPeter Wemm 	/* security: don't allow writable directories */
2301c2aa98e2SPeter Wemm 	if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode))
2302c2aa98e2SPeter Wemm 	{
2303c2aa98e2SPeter Wemm 		errno = EACCES;
2304c2aa98e2SPeter Wemm 		return FALSE;
2305c2aa98e2SPeter Wemm 	}
2306c2aa98e2SPeter Wemm 
2307c2aa98e2SPeter Wemm 	return TRUE;
2308c2aa98e2SPeter Wemm }
2309c2aa98e2SPeter Wemm /*
2310c2aa98e2SPeter Wemm **  PROC_LIST_ADD -- add process id to list of our children
2311c2aa98e2SPeter Wemm **
2312c2aa98e2SPeter Wemm **	Parameters:
2313c2aa98e2SPeter Wemm **		pid -- pid to add to list.
231406f25ae9SGregory Neil Shapiro **		task -- task of pid.
231506f25ae9SGregory Neil Shapiro **		type -- type of process.
2316c2aa98e2SPeter Wemm **
2317c2aa98e2SPeter Wemm **	Returns:
2318c2aa98e2SPeter Wemm **		none
2319c2aa98e2SPeter Wemm */
2320c2aa98e2SPeter Wemm 
23218774250cSGregory Neil Shapiro static struct procs	*volatile ProcListVec = NULL;
2322c2aa98e2SPeter Wemm static int		ProcListSize = 0;
2323c2aa98e2SPeter Wemm 
2324c2aa98e2SPeter Wemm void
232506f25ae9SGregory Neil Shapiro proc_list_add(pid, task, type)
2326c2aa98e2SPeter Wemm 	pid_t pid;
2327065a643dSPeter Wemm 	char *task;
232806f25ae9SGregory Neil Shapiro 	int type;
2329c2aa98e2SPeter Wemm {
2330c2aa98e2SPeter Wemm 	int i;
2331c2aa98e2SPeter Wemm 
2332c2aa98e2SPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2333c2aa98e2SPeter Wemm 	{
2334065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == NO_PID)
2335c2aa98e2SPeter Wemm 			break;
2336c2aa98e2SPeter Wemm 	}
2337c2aa98e2SPeter Wemm 	if (i >= ProcListSize)
2338c2aa98e2SPeter Wemm 	{
2339c2aa98e2SPeter Wemm 		/* probe the existing vector to avoid growing infinitely */
2340c2aa98e2SPeter Wemm 		proc_list_probe();
2341c2aa98e2SPeter Wemm 
2342c2aa98e2SPeter Wemm 		/* now scan again */
2343c2aa98e2SPeter Wemm 		for (i = 0; i < ProcListSize; i++)
2344c2aa98e2SPeter Wemm 		{
2345065a643dSPeter Wemm 			if (ProcListVec[i].proc_pid == NO_PID)
2346c2aa98e2SPeter Wemm 				break;
2347c2aa98e2SPeter Wemm 		}
2348c2aa98e2SPeter Wemm 	}
2349c2aa98e2SPeter Wemm 	if (i >= ProcListSize)
2350c2aa98e2SPeter Wemm 	{
2351c2aa98e2SPeter Wemm 		/* grow process list */
2352065a643dSPeter Wemm 		struct procs *npv;
2353c2aa98e2SPeter Wemm 
235406f25ae9SGregory Neil Shapiro 		npv = (struct procs *) xalloc((sizeof *npv) *
235506f25ae9SGregory Neil Shapiro 					      (ProcListSize + PROC_LIST_SEG));
2356c2aa98e2SPeter Wemm 		if (ProcListSize > 0)
2357c2aa98e2SPeter Wemm 		{
235806f25ae9SGregory Neil Shapiro 			memmove(npv, ProcListVec,
235906f25ae9SGregory Neil Shapiro 				ProcListSize * sizeof (struct procs));
23608774250cSGregory Neil Shapiro 			sm_free(ProcListVec);
2361c2aa98e2SPeter Wemm 		}
2362c2aa98e2SPeter Wemm 		for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++)
2363065a643dSPeter Wemm 		{
2364065a643dSPeter Wemm 			npv[i].proc_pid = NO_PID;
2365065a643dSPeter Wemm 			npv[i].proc_task = NULL;
236606f25ae9SGregory Neil Shapiro 			npv[i].proc_type = PROC_NONE;
2367065a643dSPeter Wemm 		}
2368c2aa98e2SPeter Wemm 		i = ProcListSize;
2369c2aa98e2SPeter Wemm 		ProcListSize += PROC_LIST_SEG;
2370c2aa98e2SPeter Wemm 		ProcListVec = npv;
2371c2aa98e2SPeter Wemm 	}
2372065a643dSPeter Wemm 	ProcListVec[i].proc_pid = pid;
237306f25ae9SGregory Neil Shapiro 	if (ProcListVec[i].proc_task != NULL)
23748774250cSGregory Neil Shapiro 		sm_free(ProcListVec[i].proc_task);
2375065a643dSPeter Wemm 	ProcListVec[i].proc_task = newstr(task);
237606f25ae9SGregory Neil Shapiro 	ProcListVec[i].proc_type = type;
2377065a643dSPeter Wemm 
2378065a643dSPeter Wemm 	/* if process adding itself, it's not a child */
2379065a643dSPeter Wemm 	if (pid != getpid())
2380c2aa98e2SPeter Wemm 		CurChildren++;
2381c2aa98e2SPeter Wemm }
2382c2aa98e2SPeter Wemm /*
2383065a643dSPeter Wemm **  PROC_LIST_SET -- set pid task in process list
2384065a643dSPeter Wemm **
2385065a643dSPeter Wemm **	Parameters:
2386065a643dSPeter Wemm **		pid -- pid to set
2387065a643dSPeter Wemm **		task -- task of pid
2388065a643dSPeter Wemm **
2389065a643dSPeter Wemm **	Returns:
2390065a643dSPeter Wemm **		none.
2391065a643dSPeter Wemm */
2392065a643dSPeter Wemm 
2393065a643dSPeter Wemm void
2394065a643dSPeter Wemm proc_list_set(pid, task)
2395065a643dSPeter Wemm 	pid_t pid;
2396065a643dSPeter Wemm 	char *task;
2397065a643dSPeter Wemm {
2398065a643dSPeter Wemm 	int i;
2399065a643dSPeter Wemm 
2400065a643dSPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2401065a643dSPeter Wemm 	{
2402065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == pid)
2403065a643dSPeter Wemm 		{
2404065a643dSPeter Wemm 			if (ProcListVec[i].proc_task != NULL)
24058774250cSGregory Neil Shapiro 				sm_free(ProcListVec[i].proc_task);
2406065a643dSPeter Wemm 			ProcListVec[i].proc_task = newstr(task);
2407065a643dSPeter Wemm 			break;
2408065a643dSPeter Wemm 		}
2409065a643dSPeter Wemm 	}
2410065a643dSPeter Wemm }
2411065a643dSPeter Wemm /*
2412c2aa98e2SPeter Wemm **  PROC_LIST_DROP -- drop pid from process list
2413c2aa98e2SPeter Wemm **
2414c2aa98e2SPeter Wemm **	Parameters:
2415c2aa98e2SPeter Wemm **		pid -- pid to drop
2416c2aa98e2SPeter Wemm **
2417c2aa98e2SPeter Wemm **	Returns:
241806f25ae9SGregory Neil Shapiro **		type of process
24198774250cSGregory Neil Shapiro **
24208774250cSGregory Neil Shapiro **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
24218774250cSGregory Neil Shapiro **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
24228774250cSGregory Neil Shapiro **		DOING.
2423c2aa98e2SPeter Wemm */
2424c2aa98e2SPeter Wemm 
242506f25ae9SGregory Neil Shapiro int
2426c2aa98e2SPeter Wemm proc_list_drop(pid)
2427c2aa98e2SPeter Wemm 	pid_t pid;
2428c2aa98e2SPeter Wemm {
2429c2aa98e2SPeter Wemm 	int i;
243006f25ae9SGregory Neil Shapiro 	int type = PROC_NONE;
2431c2aa98e2SPeter Wemm 
2432c2aa98e2SPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2433c2aa98e2SPeter Wemm 	{
2434065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == pid)
2435c2aa98e2SPeter Wemm 		{
2436065a643dSPeter Wemm 			ProcListVec[i].proc_pid = NO_PID;
243706f25ae9SGregory Neil Shapiro 			type = ProcListVec[i].proc_type;
2438c2aa98e2SPeter Wemm 			break;
2439c2aa98e2SPeter Wemm 		}
2440c2aa98e2SPeter Wemm 	}
2441c2aa98e2SPeter Wemm 	if (CurChildren > 0)
2442c2aa98e2SPeter Wemm 		CurChildren--;
244306f25ae9SGregory Neil Shapiro 
244406f25ae9SGregory Neil Shapiro 
244506f25ae9SGregory Neil Shapiro 	return type;
2446c2aa98e2SPeter Wemm }
2447c2aa98e2SPeter Wemm /*
2448c2aa98e2SPeter Wemm **  PROC_LIST_CLEAR -- clear the process list
2449c2aa98e2SPeter Wemm **
2450c2aa98e2SPeter Wemm **	Parameters:
2451c2aa98e2SPeter Wemm **		none.
2452c2aa98e2SPeter Wemm **
2453c2aa98e2SPeter Wemm **	Returns:
2454c2aa98e2SPeter Wemm **		none.
2455c2aa98e2SPeter Wemm */
2456c2aa98e2SPeter Wemm 
2457c2aa98e2SPeter Wemm void
2458c2aa98e2SPeter Wemm proc_list_clear()
2459c2aa98e2SPeter Wemm {
2460c2aa98e2SPeter Wemm 	int i;
2461c2aa98e2SPeter Wemm 
2462065a643dSPeter Wemm 	/* start from 1 since 0 is the daemon itself */
2463065a643dSPeter Wemm 	for (i = 1; i < ProcListSize; i++)
2464065a643dSPeter Wemm 	{
2465065a643dSPeter Wemm 		ProcListVec[i].proc_pid = NO_PID;
2466065a643dSPeter Wemm 	}
2467c2aa98e2SPeter Wemm 	CurChildren = 0;
2468c2aa98e2SPeter Wemm }
2469c2aa98e2SPeter Wemm /*
2470c2aa98e2SPeter Wemm **  PROC_LIST_PROBE -- probe processes in the list to see if they still exist
2471c2aa98e2SPeter Wemm **
2472c2aa98e2SPeter Wemm **	Parameters:
2473c2aa98e2SPeter Wemm **		none
2474c2aa98e2SPeter Wemm **
2475c2aa98e2SPeter Wemm **	Returns:
2476c2aa98e2SPeter Wemm **		none
2477c2aa98e2SPeter Wemm */
2478c2aa98e2SPeter Wemm 
2479c2aa98e2SPeter Wemm void
2480c2aa98e2SPeter Wemm proc_list_probe()
2481c2aa98e2SPeter Wemm {
2482c2aa98e2SPeter Wemm 	int i;
2483c2aa98e2SPeter Wemm 
2484065a643dSPeter Wemm 	/* start from 1 since 0 is the daemon itself */
2485065a643dSPeter Wemm 	for (i = 1; i < ProcListSize; i++)
2486c2aa98e2SPeter Wemm 	{
2487065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == NO_PID)
2488c2aa98e2SPeter Wemm 			continue;
2489065a643dSPeter Wemm 		if (kill(ProcListVec[i].proc_pid, 0) < 0)
2490c2aa98e2SPeter Wemm 		{
2491c2aa98e2SPeter Wemm 			if (LogLevel > 3)
2492c2aa98e2SPeter Wemm 				sm_syslog(LOG_DEBUG, CurEnv->e_id,
2493c2aa98e2SPeter Wemm 					  "proc_list_probe: lost pid %d",
2494065a643dSPeter Wemm 					  (int) ProcListVec[i].proc_pid);
2495065a643dSPeter Wemm 			ProcListVec[i].proc_pid = NO_PID;
2496c2aa98e2SPeter Wemm 			CurChildren--;
2497c2aa98e2SPeter Wemm 		}
2498c2aa98e2SPeter Wemm 	}
2499c2aa98e2SPeter Wemm 	if (CurChildren < 0)
2500c2aa98e2SPeter Wemm 		CurChildren = 0;
2501c2aa98e2SPeter Wemm }
2502c2aa98e2SPeter Wemm /*
2503065a643dSPeter Wemm **  PROC_LIST_DISPLAY -- display the process list
2504065a643dSPeter Wemm **
2505065a643dSPeter Wemm **	Parameters:
2506065a643dSPeter Wemm **		out -- output file pointer
2507065a643dSPeter Wemm **
2508065a643dSPeter Wemm **	Returns:
2509065a643dSPeter Wemm **		none.
2510065a643dSPeter Wemm */
2511065a643dSPeter Wemm 
2512065a643dSPeter Wemm void
2513065a643dSPeter Wemm proc_list_display(out)
2514065a643dSPeter Wemm 	FILE *out;
2515065a643dSPeter Wemm {
2516065a643dSPeter Wemm 	int i;
2517065a643dSPeter Wemm 
2518065a643dSPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2519065a643dSPeter Wemm 	{
2520065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == NO_PID)
2521065a643dSPeter Wemm 			continue;
2522065a643dSPeter Wemm 
2523065a643dSPeter Wemm 		fprintf(out, "%d %s%s\n", (int) ProcListVec[i].proc_pid,
2524065a643dSPeter Wemm 			ProcListVec[i].proc_task != NULL ?
2525065a643dSPeter Wemm 			ProcListVec[i].proc_task : "(unknown)",
2526065a643dSPeter Wemm 			(OpMode == MD_SMTP ||
2527065a643dSPeter Wemm 			 OpMode == MD_DAEMON ||
2528065a643dSPeter Wemm 			 OpMode == MD_ARPAFTP) ? "\r" : "");
2529065a643dSPeter Wemm 	}
2530065a643dSPeter Wemm }
2531065a643dSPeter Wemm /*
253213058a91SGregory Neil Shapiro **  SAFEFOPEN -- do a file open with extra checking
253313058a91SGregory Neil Shapiro **
253413058a91SGregory Neil Shapiro **	Parameters:
253513058a91SGregory Neil Shapiro **		fn -- the file name to open.
253613058a91SGregory Neil Shapiro **		omode -- the open-style mode flags.
253713058a91SGregory Neil Shapiro **		cmode -- the create-style mode flags.
253813058a91SGregory Neil Shapiro **		sff -- safefile flags.
253913058a91SGregory Neil Shapiro **
254013058a91SGregory Neil Shapiro **	Returns:
254113058a91SGregory Neil Shapiro **		Same as fopen.
254213058a91SGregory Neil Shapiro */
254313058a91SGregory Neil Shapiro 
254413058a91SGregory Neil Shapiro FILE *
254513058a91SGregory Neil Shapiro safefopen(fn, omode, cmode, sff)
254613058a91SGregory Neil Shapiro 	char *fn;
254713058a91SGregory Neil Shapiro 	int omode;
254813058a91SGregory Neil Shapiro 	int cmode;
254913058a91SGregory Neil Shapiro 	long sff;
255013058a91SGregory Neil Shapiro {
255113058a91SGregory Neil Shapiro 	int fd;
255213058a91SGregory Neil Shapiro 	int save_errno;
255313058a91SGregory Neil Shapiro 	FILE *fp;
255413058a91SGregory Neil Shapiro 	char *fmode;
255513058a91SGregory Neil Shapiro 
255613058a91SGregory Neil Shapiro 	switch (omode & O_ACCMODE)
255713058a91SGregory Neil Shapiro 	{
255813058a91SGregory Neil Shapiro 	  case O_RDONLY:
255913058a91SGregory Neil Shapiro 		fmode = "r";
256013058a91SGregory Neil Shapiro 		break;
256113058a91SGregory Neil Shapiro 
256213058a91SGregory Neil Shapiro 	  case O_WRONLY:
256313058a91SGregory Neil Shapiro 		if (bitset(O_APPEND, omode))
256413058a91SGregory Neil Shapiro 			fmode = "a";
256513058a91SGregory Neil Shapiro 		else
256613058a91SGregory Neil Shapiro 			fmode = "w";
256713058a91SGregory Neil Shapiro 		break;
256813058a91SGregory Neil Shapiro 
256913058a91SGregory Neil Shapiro 	  case O_RDWR:
257013058a91SGregory Neil Shapiro 		if (bitset(O_TRUNC, omode))
257113058a91SGregory Neil Shapiro 			fmode = "w+";
257213058a91SGregory Neil Shapiro 		else if (bitset(O_APPEND, omode))
257313058a91SGregory Neil Shapiro 			fmode = "a+";
257413058a91SGregory Neil Shapiro 		else
257513058a91SGregory Neil Shapiro 			fmode = "r+";
257613058a91SGregory Neil Shapiro 		break;
257713058a91SGregory Neil Shapiro 
257813058a91SGregory Neil Shapiro 	  default:
257913058a91SGregory Neil Shapiro 		syserr("554 5.3.5 safefopen: unknown omode %o", omode);
258013058a91SGregory Neil Shapiro 		fmode = "x";
258113058a91SGregory Neil Shapiro 	}
258213058a91SGregory Neil Shapiro 	fd = safeopen(fn, omode, cmode, sff);
258313058a91SGregory Neil Shapiro 	if (fd < 0)
258413058a91SGregory Neil Shapiro 	{
258513058a91SGregory Neil Shapiro 		save_errno = errno;
258613058a91SGregory Neil Shapiro 		if (tTd(44, 10))
258713058a91SGregory Neil Shapiro 			dprintf("safefopen: safeopen failed: %s\n",
258813058a91SGregory Neil Shapiro 				errstring(errno));
258913058a91SGregory Neil Shapiro 		errno = save_errno;
259013058a91SGregory Neil Shapiro 		return NULL;
259113058a91SGregory Neil Shapiro 	}
259213058a91SGregory Neil Shapiro 	fp = fdopen(fd, fmode);
259313058a91SGregory Neil Shapiro 	if (fp != NULL)
259413058a91SGregory Neil Shapiro 		return fp;
259513058a91SGregory Neil Shapiro 
259613058a91SGregory Neil Shapiro 	save_errno = errno;
259713058a91SGregory Neil Shapiro 	if (tTd(44, 10))
259813058a91SGregory Neil Shapiro 	{
259913058a91SGregory Neil Shapiro 		dprintf("safefopen: fdopen(%s, %s) failed: omode=%x, sff=%lx, err=%s\n",
260013058a91SGregory Neil Shapiro 			fn, fmode, omode, sff, errstring(errno));
260113058a91SGregory Neil Shapiro 	}
260213058a91SGregory Neil Shapiro 	(void) close(fd);
260313058a91SGregory Neil Shapiro 	errno = save_errno;
260413058a91SGregory Neil Shapiro 	return NULL;
260513058a91SGregory Neil Shapiro }
260613058a91SGregory Neil Shapiro /*
2607c2aa98e2SPeter Wemm **  SM_STRCASECMP -- 8-bit clean version of strcasecmp
2608c2aa98e2SPeter Wemm **
2609c2aa98e2SPeter Wemm **	Thank you, vendors, for making this all necessary.
2610c2aa98e2SPeter Wemm */
2611c2aa98e2SPeter Wemm 
2612c2aa98e2SPeter Wemm /*
2613c2aa98e2SPeter Wemm  * Copyright (c) 1987, 1993
2614c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
2615c2aa98e2SPeter Wemm  *
2616c2aa98e2SPeter Wemm  * Redistribution and use in source and binary forms, with or without
2617c2aa98e2SPeter Wemm  * modification, are permitted provided that the following conditions
2618c2aa98e2SPeter Wemm  * are met:
2619c2aa98e2SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
2620c2aa98e2SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
2621c2aa98e2SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
2622c2aa98e2SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
2623c2aa98e2SPeter Wemm  *    documentation and/or other materials provided with the distribution.
2624c2aa98e2SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
2625c2aa98e2SPeter Wemm  *    must display the following acknowledgement:
2626c2aa98e2SPeter Wemm  *	This product includes software developed by the University of
2627c2aa98e2SPeter Wemm  *	California, Berkeley and its contributors.
2628c2aa98e2SPeter Wemm  * 4. Neither the name of the University nor the names of its contributors
2629c2aa98e2SPeter Wemm  *    may be used to endorse or promote products derived from this software
2630c2aa98e2SPeter Wemm  *    without specific prior written permission.
2631c2aa98e2SPeter Wemm  *
2632c2aa98e2SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2633c2aa98e2SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2634c2aa98e2SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2635c2aa98e2SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2636c2aa98e2SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2637c2aa98e2SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2638c2aa98e2SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2639c2aa98e2SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2640c2aa98e2SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2641c2aa98e2SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2642c2aa98e2SPeter Wemm  * SUCH DAMAGE.
2643c2aa98e2SPeter Wemm  */
2644c2aa98e2SPeter Wemm 
2645c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint)
2646c2aa98e2SPeter Wemm static char sccsid[] = "@(#)strcasecmp.c	8.1 (Berkeley) 6/4/93";
264706f25ae9SGregory Neil Shapiro #endif /* defined(LIBC_SCCS) && !defined(lint) */
2648c2aa98e2SPeter Wemm 
2649c2aa98e2SPeter Wemm /*
2650c2aa98e2SPeter Wemm  * This array is designed for mapping upper and lower case letter
2651c2aa98e2SPeter Wemm  * together for a case independent comparison.  The mappings are
2652c2aa98e2SPeter Wemm  * based upon ascii character sequences.
2653c2aa98e2SPeter Wemm  */
2654c2aa98e2SPeter Wemm static const u_char charmap[] = {
2655c2aa98e2SPeter Wemm 	0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
2656c2aa98e2SPeter Wemm 	0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
2657c2aa98e2SPeter Wemm 	0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
2658c2aa98e2SPeter Wemm 	0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
2659c2aa98e2SPeter Wemm 	0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
2660c2aa98e2SPeter Wemm 	0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
2661c2aa98e2SPeter Wemm 	0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
2662c2aa98e2SPeter Wemm 	0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
2663c2aa98e2SPeter Wemm 	0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
2664c2aa98e2SPeter Wemm 	0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
2665c2aa98e2SPeter Wemm 	0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
2666c2aa98e2SPeter Wemm 	0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
2667c2aa98e2SPeter Wemm 	0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
2668c2aa98e2SPeter Wemm 	0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
2669c2aa98e2SPeter Wemm 	0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
2670c2aa98e2SPeter Wemm 	0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
2671c2aa98e2SPeter Wemm 	0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
2672c2aa98e2SPeter Wemm 	0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
2673c2aa98e2SPeter Wemm 	0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
2674c2aa98e2SPeter Wemm 	0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
2675c2aa98e2SPeter Wemm 	0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
2676c2aa98e2SPeter Wemm 	0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
2677c2aa98e2SPeter Wemm 	0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
2678c2aa98e2SPeter Wemm 	0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
2679c2aa98e2SPeter Wemm 	0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
2680c2aa98e2SPeter Wemm 	0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
2681c2aa98e2SPeter Wemm 	0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
2682c2aa98e2SPeter Wemm 	0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
2683c2aa98e2SPeter Wemm 	0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
2684c2aa98e2SPeter Wemm 	0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
2685c2aa98e2SPeter Wemm 	0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
2686c2aa98e2SPeter Wemm 	0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
2687c2aa98e2SPeter Wemm };
2688c2aa98e2SPeter Wemm 
2689c2aa98e2SPeter Wemm int
2690c2aa98e2SPeter Wemm sm_strcasecmp(s1, s2)
2691c2aa98e2SPeter Wemm 	const char *s1, *s2;
2692c2aa98e2SPeter Wemm {
2693c2aa98e2SPeter Wemm 	register const u_char *cm = charmap,
2694c2aa98e2SPeter Wemm 			*us1 = (const u_char *)s1,
2695c2aa98e2SPeter Wemm 			*us2 = (const u_char *)s2;
2696c2aa98e2SPeter Wemm 
2697c2aa98e2SPeter Wemm 	while (cm[*us1] == cm[*us2++])
2698c2aa98e2SPeter Wemm 		if (*us1++ == '\0')
269906f25ae9SGregory Neil Shapiro 			return 0;
2700c2aa98e2SPeter Wemm 	return (cm[*us1] - cm[*--us2]);
2701c2aa98e2SPeter Wemm }
2702c2aa98e2SPeter Wemm 
2703c2aa98e2SPeter Wemm int
2704c2aa98e2SPeter Wemm sm_strncasecmp(s1, s2, n)
2705c2aa98e2SPeter Wemm 	const char *s1, *s2;
2706c2aa98e2SPeter Wemm 	register size_t n;
2707c2aa98e2SPeter Wemm {
2708c2aa98e2SPeter Wemm 	if (n != 0) {
2709c2aa98e2SPeter Wemm 		register const u_char *cm = charmap,
2710c2aa98e2SPeter Wemm 				*us1 = (const u_char *)s1,
2711c2aa98e2SPeter Wemm 				*us2 = (const u_char *)s2;
2712c2aa98e2SPeter Wemm 
2713c2aa98e2SPeter Wemm 		do {
2714c2aa98e2SPeter Wemm 			if (cm[*us1] != cm[*us2++])
2715c2aa98e2SPeter Wemm 				return (cm[*us1] - cm[*--us2]);
2716c2aa98e2SPeter Wemm 			if (*us1++ == '\0')
2717c2aa98e2SPeter Wemm 				break;
2718c2aa98e2SPeter Wemm 		} while (--n != 0);
2719c2aa98e2SPeter Wemm 	}
272006f25ae9SGregory Neil Shapiro 	return 0;
2721c2aa98e2SPeter Wemm }
2722