xref: /freebsd/contrib/sendmail/src/util.c (revision 06f25ae9f1d6020a600a10f713046203d1a82570)
1c2aa98e2SPeter Wemm /*
206f25ae9SGregory Neil Shapiro  * Copyright (c) 1998-2000 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
1506f25ae9SGregory Neil Shapiro static char id[] = "@(#)$Id: util.c,v 8.225.2.1.2.8 2000/07/03 18:28:56 geir 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 	*/
212065a643dSPeter Wemm 	slen = strlen(string);
213065a643dSPeter Wemm 	if (length == 0 || slen < length)
214065a643dSPeter Wemm 		length = slen;
215065a643dSPeter Wemm 
216065a643dSPeter Wemm 	while (*ptr != '\0')
217065a643dSPeter Wemm 	{
218065a643dSPeter Wemm 		if (backslash)
219065a643dSPeter Wemm 		{
220065a643dSPeter Wemm 			backslash = FALSE;
221065a643dSPeter Wemm 			goto increment;
222065a643dSPeter Wemm 		}
223065a643dSPeter Wemm 
224065a643dSPeter Wemm 		if (*ptr == '\\')
225065a643dSPeter Wemm 			backslash = TRUE;
226065a643dSPeter Wemm 		else if (*ptr == '(')
227065a643dSPeter Wemm 		{
228065a643dSPeter Wemm 			if (!quoted)
229065a643dSPeter Wemm 				parencount++;
230065a643dSPeter Wemm 		}
231065a643dSPeter Wemm 		else if (*ptr == ')')
232065a643dSPeter Wemm 		{
233065a643dSPeter Wemm 			if (--parencount < 0)
234065a643dSPeter Wemm 				parencount = 0;
235065a643dSPeter Wemm 		}
236065a643dSPeter Wemm 
237065a643dSPeter Wemm 		/* Inside a comment, quotes don't matter */
238065a643dSPeter Wemm 		if (parencount <= 0 && *ptr == '"')
239065a643dSPeter Wemm 			quoted = !quoted;
240065a643dSPeter Wemm 
241065a643dSPeter Wemm increment:
242065a643dSPeter Wemm 		/* Check for sufficient space for next character */
24306f25ae9SGregory Neil Shapiro 		if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) +
244065a643dSPeter Wemm 						parencount +
245065a643dSPeter Wemm 						(quoted ? 1 : 0)))
246065a643dSPeter Wemm 		{
247065a643dSPeter Wemm 			/* Not enough, backtrack */
248065a643dSPeter Wemm 			if (*ptr == '\\')
249065a643dSPeter Wemm 				backslash = FALSE;
250065a643dSPeter Wemm 			else if (*ptr == '(' && !quoted)
251065a643dSPeter Wemm 				parencount--;
252065a643dSPeter Wemm 			else if (*ptr == '"' && parencount == 0)
253065a643dSPeter Wemm 				quoted = FALSE;
254065a643dSPeter Wemm 			break;
255065a643dSPeter Wemm 		}
256065a643dSPeter Wemm 		ptr++;
257065a643dSPeter Wemm 	}
258065a643dSPeter Wemm 
259065a643dSPeter Wemm 	/* Rebalance */
260065a643dSPeter Wemm 	while (parencount-- > 0)
261065a643dSPeter Wemm 	{
262065a643dSPeter Wemm 		if (*ptr != ')')
263065a643dSPeter Wemm 		{
264065a643dSPeter Wemm 			modified = TRUE;
265065a643dSPeter Wemm 			*ptr = ')';
266065a643dSPeter Wemm 		}
267065a643dSPeter Wemm 		ptr++;
268065a643dSPeter Wemm 	}
269065a643dSPeter Wemm 	if (quoted)
270065a643dSPeter Wemm 	{
271065a643dSPeter Wemm 		if (*ptr != '"')
272065a643dSPeter Wemm 		{
273065a643dSPeter Wemm 			modified = TRUE;
274065a643dSPeter Wemm 			*ptr = '"';
275065a643dSPeter Wemm 		}
276065a643dSPeter Wemm 		ptr++;
277065a643dSPeter Wemm 	}
278065a643dSPeter Wemm 	if (*ptr != '\0')
279065a643dSPeter Wemm 	{
280065a643dSPeter Wemm 		modified = TRUE;
281065a643dSPeter Wemm 		*ptr = '\0';
282065a643dSPeter Wemm 	}
283065a643dSPeter Wemm 	return modified;
284065a643dSPeter Wemm }
285065a643dSPeter Wemm /*
286065a643dSPeter Wemm **  FIND_CHARACTER -- find an unquoted character in an RFC822 string
287065a643dSPeter Wemm **
288065a643dSPeter Wemm **	Find an unquoted, non-commented character in an RFC822
289065a643dSPeter Wemm **	string and return a pointer to its location in the
290065a643dSPeter Wemm **	string.
291065a643dSPeter Wemm **
292065a643dSPeter Wemm **	Parameters:
293065a643dSPeter Wemm **		string -- the string to search
294065a643dSPeter Wemm **		character -- the character to find
295065a643dSPeter Wemm **
296065a643dSPeter Wemm **	Returns:
297065a643dSPeter Wemm **		pointer to the character, or
298065a643dSPeter Wemm **		a pointer to the end of the line if character is not found
299065a643dSPeter Wemm */
300065a643dSPeter Wemm 
301065a643dSPeter Wemm char *
302065a643dSPeter Wemm find_character(string, character)
303065a643dSPeter Wemm 	char *string;
30406f25ae9SGregory Neil Shapiro 	int character;
305065a643dSPeter Wemm {
306065a643dSPeter Wemm 	bool backslash = FALSE;
307065a643dSPeter Wemm 	bool quoted = FALSE;
308065a643dSPeter Wemm 	int parencount = 0;
309065a643dSPeter Wemm 
310065a643dSPeter Wemm 	while (string != NULL && *string != '\0')
311065a643dSPeter Wemm 	{
312065a643dSPeter Wemm 		if (backslash)
313065a643dSPeter Wemm 		{
314065a643dSPeter Wemm 			backslash = FALSE;
315065a643dSPeter Wemm 			if (!quoted && character == '\\' && *string == '\\')
316065a643dSPeter Wemm 				break;
317065a643dSPeter Wemm 			string++;
318065a643dSPeter Wemm 			continue;
319065a643dSPeter Wemm 		}
320065a643dSPeter Wemm 		switch (*string)
321065a643dSPeter Wemm 		{
322065a643dSPeter Wemm 		  case '\\':
323065a643dSPeter Wemm 			backslash = TRUE;
324065a643dSPeter Wemm 			break;
325065a643dSPeter Wemm 
326065a643dSPeter Wemm 		  case '(':
327065a643dSPeter Wemm 			if (!quoted)
328065a643dSPeter Wemm 				parencount++;
329065a643dSPeter Wemm 			break;
330065a643dSPeter Wemm 
331065a643dSPeter Wemm 		  case ')':
332065a643dSPeter Wemm 			if (--parencount < 0)
333065a643dSPeter Wemm 				parencount = 0;
334065a643dSPeter Wemm 			break;
335065a643dSPeter Wemm 		}
336065a643dSPeter Wemm 
337065a643dSPeter Wemm 		/* Inside a comment, nothing matters */
338065a643dSPeter Wemm 		if (parencount > 0)
339065a643dSPeter Wemm 		{
340065a643dSPeter Wemm 			string++;
341065a643dSPeter Wemm 			continue;
342065a643dSPeter Wemm 		}
343065a643dSPeter Wemm 
344065a643dSPeter Wemm 		if (*string == '"')
345065a643dSPeter Wemm 			quoted = !quoted;
346065a643dSPeter Wemm 		else if (*string == character && !quoted)
347065a643dSPeter Wemm 			break;
348065a643dSPeter Wemm 		string++;
349065a643dSPeter Wemm 	}
350065a643dSPeter Wemm 
351065a643dSPeter Wemm 	/* Return pointer to the character */
352065a643dSPeter Wemm 	return string;
353065a643dSPeter Wemm }
354065a643dSPeter Wemm /*
355c2aa98e2SPeter Wemm **  XALLOC -- Allocate memory and bitch wildly on failure.
356c2aa98e2SPeter Wemm **
357c2aa98e2SPeter Wemm **	THIS IS A CLUDGE.  This should be made to give a proper
358c2aa98e2SPeter Wemm **	error -- but after all, what can we do?
359c2aa98e2SPeter Wemm **
360c2aa98e2SPeter Wemm **	Parameters:
361c2aa98e2SPeter Wemm **		sz -- size of area to allocate.
362c2aa98e2SPeter Wemm **
363c2aa98e2SPeter Wemm **	Returns:
364c2aa98e2SPeter Wemm **		pointer to data region.
365c2aa98e2SPeter Wemm **
366c2aa98e2SPeter Wemm **	Side Effects:
367c2aa98e2SPeter Wemm **		Memory is allocated.
368c2aa98e2SPeter Wemm */
369c2aa98e2SPeter Wemm 
370c2aa98e2SPeter Wemm char *
371c2aa98e2SPeter Wemm xalloc(sz)
372c2aa98e2SPeter Wemm 	register int sz;
373c2aa98e2SPeter Wemm {
374c2aa98e2SPeter Wemm 	register char *p;
375c2aa98e2SPeter Wemm 
376c2aa98e2SPeter Wemm 	/* some systems can't handle size zero mallocs */
377c2aa98e2SPeter Wemm 	if (sz <= 0)
378c2aa98e2SPeter Wemm 		sz = 1;
379c2aa98e2SPeter Wemm 
380c2aa98e2SPeter Wemm 	p = malloc((unsigned) sz);
381c2aa98e2SPeter Wemm 	if (p == NULL)
382c2aa98e2SPeter Wemm 	{
383c2aa98e2SPeter Wemm 		syserr("!Out of memory!!");
384c2aa98e2SPeter Wemm 		/* exit(EX_UNAVAILABLE); */
385c2aa98e2SPeter Wemm 	}
38606f25ae9SGregory Neil Shapiro 	return p;
387c2aa98e2SPeter Wemm }
388c2aa98e2SPeter Wemm /*
389c2aa98e2SPeter Wemm **  COPYPLIST -- copy list of pointers.
390c2aa98e2SPeter Wemm **
391c2aa98e2SPeter Wemm **	This routine is the equivalent of newstr for lists of
392c2aa98e2SPeter Wemm **	pointers.
393c2aa98e2SPeter Wemm **
394c2aa98e2SPeter Wemm **	Parameters:
395c2aa98e2SPeter Wemm **		list -- list of pointers to copy.
396c2aa98e2SPeter Wemm **			Must be NULL terminated.
397c2aa98e2SPeter Wemm **		copycont -- if TRUE, copy the contents of the vector
398c2aa98e2SPeter Wemm **			(which must be a string) also.
399c2aa98e2SPeter Wemm **
400c2aa98e2SPeter Wemm **	Returns:
401c2aa98e2SPeter Wemm **		a copy of 'list'.
402c2aa98e2SPeter Wemm **
403c2aa98e2SPeter Wemm **	Side Effects:
404c2aa98e2SPeter Wemm **		none.
405c2aa98e2SPeter Wemm */
406c2aa98e2SPeter Wemm 
407c2aa98e2SPeter Wemm char **
408c2aa98e2SPeter Wemm copyplist(list, copycont)
409c2aa98e2SPeter Wemm 	char **list;
410c2aa98e2SPeter Wemm 	bool copycont;
411c2aa98e2SPeter Wemm {
412c2aa98e2SPeter Wemm 	register char **vp;
413c2aa98e2SPeter Wemm 	register char **newvp;
414c2aa98e2SPeter Wemm 
415c2aa98e2SPeter Wemm 	for (vp = list; *vp != NULL; vp++)
416c2aa98e2SPeter Wemm 		continue;
417c2aa98e2SPeter Wemm 
418c2aa98e2SPeter Wemm 	vp++;
419c2aa98e2SPeter Wemm 
420c2aa98e2SPeter Wemm 	newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
42106f25ae9SGregory Neil Shapiro 	memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp);
422c2aa98e2SPeter Wemm 
423c2aa98e2SPeter Wemm 	if (copycont)
424c2aa98e2SPeter Wemm 	{
425c2aa98e2SPeter Wemm 		for (vp = newvp; *vp != NULL; vp++)
426c2aa98e2SPeter Wemm 			*vp = newstr(*vp);
427c2aa98e2SPeter Wemm 	}
428c2aa98e2SPeter Wemm 
42906f25ae9SGregory Neil Shapiro 	return newvp;
430c2aa98e2SPeter Wemm }
431c2aa98e2SPeter Wemm /*
432c2aa98e2SPeter Wemm **  COPYQUEUE -- copy address queue.
433c2aa98e2SPeter Wemm **
434c2aa98e2SPeter Wemm **	This routine is the equivalent of newstr for address queues
43506f25ae9SGregory Neil Shapiro **	addresses marked as QS_IS_DEAD() aren't copied
436c2aa98e2SPeter Wemm **
437c2aa98e2SPeter Wemm **	Parameters:
438c2aa98e2SPeter Wemm **		addr -- list of address structures to copy.
439c2aa98e2SPeter Wemm **
440c2aa98e2SPeter Wemm **	Returns:
441c2aa98e2SPeter Wemm **		a copy of 'addr'.
442c2aa98e2SPeter Wemm **
443c2aa98e2SPeter Wemm **	Side Effects:
444c2aa98e2SPeter Wemm **		none.
445c2aa98e2SPeter Wemm */
446c2aa98e2SPeter Wemm 
447c2aa98e2SPeter Wemm ADDRESS *
448c2aa98e2SPeter Wemm copyqueue(addr)
449c2aa98e2SPeter Wemm 	ADDRESS *addr;
450c2aa98e2SPeter Wemm {
451c2aa98e2SPeter Wemm 	register ADDRESS *newaddr;
452c2aa98e2SPeter Wemm 	ADDRESS *ret;
453c2aa98e2SPeter Wemm 	register ADDRESS **tail = &ret;
454c2aa98e2SPeter Wemm 
455c2aa98e2SPeter Wemm 	while (addr != NULL)
456c2aa98e2SPeter Wemm 	{
45706f25ae9SGregory Neil Shapiro 		if (!QS_IS_DEAD(addr->q_state))
458c2aa98e2SPeter Wemm 		{
45906f25ae9SGregory Neil Shapiro 			newaddr = (ADDRESS *) xalloc(sizeof *newaddr);
460c2aa98e2SPeter Wemm 			STRUCTCOPY(*addr, *newaddr);
461c2aa98e2SPeter Wemm 			*tail = newaddr;
462c2aa98e2SPeter Wemm 			tail = &newaddr->q_next;
463c2aa98e2SPeter Wemm 		}
464c2aa98e2SPeter Wemm 		addr = addr->q_next;
465c2aa98e2SPeter Wemm 	}
466c2aa98e2SPeter Wemm 	*tail = NULL;
467c2aa98e2SPeter Wemm 
468c2aa98e2SPeter Wemm 	return ret;
469c2aa98e2SPeter Wemm }
470c2aa98e2SPeter Wemm /*
47106f25ae9SGregory Neil Shapiro **  LOG_SENDMAIL_PID -- record sendmail pid and command line.
47206f25ae9SGregory Neil Shapiro **
47306f25ae9SGregory Neil Shapiro **	Parameters:
47406f25ae9SGregory Neil Shapiro **		e -- the current envelope.
47506f25ae9SGregory Neil Shapiro **
47606f25ae9SGregory Neil Shapiro **	Returns:
47706f25ae9SGregory Neil Shapiro **		none.
47806f25ae9SGregory Neil Shapiro **
47906f25ae9SGregory Neil Shapiro **	Side Effects:
48006f25ae9SGregory Neil Shapiro **		writes pidfile.
48106f25ae9SGregory Neil Shapiro */
48206f25ae9SGregory Neil Shapiro 
48306f25ae9SGregory Neil Shapiro void
48406f25ae9SGregory Neil Shapiro log_sendmail_pid(e)
48506f25ae9SGregory Neil Shapiro 	ENVELOPE *e;
48606f25ae9SGregory Neil Shapiro {
48706f25ae9SGregory Neil Shapiro 	long sff;
48806f25ae9SGregory Neil Shapiro 	FILE *pidf;
48906f25ae9SGregory Neil Shapiro 	char pidpath[MAXPATHLEN + 1];
49006f25ae9SGregory Neil Shapiro 
49106f25ae9SGregory Neil Shapiro 	/* write the pid to the log file for posterity */
49206f25ae9SGregory Neil Shapiro 	sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
49306f25ae9SGregory Neil Shapiro 	if (TrustedUid != 0 && RealUid == TrustedUid)
49406f25ae9SGregory Neil Shapiro 		sff |= SFF_OPENASROOT;
49506f25ae9SGregory Neil Shapiro 	expand(PidFile, pidpath, sizeof pidpath, e);
49606f25ae9SGregory Neil Shapiro 	pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, 0644, sff);
49706f25ae9SGregory Neil Shapiro 	if (pidf == NULL)
49806f25ae9SGregory Neil Shapiro 	{
49906f25ae9SGregory Neil Shapiro 		sm_syslog(LOG_ERR, NOQID, "unable to write %s", pidpath);
50006f25ae9SGregory Neil Shapiro 	}
50106f25ae9SGregory Neil Shapiro 	else
50206f25ae9SGregory Neil Shapiro 	{
50306f25ae9SGregory Neil Shapiro 		extern char *CommandLineArgs;
50406f25ae9SGregory Neil Shapiro 
50506f25ae9SGregory Neil Shapiro 		/* write the process id on line 1 */
50606f25ae9SGregory Neil Shapiro 		fprintf(pidf, "%ld\n", (long) getpid());
50706f25ae9SGregory Neil Shapiro 
50806f25ae9SGregory Neil Shapiro 		/* line 2 contains all command line flags */
50906f25ae9SGregory Neil Shapiro 		fprintf(pidf, "%s\n", CommandLineArgs);
51006f25ae9SGregory Neil Shapiro 
51106f25ae9SGregory Neil Shapiro 		/* flush and close */
51206f25ae9SGregory Neil Shapiro 		(void) fclose(pidf);
51306f25ae9SGregory Neil Shapiro 	}
51406f25ae9SGregory Neil Shapiro }
51506f25ae9SGregory Neil Shapiro /*
51606f25ae9SGregory Neil Shapiro **  SET_DELIVERY_MODE -- set and record the delivery mode
51706f25ae9SGregory Neil Shapiro **
51806f25ae9SGregory Neil Shapiro **	Parameters:
51906f25ae9SGregory Neil Shapiro **		mode -- delivery mode
52006f25ae9SGregory Neil Shapiro **		e -- the current envelope.
52106f25ae9SGregory Neil Shapiro **
52206f25ae9SGregory Neil Shapiro **	Returns:
52306f25ae9SGregory Neil Shapiro **		none.
52406f25ae9SGregory Neil Shapiro **
52506f25ae9SGregory Neil Shapiro **	Side Effects:
52606f25ae9SGregory Neil Shapiro **		sets $&{deliveryMode} macro
52706f25ae9SGregory Neil Shapiro */
52806f25ae9SGregory Neil Shapiro 
52906f25ae9SGregory Neil Shapiro void
53006f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e)
53106f25ae9SGregory Neil Shapiro 	int mode;
53206f25ae9SGregory Neil Shapiro 	ENVELOPE *e;
53306f25ae9SGregory Neil Shapiro {
53406f25ae9SGregory Neil Shapiro 	char buf[2];
53506f25ae9SGregory Neil Shapiro 
53606f25ae9SGregory Neil Shapiro 	e->e_sendmode = (char)mode;
53706f25ae9SGregory Neil Shapiro 	buf[0] = (char)mode;
53806f25ae9SGregory Neil Shapiro 	buf[1] = '\0';
53906f25ae9SGregory Neil Shapiro 	define(macid("{deliveryMode}", NULL), newstr(buf), e);
54006f25ae9SGregory Neil Shapiro }
54106f25ae9SGregory Neil Shapiro /*
542c2aa98e2SPeter Wemm **  PRINTAV -- print argument vector.
543c2aa98e2SPeter Wemm **
544c2aa98e2SPeter Wemm **	Parameters:
545c2aa98e2SPeter Wemm **		av -- argument vector.
546c2aa98e2SPeter Wemm **
547c2aa98e2SPeter Wemm **	Returns:
548c2aa98e2SPeter Wemm **		none.
549c2aa98e2SPeter Wemm **
550c2aa98e2SPeter Wemm **	Side Effects:
551c2aa98e2SPeter Wemm **		prints av.
552c2aa98e2SPeter Wemm */
553c2aa98e2SPeter Wemm 
554c2aa98e2SPeter Wemm void
555c2aa98e2SPeter Wemm printav(av)
556c2aa98e2SPeter Wemm 	register char **av;
557c2aa98e2SPeter Wemm {
558c2aa98e2SPeter Wemm 	while (*av != NULL)
559c2aa98e2SPeter Wemm 	{
560c2aa98e2SPeter Wemm 		if (tTd(0, 44))
56106f25ae9SGregory Neil Shapiro 			dprintf("\n\t%08lx=", (u_long) *av);
562c2aa98e2SPeter Wemm 		else
563c2aa98e2SPeter Wemm 			(void) putchar(' ');
564c2aa98e2SPeter Wemm 		xputs(*av++);
565c2aa98e2SPeter Wemm 	}
566c2aa98e2SPeter Wemm 	(void) putchar('\n');
567c2aa98e2SPeter Wemm }
568c2aa98e2SPeter Wemm /*
569c2aa98e2SPeter Wemm **  LOWER -- turn letter into lower case.
570c2aa98e2SPeter Wemm **
571c2aa98e2SPeter Wemm **	Parameters:
572c2aa98e2SPeter Wemm **		c -- character to turn into lower case.
573c2aa98e2SPeter Wemm **
574c2aa98e2SPeter Wemm **	Returns:
575c2aa98e2SPeter Wemm **		c, in lower case.
576c2aa98e2SPeter Wemm **
577c2aa98e2SPeter Wemm **	Side Effects:
578c2aa98e2SPeter Wemm **		none.
579c2aa98e2SPeter Wemm */
580c2aa98e2SPeter Wemm 
581c2aa98e2SPeter Wemm char
582c2aa98e2SPeter Wemm lower(c)
58306f25ae9SGregory Neil Shapiro 	register int c;
584c2aa98e2SPeter Wemm {
585c2aa98e2SPeter Wemm 	return ((isascii(c) && isupper(c)) ? tolower(c) : c);
586c2aa98e2SPeter Wemm }
587c2aa98e2SPeter Wemm /*
588c2aa98e2SPeter Wemm **  XPUTS -- put string doing control escapes.
589c2aa98e2SPeter Wemm **
590c2aa98e2SPeter Wemm **	Parameters:
591c2aa98e2SPeter Wemm **		s -- string to put.
592c2aa98e2SPeter Wemm **
593c2aa98e2SPeter Wemm **	Returns:
594c2aa98e2SPeter Wemm **		none.
595c2aa98e2SPeter Wemm **
596c2aa98e2SPeter Wemm **	Side Effects:
597c2aa98e2SPeter Wemm **		output to stdout
598c2aa98e2SPeter Wemm */
599c2aa98e2SPeter Wemm 
600c2aa98e2SPeter Wemm void
601c2aa98e2SPeter Wemm xputs(s)
602c2aa98e2SPeter Wemm 	register const char *s;
603c2aa98e2SPeter Wemm {
604c2aa98e2SPeter Wemm 	register int c;
605c2aa98e2SPeter Wemm 	register struct metamac *mp;
606c2aa98e2SPeter Wemm 	bool shiftout = FALSE;
607c2aa98e2SPeter Wemm 	extern struct metamac MetaMacros[];
608c2aa98e2SPeter Wemm 
609c2aa98e2SPeter Wemm 	if (s == NULL)
610c2aa98e2SPeter Wemm 	{
611c2aa98e2SPeter Wemm 		printf("%s<null>%s", TermEscape.te_rv_on, TermEscape.te_rv_off);
612c2aa98e2SPeter Wemm 		return;
613c2aa98e2SPeter Wemm 	}
614c2aa98e2SPeter Wemm 	while ((c = (*s++ & 0377)) != '\0')
615c2aa98e2SPeter Wemm 	{
616c2aa98e2SPeter Wemm 		if (shiftout)
617c2aa98e2SPeter Wemm 		{
618c2aa98e2SPeter Wemm 			printf("%s", TermEscape.te_rv_off);
619c2aa98e2SPeter Wemm 			shiftout = FALSE;
620c2aa98e2SPeter Wemm 		}
621c2aa98e2SPeter Wemm 		if (!isascii(c))
622c2aa98e2SPeter Wemm 		{
623c2aa98e2SPeter Wemm 			if (c == MATCHREPL)
624c2aa98e2SPeter Wemm 			{
625c2aa98e2SPeter Wemm 				printf("%s$", TermEscape.te_rv_on);
626c2aa98e2SPeter Wemm 				shiftout = TRUE;
627c2aa98e2SPeter Wemm 				if (*s == '\0')
628c2aa98e2SPeter Wemm 					continue;
629c2aa98e2SPeter Wemm 				c = *s++ & 0377;
630c2aa98e2SPeter Wemm 				goto printchar;
631c2aa98e2SPeter Wemm 			}
632c2aa98e2SPeter Wemm 			if (c == MACROEXPAND || c == MACRODEXPAND)
633c2aa98e2SPeter Wemm 			{
634c2aa98e2SPeter Wemm 				printf("%s$", TermEscape.te_rv_on);
635c2aa98e2SPeter Wemm 				if (c == MACRODEXPAND)
63606f25ae9SGregory Neil Shapiro 					(void) putchar('&');
637c2aa98e2SPeter Wemm 				shiftout = TRUE;
638c2aa98e2SPeter Wemm 				if (*s == '\0')
639c2aa98e2SPeter Wemm 					continue;
640c2aa98e2SPeter Wemm 				if (strchr("=~&?", *s) != NULL)
64106f25ae9SGregory Neil Shapiro 					(void) putchar(*s++);
642c2aa98e2SPeter Wemm 				if (bitset(0200, *s))
643c2aa98e2SPeter Wemm 					printf("{%s}", macname(*s++ & 0377));
644c2aa98e2SPeter Wemm 				else
645c2aa98e2SPeter Wemm 					printf("%c", *s++);
646c2aa98e2SPeter Wemm 				continue;
647c2aa98e2SPeter Wemm 			}
648c2aa98e2SPeter Wemm 			for (mp = MetaMacros; mp->metaname != '\0'; mp++)
649c2aa98e2SPeter Wemm 			{
650c2aa98e2SPeter Wemm 				if ((mp->metaval & 0377) == c)
651c2aa98e2SPeter Wemm 				{
652c2aa98e2SPeter Wemm 					printf("%s$%c",
653c2aa98e2SPeter Wemm 						TermEscape.te_rv_on,
654c2aa98e2SPeter Wemm 						mp->metaname);
655c2aa98e2SPeter Wemm 					shiftout = TRUE;
656c2aa98e2SPeter Wemm 					break;
657c2aa98e2SPeter Wemm 				}
658c2aa98e2SPeter Wemm 			}
659c2aa98e2SPeter Wemm 			if (c == MATCHCLASS || c == MATCHNCLASS)
660c2aa98e2SPeter Wemm 			{
661c2aa98e2SPeter Wemm 				if (bitset(0200, *s))
662c2aa98e2SPeter Wemm 					printf("{%s}", macname(*s++ & 0377));
663c2aa98e2SPeter Wemm 				else if (*s != '\0')
664c2aa98e2SPeter Wemm 					printf("%c", *s++);
665c2aa98e2SPeter Wemm 			}
666c2aa98e2SPeter Wemm 			if (mp->metaname != '\0')
667c2aa98e2SPeter Wemm 				continue;
668c2aa98e2SPeter Wemm 
669c2aa98e2SPeter Wemm 			/* unrecognized meta character */
670c2aa98e2SPeter Wemm 			printf("%sM-", TermEscape.te_rv_on);
671c2aa98e2SPeter Wemm 			shiftout = TRUE;
672c2aa98e2SPeter Wemm 			c &= 0177;
673c2aa98e2SPeter Wemm 		}
674c2aa98e2SPeter Wemm   printchar:
675c2aa98e2SPeter Wemm 		if (isprint(c))
676c2aa98e2SPeter Wemm 		{
67706f25ae9SGregory Neil Shapiro 			(void) putchar(c);
678c2aa98e2SPeter Wemm 			continue;
679c2aa98e2SPeter Wemm 		}
680c2aa98e2SPeter Wemm 
681c2aa98e2SPeter Wemm 		/* wasn't a meta-macro -- find another way to print it */
682c2aa98e2SPeter Wemm 		switch (c)
683c2aa98e2SPeter Wemm 		{
684c2aa98e2SPeter Wemm 		  case '\n':
685c2aa98e2SPeter Wemm 			c = 'n';
686c2aa98e2SPeter Wemm 			break;
687c2aa98e2SPeter Wemm 
688c2aa98e2SPeter Wemm 		  case '\r':
689c2aa98e2SPeter Wemm 			c = 'r';
690c2aa98e2SPeter Wemm 			break;
691c2aa98e2SPeter Wemm 
692c2aa98e2SPeter Wemm 		  case '\t':
693c2aa98e2SPeter Wemm 			c = 't';
694c2aa98e2SPeter Wemm 			break;
695c2aa98e2SPeter Wemm 		}
696c2aa98e2SPeter Wemm 		if (!shiftout)
697c2aa98e2SPeter Wemm 		{
698c2aa98e2SPeter Wemm 			printf("%s", TermEscape.te_rv_on);
699c2aa98e2SPeter Wemm 			shiftout = TRUE;
700c2aa98e2SPeter Wemm 		}
701c2aa98e2SPeter Wemm 		if (isprint(c))
702c2aa98e2SPeter Wemm 		{
703c2aa98e2SPeter Wemm 			(void) putchar('\\');
704c2aa98e2SPeter Wemm 			(void) putchar(c);
705c2aa98e2SPeter Wemm 		}
706c2aa98e2SPeter Wemm 		else
707c2aa98e2SPeter Wemm 		{
708c2aa98e2SPeter Wemm 			(void) putchar('^');
709c2aa98e2SPeter Wemm 			(void) putchar(c ^ 0100);
710c2aa98e2SPeter Wemm 		}
711c2aa98e2SPeter Wemm 	}
712c2aa98e2SPeter Wemm 	if (shiftout)
713c2aa98e2SPeter Wemm 		printf("%s", TermEscape.te_rv_off);
714c2aa98e2SPeter Wemm 	(void) fflush(stdout);
715c2aa98e2SPeter Wemm }
716c2aa98e2SPeter Wemm /*
717c2aa98e2SPeter Wemm **  MAKELOWER -- Translate a line into lower case
718c2aa98e2SPeter Wemm **
719c2aa98e2SPeter Wemm **	Parameters:
720c2aa98e2SPeter Wemm **		p -- the string to translate.  If NULL, return is
721c2aa98e2SPeter Wemm **			immediate.
722c2aa98e2SPeter Wemm **
723c2aa98e2SPeter Wemm **	Returns:
724c2aa98e2SPeter Wemm **		none.
725c2aa98e2SPeter Wemm **
726c2aa98e2SPeter Wemm **	Side Effects:
727c2aa98e2SPeter Wemm **		String pointed to by p is translated to lower case.
728c2aa98e2SPeter Wemm */
729c2aa98e2SPeter Wemm 
730c2aa98e2SPeter Wemm void
731c2aa98e2SPeter Wemm makelower(p)
732c2aa98e2SPeter Wemm 	register char *p;
733c2aa98e2SPeter Wemm {
734c2aa98e2SPeter Wemm 	register char c;
735c2aa98e2SPeter Wemm 
736c2aa98e2SPeter Wemm 	if (p == NULL)
737c2aa98e2SPeter Wemm 		return;
738c2aa98e2SPeter Wemm 	for (; (c = *p) != '\0'; p++)
739c2aa98e2SPeter Wemm 		if (isascii(c) && isupper(c))
740c2aa98e2SPeter Wemm 			*p = tolower(c);
741c2aa98e2SPeter Wemm }
742c2aa98e2SPeter Wemm /*
743c2aa98e2SPeter Wemm **  BUILDFNAME -- build full name from gecos style entry.
744c2aa98e2SPeter Wemm **
745c2aa98e2SPeter Wemm **	This routine interprets the strange entry that would appear
746c2aa98e2SPeter Wemm **	in the GECOS field of the password file.
747c2aa98e2SPeter Wemm **
748c2aa98e2SPeter Wemm **	Parameters:
749c2aa98e2SPeter Wemm **		p -- name to build.
75006f25ae9SGregory Neil Shapiro **		user -- the login name of this user (for &).
751c2aa98e2SPeter Wemm **		buf -- place to put the result.
752c2aa98e2SPeter Wemm **		buflen -- length of buf.
753c2aa98e2SPeter Wemm **
754c2aa98e2SPeter Wemm **	Returns:
755c2aa98e2SPeter Wemm **		none.
756c2aa98e2SPeter Wemm **
757c2aa98e2SPeter Wemm **	Side Effects:
758c2aa98e2SPeter Wemm **		none.
759c2aa98e2SPeter Wemm */
760c2aa98e2SPeter Wemm 
761c2aa98e2SPeter Wemm void
76206f25ae9SGregory Neil Shapiro buildfname(gecos, user, buf, buflen)
763c2aa98e2SPeter Wemm 	register char *gecos;
76406f25ae9SGregory Neil Shapiro 	char *user;
765c2aa98e2SPeter Wemm 	char *buf;
766c2aa98e2SPeter Wemm 	int buflen;
767c2aa98e2SPeter Wemm {
768c2aa98e2SPeter Wemm 	register char *p;
769c2aa98e2SPeter Wemm 	register char *bp = buf;
770c2aa98e2SPeter Wemm 
771c2aa98e2SPeter Wemm 	if (*gecos == '*')
772c2aa98e2SPeter Wemm 		gecos++;
773c2aa98e2SPeter Wemm 
774c2aa98e2SPeter Wemm 	/* copy gecos, interpolating & to be full name */
775c2aa98e2SPeter Wemm 	for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
776c2aa98e2SPeter Wemm 	{
777c2aa98e2SPeter Wemm 		if (bp >= &buf[buflen - 1])
778c2aa98e2SPeter Wemm 		{
779c2aa98e2SPeter Wemm 			/* buffer overflow -- just use login name */
78006f25ae9SGregory Neil Shapiro 			snprintf(buf, buflen, "%s", user);
781c2aa98e2SPeter Wemm 			return;
782c2aa98e2SPeter Wemm 		}
783c2aa98e2SPeter Wemm 		if (*p == '&')
784c2aa98e2SPeter Wemm 		{
785c2aa98e2SPeter Wemm 			/* interpolate full name */
78606f25ae9SGregory Neil Shapiro 			snprintf(bp, buflen - (bp - buf), "%s", user);
787c2aa98e2SPeter Wemm 			*bp = toupper(*bp);
788c2aa98e2SPeter Wemm 			bp += strlen(bp);
789c2aa98e2SPeter Wemm 		}
790c2aa98e2SPeter Wemm 		else
791c2aa98e2SPeter Wemm 			*bp++ = *p;
792c2aa98e2SPeter Wemm 	}
793c2aa98e2SPeter Wemm 	*bp = '\0';
794c2aa98e2SPeter Wemm }
795c2aa98e2SPeter Wemm /*
796c2aa98e2SPeter Wemm **  FIXCRLF -- fix <CR><LF> in line.
797c2aa98e2SPeter Wemm **
798c2aa98e2SPeter Wemm **	Looks for the <CR><LF> combination and turns it into the
799c2aa98e2SPeter Wemm **	UNIX canonical <NL> character.  It only takes one line,
800c2aa98e2SPeter Wemm **	i.e., it is assumed that the first <NL> found is the end
801c2aa98e2SPeter Wemm **	of the line.
802c2aa98e2SPeter Wemm **
803c2aa98e2SPeter Wemm **	Parameters:
804c2aa98e2SPeter Wemm **		line -- the line to fix.
805c2aa98e2SPeter Wemm **		stripnl -- if true, strip the newline also.
806c2aa98e2SPeter Wemm **
807c2aa98e2SPeter Wemm **	Returns:
808c2aa98e2SPeter Wemm **		none.
809c2aa98e2SPeter Wemm **
810c2aa98e2SPeter Wemm **	Side Effects:
811c2aa98e2SPeter Wemm **		line is changed in place.
812c2aa98e2SPeter Wemm */
813c2aa98e2SPeter Wemm 
814c2aa98e2SPeter Wemm void
815c2aa98e2SPeter Wemm fixcrlf(line, stripnl)
816c2aa98e2SPeter Wemm 	char *line;
817c2aa98e2SPeter Wemm 	bool stripnl;
818c2aa98e2SPeter Wemm {
819c2aa98e2SPeter Wemm 	register char *p;
820c2aa98e2SPeter Wemm 
821c2aa98e2SPeter Wemm 	p = strchr(line, '\n');
822c2aa98e2SPeter Wemm 	if (p == NULL)
823c2aa98e2SPeter Wemm 		return;
824c2aa98e2SPeter Wemm 	if (p > line && p[-1] == '\r')
825c2aa98e2SPeter Wemm 		p--;
826c2aa98e2SPeter Wemm 	if (!stripnl)
827c2aa98e2SPeter Wemm 		*p++ = '\n';
828c2aa98e2SPeter Wemm 	*p = '\0';
829c2aa98e2SPeter Wemm }
830c2aa98e2SPeter Wemm /*
831c2aa98e2SPeter Wemm **  PUTLINE -- put a line like fputs obeying SMTP conventions
832c2aa98e2SPeter Wemm **
833c2aa98e2SPeter Wemm **	This routine always guarantees outputing a newline (or CRLF,
834c2aa98e2SPeter Wemm **	as appropriate) at the end of the string.
835c2aa98e2SPeter Wemm **
836c2aa98e2SPeter Wemm **	Parameters:
837c2aa98e2SPeter Wemm **		l -- line to put.
838c2aa98e2SPeter Wemm **		mci -- the mailer connection information.
839c2aa98e2SPeter Wemm **
840c2aa98e2SPeter Wemm **	Returns:
841c2aa98e2SPeter Wemm **		none
842c2aa98e2SPeter Wemm **
843c2aa98e2SPeter Wemm **	Side Effects:
844c2aa98e2SPeter Wemm **		output of l to fp.
845c2aa98e2SPeter Wemm */
846c2aa98e2SPeter Wemm 
847c2aa98e2SPeter Wemm void
848c2aa98e2SPeter Wemm putline(l, mci)
849c2aa98e2SPeter Wemm 	register char *l;
850c2aa98e2SPeter Wemm 	register MCI *mci;
851c2aa98e2SPeter Wemm {
852c2aa98e2SPeter Wemm 	putxline(l, strlen(l), mci, PXLF_MAPFROM);
853c2aa98e2SPeter Wemm }
854c2aa98e2SPeter Wemm /*
855c2aa98e2SPeter Wemm **  PUTXLINE -- putline with flags bits.
856c2aa98e2SPeter Wemm **
857c2aa98e2SPeter Wemm **	This routine always guarantees outputing a newline (or CRLF,
858c2aa98e2SPeter Wemm **	as appropriate) at the end of the string.
859c2aa98e2SPeter Wemm **
860c2aa98e2SPeter Wemm **	Parameters:
861c2aa98e2SPeter Wemm **		l -- line to put.
862c2aa98e2SPeter Wemm **		len -- the length of the line.
863c2aa98e2SPeter Wemm **		mci -- the mailer connection information.
864c2aa98e2SPeter Wemm **		pxflags -- flag bits:
865c2aa98e2SPeter Wemm **		    PXLF_MAPFROM -- map From_ to >From_.
866c2aa98e2SPeter Wemm **		    PXLF_STRIP8BIT -- strip 8th bit.
867c2aa98e2SPeter Wemm **		    PXLF_HEADER -- map bare newline in header to newline space.
868c2aa98e2SPeter Wemm **
869c2aa98e2SPeter Wemm **	Returns:
870c2aa98e2SPeter Wemm **		none
871c2aa98e2SPeter Wemm **
872c2aa98e2SPeter Wemm **	Side Effects:
873c2aa98e2SPeter Wemm **		output of l to fp.
874c2aa98e2SPeter Wemm */
875c2aa98e2SPeter Wemm 
876c2aa98e2SPeter Wemm void
877c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags)
878c2aa98e2SPeter Wemm 	register char *l;
879c2aa98e2SPeter Wemm 	size_t len;
880c2aa98e2SPeter Wemm 	register MCI *mci;
881c2aa98e2SPeter Wemm 	int pxflags;
882c2aa98e2SPeter Wemm {
88306f25ae9SGregory Neil Shapiro 	bool dead = FALSE;
884c2aa98e2SPeter Wemm 	register char *p, *end;
885c2aa98e2SPeter Wemm 	int slop = 0;
886c2aa98e2SPeter Wemm 
887c2aa98e2SPeter Wemm 	/* strip out 0200 bits -- these can look like TELNET protocol */
888c2aa98e2SPeter Wemm 	if (bitset(MCIF_7BIT, mci->mci_flags) ||
889c2aa98e2SPeter Wemm 	    bitset(PXLF_STRIP8BIT, pxflags))
890c2aa98e2SPeter Wemm 	{
891c2aa98e2SPeter Wemm 		register char svchar;
892c2aa98e2SPeter Wemm 
893c2aa98e2SPeter Wemm 		for (p = l; (svchar = *p) != '\0'; ++p)
894c2aa98e2SPeter Wemm 			if (bitset(0200, svchar))
895c2aa98e2SPeter Wemm 				*p = svchar &~ 0200;
896c2aa98e2SPeter Wemm 	}
897c2aa98e2SPeter Wemm 
898c2aa98e2SPeter Wemm 	end = l + len;
899c2aa98e2SPeter Wemm 	do
900c2aa98e2SPeter Wemm 	{
901c2aa98e2SPeter Wemm 		/* find the end of the line */
902c2aa98e2SPeter Wemm 		p = memchr(l, '\n', end - l);
903c2aa98e2SPeter Wemm 		if (p == NULL)
904c2aa98e2SPeter Wemm 			p = end;
905c2aa98e2SPeter Wemm 
906c2aa98e2SPeter Wemm 		if (TrafficLogFile != NULL)
907c2aa98e2SPeter Wemm 			fprintf(TrafficLogFile, "%05d >>> ", (int) getpid());
908c2aa98e2SPeter Wemm 
909c2aa98e2SPeter Wemm 		/* check for line overflow */
910c2aa98e2SPeter Wemm 		while (mci->mci_mailer->m_linelimit > 0 &&
911c2aa98e2SPeter Wemm 		       (p - l + slop) > mci->mci_mailer->m_linelimit)
912c2aa98e2SPeter Wemm 		{
913c2aa98e2SPeter Wemm 			char *l_base = l;
914c2aa98e2SPeter Wemm 			register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1];
915c2aa98e2SPeter Wemm 
916c2aa98e2SPeter Wemm 			if (l[0] == '.' && slop == 0 &&
917c2aa98e2SPeter Wemm 			    bitnset(M_XDOT, mci->mci_mailer->m_flags))
918c2aa98e2SPeter Wemm 			{
91906f25ae9SGregory Neil Shapiro 				if (putc('.', mci->mci_out) == EOF)
92006f25ae9SGregory Neil Shapiro 					dead = TRUE;
921c2aa98e2SPeter Wemm 				if (TrafficLogFile != NULL)
922c2aa98e2SPeter Wemm 					(void) putc('.', TrafficLogFile);
923c2aa98e2SPeter Wemm 			}
924c2aa98e2SPeter Wemm 			else if (l[0] == 'F' && slop == 0 &&
925c2aa98e2SPeter Wemm 				 bitset(PXLF_MAPFROM, pxflags) &&
926c2aa98e2SPeter Wemm 				 strncmp(l, "From ", 5) == 0 &&
927c2aa98e2SPeter Wemm 				 bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
928c2aa98e2SPeter Wemm 			{
92906f25ae9SGregory Neil Shapiro 				if (putc('>', mci->mci_out) == EOF)
93006f25ae9SGregory Neil Shapiro 					dead = TRUE;
931c2aa98e2SPeter Wemm 				if (TrafficLogFile != NULL)
932c2aa98e2SPeter Wemm 					(void) putc('>', TrafficLogFile);
933c2aa98e2SPeter Wemm 			}
93406f25ae9SGregory Neil Shapiro 			if (dead)
93506f25ae9SGregory Neil Shapiro 				break;
93606f25ae9SGregory Neil Shapiro 
937c2aa98e2SPeter Wemm 			while (l < q)
938c2aa98e2SPeter Wemm 			{
93906f25ae9SGregory Neil Shapiro 				if (putc((unsigned char) *l++, mci->mci_out) ==
94006f25ae9SGregory Neil Shapiro 				    EOF)
94106f25ae9SGregory Neil Shapiro 				{
94206f25ae9SGregory Neil Shapiro 					dead = TRUE;
94306f25ae9SGregory Neil Shapiro 					break;
944c2aa98e2SPeter Wemm 				}
94506f25ae9SGregory Neil Shapiro 
94606f25ae9SGregory Neil Shapiro 				/* record progress for DATA timeout */
94706f25ae9SGregory Neil Shapiro 				DataProgress = TRUE;
94806f25ae9SGregory Neil Shapiro 			}
94906f25ae9SGregory Neil Shapiro 			if (dead)
95006f25ae9SGregory Neil Shapiro 				break;
95106f25ae9SGregory Neil Shapiro 
95206f25ae9SGregory Neil Shapiro 			if (putc('!', mci->mci_out) == EOF ||
95306f25ae9SGregory Neil Shapiro 			    fputs(mci->mci_mailer->m_eol,
95406f25ae9SGregory Neil Shapiro 				  mci->mci_out) == EOF ||
95506f25ae9SGregory Neil Shapiro 			    putc(' ', mci->mci_out) == EOF)
95606f25ae9SGregory Neil Shapiro 			{
95706f25ae9SGregory Neil Shapiro 				dead = TRUE;
95806f25ae9SGregory Neil Shapiro 				break;
95906f25ae9SGregory Neil Shapiro 			}
96006f25ae9SGregory Neil Shapiro 
96106f25ae9SGregory Neil Shapiro 			/* record progress for DATA timeout */
96206f25ae9SGregory Neil Shapiro 			DataProgress = TRUE;
96306f25ae9SGregory Neil Shapiro 
964c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
965c2aa98e2SPeter Wemm 			{
966c2aa98e2SPeter Wemm 				for (l = l_base; l < q; l++)
96706f25ae9SGregory Neil Shapiro 					(void) putc((unsigned char)*l,
96806f25ae9SGregory Neil Shapiro 						    TrafficLogFile);
969c2aa98e2SPeter Wemm 				fprintf(TrafficLogFile, "!\n%05d >>>  ",
970c2aa98e2SPeter Wemm 					(int) getpid());
971c2aa98e2SPeter Wemm 			}
972c2aa98e2SPeter Wemm 			slop = 1;
973c2aa98e2SPeter Wemm 		}
974c2aa98e2SPeter Wemm 
97506f25ae9SGregory Neil Shapiro 		if (dead)
97606f25ae9SGregory Neil Shapiro 			break;
97706f25ae9SGregory Neil Shapiro 
978c2aa98e2SPeter Wemm 		/* output last part */
979c2aa98e2SPeter Wemm 		if (l[0] == '.' && slop == 0 &&
980c2aa98e2SPeter Wemm 		    bitnset(M_XDOT, mci->mci_mailer->m_flags))
981c2aa98e2SPeter Wemm 		{
98206f25ae9SGregory Neil Shapiro 			if (putc('.', mci->mci_out) == EOF)
98306f25ae9SGregory Neil Shapiro 				break;
984c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
985c2aa98e2SPeter Wemm 				(void) putc('.', TrafficLogFile);
986c2aa98e2SPeter Wemm 		}
987c2aa98e2SPeter Wemm 		else if (l[0] == 'F' && slop == 0 &&
988c2aa98e2SPeter Wemm 			 bitset(PXLF_MAPFROM, pxflags) &&
989c2aa98e2SPeter Wemm 			 strncmp(l, "From ", 5) == 0 &&
990c2aa98e2SPeter Wemm 			 bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
991c2aa98e2SPeter Wemm 		{
99206f25ae9SGregory Neil Shapiro 			if (putc('>', mci->mci_out) == EOF)
99306f25ae9SGregory Neil Shapiro 				break;
994c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
995c2aa98e2SPeter Wemm 				(void) putc('>', TrafficLogFile);
996c2aa98e2SPeter Wemm 		}
997c2aa98e2SPeter Wemm 		for ( ; l < p; ++l)
998c2aa98e2SPeter Wemm 		{
999c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
100006f25ae9SGregory Neil Shapiro 				(void) putc((unsigned char)*l, TrafficLogFile);
100106f25ae9SGregory Neil Shapiro 			if (putc((unsigned char) *l, mci->mci_out) == EOF)
100206f25ae9SGregory Neil Shapiro 			{
100306f25ae9SGregory Neil Shapiro 				dead = TRUE;
100406f25ae9SGregory Neil Shapiro 				break;
1005c2aa98e2SPeter Wemm 			}
100606f25ae9SGregory Neil Shapiro 
100706f25ae9SGregory Neil Shapiro 			/* record progress for DATA timeout */
100806f25ae9SGregory Neil Shapiro 			DataProgress = TRUE;
100906f25ae9SGregory Neil Shapiro 		}
101006f25ae9SGregory Neil Shapiro 		if (dead)
101106f25ae9SGregory Neil Shapiro 			break;
101206f25ae9SGregory Neil Shapiro 
1013c2aa98e2SPeter Wemm 		if (TrafficLogFile != NULL)
1014c2aa98e2SPeter Wemm 			(void) putc('\n', TrafficLogFile);
101506f25ae9SGregory Neil Shapiro 		if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF)
101606f25ae9SGregory Neil Shapiro 			break;
1017c2aa98e2SPeter Wemm 		if (l < end && *l == '\n')
1018c2aa98e2SPeter Wemm 		{
1019c2aa98e2SPeter Wemm 			if (*++l != ' ' && *l != '\t' && *l != '\0' &&
1020c2aa98e2SPeter Wemm 			    bitset(PXLF_HEADER, pxflags))
1021c2aa98e2SPeter Wemm 			{
102206f25ae9SGregory Neil Shapiro 				if (putc(' ', mci->mci_out) == EOF)
102306f25ae9SGregory Neil Shapiro 					break;
1024c2aa98e2SPeter Wemm 				if (TrafficLogFile != NULL)
1025c2aa98e2SPeter Wemm 					(void) putc(' ', TrafficLogFile);
1026c2aa98e2SPeter Wemm 			}
1027c2aa98e2SPeter Wemm 		}
102806f25ae9SGregory Neil Shapiro 
102906f25ae9SGregory Neil Shapiro 		/* record progress for DATA timeout */
103006f25ae9SGregory Neil Shapiro 		DataProgress = TRUE;
1031c2aa98e2SPeter Wemm 	} while (l < end);
1032c2aa98e2SPeter Wemm }
1033c2aa98e2SPeter Wemm /*
1034c2aa98e2SPeter Wemm **  XUNLINK -- unlink a file, doing logging as appropriate.
1035c2aa98e2SPeter Wemm **
1036c2aa98e2SPeter Wemm **	Parameters:
1037c2aa98e2SPeter Wemm **		f -- name of file to unlink.
1038c2aa98e2SPeter Wemm **
1039c2aa98e2SPeter Wemm **	Returns:
1040c2aa98e2SPeter Wemm **		none.
1041c2aa98e2SPeter Wemm **
1042c2aa98e2SPeter Wemm **	Side Effects:
1043c2aa98e2SPeter Wemm **		f is unlinked.
1044c2aa98e2SPeter Wemm */
1045c2aa98e2SPeter Wemm 
1046c2aa98e2SPeter Wemm void
1047c2aa98e2SPeter Wemm xunlink(f)
1048c2aa98e2SPeter Wemm 	char *f;
1049c2aa98e2SPeter Wemm {
1050c2aa98e2SPeter Wemm 	register int i;
1051c2aa98e2SPeter Wemm 
1052c2aa98e2SPeter Wemm 	if (LogLevel > 98)
1053c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, CurEnv->e_id,
1054c2aa98e2SPeter Wemm 			  "unlink %s",
1055c2aa98e2SPeter Wemm 			  f);
1056c2aa98e2SPeter Wemm 
1057c2aa98e2SPeter Wemm 	i = unlink(f);
1058c2aa98e2SPeter Wemm 	if (i < 0 && LogLevel > 97)
1059c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, CurEnv->e_id,
1060c2aa98e2SPeter Wemm 			  "%s: unlink-fail %d",
1061c2aa98e2SPeter Wemm 			  f, errno);
1062c2aa98e2SPeter Wemm }
1063c2aa98e2SPeter Wemm /*
1064c2aa98e2SPeter Wemm **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
1065c2aa98e2SPeter Wemm **
1066c2aa98e2SPeter Wemm **	Parameters:
1067c2aa98e2SPeter Wemm **		buf -- place to put the input line.
1068c2aa98e2SPeter Wemm **		siz -- size of buf.
1069c2aa98e2SPeter Wemm **		fp -- file to read from.
1070c2aa98e2SPeter Wemm **		timeout -- the timeout before error occurs.
1071c2aa98e2SPeter Wemm **		during -- what we are trying to read (for error messages).
1072c2aa98e2SPeter Wemm **
1073c2aa98e2SPeter Wemm **	Returns:
1074c2aa98e2SPeter Wemm **		NULL on error (including timeout).  This will also leave
1075c2aa98e2SPeter Wemm **			buf containing a null string.
1076c2aa98e2SPeter Wemm **		buf otherwise.
1077c2aa98e2SPeter Wemm **
1078c2aa98e2SPeter Wemm **	Side Effects:
1079c2aa98e2SPeter Wemm **		none.
1080c2aa98e2SPeter Wemm */
1081c2aa98e2SPeter Wemm 
108206f25ae9SGregory Neil Shapiro 
1083c2aa98e2SPeter Wemm static jmp_buf	CtxReadTimeout;
1084c2aa98e2SPeter Wemm 
1085c2aa98e2SPeter Wemm char *
1086c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during)
1087c2aa98e2SPeter Wemm 	char *buf;
1088c2aa98e2SPeter Wemm 	int siz;
1089c2aa98e2SPeter Wemm 	FILE *fp;
1090c2aa98e2SPeter Wemm 	time_t timeout;
1091c2aa98e2SPeter Wemm 	char *during;
1092c2aa98e2SPeter Wemm {
1093c2aa98e2SPeter Wemm 	register EVENT *ev = NULL;
1094c2aa98e2SPeter Wemm 	register char *p;
10952e43090eSPeter Wemm 	int save_errno;
1096c2aa98e2SPeter Wemm 
1097c2aa98e2SPeter Wemm 	if (fp == NULL)
1098c2aa98e2SPeter Wemm 	{
1099c2aa98e2SPeter Wemm 		buf[0] = '\0';
1100c2aa98e2SPeter Wemm 		return NULL;
1101c2aa98e2SPeter Wemm 	}
1102c2aa98e2SPeter Wemm 
1103c2aa98e2SPeter Wemm 	/* set the timeout */
1104c2aa98e2SPeter Wemm 	if (timeout != 0)
1105c2aa98e2SPeter Wemm 	{
1106c2aa98e2SPeter Wemm 		if (setjmp(CtxReadTimeout) != 0)
1107c2aa98e2SPeter Wemm 		{
1108c2aa98e2SPeter Wemm 			if (LogLevel > 1)
1109c2aa98e2SPeter Wemm 				sm_syslog(LOG_NOTICE, CurEnv->e_id,
1110c2aa98e2SPeter Wemm 					  "timeout waiting for input from %.100s during %s",
1111c2aa98e2SPeter Wemm 					  CurHostName ? CurHostName : "local",
1112c2aa98e2SPeter Wemm 					  during);
1113c2aa98e2SPeter Wemm 			buf[0] = '\0';
1114c2aa98e2SPeter Wemm #if XDEBUG
1115c2aa98e2SPeter Wemm 			checkfd012(during);
111606f25ae9SGregory Neil Shapiro #endif /* XDEBUG */
1117c2aa98e2SPeter Wemm 			if (TrafficLogFile != NULL)
1118c2aa98e2SPeter Wemm 				fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n",
1119c2aa98e2SPeter Wemm 					(int) getpid());
11202e43090eSPeter Wemm 			errno = 0;
112106f25ae9SGregory Neil Shapiro 			return NULL;
1122c2aa98e2SPeter Wemm 		}
1123c2aa98e2SPeter Wemm 		ev = setevent(timeout, readtimeout, 0);
1124c2aa98e2SPeter Wemm 	}
1125c2aa98e2SPeter Wemm 
1126c2aa98e2SPeter Wemm 	/* try to read */
1127c2aa98e2SPeter Wemm 	p = NULL;
11282e43090eSPeter Wemm 	errno = 0;
1129c2aa98e2SPeter Wemm 	while (!feof(fp) && !ferror(fp))
1130c2aa98e2SPeter Wemm 	{
1131c2aa98e2SPeter Wemm 		errno = 0;
1132c2aa98e2SPeter Wemm 		p = fgets(buf, siz, fp);
1133c2aa98e2SPeter Wemm 		if (p != NULL || errno != EINTR)
1134c2aa98e2SPeter Wemm 			break;
1135c2aa98e2SPeter Wemm 		clearerr(fp);
1136c2aa98e2SPeter Wemm 	}
11372e43090eSPeter Wemm 	save_errno = errno;
1138c2aa98e2SPeter Wemm 
1139c2aa98e2SPeter Wemm 	/* clear the event if it has not sprung */
1140c2aa98e2SPeter Wemm 	clrevent(ev);
1141c2aa98e2SPeter Wemm 
1142c2aa98e2SPeter Wemm 	/* clean up the books and exit */
1143c2aa98e2SPeter Wemm 	LineNumber++;
1144c2aa98e2SPeter Wemm 	if (p == NULL)
1145c2aa98e2SPeter Wemm 	{
1146c2aa98e2SPeter Wemm 		buf[0] = '\0';
1147c2aa98e2SPeter Wemm 		if (TrafficLogFile != NULL)
1148c2aa98e2SPeter Wemm 			fprintf(TrafficLogFile, "%05d <<< [EOF]\n", (int) getpid());
11492e43090eSPeter Wemm 		errno = save_errno;
115006f25ae9SGregory Neil Shapiro 		return NULL;
1151c2aa98e2SPeter Wemm 	}
1152c2aa98e2SPeter Wemm 	if (TrafficLogFile != NULL)
1153c2aa98e2SPeter Wemm 		fprintf(TrafficLogFile, "%05d <<< %s", (int) getpid(), buf);
1154c2aa98e2SPeter Wemm 	if (SevenBitInput)
1155c2aa98e2SPeter Wemm 	{
1156c2aa98e2SPeter Wemm 		for (p = buf; *p != '\0'; p++)
1157c2aa98e2SPeter Wemm 			*p &= ~0200;
1158c2aa98e2SPeter Wemm 	}
1159c2aa98e2SPeter Wemm 	else if (!HasEightBits)
1160c2aa98e2SPeter Wemm 	{
1161c2aa98e2SPeter Wemm 		for (p = buf; *p != '\0'; p++)
1162c2aa98e2SPeter Wemm 		{
1163c2aa98e2SPeter Wemm 			if (bitset(0200, *p))
1164c2aa98e2SPeter Wemm 			{
1165c2aa98e2SPeter Wemm 				HasEightBits = TRUE;
1166c2aa98e2SPeter Wemm 				break;
1167c2aa98e2SPeter Wemm 			}
1168c2aa98e2SPeter Wemm 		}
1169c2aa98e2SPeter Wemm 	}
117006f25ae9SGregory Neil Shapiro 	return buf;
1171c2aa98e2SPeter Wemm }
1172c2aa98e2SPeter Wemm 
1173c2aa98e2SPeter Wemm /* ARGSUSED */
1174c2aa98e2SPeter Wemm static void
1175c2aa98e2SPeter Wemm readtimeout(timeout)
1176c2aa98e2SPeter Wemm 	time_t timeout;
1177c2aa98e2SPeter Wemm {
1178c2aa98e2SPeter Wemm 	longjmp(CtxReadTimeout, 1);
1179c2aa98e2SPeter Wemm }
1180c2aa98e2SPeter Wemm /*
1181c2aa98e2SPeter Wemm **  FGETFOLDED -- like fgets, but know about folded lines.
1182c2aa98e2SPeter Wemm **
1183c2aa98e2SPeter Wemm **	Parameters:
1184c2aa98e2SPeter Wemm **		buf -- place to put result.
1185c2aa98e2SPeter Wemm **		n -- bytes available.
1186c2aa98e2SPeter Wemm **		f -- file to read from.
1187c2aa98e2SPeter Wemm **
1188c2aa98e2SPeter Wemm **	Returns:
1189c2aa98e2SPeter Wemm **		input line(s) on success, NULL on error or EOF.
1190c2aa98e2SPeter Wemm **		This will normally be buf -- unless the line is too
1191c2aa98e2SPeter Wemm **			long, when it will be xalloc()ed.
1192c2aa98e2SPeter Wemm **
1193c2aa98e2SPeter Wemm **	Side Effects:
1194c2aa98e2SPeter Wemm **		buf gets lines from f, with continuation lines (lines
1195c2aa98e2SPeter Wemm **		with leading white space) appended.  CRLF's are mapped
1196c2aa98e2SPeter Wemm **		into single newlines.  Any trailing NL is stripped.
1197c2aa98e2SPeter Wemm */
1198c2aa98e2SPeter Wemm 
1199c2aa98e2SPeter Wemm char *
1200c2aa98e2SPeter Wemm fgetfolded(buf, n, f)
1201c2aa98e2SPeter Wemm 	char *buf;
1202c2aa98e2SPeter Wemm 	register int n;
1203c2aa98e2SPeter Wemm 	FILE *f;
1204c2aa98e2SPeter Wemm {
1205c2aa98e2SPeter Wemm 	register char *p = buf;
1206c2aa98e2SPeter Wemm 	char *bp = buf;
1207c2aa98e2SPeter Wemm 	register int i;
1208c2aa98e2SPeter Wemm 
1209c2aa98e2SPeter Wemm 	n--;
1210c2aa98e2SPeter Wemm 	while ((i = getc(f)) != EOF)
1211c2aa98e2SPeter Wemm 	{
1212c2aa98e2SPeter Wemm 		if (i == '\r')
1213c2aa98e2SPeter Wemm 		{
1214c2aa98e2SPeter Wemm 			i = getc(f);
1215c2aa98e2SPeter Wemm 			if (i != '\n')
1216c2aa98e2SPeter Wemm 			{
1217c2aa98e2SPeter Wemm 				if (i != EOF)
1218c2aa98e2SPeter Wemm 					(void) ungetc(i, f);
1219c2aa98e2SPeter Wemm 				i = '\r';
1220c2aa98e2SPeter Wemm 			}
1221c2aa98e2SPeter Wemm 		}
1222c2aa98e2SPeter Wemm 		if (--n <= 0)
1223c2aa98e2SPeter Wemm 		{
1224c2aa98e2SPeter Wemm 			/* allocate new space */
1225c2aa98e2SPeter Wemm 			char *nbp;
1226c2aa98e2SPeter Wemm 			int nn;
1227c2aa98e2SPeter Wemm 
1228c2aa98e2SPeter Wemm 			nn = (p - bp);
1229c2aa98e2SPeter Wemm 			if (nn < MEMCHUNKSIZE)
1230c2aa98e2SPeter Wemm 				nn *= 2;
1231c2aa98e2SPeter Wemm 			else
1232c2aa98e2SPeter Wemm 				nn += MEMCHUNKSIZE;
1233c2aa98e2SPeter Wemm 			nbp = xalloc(nn);
123406f25ae9SGregory Neil Shapiro 			memmove(nbp, bp, p - bp);
1235c2aa98e2SPeter Wemm 			p = &nbp[p - bp];
1236c2aa98e2SPeter Wemm 			if (bp != buf)
1237c2aa98e2SPeter Wemm 				free(bp);
1238c2aa98e2SPeter Wemm 			bp = nbp;
1239c2aa98e2SPeter Wemm 			n = nn - (p - bp);
1240c2aa98e2SPeter Wemm 		}
1241c2aa98e2SPeter Wemm 		*p++ = i;
1242c2aa98e2SPeter Wemm 		if (i == '\n')
1243c2aa98e2SPeter Wemm 		{
1244c2aa98e2SPeter Wemm 			LineNumber++;
1245c2aa98e2SPeter Wemm 			i = getc(f);
1246c2aa98e2SPeter Wemm 			if (i != EOF)
1247c2aa98e2SPeter Wemm 				(void) ungetc(i, f);
1248c2aa98e2SPeter Wemm 			if (i != ' ' && i != '\t')
1249c2aa98e2SPeter Wemm 				break;
1250c2aa98e2SPeter Wemm 		}
1251c2aa98e2SPeter Wemm 	}
1252c2aa98e2SPeter Wemm 	if (p == bp)
125306f25ae9SGregory Neil Shapiro 		return NULL;
1254c2aa98e2SPeter Wemm 	if (p[-1] == '\n')
1255c2aa98e2SPeter Wemm 		p--;
1256c2aa98e2SPeter Wemm 	*p = '\0';
125706f25ae9SGregory Neil Shapiro 	return bp;
1258c2aa98e2SPeter Wemm }
1259c2aa98e2SPeter Wemm /*
1260c2aa98e2SPeter Wemm **  CURTIME -- return current time.
1261c2aa98e2SPeter Wemm **
1262c2aa98e2SPeter Wemm **	Parameters:
1263c2aa98e2SPeter Wemm **		none.
1264c2aa98e2SPeter Wemm **
1265c2aa98e2SPeter Wemm **	Returns:
1266c2aa98e2SPeter Wemm **		the current time.
1267c2aa98e2SPeter Wemm **
1268c2aa98e2SPeter Wemm **	Side Effects:
1269c2aa98e2SPeter Wemm **		none.
1270c2aa98e2SPeter Wemm */
1271c2aa98e2SPeter Wemm 
1272c2aa98e2SPeter Wemm time_t
1273c2aa98e2SPeter Wemm curtime()
1274c2aa98e2SPeter Wemm {
1275c2aa98e2SPeter Wemm 	auto time_t t;
1276c2aa98e2SPeter Wemm 
1277c2aa98e2SPeter Wemm 	(void) time(&t);
127806f25ae9SGregory Neil Shapiro 	return t;
1279c2aa98e2SPeter Wemm }
1280c2aa98e2SPeter Wemm /*
1281c2aa98e2SPeter Wemm **  ATOBOOL -- convert a string representation to boolean.
1282c2aa98e2SPeter Wemm **
1283c2aa98e2SPeter Wemm **	Defaults to "TRUE"
1284c2aa98e2SPeter Wemm **
1285c2aa98e2SPeter Wemm **	Parameters:
1286c2aa98e2SPeter Wemm **		s -- string to convert.  Takes "tTyY" as true,
1287c2aa98e2SPeter Wemm **			others as false.
1288c2aa98e2SPeter Wemm **
1289c2aa98e2SPeter Wemm **	Returns:
1290c2aa98e2SPeter Wemm **		A boolean representation of the string.
1291c2aa98e2SPeter Wemm **
1292c2aa98e2SPeter Wemm **	Side Effects:
1293c2aa98e2SPeter Wemm **		none.
1294c2aa98e2SPeter Wemm */
1295c2aa98e2SPeter Wemm 
1296c2aa98e2SPeter Wemm bool
1297c2aa98e2SPeter Wemm atobool(s)
1298c2aa98e2SPeter Wemm 	register char *s;
1299c2aa98e2SPeter Wemm {
1300c2aa98e2SPeter Wemm 	if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL)
130106f25ae9SGregory Neil Shapiro 		return TRUE;
130206f25ae9SGregory Neil Shapiro 	return FALSE;
1303c2aa98e2SPeter Wemm }
1304c2aa98e2SPeter Wemm /*
1305c2aa98e2SPeter Wemm **  ATOOCT -- convert a string representation to octal.
1306c2aa98e2SPeter Wemm **
1307c2aa98e2SPeter Wemm **	Parameters:
1308c2aa98e2SPeter Wemm **		s -- string to convert.
1309c2aa98e2SPeter Wemm **
1310c2aa98e2SPeter Wemm **	Returns:
1311c2aa98e2SPeter Wemm **		An integer representing the string interpreted as an
1312c2aa98e2SPeter Wemm **		octal number.
1313c2aa98e2SPeter Wemm **
1314c2aa98e2SPeter Wemm **	Side Effects:
1315c2aa98e2SPeter Wemm **		none.
1316c2aa98e2SPeter Wemm */
1317c2aa98e2SPeter Wemm 
1318c2aa98e2SPeter Wemm int
1319c2aa98e2SPeter Wemm atooct(s)
1320c2aa98e2SPeter Wemm 	register char *s;
1321c2aa98e2SPeter Wemm {
1322c2aa98e2SPeter Wemm 	register int i = 0;
1323c2aa98e2SPeter Wemm 
1324c2aa98e2SPeter Wemm 	while (*s >= '0' && *s <= '7')
1325c2aa98e2SPeter Wemm 		i = (i << 3) | (*s++ - '0');
132606f25ae9SGregory Neil Shapiro 	return i;
1327c2aa98e2SPeter Wemm }
1328c2aa98e2SPeter Wemm /*
1329c2aa98e2SPeter Wemm **  BITINTERSECT -- tell if two bitmaps intersect
1330c2aa98e2SPeter Wemm **
1331c2aa98e2SPeter Wemm **	Parameters:
1332c2aa98e2SPeter Wemm **		a, b -- the bitmaps in question
1333c2aa98e2SPeter Wemm **
1334c2aa98e2SPeter Wemm **	Returns:
1335c2aa98e2SPeter Wemm **		TRUE if they have a non-null intersection
1336c2aa98e2SPeter Wemm **		FALSE otherwise
1337c2aa98e2SPeter Wemm **
1338c2aa98e2SPeter Wemm **	Side Effects:
1339c2aa98e2SPeter Wemm **		none.
1340c2aa98e2SPeter Wemm */
1341c2aa98e2SPeter Wemm 
1342c2aa98e2SPeter Wemm bool
1343c2aa98e2SPeter Wemm bitintersect(a, b)
134406f25ae9SGregory Neil Shapiro 	BITMAP256 a;
134506f25ae9SGregory Neil Shapiro 	BITMAP256 b;
1346c2aa98e2SPeter Wemm {
1347c2aa98e2SPeter Wemm 	int i;
1348c2aa98e2SPeter Wemm 
1349c2aa98e2SPeter Wemm 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
1350c2aa98e2SPeter Wemm 		if ((a[i] & b[i]) != 0)
135106f25ae9SGregory Neil Shapiro 			return TRUE;
135206f25ae9SGregory Neil Shapiro 	return FALSE;
1353c2aa98e2SPeter Wemm }
1354c2aa98e2SPeter Wemm /*
1355c2aa98e2SPeter Wemm **  BITZEROP -- tell if a bitmap is all zero
1356c2aa98e2SPeter Wemm **
1357c2aa98e2SPeter Wemm **	Parameters:
1358c2aa98e2SPeter Wemm **		map -- the bit map to check
1359c2aa98e2SPeter Wemm **
1360c2aa98e2SPeter Wemm **	Returns:
1361c2aa98e2SPeter Wemm **		TRUE if map is all zero.
1362c2aa98e2SPeter Wemm **		FALSE if there are any bits set in map.
1363c2aa98e2SPeter Wemm **
1364c2aa98e2SPeter Wemm **	Side Effects:
1365c2aa98e2SPeter Wemm **		none.
1366c2aa98e2SPeter Wemm */
1367c2aa98e2SPeter Wemm 
1368c2aa98e2SPeter Wemm bool
1369c2aa98e2SPeter Wemm bitzerop(map)
137006f25ae9SGregory Neil Shapiro 	BITMAP256 map;
1371c2aa98e2SPeter Wemm {
1372c2aa98e2SPeter Wemm 	int i;
1373c2aa98e2SPeter Wemm 
1374c2aa98e2SPeter Wemm 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
1375c2aa98e2SPeter Wemm 		if (map[i] != 0)
137606f25ae9SGregory Neil Shapiro 			return FALSE;
137706f25ae9SGregory Neil Shapiro 	return TRUE;
1378c2aa98e2SPeter Wemm }
1379c2aa98e2SPeter Wemm /*
1380c2aa98e2SPeter Wemm **  STRCONTAINEDIN -- tell if one string is contained in another
1381c2aa98e2SPeter Wemm **
1382c2aa98e2SPeter Wemm **	Parameters:
1383c2aa98e2SPeter Wemm **		a -- possible substring.
1384c2aa98e2SPeter Wemm **		b -- possible superstring.
1385c2aa98e2SPeter Wemm **
1386c2aa98e2SPeter Wemm **	Returns:
1387c2aa98e2SPeter Wemm **		TRUE if a is contained in b.
1388c2aa98e2SPeter Wemm **		FALSE otherwise.
1389c2aa98e2SPeter Wemm */
1390c2aa98e2SPeter Wemm 
1391c2aa98e2SPeter Wemm bool
1392c2aa98e2SPeter Wemm strcontainedin(a, b)
1393c2aa98e2SPeter Wemm 	register char *a;
1394c2aa98e2SPeter Wemm 	register char *b;
1395c2aa98e2SPeter Wemm {
1396c2aa98e2SPeter Wemm 	int la;
1397c2aa98e2SPeter Wemm 	int lb;
1398c2aa98e2SPeter Wemm 	int c;
1399c2aa98e2SPeter Wemm 
1400c2aa98e2SPeter Wemm 	la = strlen(a);
1401c2aa98e2SPeter Wemm 	lb = strlen(b);
1402c2aa98e2SPeter Wemm 	c = *a;
1403c2aa98e2SPeter Wemm 	if (isascii(c) && isupper(c))
1404c2aa98e2SPeter Wemm 		c = tolower(c);
1405c2aa98e2SPeter Wemm 	for (; lb-- >= la; b++)
1406c2aa98e2SPeter Wemm 	{
1407c2aa98e2SPeter Wemm 		if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c)
1408c2aa98e2SPeter Wemm 			continue;
1409c2aa98e2SPeter Wemm 		if (strncasecmp(a, b, la) == 0)
1410c2aa98e2SPeter Wemm 			return TRUE;
1411c2aa98e2SPeter Wemm 	}
1412c2aa98e2SPeter Wemm 	return FALSE;
1413c2aa98e2SPeter Wemm }
1414c2aa98e2SPeter Wemm /*
1415c2aa98e2SPeter Wemm **  CHECKFD012 -- check low numbered file descriptors
1416c2aa98e2SPeter Wemm **
1417c2aa98e2SPeter Wemm **	File descriptors 0, 1, and 2 should be open at all times.
1418c2aa98e2SPeter Wemm **	This routine verifies that, and fixes it if not true.
1419c2aa98e2SPeter Wemm **
1420c2aa98e2SPeter Wemm **	Parameters:
1421c2aa98e2SPeter Wemm **		where -- a tag printed if the assertion failed
1422c2aa98e2SPeter Wemm **
1423c2aa98e2SPeter Wemm **	Returns:
1424c2aa98e2SPeter Wemm **		none
1425c2aa98e2SPeter Wemm */
1426c2aa98e2SPeter Wemm 
1427c2aa98e2SPeter Wemm void
1428c2aa98e2SPeter Wemm checkfd012(where)
1429c2aa98e2SPeter Wemm 	char *where;
1430c2aa98e2SPeter Wemm {
1431c2aa98e2SPeter Wemm #if XDEBUG
1432c2aa98e2SPeter Wemm 	register int i;
1433c2aa98e2SPeter Wemm 
1434c2aa98e2SPeter Wemm 	for (i = 0; i < 3; i++)
1435c2aa98e2SPeter Wemm 		fill_fd(i, where);
1436c2aa98e2SPeter Wemm #endif /* XDEBUG */
1437c2aa98e2SPeter Wemm }
1438c2aa98e2SPeter Wemm /*
1439c2aa98e2SPeter Wemm **  CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging
1440c2aa98e2SPeter Wemm **
1441c2aa98e2SPeter Wemm **	Parameters:
1442c2aa98e2SPeter Wemm **		fd -- file descriptor to check.
1443c2aa98e2SPeter Wemm **		where -- tag to print on failure.
1444c2aa98e2SPeter Wemm **
1445c2aa98e2SPeter Wemm **	Returns:
1446c2aa98e2SPeter Wemm **		none.
1447c2aa98e2SPeter Wemm */
1448c2aa98e2SPeter Wemm 
1449c2aa98e2SPeter Wemm void
1450c2aa98e2SPeter Wemm checkfdopen(fd, where)
1451c2aa98e2SPeter Wemm 	int fd;
1452c2aa98e2SPeter Wemm 	char *where;
1453c2aa98e2SPeter Wemm {
1454c2aa98e2SPeter Wemm #if XDEBUG
1455c2aa98e2SPeter Wemm 	struct stat st;
1456c2aa98e2SPeter Wemm 
1457c2aa98e2SPeter Wemm 	if (fstat(fd, &st) < 0 && errno == EBADF)
1458c2aa98e2SPeter Wemm 	{
1459c2aa98e2SPeter Wemm 		syserr("checkfdopen(%d): %s not open as expected!", fd, where);
1460c2aa98e2SPeter Wemm 		printopenfds(TRUE);
1461c2aa98e2SPeter Wemm 	}
146206f25ae9SGregory Neil Shapiro #endif /* XDEBUG */
1463c2aa98e2SPeter Wemm }
1464c2aa98e2SPeter Wemm /*
1465c2aa98e2SPeter Wemm **  CHECKFDS -- check for new or missing file descriptors
1466c2aa98e2SPeter Wemm **
1467c2aa98e2SPeter Wemm **	Parameters:
1468c2aa98e2SPeter Wemm **		where -- tag for printing.  If null, take a base line.
1469c2aa98e2SPeter Wemm **
1470c2aa98e2SPeter Wemm **	Returns:
1471c2aa98e2SPeter Wemm **		none
1472c2aa98e2SPeter Wemm **
1473c2aa98e2SPeter Wemm **	Side Effects:
1474c2aa98e2SPeter Wemm **		If where is set, shows changes since the last call.
1475c2aa98e2SPeter Wemm */
1476c2aa98e2SPeter Wemm 
1477c2aa98e2SPeter Wemm void
1478c2aa98e2SPeter Wemm checkfds(where)
1479c2aa98e2SPeter Wemm 	char *where;
1480c2aa98e2SPeter Wemm {
1481c2aa98e2SPeter Wemm 	int maxfd;
1482c2aa98e2SPeter Wemm 	register int fd;
1483c2aa98e2SPeter Wemm 	bool printhdr = TRUE;
1484c2aa98e2SPeter Wemm 	int save_errno = errno;
148506f25ae9SGregory Neil Shapiro 	static BITMAP256 baseline;
1486c2aa98e2SPeter Wemm 	extern int DtableSize;
1487c2aa98e2SPeter Wemm 
1488c2aa98e2SPeter Wemm 	if (DtableSize > 256)
1489c2aa98e2SPeter Wemm 		maxfd = 256;
1490c2aa98e2SPeter Wemm 	else
1491c2aa98e2SPeter Wemm 		maxfd = DtableSize;
1492c2aa98e2SPeter Wemm 	if (where == NULL)
1493c2aa98e2SPeter Wemm 		clrbitmap(baseline);
1494c2aa98e2SPeter Wemm 
1495c2aa98e2SPeter Wemm 	for (fd = 0; fd < maxfd; fd++)
1496c2aa98e2SPeter Wemm 	{
1497c2aa98e2SPeter Wemm 		struct stat stbuf;
1498c2aa98e2SPeter Wemm 
1499c2aa98e2SPeter Wemm 		if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP)
1500c2aa98e2SPeter Wemm 		{
1501c2aa98e2SPeter Wemm 			if (!bitnset(fd, baseline))
1502c2aa98e2SPeter Wemm 				continue;
1503c2aa98e2SPeter Wemm 			clrbitn(fd, baseline);
1504c2aa98e2SPeter Wemm 		}
1505c2aa98e2SPeter Wemm 		else if (!bitnset(fd, baseline))
1506c2aa98e2SPeter Wemm 			setbitn(fd, baseline);
1507c2aa98e2SPeter Wemm 		else
1508c2aa98e2SPeter Wemm 			continue;
1509c2aa98e2SPeter Wemm 
1510c2aa98e2SPeter Wemm 		/* file state has changed */
1511c2aa98e2SPeter Wemm 		if (where == NULL)
1512c2aa98e2SPeter Wemm 			continue;
1513c2aa98e2SPeter Wemm 		if (printhdr)
1514c2aa98e2SPeter Wemm 		{
1515c2aa98e2SPeter Wemm 			sm_syslog(LOG_DEBUG, CurEnv->e_id,
1516c2aa98e2SPeter Wemm 				  "%s: changed fds:",
1517c2aa98e2SPeter Wemm 				  where);
1518c2aa98e2SPeter Wemm 			printhdr = FALSE;
1519c2aa98e2SPeter Wemm 		}
1520c2aa98e2SPeter Wemm 		dumpfd(fd, TRUE, TRUE);
1521c2aa98e2SPeter Wemm 	}
1522c2aa98e2SPeter Wemm 	errno = save_errno;
1523c2aa98e2SPeter Wemm }
1524c2aa98e2SPeter Wemm /*
1525c2aa98e2SPeter Wemm **  PRINTOPENFDS -- print the open file descriptors (for debugging)
1526c2aa98e2SPeter Wemm **
1527c2aa98e2SPeter Wemm **	Parameters:
1528c2aa98e2SPeter Wemm **		logit -- if set, send output to syslog; otherwise
1529c2aa98e2SPeter Wemm **			print for debugging.
1530c2aa98e2SPeter Wemm **
1531c2aa98e2SPeter Wemm **	Returns:
1532c2aa98e2SPeter Wemm **		none.
1533c2aa98e2SPeter Wemm */
1534c2aa98e2SPeter Wemm 
153506f25ae9SGregory Neil Shapiro #if NETINET || NETINET6
1536c2aa98e2SPeter Wemm # include <arpa/inet.h>
153706f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */
1538c2aa98e2SPeter Wemm 
1539c2aa98e2SPeter Wemm void
1540c2aa98e2SPeter Wemm printopenfds(logit)
1541c2aa98e2SPeter Wemm 	bool logit;
1542c2aa98e2SPeter Wemm {
1543c2aa98e2SPeter Wemm 	register int fd;
1544c2aa98e2SPeter Wemm 	extern int DtableSize;
1545c2aa98e2SPeter Wemm 
1546c2aa98e2SPeter Wemm 	for (fd = 0; fd < DtableSize; fd++)
1547c2aa98e2SPeter Wemm 		dumpfd(fd, FALSE, logit);
1548c2aa98e2SPeter Wemm }
1549c2aa98e2SPeter Wemm /*
1550c2aa98e2SPeter Wemm **  DUMPFD -- dump a file descriptor
1551c2aa98e2SPeter Wemm **
1552c2aa98e2SPeter Wemm **	Parameters:
1553c2aa98e2SPeter Wemm **		fd -- the file descriptor to dump.
1554c2aa98e2SPeter Wemm **		printclosed -- if set, print a notification even if
1555c2aa98e2SPeter Wemm **			it is closed; otherwise print nothing.
1556c2aa98e2SPeter Wemm **		logit -- if set, send output to syslog instead of stdout.
1557c2aa98e2SPeter Wemm */
1558c2aa98e2SPeter Wemm 
1559c2aa98e2SPeter Wemm void
1560c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit)
1561c2aa98e2SPeter Wemm 	int fd;
1562c2aa98e2SPeter Wemm 	bool printclosed;
1563c2aa98e2SPeter Wemm 	bool logit;
1564c2aa98e2SPeter Wemm {
1565c2aa98e2SPeter Wemm 	register char *p;
1566c2aa98e2SPeter Wemm 	char *hp;
1567c2aa98e2SPeter Wemm #ifdef S_IFSOCK
1568c2aa98e2SPeter Wemm 	SOCKADDR sa;
156906f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */
1570c2aa98e2SPeter Wemm 	auto SOCKADDR_LEN_T slen;
1571c2aa98e2SPeter Wemm 	int i;
1572c2aa98e2SPeter Wemm #if STAT64 > 0
1573c2aa98e2SPeter Wemm 	struct stat64 st;
157406f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */
1575c2aa98e2SPeter Wemm 	struct stat st;
157606f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */
1577c2aa98e2SPeter Wemm 	char buf[200];
1578c2aa98e2SPeter Wemm 
1579c2aa98e2SPeter Wemm 	p = buf;
1580c2aa98e2SPeter Wemm 	snprintf(p, SPACELEFT(buf, p), "%3d: ", fd);
1581c2aa98e2SPeter Wemm 	p += strlen(p);
1582c2aa98e2SPeter Wemm 
1583c2aa98e2SPeter Wemm 	if (
1584c2aa98e2SPeter Wemm #if STAT64 > 0
1585c2aa98e2SPeter Wemm 	    fstat64(fd, &st)
158606f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */
1587c2aa98e2SPeter Wemm 	    fstat(fd, &st)
158806f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */
1589c2aa98e2SPeter Wemm 	    < 0)
1590c2aa98e2SPeter Wemm 	{
1591c2aa98e2SPeter Wemm 		if (errno != EBADF)
1592c2aa98e2SPeter Wemm 		{
1593c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)",
1594c2aa98e2SPeter Wemm 				errstring(errno));
1595c2aa98e2SPeter Wemm 			goto printit;
1596c2aa98e2SPeter Wemm 		}
1597c2aa98e2SPeter Wemm 		else if (printclosed)
1598c2aa98e2SPeter Wemm 		{
1599c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "CLOSED");
1600c2aa98e2SPeter Wemm 			goto printit;
1601c2aa98e2SPeter Wemm 		}
1602c2aa98e2SPeter Wemm 		return;
1603c2aa98e2SPeter Wemm 	}
1604c2aa98e2SPeter Wemm 
1605c2aa98e2SPeter Wemm 	i = fcntl(fd, F_GETFL, NULL);
1606c2aa98e2SPeter Wemm 	if (i != -1)
1607c2aa98e2SPeter Wemm 	{
1608c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i);
1609c2aa98e2SPeter Wemm 		p += strlen(p);
1610c2aa98e2SPeter Wemm 	}
1611c2aa98e2SPeter Wemm 
161206f25ae9SGregory Neil Shapiro 	snprintf(p, SPACELEFT(buf, p), "mode=%o: ", (int) st.st_mode);
1613c2aa98e2SPeter Wemm 	p += strlen(p);
1614c2aa98e2SPeter Wemm 	switch (st.st_mode & S_IFMT)
1615c2aa98e2SPeter Wemm 	{
1616c2aa98e2SPeter Wemm #ifdef S_IFSOCK
1617c2aa98e2SPeter Wemm 	  case S_IFSOCK:
1618c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "SOCK ");
1619c2aa98e2SPeter Wemm 		p += strlen(p);
162006f25ae9SGregory Neil Shapiro 		memset(&sa, '\0', sizeof sa);
1621c2aa98e2SPeter Wemm 		slen = sizeof sa;
1622c2aa98e2SPeter Wemm 		if (getsockname(fd, &sa.sa, &slen) < 0)
162306f25ae9SGregory Neil Shapiro 			snprintf(p, SPACELEFT(buf, p), "(%s)",
162406f25ae9SGregory Neil Shapiro 				 errstring(errno));
1625c2aa98e2SPeter Wemm 		else
1626c2aa98e2SPeter Wemm 		{
1627c2aa98e2SPeter Wemm 			hp = hostnamebyanyaddr(&sa);
162806f25ae9SGregory Neil Shapiro 			if (hp == NULL)
162906f25ae9SGregory Neil Shapiro 			{
163006f25ae9SGregory Neil Shapiro 				/* EMPTY */
163106f25ae9SGregory Neil Shapiro 				/* do nothing */
163206f25ae9SGregory Neil Shapiro 			}
163306f25ae9SGregory Neil Shapiro # if NETINET
163406f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET)
1635c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
1636c2aa98e2SPeter Wemm 					 hp, ntohs(sa.sin.sin_port));
163706f25ae9SGregory Neil Shapiro # endif /* NETINET */
163806f25ae9SGregory Neil Shapiro # if NETINET6
163906f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET6)
164006f25ae9SGregory Neil Shapiro 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
164106f25ae9SGregory Neil Shapiro 					 hp, ntohs(sa.sin6.sin6_port));
164206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1643c2aa98e2SPeter Wemm 			else
1644c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s", hp);
1645c2aa98e2SPeter Wemm 		}
1646c2aa98e2SPeter Wemm 		p += strlen(p);
1647c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "->");
1648c2aa98e2SPeter Wemm 		p += strlen(p);
1649c2aa98e2SPeter Wemm 		slen = sizeof sa;
1650c2aa98e2SPeter Wemm 		if (getpeername(fd, &sa.sa, &slen) < 0)
1651c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno));
1652c2aa98e2SPeter Wemm 		else
1653c2aa98e2SPeter Wemm 		{
1654c2aa98e2SPeter Wemm 			hp = hostnamebyanyaddr(&sa);
165506f25ae9SGregory Neil Shapiro 			if (hp == NULL)
165606f25ae9SGregory Neil Shapiro 			{
165706f25ae9SGregory Neil Shapiro 				/* EMPTY */
165806f25ae9SGregory Neil Shapiro 				/* do nothing */
165906f25ae9SGregory Neil Shapiro 			}
166006f25ae9SGregory Neil Shapiro # if NETINET
166106f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET)
1662c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
1663c2aa98e2SPeter Wemm 					 hp, ntohs(sa.sin.sin_port));
166406f25ae9SGregory Neil Shapiro # endif /* NETINET */
166506f25ae9SGregory Neil Shapiro # if NETINET6
166606f25ae9SGregory Neil Shapiro 			else if (sa.sa.sa_family == AF_INET6)
166706f25ae9SGregory Neil Shapiro 				snprintf(p, SPACELEFT(buf, p), "%s/%d",
166806f25ae9SGregory Neil Shapiro 					 hp, ntohs(sa.sin6.sin6_port));
166906f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1670c2aa98e2SPeter Wemm 			else
1671c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(buf, p), "%s", hp);
1672c2aa98e2SPeter Wemm 		}
1673c2aa98e2SPeter Wemm 		break;
167406f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */
1675c2aa98e2SPeter Wemm 
1676c2aa98e2SPeter Wemm 	  case S_IFCHR:
1677c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "CHR: ");
1678c2aa98e2SPeter Wemm 		p += strlen(p);
1679c2aa98e2SPeter Wemm 		goto defprint;
1680c2aa98e2SPeter Wemm 
1681c2aa98e2SPeter Wemm 	  case S_IFBLK:
1682c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "BLK: ");
1683c2aa98e2SPeter Wemm 		p += strlen(p);
1684c2aa98e2SPeter Wemm 		goto defprint;
1685c2aa98e2SPeter Wemm 
1686c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK)
1687c2aa98e2SPeter Wemm 	  case S_IFIFO:
1688c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "FIFO: ");
1689c2aa98e2SPeter Wemm 		p += strlen(p);
1690c2aa98e2SPeter Wemm 		goto defprint;
169106f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */
1692c2aa98e2SPeter Wemm 
1693c2aa98e2SPeter Wemm #ifdef S_IFDIR
1694c2aa98e2SPeter Wemm 	  case S_IFDIR:
1695c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "DIR: ");
1696c2aa98e2SPeter Wemm 		p += strlen(p);
1697c2aa98e2SPeter Wemm 		goto defprint;
169806f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */
1699c2aa98e2SPeter Wemm 
1700c2aa98e2SPeter Wemm #ifdef S_IFLNK
1701c2aa98e2SPeter Wemm 	  case S_IFLNK:
1702c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(buf, p), "LNK: ");
1703c2aa98e2SPeter Wemm 		p += strlen(p);
1704c2aa98e2SPeter Wemm 		goto defprint;
170506f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */
1706c2aa98e2SPeter Wemm 
1707c2aa98e2SPeter Wemm 	  default:
1708c2aa98e2SPeter Wemm defprint:
170906f25ae9SGregory Neil Shapiro 		/*CONSTCOND*/
1710c2aa98e2SPeter Wemm 		if (sizeof st.st_ino > sizeof (long))
1711c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p),
1712c2aa98e2SPeter Wemm 				 "dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ",
1713c2aa98e2SPeter Wemm 				 major(st.st_dev), minor(st.st_dev),
1714c2aa98e2SPeter Wemm 				 quad_to_string(st.st_ino),
171506f25ae9SGregory Neil Shapiro 				 (int) st.st_nlink, (int) st.st_uid,
171606f25ae9SGregory Neil Shapiro 				 (int) st.st_gid);
1717c2aa98e2SPeter Wemm 		else
1718c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p),
1719c2aa98e2SPeter Wemm 				 "dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ",
1720c2aa98e2SPeter Wemm 				 major(st.st_dev), minor(st.st_dev),
1721c2aa98e2SPeter Wemm 				 (unsigned long) st.st_ino,
172206f25ae9SGregory Neil Shapiro 				 (int) st.st_nlink, (int) st.st_uid,
172306f25ae9SGregory Neil Shapiro 				 (int) st.st_gid);
172406f25ae9SGregory Neil Shapiro 		/*CONSTCOND*/
1725c2aa98e2SPeter Wemm 		if (sizeof st.st_size > sizeof (long))
1726c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "size=%s",
1727c2aa98e2SPeter Wemm 				 quad_to_string(st.st_size));
1728c2aa98e2SPeter Wemm 		else
1729c2aa98e2SPeter Wemm 			snprintf(p, SPACELEFT(buf, p), "size=%lu",
1730c2aa98e2SPeter Wemm 				 (unsigned long) st.st_size);
1731c2aa98e2SPeter Wemm 		break;
1732c2aa98e2SPeter Wemm 	}
1733c2aa98e2SPeter Wemm 
1734c2aa98e2SPeter Wemm printit:
1735c2aa98e2SPeter Wemm 	if (logit)
1736c2aa98e2SPeter Wemm 		sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL,
1737c2aa98e2SPeter Wemm 			  "%.800s", buf);
1738c2aa98e2SPeter Wemm 	else
1739c2aa98e2SPeter Wemm 		printf("%s\n", buf);
1740c2aa98e2SPeter Wemm }
1741c2aa98e2SPeter Wemm /*
1742c2aa98e2SPeter Wemm **  SHORTEN_HOSTNAME -- strip local domain information off of hostname.
1743c2aa98e2SPeter Wemm **
1744c2aa98e2SPeter Wemm **	Parameters:
1745c2aa98e2SPeter Wemm **		host -- the host to shorten (stripped in place).
1746c2aa98e2SPeter Wemm **
1747c2aa98e2SPeter Wemm **	Returns:
1748c2aa98e2SPeter Wemm **		none.
1749c2aa98e2SPeter Wemm */
1750c2aa98e2SPeter Wemm 
1751c2aa98e2SPeter Wemm void
1752c2aa98e2SPeter Wemm shorten_hostname(host)
1753c2aa98e2SPeter Wemm 	char host[];
1754c2aa98e2SPeter Wemm {
1755c2aa98e2SPeter Wemm 	register char *p;
1756c2aa98e2SPeter Wemm 	char *mydom;
1757c2aa98e2SPeter Wemm 	int i;
1758c2aa98e2SPeter Wemm 	bool canon = FALSE;
1759c2aa98e2SPeter Wemm 
1760c2aa98e2SPeter Wemm 	/* strip off final dot */
1761c2aa98e2SPeter Wemm 	p = &host[strlen(host) - 1];
1762c2aa98e2SPeter Wemm 	if (*p == '.')
1763c2aa98e2SPeter Wemm 	{
1764c2aa98e2SPeter Wemm 		*p = '\0';
1765c2aa98e2SPeter Wemm 		canon = TRUE;
1766c2aa98e2SPeter Wemm 	}
1767c2aa98e2SPeter Wemm 
1768c2aa98e2SPeter Wemm 	/* see if there is any domain at all -- if not, we are done */
1769c2aa98e2SPeter Wemm 	p = strchr(host, '.');
1770c2aa98e2SPeter Wemm 	if (p == NULL)
1771c2aa98e2SPeter Wemm 		return;
1772c2aa98e2SPeter Wemm 
1773c2aa98e2SPeter Wemm 	/* yes, we have a domain -- see if it looks like us */
1774c2aa98e2SPeter Wemm 	mydom = macvalue('m', CurEnv);
1775c2aa98e2SPeter Wemm 	if (mydom == NULL)
1776c2aa98e2SPeter Wemm 		mydom = "";
1777c2aa98e2SPeter Wemm 	i = strlen(++p);
1778c2aa98e2SPeter Wemm 	if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 &&
1779c2aa98e2SPeter Wemm 	    (mydom[i] == '.' || mydom[i] == '\0'))
1780c2aa98e2SPeter Wemm 		*--p = '\0';
1781c2aa98e2SPeter Wemm }
1782c2aa98e2SPeter Wemm /*
1783c2aa98e2SPeter Wemm **  PROG_OPEN -- open a program for reading
1784c2aa98e2SPeter Wemm **
1785c2aa98e2SPeter Wemm **	Parameters:
1786c2aa98e2SPeter Wemm **		argv -- the argument list.
1787c2aa98e2SPeter Wemm **		pfd -- pointer to a place to store the file descriptor.
1788c2aa98e2SPeter Wemm **		e -- the current envelope.
1789c2aa98e2SPeter Wemm **
1790c2aa98e2SPeter Wemm **	Returns:
1791c2aa98e2SPeter Wemm **		pid of the process -- -1 if it failed.
1792c2aa98e2SPeter Wemm */
1793c2aa98e2SPeter Wemm 
1794c2aa98e2SPeter Wemm int
1795c2aa98e2SPeter Wemm prog_open(argv, pfd, e)
1796c2aa98e2SPeter Wemm 	char **argv;
1797c2aa98e2SPeter Wemm 	int *pfd;
1798c2aa98e2SPeter Wemm 	ENVELOPE *e;
1799c2aa98e2SPeter Wemm {
1800c2aa98e2SPeter Wemm 	int pid;
1801c2aa98e2SPeter Wemm 	int i;
180206f25ae9SGregory Neil Shapiro 	int save_errno;
1803c2aa98e2SPeter Wemm 	int fdv[2];
1804c2aa98e2SPeter Wemm 	char *p, *q;
1805c2aa98e2SPeter Wemm 	char buf[MAXLINE + 1];
1806c2aa98e2SPeter Wemm 	extern int DtableSize;
1807c2aa98e2SPeter Wemm 
1808c2aa98e2SPeter Wemm 	if (pipe(fdv) < 0)
1809c2aa98e2SPeter Wemm 	{
1810c2aa98e2SPeter Wemm 		syserr("%s: cannot create pipe for stdout", argv[0]);
1811c2aa98e2SPeter Wemm 		return -1;
1812c2aa98e2SPeter Wemm 	}
1813c2aa98e2SPeter Wemm 	pid = fork();
1814c2aa98e2SPeter Wemm 	if (pid < 0)
1815c2aa98e2SPeter Wemm 	{
1816c2aa98e2SPeter Wemm 		syserr("%s: cannot fork", argv[0]);
181706f25ae9SGregory Neil Shapiro 		(void) close(fdv[0]);
181806f25ae9SGregory Neil Shapiro 		(void) close(fdv[1]);
1819c2aa98e2SPeter Wemm 		return -1;
1820c2aa98e2SPeter Wemm 	}
1821c2aa98e2SPeter Wemm 	if (pid > 0)
1822c2aa98e2SPeter Wemm 	{
1823c2aa98e2SPeter Wemm 		/* parent */
182406f25ae9SGregory Neil Shapiro 		(void) close(fdv[1]);
1825c2aa98e2SPeter Wemm 		*pfd = fdv[0];
1826c2aa98e2SPeter Wemm 		return pid;
1827c2aa98e2SPeter Wemm 	}
1828c2aa98e2SPeter Wemm 
1829c2aa98e2SPeter Wemm 	/* child -- close stdin */
183006f25ae9SGregory Neil Shapiro 	(void) close(0);
1831c2aa98e2SPeter Wemm 
1832c2aa98e2SPeter Wemm 	/* stdout goes back to parent */
183306f25ae9SGregory Neil Shapiro 	(void) close(fdv[0]);
1834c2aa98e2SPeter Wemm 	if (dup2(fdv[1], 1) < 0)
1835c2aa98e2SPeter Wemm 	{
1836c2aa98e2SPeter Wemm 		syserr("%s: cannot dup2 for stdout", argv[0]);
1837c2aa98e2SPeter Wemm 		_exit(EX_OSERR);
1838c2aa98e2SPeter Wemm 	}
183906f25ae9SGregory Neil Shapiro 	(void) close(fdv[1]);
1840c2aa98e2SPeter Wemm 
1841c2aa98e2SPeter Wemm 	/* stderr goes to transcript if available */
1842c2aa98e2SPeter Wemm 	if (e->e_xfp != NULL)
1843c2aa98e2SPeter Wemm 	{
184406f25ae9SGregory Neil Shapiro 		int xfd;
184506f25ae9SGregory Neil Shapiro 
184606f25ae9SGregory Neil Shapiro 		xfd = fileno(e->e_xfp);
184706f25ae9SGregory Neil Shapiro 		if (xfd >= 0 && dup2(xfd, 2) < 0)
1848c2aa98e2SPeter Wemm 		{
1849c2aa98e2SPeter Wemm 			syserr("%s: cannot dup2 for stderr", argv[0]);
1850c2aa98e2SPeter Wemm 			_exit(EX_OSERR);
1851c2aa98e2SPeter Wemm 		}
1852c2aa98e2SPeter Wemm 	}
1853c2aa98e2SPeter Wemm 
1854c2aa98e2SPeter Wemm 	/* this process has no right to the queue file */
1855c2aa98e2SPeter Wemm 	if (e->e_lockfp != NULL)
185606f25ae9SGregory Neil Shapiro 		(void) close(fileno(e->e_lockfp));
185706f25ae9SGregory Neil Shapiro 
185806f25ae9SGregory Neil Shapiro 	/* chroot to the program mailer directory, if defined */
185906f25ae9SGregory Neil Shapiro 	if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL)
186006f25ae9SGregory Neil Shapiro 	{
186106f25ae9SGregory Neil Shapiro 		expand(ProgMailer->m_rootdir, buf, sizeof buf, e);
186206f25ae9SGregory Neil Shapiro 		if (chroot(buf) < 0)
186306f25ae9SGregory Neil Shapiro 		{
186406f25ae9SGregory Neil Shapiro 			syserr("prog_open: cannot chroot(%s)", buf);
186506f25ae9SGregory Neil Shapiro 			exit(EX_TEMPFAIL);
186606f25ae9SGregory Neil Shapiro 		}
186706f25ae9SGregory Neil Shapiro 		if (chdir("/") < 0)
186806f25ae9SGregory Neil Shapiro 		{
186906f25ae9SGregory Neil Shapiro 			syserr("prog_open: cannot chdir(/)");
187006f25ae9SGregory Neil Shapiro 			exit(EX_TEMPFAIL);
187106f25ae9SGregory Neil Shapiro 		}
187206f25ae9SGregory Neil Shapiro 	}
1873c2aa98e2SPeter Wemm 
1874c2aa98e2SPeter Wemm 	/* run as default user */
1875c2aa98e2SPeter Wemm 	endpwent();
1876c2aa98e2SPeter Wemm 	if (setgid(DefGid) < 0 && geteuid() == 0)
187706f25ae9SGregory Neil Shapiro 	{
1878c2aa98e2SPeter Wemm 		syserr("prog_open: setgid(%ld) failed", (long) DefGid);
187906f25ae9SGregory Neil Shapiro 		exit(EX_TEMPFAIL);
188006f25ae9SGregory Neil Shapiro 	}
1881c2aa98e2SPeter Wemm 	if (setuid(DefUid) < 0 && geteuid() == 0)
188206f25ae9SGregory Neil Shapiro 	{
1883c2aa98e2SPeter Wemm 		syserr("prog_open: setuid(%ld) failed", (long) DefUid);
188406f25ae9SGregory Neil Shapiro 		exit(EX_TEMPFAIL);
188506f25ae9SGregory Neil Shapiro 	}
1886c2aa98e2SPeter Wemm 
1887c2aa98e2SPeter Wemm 	/* run in some directory */
1888c2aa98e2SPeter Wemm 	if (ProgMailer != NULL)
1889c2aa98e2SPeter Wemm 		p = ProgMailer->m_execdir;
1890c2aa98e2SPeter Wemm 	else
1891c2aa98e2SPeter Wemm 		p = NULL;
1892c2aa98e2SPeter Wemm 	for (; p != NULL; p = q)
1893c2aa98e2SPeter Wemm 	{
1894c2aa98e2SPeter Wemm 		q = strchr(p, ':');
1895c2aa98e2SPeter Wemm 		if (q != NULL)
1896c2aa98e2SPeter Wemm 			*q = '\0';
1897c2aa98e2SPeter Wemm 		expand(p, buf, sizeof buf, e);
1898c2aa98e2SPeter Wemm 		if (q != NULL)
1899c2aa98e2SPeter Wemm 			*q++ = ':';
1900c2aa98e2SPeter Wemm 		if (buf[0] != '\0' && chdir(buf) >= 0)
1901c2aa98e2SPeter Wemm 			break;
1902c2aa98e2SPeter Wemm 	}
1903c2aa98e2SPeter Wemm 	if (p == NULL)
1904c2aa98e2SPeter Wemm 	{
1905c2aa98e2SPeter Wemm 		/* backup directories */
1906c2aa98e2SPeter Wemm 		if (chdir("/tmp") < 0)
1907c2aa98e2SPeter Wemm 			(void) chdir("/");
1908c2aa98e2SPeter Wemm 	}
1909c2aa98e2SPeter Wemm 
1910c2aa98e2SPeter Wemm 	/* arrange for all the files to be closed */
1911c2aa98e2SPeter Wemm 	for (i = 3; i < DtableSize; i++)
1912c2aa98e2SPeter Wemm 	{
1913c2aa98e2SPeter Wemm 		register int j;
1914c2aa98e2SPeter Wemm 
1915c2aa98e2SPeter Wemm 		if ((j = fcntl(i, F_GETFD, 0)) != -1)
191606f25ae9SGregory Neil Shapiro 			(void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
1917c2aa98e2SPeter Wemm 	}
1918c2aa98e2SPeter Wemm 
1919c2aa98e2SPeter Wemm 	/* now exec the process */
192006f25ae9SGregory Neil Shapiro 	(void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron);
1921c2aa98e2SPeter Wemm 
1922c2aa98e2SPeter Wemm 	/* woops!  failed */
192306f25ae9SGregory Neil Shapiro 	save_errno = errno;
1924c2aa98e2SPeter Wemm 	syserr("%s: cannot exec", argv[0]);
192506f25ae9SGregory Neil Shapiro 	if (transienterror(save_errno))
1926c2aa98e2SPeter Wemm 		_exit(EX_OSERR);
1927c2aa98e2SPeter Wemm 	_exit(EX_CONFIG);
1928c2aa98e2SPeter Wemm 	return -1;	/* avoid compiler warning on IRIX */
1929c2aa98e2SPeter Wemm }
1930c2aa98e2SPeter Wemm /*
1931c2aa98e2SPeter Wemm **  GET_COLUMN -- look up a Column in a line buffer
1932c2aa98e2SPeter Wemm **
1933c2aa98e2SPeter Wemm **	Parameters:
1934c2aa98e2SPeter Wemm **		line -- the raw text line to search.
1935c2aa98e2SPeter Wemm **		col -- the column number to fetch.
1936c2aa98e2SPeter Wemm **		delim -- the delimiter between columns.  If null,
1937c2aa98e2SPeter Wemm **			use white space.
1938c2aa98e2SPeter Wemm **		buf -- the output buffer.
1939c2aa98e2SPeter Wemm **		buflen -- the length of buf.
1940c2aa98e2SPeter Wemm **
1941c2aa98e2SPeter Wemm **	Returns:
1942c2aa98e2SPeter Wemm **		buf if successful.
1943c2aa98e2SPeter Wemm **		NULL otherwise.
1944c2aa98e2SPeter Wemm */
1945c2aa98e2SPeter Wemm 
1946c2aa98e2SPeter Wemm char *
1947c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen)
1948c2aa98e2SPeter Wemm 	char line[];
1949c2aa98e2SPeter Wemm 	int col;
195006f25ae9SGregory Neil Shapiro 	int delim;
1951c2aa98e2SPeter Wemm 	char buf[];
1952c2aa98e2SPeter Wemm 	int buflen;
1953c2aa98e2SPeter Wemm {
1954c2aa98e2SPeter Wemm 	char *p;
1955c2aa98e2SPeter Wemm 	char *begin, *end;
1956c2aa98e2SPeter Wemm 	int i;
1957c2aa98e2SPeter Wemm 	char delimbuf[4];
1958c2aa98e2SPeter Wemm 
195906f25ae9SGregory Neil Shapiro 	if ((char)delim == '\0')
196006f25ae9SGregory Neil Shapiro 		(void) strlcpy(delimbuf, "\n\t ", sizeof delimbuf);
1961c2aa98e2SPeter Wemm 	else
1962c2aa98e2SPeter Wemm 	{
196306f25ae9SGregory Neil Shapiro 		delimbuf[0] = (char)delim;
1964c2aa98e2SPeter Wemm 		delimbuf[1] = '\0';
1965c2aa98e2SPeter Wemm 	}
1966c2aa98e2SPeter Wemm 
1967c2aa98e2SPeter Wemm 	p = line;
1968c2aa98e2SPeter Wemm 	if (*p == '\0')
1969c2aa98e2SPeter Wemm 		return NULL;			/* line empty */
197006f25ae9SGregory Neil Shapiro 	if (*p == (char)delim && col == 0)
1971c2aa98e2SPeter Wemm 		return NULL;			/* first column empty */
1972c2aa98e2SPeter Wemm 
1973c2aa98e2SPeter Wemm 	begin = line;
1974c2aa98e2SPeter Wemm 
197506f25ae9SGregory Neil Shapiro 	if (col == 0 && (char)delim == '\0')
1976c2aa98e2SPeter Wemm 	{
1977c2aa98e2SPeter Wemm 		while (*begin != '\0' && isascii(*begin) && isspace(*begin))
1978c2aa98e2SPeter Wemm 			begin++;
1979c2aa98e2SPeter Wemm 	}
1980c2aa98e2SPeter Wemm 
1981c2aa98e2SPeter Wemm 	for (i = 0; i < col; i++)
1982c2aa98e2SPeter Wemm 	{
1983c2aa98e2SPeter Wemm 		if ((begin = strpbrk(begin, delimbuf)) == NULL)
1984c2aa98e2SPeter Wemm 			return NULL;		/* no such column */
1985c2aa98e2SPeter Wemm 		begin++;
198606f25ae9SGregory Neil Shapiro 		if ((char)delim == '\0')
1987c2aa98e2SPeter Wemm 		{
1988c2aa98e2SPeter Wemm 			while (*begin != '\0' && isascii(*begin) && isspace(*begin))
1989c2aa98e2SPeter Wemm 				begin++;
1990c2aa98e2SPeter Wemm 		}
1991c2aa98e2SPeter Wemm 	}
1992c2aa98e2SPeter Wemm 
1993c2aa98e2SPeter Wemm 	end = strpbrk(begin, delimbuf);
1994c2aa98e2SPeter Wemm 	if (end == NULL)
1995c2aa98e2SPeter Wemm 		i = strlen(begin);
1996c2aa98e2SPeter Wemm 	else
1997c2aa98e2SPeter Wemm 		i = end - begin;
1998c2aa98e2SPeter Wemm 	if (i >= buflen)
1999c2aa98e2SPeter Wemm 		i = buflen - 1;
200006f25ae9SGregory Neil Shapiro 	(void) strlcpy(buf, begin, i + 1);
2001c2aa98e2SPeter Wemm 	return buf;
2002c2aa98e2SPeter Wemm }
2003c2aa98e2SPeter Wemm /*
2004c2aa98e2SPeter Wemm **  CLEANSTRCPY -- copy string keeping out bogus characters
2005c2aa98e2SPeter Wemm **
2006c2aa98e2SPeter Wemm **	Parameters:
2007c2aa98e2SPeter Wemm **		t -- "to" string.
2008c2aa98e2SPeter Wemm **		f -- "from" string.
2009c2aa98e2SPeter Wemm **		l -- length of space available in "to" string.
2010c2aa98e2SPeter Wemm **
2011c2aa98e2SPeter Wemm **	Returns:
2012c2aa98e2SPeter Wemm **		none.
2013c2aa98e2SPeter Wemm */
2014c2aa98e2SPeter Wemm 
2015c2aa98e2SPeter Wemm void
2016c2aa98e2SPeter Wemm cleanstrcpy(t, f, l)
2017c2aa98e2SPeter Wemm 	register char *t;
2018c2aa98e2SPeter Wemm 	register char *f;
2019c2aa98e2SPeter Wemm 	int l;
2020c2aa98e2SPeter Wemm {
2021c2aa98e2SPeter Wemm 	/* check for newlines and log if necessary */
2022c2aa98e2SPeter Wemm 	(void) denlstring(f, TRUE, TRUE);
2023c2aa98e2SPeter Wemm 
202406f25ae9SGregory Neil Shapiro 	if (l <= 0)
202506f25ae9SGregory Neil Shapiro 		syserr("!cleanstrcpy: length == 0");
202606f25ae9SGregory Neil Shapiro 
2027c2aa98e2SPeter Wemm 	l--;
2028c2aa98e2SPeter Wemm 	while (l > 0 && *f != '\0')
2029c2aa98e2SPeter Wemm 	{
2030c2aa98e2SPeter Wemm 		if (isascii(*f) &&
2031c2aa98e2SPeter Wemm 		    (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL))
2032c2aa98e2SPeter Wemm 		{
2033c2aa98e2SPeter Wemm 			l--;
2034c2aa98e2SPeter Wemm 			*t++ = *f;
2035c2aa98e2SPeter Wemm 		}
2036c2aa98e2SPeter Wemm 		f++;
2037c2aa98e2SPeter Wemm 	}
2038c2aa98e2SPeter Wemm 	*t = '\0';
2039c2aa98e2SPeter Wemm }
204006f25ae9SGregory Neil Shapiro 
2041c2aa98e2SPeter Wemm /*
2042c2aa98e2SPeter Wemm **  DENLSTRING -- convert newlines in a string to spaces
2043c2aa98e2SPeter Wemm **
2044c2aa98e2SPeter Wemm **	Parameters:
2045c2aa98e2SPeter Wemm **		s -- the input string
2046c2aa98e2SPeter Wemm **		strict -- if set, don't permit continuation lines.
2047c2aa98e2SPeter Wemm **		logattacks -- if set, log attempted attacks.
2048c2aa98e2SPeter Wemm **
2049c2aa98e2SPeter Wemm **	Returns:
2050c2aa98e2SPeter Wemm **		A pointer to a version of the string with newlines
2051c2aa98e2SPeter Wemm **		mapped to spaces.  This should be copied.
2052c2aa98e2SPeter Wemm */
2053c2aa98e2SPeter Wemm 
2054c2aa98e2SPeter Wemm char *
2055c2aa98e2SPeter Wemm denlstring(s, strict, logattacks)
2056c2aa98e2SPeter Wemm 	char *s;
2057c2aa98e2SPeter Wemm 	bool strict;
2058c2aa98e2SPeter Wemm 	bool logattacks;
2059c2aa98e2SPeter Wemm {
2060c2aa98e2SPeter Wemm 	register char *p;
2061c2aa98e2SPeter Wemm 	int l;
2062c2aa98e2SPeter Wemm 	static char *bp = NULL;
2063c2aa98e2SPeter Wemm 	static int bl = 0;
2064c2aa98e2SPeter Wemm 
2065c2aa98e2SPeter Wemm 	p = s;
2066c2aa98e2SPeter Wemm 	while ((p = strchr(p, '\n')) != NULL)
2067c2aa98e2SPeter Wemm 		if (strict || (*++p != ' ' && *p != '\t'))
2068c2aa98e2SPeter Wemm 			break;
2069c2aa98e2SPeter Wemm 	if (p == NULL)
2070c2aa98e2SPeter Wemm 		return s;
2071c2aa98e2SPeter Wemm 
2072c2aa98e2SPeter Wemm 	l = strlen(s) + 1;
2073c2aa98e2SPeter Wemm 	if (bl < l)
2074c2aa98e2SPeter Wemm 	{
2075c2aa98e2SPeter Wemm 		/* allocate more space */
2076c2aa98e2SPeter Wemm 		if (bp != NULL)
2077c2aa98e2SPeter Wemm 			free(bp);
2078c2aa98e2SPeter Wemm 		bp = xalloc(l);
2079c2aa98e2SPeter Wemm 		bl = l;
2080c2aa98e2SPeter Wemm 	}
208106f25ae9SGregory Neil Shapiro 	(void) strlcpy(bp, s, l);
2082c2aa98e2SPeter Wemm 	for (p = bp; (p = strchr(p, '\n')) != NULL; )
2083c2aa98e2SPeter Wemm 		*p++ = ' ';
2084c2aa98e2SPeter Wemm 
2085c2aa98e2SPeter Wemm 	if (logattacks)
2086c2aa98e2SPeter Wemm 	{
2087c2aa98e2SPeter Wemm 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
2088c2aa98e2SPeter Wemm 			  "POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
2089c2aa98e2SPeter Wemm 			  RealHostName == NULL ? "[UNKNOWN]" : RealHostName,
2090c2aa98e2SPeter Wemm 			  shortenstring(bp, MAXSHORTSTR));
2091c2aa98e2SPeter Wemm 	}
2092c2aa98e2SPeter Wemm 
2093c2aa98e2SPeter Wemm 	return bp;
2094c2aa98e2SPeter Wemm }
2095c2aa98e2SPeter Wemm /*
2096c2aa98e2SPeter Wemm **  PATH_IS_DIR -- check to see if file exists and is a directory.
2097c2aa98e2SPeter Wemm **
2098c2aa98e2SPeter Wemm **	There are some additional checks for security violations in
2099c2aa98e2SPeter Wemm **	here.  This routine is intended to be used for the host status
2100c2aa98e2SPeter Wemm **	support.
2101c2aa98e2SPeter Wemm **
2102c2aa98e2SPeter Wemm **	Parameters:
2103c2aa98e2SPeter Wemm **		pathname -- pathname to check for directory-ness.
2104c2aa98e2SPeter Wemm **		createflag -- if set, create directory if needed.
2105c2aa98e2SPeter Wemm **
2106c2aa98e2SPeter Wemm **	Returns:
2107c2aa98e2SPeter Wemm **		TRUE -- if the indicated pathname is a directory
2108c2aa98e2SPeter Wemm **		FALSE -- otherwise
2109c2aa98e2SPeter Wemm */
2110c2aa98e2SPeter Wemm 
2111c2aa98e2SPeter Wemm int
2112c2aa98e2SPeter Wemm path_is_dir(pathname, createflag)
2113c2aa98e2SPeter Wemm 	char *pathname;
2114c2aa98e2SPeter Wemm 	bool createflag;
2115c2aa98e2SPeter Wemm {
2116c2aa98e2SPeter Wemm 	struct stat statbuf;
2117c2aa98e2SPeter Wemm 
2118c2aa98e2SPeter Wemm #if HASLSTAT
2119c2aa98e2SPeter Wemm 	if (lstat(pathname, &statbuf) < 0)
212006f25ae9SGregory Neil Shapiro #else /* HASLSTAT */
2121c2aa98e2SPeter Wemm 	if (stat(pathname, &statbuf) < 0)
212206f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */
2123c2aa98e2SPeter Wemm 	{
2124c2aa98e2SPeter Wemm 		if (errno != ENOENT || !createflag)
2125c2aa98e2SPeter Wemm 			return FALSE;
2126c2aa98e2SPeter Wemm 		if (mkdir(pathname, 0755) < 0)
2127c2aa98e2SPeter Wemm 			return FALSE;
2128c2aa98e2SPeter Wemm 		return TRUE;
2129c2aa98e2SPeter Wemm 	}
2130c2aa98e2SPeter Wemm 	if (!S_ISDIR(statbuf.st_mode))
2131c2aa98e2SPeter Wemm 	{
2132c2aa98e2SPeter Wemm 		errno = ENOTDIR;
2133c2aa98e2SPeter Wemm 		return FALSE;
2134c2aa98e2SPeter Wemm 	}
2135c2aa98e2SPeter Wemm 
2136c2aa98e2SPeter Wemm 	/* security: don't allow writable directories */
2137c2aa98e2SPeter Wemm 	if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode))
2138c2aa98e2SPeter Wemm 	{
2139c2aa98e2SPeter Wemm 		errno = EACCES;
2140c2aa98e2SPeter Wemm 		return FALSE;
2141c2aa98e2SPeter Wemm 	}
2142c2aa98e2SPeter Wemm 
2143c2aa98e2SPeter Wemm 	return TRUE;
2144c2aa98e2SPeter Wemm }
2145c2aa98e2SPeter Wemm /*
2146c2aa98e2SPeter Wemm **  PROC_LIST_ADD -- add process id to list of our children
2147c2aa98e2SPeter Wemm **
2148c2aa98e2SPeter Wemm **	Parameters:
2149c2aa98e2SPeter Wemm **		pid -- pid to add to list.
215006f25ae9SGregory Neil Shapiro **		task -- task of pid.
215106f25ae9SGregory Neil Shapiro **		type -- type of process.
2152c2aa98e2SPeter Wemm **
2153c2aa98e2SPeter Wemm **	Returns:
2154c2aa98e2SPeter Wemm **		none
2155c2aa98e2SPeter Wemm */
2156c2aa98e2SPeter Wemm 
2157065a643dSPeter Wemm static struct procs	*ProcListVec = NULL;
2158c2aa98e2SPeter Wemm static int		ProcListSize = 0;
2159c2aa98e2SPeter Wemm 
2160c2aa98e2SPeter Wemm void
216106f25ae9SGregory Neil Shapiro proc_list_add(pid, task, type)
2162c2aa98e2SPeter Wemm 	pid_t pid;
2163065a643dSPeter Wemm 	char *task;
216406f25ae9SGregory Neil Shapiro 	int type;
2165c2aa98e2SPeter Wemm {
2166c2aa98e2SPeter Wemm 	int i;
2167c2aa98e2SPeter Wemm 
2168c2aa98e2SPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2169c2aa98e2SPeter Wemm 	{
2170065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == NO_PID)
2171c2aa98e2SPeter Wemm 			break;
2172c2aa98e2SPeter Wemm 	}
2173c2aa98e2SPeter Wemm 	if (i >= ProcListSize)
2174c2aa98e2SPeter Wemm 	{
2175c2aa98e2SPeter Wemm 		/* probe the existing vector to avoid growing infinitely */
2176c2aa98e2SPeter Wemm 		proc_list_probe();
2177c2aa98e2SPeter Wemm 
2178c2aa98e2SPeter Wemm 		/* now scan again */
2179c2aa98e2SPeter Wemm 		for (i = 0; i < ProcListSize; i++)
2180c2aa98e2SPeter Wemm 		{
2181065a643dSPeter Wemm 			if (ProcListVec[i].proc_pid == NO_PID)
2182c2aa98e2SPeter Wemm 				break;
2183c2aa98e2SPeter Wemm 		}
2184c2aa98e2SPeter Wemm 	}
2185c2aa98e2SPeter Wemm 	if (i >= ProcListSize)
2186c2aa98e2SPeter Wemm 	{
2187c2aa98e2SPeter Wemm 		/* grow process list */
2188065a643dSPeter Wemm 		struct procs *npv;
2189c2aa98e2SPeter Wemm 
219006f25ae9SGregory Neil Shapiro 		npv = (struct procs *) xalloc((sizeof *npv) *
219106f25ae9SGregory Neil Shapiro 					      (ProcListSize + PROC_LIST_SEG));
2192c2aa98e2SPeter Wemm 		if (ProcListSize > 0)
2193c2aa98e2SPeter Wemm 		{
219406f25ae9SGregory Neil Shapiro 			memmove(npv, ProcListVec,
219506f25ae9SGregory Neil Shapiro 				ProcListSize * sizeof (struct procs));
2196c2aa98e2SPeter Wemm 			free(ProcListVec);
2197c2aa98e2SPeter Wemm 		}
2198c2aa98e2SPeter Wemm 		for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++)
2199065a643dSPeter Wemm 		{
2200065a643dSPeter Wemm 			npv[i].proc_pid = NO_PID;
2201065a643dSPeter Wemm 			npv[i].proc_task = NULL;
220206f25ae9SGregory Neil Shapiro 			npv[i].proc_type = PROC_NONE;
2203065a643dSPeter Wemm 		}
2204c2aa98e2SPeter Wemm 		i = ProcListSize;
2205c2aa98e2SPeter Wemm 		ProcListSize += PROC_LIST_SEG;
2206c2aa98e2SPeter Wemm 		ProcListVec = npv;
2207c2aa98e2SPeter Wemm 	}
2208065a643dSPeter Wemm 	ProcListVec[i].proc_pid = pid;
220906f25ae9SGregory Neil Shapiro 	if (ProcListVec[i].proc_task != NULL)
221006f25ae9SGregory Neil Shapiro 		free(ProcListVec[i].proc_task);
2211065a643dSPeter Wemm 	ProcListVec[i].proc_task = newstr(task);
221206f25ae9SGregory Neil Shapiro 	ProcListVec[i].proc_type = type;
2213065a643dSPeter Wemm 
2214065a643dSPeter Wemm 	/* if process adding itself, it's not a child */
2215065a643dSPeter Wemm 	if (pid != getpid())
2216c2aa98e2SPeter Wemm 		CurChildren++;
2217c2aa98e2SPeter Wemm }
2218c2aa98e2SPeter Wemm /*
2219065a643dSPeter Wemm **  PROC_LIST_SET -- set pid task in process list
2220065a643dSPeter Wemm **
2221065a643dSPeter Wemm **	Parameters:
2222065a643dSPeter Wemm **		pid -- pid to set
2223065a643dSPeter Wemm **		task -- task of pid
2224065a643dSPeter Wemm **
2225065a643dSPeter Wemm **	Returns:
2226065a643dSPeter Wemm **		none.
2227065a643dSPeter Wemm */
2228065a643dSPeter Wemm 
2229065a643dSPeter Wemm void
2230065a643dSPeter Wemm proc_list_set(pid, task)
2231065a643dSPeter Wemm 	pid_t pid;
2232065a643dSPeter Wemm 	char *task;
2233065a643dSPeter Wemm {
2234065a643dSPeter Wemm 	int i;
2235065a643dSPeter Wemm 
2236065a643dSPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2237065a643dSPeter Wemm 	{
2238065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == pid)
2239065a643dSPeter Wemm 		{
2240065a643dSPeter Wemm 			if (ProcListVec[i].proc_task != NULL)
2241065a643dSPeter Wemm 				free(ProcListVec[i].proc_task);
2242065a643dSPeter Wemm 			ProcListVec[i].proc_task = newstr(task);
2243065a643dSPeter Wemm 			break;
2244065a643dSPeter Wemm 		}
2245065a643dSPeter Wemm 	}
2246065a643dSPeter Wemm }
2247065a643dSPeter Wemm /*
2248c2aa98e2SPeter Wemm **  PROC_LIST_DROP -- drop pid from process list
2249c2aa98e2SPeter Wemm **
2250c2aa98e2SPeter Wemm **	Parameters:
2251c2aa98e2SPeter Wemm **		pid -- pid to drop
2252c2aa98e2SPeter Wemm **
2253c2aa98e2SPeter Wemm **	Returns:
225406f25ae9SGregory Neil Shapiro **		type of process
2255c2aa98e2SPeter Wemm */
2256c2aa98e2SPeter Wemm 
225706f25ae9SGregory Neil Shapiro int
2258c2aa98e2SPeter Wemm proc_list_drop(pid)
2259c2aa98e2SPeter Wemm 	pid_t pid;
2260c2aa98e2SPeter Wemm {
2261c2aa98e2SPeter Wemm 	int i;
226206f25ae9SGregory Neil Shapiro 	int type = PROC_NONE;
2263c2aa98e2SPeter Wemm 
2264c2aa98e2SPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2265c2aa98e2SPeter Wemm 	{
2266065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == pid)
2267c2aa98e2SPeter Wemm 		{
2268065a643dSPeter Wemm 			ProcListVec[i].proc_pid = NO_PID;
226906f25ae9SGregory Neil Shapiro 			type = ProcListVec[i].proc_type;
2270c2aa98e2SPeter Wemm 			break;
2271c2aa98e2SPeter Wemm 		}
2272c2aa98e2SPeter Wemm 	}
2273c2aa98e2SPeter Wemm 	if (CurChildren > 0)
2274c2aa98e2SPeter Wemm 		CurChildren--;
227506f25ae9SGregory Neil Shapiro 
227606f25ae9SGregory Neil Shapiro 
227706f25ae9SGregory Neil Shapiro 	return type;
2278c2aa98e2SPeter Wemm }
2279c2aa98e2SPeter Wemm /*
2280c2aa98e2SPeter Wemm **  PROC_LIST_CLEAR -- clear the process list
2281c2aa98e2SPeter Wemm **
2282c2aa98e2SPeter Wemm **	Parameters:
2283c2aa98e2SPeter Wemm **		none.
2284c2aa98e2SPeter Wemm **
2285c2aa98e2SPeter Wemm **	Returns:
2286c2aa98e2SPeter Wemm **		none.
2287c2aa98e2SPeter Wemm */
2288c2aa98e2SPeter Wemm 
2289c2aa98e2SPeter Wemm void
2290c2aa98e2SPeter Wemm proc_list_clear()
2291c2aa98e2SPeter Wemm {
2292c2aa98e2SPeter Wemm 	int i;
2293c2aa98e2SPeter Wemm 
2294065a643dSPeter Wemm 	/* start from 1 since 0 is the daemon itself */
2295065a643dSPeter Wemm 	for (i = 1; i < ProcListSize; i++)
2296065a643dSPeter Wemm 	{
2297065a643dSPeter Wemm 		ProcListVec[i].proc_pid = NO_PID;
2298065a643dSPeter Wemm 	}
2299c2aa98e2SPeter Wemm 	CurChildren = 0;
2300c2aa98e2SPeter Wemm }
2301c2aa98e2SPeter Wemm /*
2302c2aa98e2SPeter Wemm **  PROC_LIST_PROBE -- probe processes in the list to see if they still exist
2303c2aa98e2SPeter Wemm **
2304c2aa98e2SPeter Wemm **	Parameters:
2305c2aa98e2SPeter Wemm **		none
2306c2aa98e2SPeter Wemm **
2307c2aa98e2SPeter Wemm **	Returns:
2308c2aa98e2SPeter Wemm **		none
2309c2aa98e2SPeter Wemm */
2310c2aa98e2SPeter Wemm 
2311c2aa98e2SPeter Wemm void
2312c2aa98e2SPeter Wemm proc_list_probe()
2313c2aa98e2SPeter Wemm {
2314c2aa98e2SPeter Wemm 	int i;
2315c2aa98e2SPeter Wemm 
2316065a643dSPeter Wemm 	/* start from 1 since 0 is the daemon itself */
2317065a643dSPeter Wemm 	for (i = 1; i < ProcListSize; i++)
2318c2aa98e2SPeter Wemm 	{
2319065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == NO_PID)
2320c2aa98e2SPeter Wemm 			continue;
2321065a643dSPeter Wemm 		if (kill(ProcListVec[i].proc_pid, 0) < 0)
2322c2aa98e2SPeter Wemm 		{
2323c2aa98e2SPeter Wemm 			if (LogLevel > 3)
2324c2aa98e2SPeter Wemm 				sm_syslog(LOG_DEBUG, CurEnv->e_id,
2325c2aa98e2SPeter Wemm 					  "proc_list_probe: lost pid %d",
2326065a643dSPeter Wemm 					  (int) ProcListVec[i].proc_pid);
2327065a643dSPeter Wemm 			ProcListVec[i].proc_pid = NO_PID;
2328c2aa98e2SPeter Wemm 			CurChildren--;
2329c2aa98e2SPeter Wemm 		}
2330c2aa98e2SPeter Wemm 	}
2331c2aa98e2SPeter Wemm 	if (CurChildren < 0)
2332c2aa98e2SPeter Wemm 		CurChildren = 0;
2333c2aa98e2SPeter Wemm }
2334c2aa98e2SPeter Wemm /*
2335065a643dSPeter Wemm **  PROC_LIST_DISPLAY -- display the process list
2336065a643dSPeter Wemm **
2337065a643dSPeter Wemm **	Parameters:
2338065a643dSPeter Wemm **		out -- output file pointer
2339065a643dSPeter Wemm **
2340065a643dSPeter Wemm **	Returns:
2341065a643dSPeter Wemm **		none.
2342065a643dSPeter Wemm */
2343065a643dSPeter Wemm 
2344065a643dSPeter Wemm void
2345065a643dSPeter Wemm proc_list_display(out)
2346065a643dSPeter Wemm 	FILE *out;
2347065a643dSPeter Wemm {
2348065a643dSPeter Wemm 	int i;
2349065a643dSPeter Wemm 
2350065a643dSPeter Wemm 	for (i = 0; i < ProcListSize; i++)
2351065a643dSPeter Wemm 	{
2352065a643dSPeter Wemm 		if (ProcListVec[i].proc_pid == NO_PID)
2353065a643dSPeter Wemm 			continue;
2354065a643dSPeter Wemm 
2355065a643dSPeter Wemm 		fprintf(out, "%d %s%s\n", (int) ProcListVec[i].proc_pid,
2356065a643dSPeter Wemm 			ProcListVec[i].proc_task != NULL ?
2357065a643dSPeter Wemm 			ProcListVec[i].proc_task : "(unknown)",
2358065a643dSPeter Wemm 			(OpMode == MD_SMTP ||
2359065a643dSPeter Wemm 			 OpMode == MD_DAEMON ||
2360065a643dSPeter Wemm 			 OpMode == MD_ARPAFTP) ? "\r" : "");
2361065a643dSPeter Wemm 	}
2362065a643dSPeter Wemm }
2363065a643dSPeter Wemm /*
2364c2aa98e2SPeter Wemm **  SM_STRCASECMP -- 8-bit clean version of strcasecmp
2365c2aa98e2SPeter Wemm **
2366c2aa98e2SPeter Wemm **	Thank you, vendors, for making this all necessary.
2367c2aa98e2SPeter Wemm */
2368c2aa98e2SPeter Wemm 
2369c2aa98e2SPeter Wemm /*
2370c2aa98e2SPeter Wemm  * Copyright (c) 1987, 1993
2371c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
2372c2aa98e2SPeter Wemm  *
2373c2aa98e2SPeter Wemm  * Redistribution and use in source and binary forms, with or without
2374c2aa98e2SPeter Wemm  * modification, are permitted provided that the following conditions
2375c2aa98e2SPeter Wemm  * are met:
2376c2aa98e2SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
2377c2aa98e2SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
2378c2aa98e2SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
2379c2aa98e2SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
2380c2aa98e2SPeter Wemm  *    documentation and/or other materials provided with the distribution.
2381c2aa98e2SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
2382c2aa98e2SPeter Wemm  *    must display the following acknowledgement:
2383c2aa98e2SPeter Wemm  *	This product includes software developed by the University of
2384c2aa98e2SPeter Wemm  *	California, Berkeley and its contributors.
2385c2aa98e2SPeter Wemm  * 4. Neither the name of the University nor the names of its contributors
2386c2aa98e2SPeter Wemm  *    may be used to endorse or promote products derived from this software
2387c2aa98e2SPeter Wemm  *    without specific prior written permission.
2388c2aa98e2SPeter Wemm  *
2389c2aa98e2SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2390c2aa98e2SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2391c2aa98e2SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2392c2aa98e2SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2393c2aa98e2SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2394c2aa98e2SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2395c2aa98e2SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2396c2aa98e2SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2397c2aa98e2SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2398c2aa98e2SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2399c2aa98e2SPeter Wemm  * SUCH DAMAGE.
2400c2aa98e2SPeter Wemm  */
2401c2aa98e2SPeter Wemm 
2402c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint)
2403c2aa98e2SPeter Wemm static char sccsid[] = "@(#)strcasecmp.c	8.1 (Berkeley) 6/4/93";
240406f25ae9SGregory Neil Shapiro #endif /* defined(LIBC_SCCS) && !defined(lint) */
2405c2aa98e2SPeter Wemm 
2406c2aa98e2SPeter Wemm /*
2407c2aa98e2SPeter Wemm  * This array is designed for mapping upper and lower case letter
2408c2aa98e2SPeter Wemm  * together for a case independent comparison.  The mappings are
2409c2aa98e2SPeter Wemm  * based upon ascii character sequences.
2410c2aa98e2SPeter Wemm  */
2411c2aa98e2SPeter Wemm static const u_char charmap[] = {
2412c2aa98e2SPeter Wemm 	0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
2413c2aa98e2SPeter Wemm 	0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
2414c2aa98e2SPeter Wemm 	0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
2415c2aa98e2SPeter Wemm 	0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
2416c2aa98e2SPeter Wemm 	0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
2417c2aa98e2SPeter Wemm 	0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
2418c2aa98e2SPeter Wemm 	0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
2419c2aa98e2SPeter Wemm 	0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
2420c2aa98e2SPeter Wemm 	0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
2421c2aa98e2SPeter Wemm 	0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
2422c2aa98e2SPeter Wemm 	0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
2423c2aa98e2SPeter Wemm 	0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
2424c2aa98e2SPeter Wemm 	0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
2425c2aa98e2SPeter Wemm 	0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
2426c2aa98e2SPeter Wemm 	0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
2427c2aa98e2SPeter Wemm 	0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
2428c2aa98e2SPeter Wemm 	0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
2429c2aa98e2SPeter Wemm 	0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
2430c2aa98e2SPeter Wemm 	0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
2431c2aa98e2SPeter Wemm 	0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
2432c2aa98e2SPeter Wemm 	0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
2433c2aa98e2SPeter Wemm 	0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
2434c2aa98e2SPeter Wemm 	0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
2435c2aa98e2SPeter Wemm 	0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
2436c2aa98e2SPeter Wemm 	0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
2437c2aa98e2SPeter Wemm 	0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
2438c2aa98e2SPeter Wemm 	0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
2439c2aa98e2SPeter Wemm 	0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
2440c2aa98e2SPeter Wemm 	0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
2441c2aa98e2SPeter Wemm 	0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
2442c2aa98e2SPeter Wemm 	0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
2443c2aa98e2SPeter Wemm 	0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
2444c2aa98e2SPeter Wemm };
2445c2aa98e2SPeter Wemm 
2446c2aa98e2SPeter Wemm int
2447c2aa98e2SPeter Wemm sm_strcasecmp(s1, s2)
2448c2aa98e2SPeter Wemm 	const char *s1, *s2;
2449c2aa98e2SPeter Wemm {
2450c2aa98e2SPeter Wemm 	register const u_char *cm = charmap,
2451c2aa98e2SPeter Wemm 			*us1 = (const u_char *)s1,
2452c2aa98e2SPeter Wemm 			*us2 = (const u_char *)s2;
2453c2aa98e2SPeter Wemm 
2454c2aa98e2SPeter Wemm 	while (cm[*us1] == cm[*us2++])
2455c2aa98e2SPeter Wemm 		if (*us1++ == '\0')
245606f25ae9SGregory Neil Shapiro 			return 0;
2457c2aa98e2SPeter Wemm 	return (cm[*us1] - cm[*--us2]);
2458c2aa98e2SPeter Wemm }
2459c2aa98e2SPeter Wemm 
2460c2aa98e2SPeter Wemm int
2461c2aa98e2SPeter Wemm sm_strncasecmp(s1, s2, n)
2462c2aa98e2SPeter Wemm 	const char *s1, *s2;
2463c2aa98e2SPeter Wemm 	register size_t n;
2464c2aa98e2SPeter Wemm {
2465c2aa98e2SPeter Wemm 	if (n != 0) {
2466c2aa98e2SPeter Wemm 		register const u_char *cm = charmap,
2467c2aa98e2SPeter Wemm 				*us1 = (const u_char *)s1,
2468c2aa98e2SPeter Wemm 				*us2 = (const u_char *)s2;
2469c2aa98e2SPeter Wemm 
2470c2aa98e2SPeter Wemm 		do {
2471c2aa98e2SPeter Wemm 			if (cm[*us1] != cm[*us2++])
2472c2aa98e2SPeter Wemm 				return (cm[*us1] - cm[*--us2]);
2473c2aa98e2SPeter Wemm 			if (*us1++ == '\0')
2474c2aa98e2SPeter Wemm 				break;
2475c2aa98e2SPeter Wemm 		} while (--n != 0);
2476c2aa98e2SPeter Wemm 	}
247706f25ae9SGregory Neil Shapiro 	return 0;
2478c2aa98e2SPeter Wemm }
2479