xref: /freebsd/contrib/sendmail/src/conf.c (revision e01d6f6164d26cbad2f5ce30c2d755c57da9b354)
1c2aa98e2SPeter Wemm /*
2c2aa98e2SPeter Wemm  * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3c2aa98e2SPeter Wemm  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1988, 1993
5c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
6c2aa98e2SPeter Wemm  *
7c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
8c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
9c2aa98e2SPeter Wemm  * the sendmail distribution.
10c2aa98e2SPeter Wemm  *
11c2aa98e2SPeter Wemm  */
12c2aa98e2SPeter Wemm 
13c2aa98e2SPeter Wemm #ifndef lint
14e01d6f61SPeter Wemm static char sccsid[] = "@(#)conf.c	8.452 (Berkeley) 1/26/1999";
15c2aa98e2SPeter Wemm #endif /* not lint */
16c2aa98e2SPeter Wemm 
17c2aa98e2SPeter Wemm # include "sendmail.h"
18c2aa98e2SPeter Wemm # include "pathnames.h"
19c2aa98e2SPeter Wemm # include <sys/ioctl.h>
20c2aa98e2SPeter Wemm # include <sys/param.h>
21c2aa98e2SPeter Wemm # include <limits.h>
22c2aa98e2SPeter Wemm 
23c2aa98e2SPeter Wemm /*
24c2aa98e2SPeter Wemm **  CONF.C -- Sendmail Configuration Tables.
25c2aa98e2SPeter Wemm **
26c2aa98e2SPeter Wemm **	Defines the configuration of this installation.
27c2aa98e2SPeter Wemm **
28c2aa98e2SPeter Wemm **	Configuration Variables:
29c2aa98e2SPeter Wemm **		HdrInfo -- a table describing well-known header fields.
30c2aa98e2SPeter Wemm **			Each entry has the field name and some flags,
31c2aa98e2SPeter Wemm **			which are described in sendmail.h.
32c2aa98e2SPeter Wemm **
33c2aa98e2SPeter Wemm **	Notes:
34c2aa98e2SPeter Wemm **		I have tried to put almost all the reasonable
35c2aa98e2SPeter Wemm **		configuration information into the configuration
36c2aa98e2SPeter Wemm **		file read at runtime.  My intent is that anything
37c2aa98e2SPeter Wemm **		here is a function of the version of UNIX you
38c2aa98e2SPeter Wemm **		are running, or is really static -- for example
39c2aa98e2SPeter Wemm **		the headers are a superset of widely used
40c2aa98e2SPeter Wemm **		protocols.  If you find yourself playing with
41c2aa98e2SPeter Wemm **		this file too much, you may be making a mistake!
42c2aa98e2SPeter Wemm */
43c2aa98e2SPeter Wemm 
44c2aa98e2SPeter Wemm 
45c2aa98e2SPeter Wemm /*
46c2aa98e2SPeter Wemm **  Header info table
47c2aa98e2SPeter Wemm **	Final (null) entry contains the flags used for any other field.
48c2aa98e2SPeter Wemm **
49c2aa98e2SPeter Wemm **	Not all of these are actually handled specially by sendmail
50c2aa98e2SPeter Wemm **	at this time.  They are included as placeholders, to let
51c2aa98e2SPeter Wemm **	you know that "someday" I intend to have sendmail do
52c2aa98e2SPeter Wemm **	something with them.
53c2aa98e2SPeter Wemm */
54c2aa98e2SPeter Wemm 
55c2aa98e2SPeter Wemm struct hdrinfo	HdrInfo[] =
56c2aa98e2SPeter Wemm {
57c2aa98e2SPeter Wemm 		/* originator fields, most to least significant  */
58c2aa98e2SPeter Wemm 	{ "resent-sender",		H_FROM|H_RESENT			},
59c2aa98e2SPeter Wemm 	{ "resent-from",		H_FROM|H_RESENT			},
60c2aa98e2SPeter Wemm 	{ "resent-reply-to",		H_FROM|H_RESENT			},
61c2aa98e2SPeter Wemm 	{ "sender",			H_FROM				},
62c2aa98e2SPeter Wemm 	{ "from",			H_FROM				},
63c2aa98e2SPeter Wemm 	{ "reply-to",			H_FROM				},
64c2aa98e2SPeter Wemm 	{ "errors-to",			H_FROM|H_ERRORSTO		},
65c2aa98e2SPeter Wemm 	{ "full-name",			H_ACHECK			},
66c2aa98e2SPeter Wemm 	{ "return-receipt-to",		H_RECEIPTTO			},
67c2aa98e2SPeter Wemm 
68c2aa98e2SPeter Wemm 		/* destination fields */
69c2aa98e2SPeter Wemm 	{ "to",				H_RCPT				},
70c2aa98e2SPeter Wemm 	{ "resent-to",			H_RCPT|H_RESENT			},
71c2aa98e2SPeter Wemm 	{ "cc",				H_RCPT				},
72c2aa98e2SPeter Wemm 	{ "resent-cc",			H_RCPT|H_RESENT			},
73c2aa98e2SPeter Wemm 	{ "bcc",			H_RCPT|H_BCC			},
74c2aa98e2SPeter Wemm 	{ "resent-bcc",			H_RCPT|H_BCC|H_RESENT		},
75c2aa98e2SPeter Wemm 	{ "apparently-to",		H_RCPT				},
76c2aa98e2SPeter Wemm 
77c2aa98e2SPeter Wemm 		/* message identification and control */
78c2aa98e2SPeter Wemm 	{ "message-id",			0				},
79c2aa98e2SPeter Wemm 	{ "resent-message-id",		H_RESENT			},
80c2aa98e2SPeter Wemm 	{ "message",			H_EOH				},
81c2aa98e2SPeter Wemm 	{ "text",			H_EOH				},
82c2aa98e2SPeter Wemm 
83c2aa98e2SPeter Wemm 		/* date fields */
84c2aa98e2SPeter Wemm 	{ "date",			0				},
85c2aa98e2SPeter Wemm 	{ "resent-date",		H_RESENT			},
86c2aa98e2SPeter Wemm 
87c2aa98e2SPeter Wemm 		/* trace fields */
88c2aa98e2SPeter Wemm 	{ "received",			H_TRACE|H_FORCE			},
89c2aa98e2SPeter Wemm 	{ "x400-received",		H_TRACE|H_FORCE			},
90c2aa98e2SPeter Wemm 	{ "via",			H_TRACE|H_FORCE			},
91c2aa98e2SPeter Wemm 	{ "mail-from",			H_TRACE|H_FORCE			},
92c2aa98e2SPeter Wemm 
93c2aa98e2SPeter Wemm 		/* miscellaneous fields */
94c2aa98e2SPeter Wemm 	{ "comments",			H_FORCE|H_ENCODABLE		},
95c2aa98e2SPeter Wemm 	{ "return-path",		H_FORCE|H_ACHECK		},
96c2aa98e2SPeter Wemm 	{ "content-transfer-encoding",	H_CTE				},
97c2aa98e2SPeter Wemm 	{ "content-type",		H_CTYPE				},
98c2aa98e2SPeter Wemm 	{ "content-length",		H_ACHECK			},
99c2aa98e2SPeter Wemm 	{ "subject",			H_ENCODABLE			},
100c2aa98e2SPeter Wemm 
101c2aa98e2SPeter Wemm 	{ NULL,				0				}
102c2aa98e2SPeter Wemm };
103c2aa98e2SPeter Wemm 
104c2aa98e2SPeter Wemm 
105c2aa98e2SPeter Wemm 
106c2aa98e2SPeter Wemm /*
107c2aa98e2SPeter Wemm **  Privacy values
108c2aa98e2SPeter Wemm */
109c2aa98e2SPeter Wemm 
110c2aa98e2SPeter Wemm struct prival PrivacyValues[] =
111c2aa98e2SPeter Wemm {
112c2aa98e2SPeter Wemm 	{ "public",		PRIV_PUBLIC		},
113c2aa98e2SPeter Wemm 	{ "needmailhelo",	PRIV_NEEDMAILHELO	},
114c2aa98e2SPeter Wemm 	{ "needexpnhelo",	PRIV_NEEDEXPNHELO	},
115c2aa98e2SPeter Wemm 	{ "needvrfyhelo",	PRIV_NEEDVRFYHELO	},
116c2aa98e2SPeter Wemm 	{ "noexpn",		PRIV_NOEXPN		},
117c2aa98e2SPeter Wemm 	{ "novrfy",		PRIV_NOVRFY		},
118c2aa98e2SPeter Wemm 	{ "restrictmailq",	PRIV_RESTRICTMAILQ	},
119c2aa98e2SPeter Wemm 	{ "restrictqrun",	PRIV_RESTRICTQRUN	},
120c2aa98e2SPeter Wemm 	{ "noetrn",		PRIV_NOETRN		},
121c2aa98e2SPeter Wemm 	{ "noverb",		PRIV_NOVERB		},
122c2aa98e2SPeter Wemm 	{ "authwarnings",	PRIV_AUTHWARNINGS	},
123c2aa98e2SPeter Wemm 	{ "noreceipts",		PRIV_NORECEIPTS		},
124c2aa98e2SPeter Wemm 	{ "goaway",		PRIV_GOAWAY		},
125c2aa98e2SPeter Wemm 	{ NULL,			0			}
126c2aa98e2SPeter Wemm };
127c2aa98e2SPeter Wemm 
128c2aa98e2SPeter Wemm /*
129c2aa98e2SPeter Wemm **  DontBlameSendmail values
130c2aa98e2SPeter Wemm */
131c2aa98e2SPeter Wemm struct dbsval DontBlameSendmailValues[] =
132c2aa98e2SPeter Wemm {
133c2aa98e2SPeter Wemm 	{ "safe",			DBS_SAFE			},
134c2aa98e2SPeter Wemm 	{ "assumesafechown",		DBS_ASSUMESAFECHOWN		},
135c2aa98e2SPeter Wemm 	{ "groupwritabledirpathsafe",	DBS_GROUPWRITABLEDIRPATHSAFE	},
136c2aa98e2SPeter Wemm 	{ "groupwritableforwardfilesafe",
137c2aa98e2SPeter Wemm 					DBS_GROUPWRITABLEFORWARDFILESAFE },
138c2aa98e2SPeter Wemm 	{ "groupwritableincludefilesafe",
139c2aa98e2SPeter Wemm 					DBS_GROUPWRITABLEINCLUDEFILESAFE },
140c2aa98e2SPeter Wemm 	{ "groupwritablealiasfile",	DBS_GROUPWRITABLEALIASFILE	},
141c2aa98e2SPeter Wemm 	{ "worldwritablealiasfile",	DBS_WORLDWRITABLEALIASFILE	},
142c2aa98e2SPeter Wemm 	{ "forwardfileinunsafedirpath",	DBS_FORWARDFILEINUNSAFEDIRPATH	},
143c2aa98e2SPeter Wemm 	{ "includefileinunsafedirpath",	DBS_INCLUDEFILEINUNSAFEDIRPATH	},
144c2aa98e2SPeter Wemm 	{ "mapinunsafedirpath",		DBS_MAPINUNSAFEDIRPATH	},
145c2aa98e2SPeter Wemm 	{ "linkedaliasfileinwritabledir",
146c2aa98e2SPeter Wemm 					DBS_LINKEDALIASFILEINWRITABLEDIR },
147c2aa98e2SPeter Wemm 	{ "linkedclassfileinwritabledir",
148c2aa98e2SPeter Wemm 					DBS_LINKEDCLASSFILEINWRITABLEDIR },
149c2aa98e2SPeter Wemm 	{ "linkedforwardfileinwritabledir",
150c2aa98e2SPeter Wemm 					DBS_LINKEDFORWARDFILEINWRITABLEDIR },
151c2aa98e2SPeter Wemm 	{ "linkedincludefileinwritabledir",
152c2aa98e2SPeter Wemm 					DBS_LINKEDINCLUDEFILEINWRITABLEDIR },
153c2aa98e2SPeter Wemm 	{ "linkedmapinwritabledir",	DBS_LINKEDMAPINWRITABLEDIR	},
154c2aa98e2SPeter Wemm 	{ "linkedserviceswitchfileinwritabledir",
155c2aa98e2SPeter Wemm 					DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR },
156c2aa98e2SPeter Wemm 	{ "filedeliverytohardlink",	DBS_FILEDELIVERYTOHARDLINK	},
157c2aa98e2SPeter Wemm 	{ "filedeliverytosymlink",	DBS_FILEDELIVERYTOSYMLINK	},
158c2aa98e2SPeter Wemm 	{ "writemaptohardlink",		DBS_WRITEMAPTOHARDLINK		},
159c2aa98e2SPeter Wemm 	{ "writemaptosymlink",		DBS_WRITEMAPTOSYMLINK		},
160c2aa98e2SPeter Wemm 	{ "writestatstohardlink",	DBS_WRITESTATSTOHARDLINK	},
161c2aa98e2SPeter Wemm 	{ "writestatstosymlink",	DBS_WRITESTATSTOSYMLINK		},
162c2aa98e2SPeter Wemm 	{ "forwardfileingroupwritabledirpath",
163c2aa98e2SPeter Wemm 					DBS_FORWARDFILEINGROUPWRITABLEDIRPATH },
164c2aa98e2SPeter Wemm 	{ "includefileingroupwritabledirpath",
165c2aa98e2SPeter Wemm 					DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH },
166c2aa98e2SPeter Wemm 	{ "classfileinunsafedirpath",	DBS_CLASSFILEINUNSAFEDIRPATH	},
167c2aa98e2SPeter Wemm 	{ "errorheaderinunsafedirpath",	DBS_ERRORHEADERINUNSAFEDIRPATH	},
168c2aa98e2SPeter Wemm 	{ "helpfileinunsafedirpath",	DBS_HELPFILEINUNSAFEDIRPATH	},
169c2aa98e2SPeter Wemm 	{ "forwardfileinunsafedirpathsafe",
170c2aa98e2SPeter Wemm 					DBS_FORWARDFILEINUNSAFEDIRPATHSAFE },
171c2aa98e2SPeter Wemm 	{ "includefileinunsafedirpathsafe",
172c2aa98e2SPeter Wemm 					DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE },
173c2aa98e2SPeter Wemm 	{ "runprograminunsafedirpath",	DBS_RUNPROGRAMINUNSAFEDIRPATH	},
174c2aa98e2SPeter Wemm 	{ "runwritableprogram",		DBS_RUNWRITABLEPROGRAM		},
175c2aa98e2SPeter Wemm 	{ NULL,				0				}
176c2aa98e2SPeter Wemm };
177c2aa98e2SPeter Wemm 
178c2aa98e2SPeter Wemm 
179c2aa98e2SPeter Wemm /*
180c2aa98e2SPeter Wemm **  Miscellaneous stuff.
181c2aa98e2SPeter Wemm */
182c2aa98e2SPeter Wemm 
183c2aa98e2SPeter Wemm int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
184c2aa98e2SPeter Wemm /*
185c2aa98e2SPeter Wemm **  SETDEFAULTS -- set default values
186c2aa98e2SPeter Wemm **
187c2aa98e2SPeter Wemm **	Because of the way freezing is done, these must be initialized
188c2aa98e2SPeter Wemm **	using direct code.
189c2aa98e2SPeter Wemm **
190c2aa98e2SPeter Wemm **	Parameters:
191c2aa98e2SPeter Wemm **		e -- the default envelope.
192c2aa98e2SPeter Wemm **
193c2aa98e2SPeter Wemm **	Returns:
194c2aa98e2SPeter Wemm **		none.
195c2aa98e2SPeter Wemm **
196c2aa98e2SPeter Wemm **	Side Effects:
197c2aa98e2SPeter Wemm **		Initializes a bunch of global variables to their
198c2aa98e2SPeter Wemm **		default values.
199c2aa98e2SPeter Wemm */
200c2aa98e2SPeter Wemm 
201c2aa98e2SPeter Wemm #define MINUTES		* 60
202c2aa98e2SPeter Wemm #define HOURS		* 60 MINUTES
203c2aa98e2SPeter Wemm #define DAYS		* 24 HOURS
204c2aa98e2SPeter Wemm 
205c2aa98e2SPeter Wemm #ifndef _PATH_VARTMP
206c2aa98e2SPeter Wemm # define _PATH_VARTMP	"/usr/tmp/"
207c2aa98e2SPeter Wemm #endif
208c2aa98e2SPeter Wemm 
209c2aa98e2SPeter Wemm #ifndef MAXRULERECURSION
210c2aa98e2SPeter Wemm # define MAXRULERECURSION	50	/* max ruleset recursion depth */
211c2aa98e2SPeter Wemm #endif
212c2aa98e2SPeter Wemm 
213c2aa98e2SPeter Wemm void
214c2aa98e2SPeter Wemm setdefaults(e)
215c2aa98e2SPeter Wemm 	register ENVELOPE *e;
216c2aa98e2SPeter Wemm {
217c2aa98e2SPeter Wemm 	int i;
218c2aa98e2SPeter Wemm 	struct passwd *pw;
219c2aa98e2SPeter Wemm 	char buf[MAXNAME];
220c2aa98e2SPeter Wemm 	extern void setdefuser __P((void));
221c2aa98e2SPeter Wemm 	extern void setupmaps __P((void));
222c2aa98e2SPeter Wemm 	extern void setupmailers __P((void));
223c2aa98e2SPeter Wemm 	extern void setupheaders __P((void));
224c2aa98e2SPeter Wemm 
225c2aa98e2SPeter Wemm 	SpaceSub = ' ';				/* option B */
226c2aa98e2SPeter Wemm 	QueueLA = 8;				/* option x */
227c2aa98e2SPeter Wemm 	RefuseLA = 12;				/* option X */
228c2aa98e2SPeter Wemm 	WkRecipFact = 30000L;			/* option y */
229c2aa98e2SPeter Wemm 	WkClassFact = 1800L;			/* option z */
230c2aa98e2SPeter Wemm 	WkTimeFact = 90000L;			/* option Z */
231c2aa98e2SPeter Wemm 	QueueFactor = WkRecipFact * 20;		/* option q */
232c2aa98e2SPeter Wemm 	FileMode = (RealUid != geteuid()) ? 0644 : 0600;
233c2aa98e2SPeter Wemm 						/* option F */
234c2aa98e2SPeter Wemm 
235c2aa98e2SPeter Wemm 	if (((pw = getpwnam("mailnull")) != NULL && pw->pw_uid != 0) ||
236c2aa98e2SPeter Wemm 	    ((pw = getpwnam("sendmail")) != NULL && pw->pw_uid != 0) ||
237c2aa98e2SPeter Wemm 	    ((pw = getpwnam("daemon")) != NULL && pw->pw_uid != 0))
238c2aa98e2SPeter Wemm 	{
239c2aa98e2SPeter Wemm 		DefUid = pw->pw_uid;		/* option u */
240c2aa98e2SPeter Wemm 		DefGid = pw->pw_gid;		/* option g */
241c2aa98e2SPeter Wemm 		DefUser = newstr(pw->pw_name);
242c2aa98e2SPeter Wemm 	}
243c2aa98e2SPeter Wemm 	else
244c2aa98e2SPeter Wemm 	{
245c2aa98e2SPeter Wemm 		DefUid = 1;			/* option u */
246c2aa98e2SPeter Wemm 		DefGid = 1;			/* option g */
247c2aa98e2SPeter Wemm 		setdefuser();
248c2aa98e2SPeter Wemm 	}
24976b7bf71SPeter Wemm 	TrustedUid = 0;
250c2aa98e2SPeter Wemm 	if (tTd(37, 4))
251c2aa98e2SPeter Wemm 		printf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n",
252c2aa98e2SPeter Wemm 		       DefUser != NULL ? DefUser : "<1:1>",
253c2aa98e2SPeter Wemm 		       (int) DefUid, (int) DefGid);
254c2aa98e2SPeter Wemm 	CheckpointInterval = 10;		/* option C */
255c2aa98e2SPeter Wemm 	MaxHopCount = 25;			/* option h */
256c2aa98e2SPeter Wemm 	e->e_sendmode = SM_FORK;		/* option d */
257c2aa98e2SPeter Wemm 	e->e_errormode = EM_PRINT;		/* option e */
258c2aa98e2SPeter Wemm 	SevenBitInput = FALSE;			/* option 7 */
259c2aa98e2SPeter Wemm 	MaxMciCache = 1;			/* option k */
260c2aa98e2SPeter Wemm 	MciCacheTimeout = 5 MINUTES;		/* option K */
261c2aa98e2SPeter Wemm 	LogLevel = 9;				/* option L */
262c2aa98e2SPeter Wemm 	inittimeouts(NULL);			/* option r */
263c2aa98e2SPeter Wemm 	PrivacyFlags = PRIV_PUBLIC;		/* option p */
264c2aa98e2SPeter Wemm 	DontBlameSendmail = DBS_SAFE;		/* DontBlameSendmail option */
265c2aa98e2SPeter Wemm #if MIME8TO7
266c2aa98e2SPeter Wemm 	MimeMode = MM_CVTMIME|MM_PASS8BIT;	/* option 8 */
267c2aa98e2SPeter Wemm #else
268c2aa98e2SPeter Wemm 	MimeMode = MM_PASS8BIT;
269c2aa98e2SPeter Wemm #endif
270c2aa98e2SPeter Wemm 	for (i = 0; i < MAXTOCLASS; i++)
271c2aa98e2SPeter Wemm 	{
272c2aa98e2SPeter Wemm 		TimeOuts.to_q_return[i] = 5 DAYS;	/* option T */
273c2aa98e2SPeter Wemm 		TimeOuts.to_q_warning[i] = 0;		/* option T */
274c2aa98e2SPeter Wemm 	}
275c2aa98e2SPeter Wemm 	ServiceSwitchFile = "/etc/service.switch";
276c2aa98e2SPeter Wemm 	ServiceCacheMaxAge = (time_t) 10;
277c2aa98e2SPeter Wemm 	HostsFile = _PATH_HOSTS;
278c2aa98e2SPeter Wemm 	PidFile = newstr(_PATH_SENDMAILPID);
279c2aa98e2SPeter Wemm 	MustQuoteChars = "@,;:\\()[].'";
280c2aa98e2SPeter Wemm 	MciInfoTimeout = 30 MINUTES;
281c2aa98e2SPeter Wemm 	MaxRuleRecursion = MAXRULERECURSION;
282c2aa98e2SPeter Wemm 	MaxAliasRecursion = 10;
283c2aa98e2SPeter Wemm 	MaxMacroRecursion = 10;
284c2aa98e2SPeter Wemm 	ColonOkInAddr = TRUE;
285c2aa98e2SPeter Wemm 	DontLockReadFiles = TRUE;
286c2aa98e2SPeter Wemm 	DoubleBounceAddr = "postmaster";
287e01d6f61SPeter Wemm 	MaxHeadersLength = MAXHDRSLEN;
288c2aa98e2SPeter Wemm 	snprintf(buf, sizeof buf, "%s%sdead.letter",
289c2aa98e2SPeter Wemm 		_PATH_VARTMP,
290c2aa98e2SPeter Wemm 		_PATH_VARTMP[sizeof _PATH_VARTMP - 2] == '/' ? "" : "/");
291c2aa98e2SPeter Wemm 	DeadLetterDrop = newstr(buf);
292c2aa98e2SPeter Wemm #ifdef HESIOD_INIT
293c2aa98e2SPeter Wemm 	HesiodContext = NULL;
294c2aa98e2SPeter Wemm #endif
29576b7bf71SPeter Wemm 	ControlSocketName = NULL;
296c2aa98e2SPeter Wemm 	setupmaps();
297c2aa98e2SPeter Wemm 	setupmailers();
298c2aa98e2SPeter Wemm 	setupheaders();
299c2aa98e2SPeter Wemm }
300c2aa98e2SPeter Wemm 
301c2aa98e2SPeter Wemm 
302c2aa98e2SPeter Wemm /*
303c2aa98e2SPeter Wemm **  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
304c2aa98e2SPeter Wemm */
305c2aa98e2SPeter Wemm 
306c2aa98e2SPeter Wemm void
307c2aa98e2SPeter Wemm setdefuser()
308c2aa98e2SPeter Wemm {
309c2aa98e2SPeter Wemm 	struct passwd *defpwent;
310c2aa98e2SPeter Wemm 	static char defuserbuf[40];
311c2aa98e2SPeter Wemm 
312c2aa98e2SPeter Wemm 	DefUser = defuserbuf;
313c2aa98e2SPeter Wemm 	defpwent = sm_getpwuid(DefUid);
314c2aa98e2SPeter Wemm 	snprintf(defuserbuf, sizeof defuserbuf, "%s",
315c2aa98e2SPeter Wemm 		defpwent == NULL ? "nobody" : defpwent->pw_name);
316c2aa98e2SPeter Wemm 	if (tTd(37, 4))
317c2aa98e2SPeter Wemm 		printf("setdefuser: DefUid=%d, DefUser=%s\n",
318c2aa98e2SPeter Wemm 		       (int) DefUid, DefUser);
319c2aa98e2SPeter Wemm }
320c2aa98e2SPeter Wemm /*
321c2aa98e2SPeter Wemm **  SETUPMAILERS -- initialize default mailers
322c2aa98e2SPeter Wemm */
323c2aa98e2SPeter Wemm 
324c2aa98e2SPeter Wemm void
325c2aa98e2SPeter Wemm setupmailers()
326c2aa98e2SPeter Wemm {
327c2aa98e2SPeter Wemm 	char buf[100];
328c2aa98e2SPeter Wemm 
329c2aa98e2SPeter Wemm 	strcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=DNS/RFC822/X-Unix, A=sh -c \201u");
330c2aa98e2SPeter Wemm 	makemailer(buf);
331c2aa98e2SPeter Wemm 
332c2aa98e2SPeter Wemm 	strcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=DNS/RFC822/X-Unix, A=FILE \201u");
333c2aa98e2SPeter Wemm 	makemailer(buf);
334c2aa98e2SPeter Wemm 
335c2aa98e2SPeter Wemm 	strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u");
336c2aa98e2SPeter Wemm 	makemailer(buf);
337c2aa98e2SPeter Wemm }
338c2aa98e2SPeter Wemm /*
339c2aa98e2SPeter Wemm **  SETUPMAPS -- set up map classes
340c2aa98e2SPeter Wemm */
341c2aa98e2SPeter Wemm 
342c2aa98e2SPeter Wemm #define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \
343c2aa98e2SPeter Wemm 	{ \
344c2aa98e2SPeter Wemm 		extern bool parse __P((MAP *, char *)); \
345c2aa98e2SPeter Wemm 		extern bool open __P((MAP *, int)); \
346c2aa98e2SPeter Wemm 		extern void close __P((MAP *)); \
347c2aa98e2SPeter Wemm 		extern char *lookup __P((MAP *, char *, char **, int *)); \
348c2aa98e2SPeter Wemm 		extern void store __P((MAP *, char *, char *)); \
349c2aa98e2SPeter Wemm 		s = stab(name, ST_MAPCLASS, ST_ENTER); \
350c2aa98e2SPeter Wemm 		s->s_mapclass.map_cname = name; \
351c2aa98e2SPeter Wemm 		s->s_mapclass.map_ext = ext; \
352c2aa98e2SPeter Wemm 		s->s_mapclass.map_cflags = flags; \
353c2aa98e2SPeter Wemm 		s->s_mapclass.map_parse = parse; \
354c2aa98e2SPeter Wemm 		s->s_mapclass.map_open = open; \
355c2aa98e2SPeter Wemm 		s->s_mapclass.map_close = close; \
356c2aa98e2SPeter Wemm 		s->s_mapclass.map_lookup = lookup; \
357c2aa98e2SPeter Wemm 		s->s_mapclass.map_store = store; \
358c2aa98e2SPeter Wemm 	}
359c2aa98e2SPeter Wemm 
360c2aa98e2SPeter Wemm void
361c2aa98e2SPeter Wemm setupmaps()
362c2aa98e2SPeter Wemm {
363c2aa98e2SPeter Wemm 	register STAB *s;
364c2aa98e2SPeter Wemm 
365c2aa98e2SPeter Wemm #ifdef NEWDB
366c2aa98e2SPeter Wemm 	MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
367c2aa98e2SPeter Wemm 		map_parseargs, hash_map_open, db_map_close,
368c2aa98e2SPeter Wemm 		db_map_lookup, db_map_store);
369c2aa98e2SPeter Wemm 
370c2aa98e2SPeter Wemm 	MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
371c2aa98e2SPeter Wemm 		map_parseargs, bt_map_open, db_map_close,
372c2aa98e2SPeter Wemm 		db_map_lookup, db_map_store);
373c2aa98e2SPeter Wemm #endif
374c2aa98e2SPeter Wemm 
375c2aa98e2SPeter Wemm #ifdef NDBM
376c2aa98e2SPeter Wemm 	MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
377c2aa98e2SPeter Wemm 		map_parseargs, ndbm_map_open, ndbm_map_close,
378c2aa98e2SPeter Wemm 		ndbm_map_lookup, ndbm_map_store);
379c2aa98e2SPeter Wemm #endif
380c2aa98e2SPeter Wemm 
381c2aa98e2SPeter Wemm #ifdef NIS
382c2aa98e2SPeter Wemm 	MAPDEF("nis", NULL, MCF_ALIASOK,
383c2aa98e2SPeter Wemm 		map_parseargs, nis_map_open, null_map_close,
384c2aa98e2SPeter Wemm 		nis_map_lookup, null_map_store);
385c2aa98e2SPeter Wemm #endif
386c2aa98e2SPeter Wemm 
387c2aa98e2SPeter Wemm #ifdef NISPLUS
388c2aa98e2SPeter Wemm 	MAPDEF("nisplus", NULL, MCF_ALIASOK,
389c2aa98e2SPeter Wemm 		map_parseargs, nisplus_map_open, null_map_close,
390c2aa98e2SPeter Wemm 		nisplus_map_lookup, null_map_store);
391c2aa98e2SPeter Wemm #endif
392c2aa98e2SPeter Wemm #ifdef LDAPMAP
393c2aa98e2SPeter Wemm 	MAPDEF("ldapx", NULL, 0,
394c2aa98e2SPeter Wemm 		ldap_map_parseargs, ldap_map_open, ldap_map_close,
395c2aa98e2SPeter Wemm 		ldap_map_lookup, null_map_store);
396c2aa98e2SPeter Wemm #endif
397c2aa98e2SPeter Wemm 
398c2aa98e2SPeter Wemm #ifdef HESIOD
399c2aa98e2SPeter Wemm 	MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY,
400c2aa98e2SPeter Wemm 		map_parseargs, hes_map_open, null_map_close,
401c2aa98e2SPeter Wemm 		hes_map_lookup, null_map_store);
402c2aa98e2SPeter Wemm #endif
403c2aa98e2SPeter Wemm 
404c2aa98e2SPeter Wemm #if NETINFO
405c2aa98e2SPeter Wemm 	MAPDEF("netinfo", NULL, MCF_ALIASOK,
406c2aa98e2SPeter Wemm 		map_parseargs, ni_map_open, null_map_close,
407c2aa98e2SPeter Wemm 		ni_map_lookup, null_map_store);
408c2aa98e2SPeter Wemm #endif
409c2aa98e2SPeter Wemm 
410c2aa98e2SPeter Wemm #if 0
411c2aa98e2SPeter Wemm 	MAPDEF("dns", NULL, 0,
412c2aa98e2SPeter Wemm 		dns_map_init, null_map_open, null_map_close,
413c2aa98e2SPeter Wemm 		dns_map_lookup, null_map_store);
414c2aa98e2SPeter Wemm #endif
415c2aa98e2SPeter Wemm 
416c2aa98e2SPeter Wemm #if NAMED_BIND
417c2aa98e2SPeter Wemm 	/* best MX DNS lookup */
418c2aa98e2SPeter Wemm 	MAPDEF("bestmx", NULL, MCF_OPTFILE,
419c2aa98e2SPeter Wemm 		map_parseargs, null_map_open, null_map_close,
420c2aa98e2SPeter Wemm 		bestmx_map_lookup, null_map_store);
421c2aa98e2SPeter Wemm #endif
422c2aa98e2SPeter Wemm 
423c2aa98e2SPeter Wemm 	MAPDEF("host", NULL, 0,
424c2aa98e2SPeter Wemm 		host_map_init, null_map_open, null_map_close,
425c2aa98e2SPeter Wemm 		host_map_lookup, null_map_store);
426c2aa98e2SPeter Wemm 
427c2aa98e2SPeter Wemm 	MAPDEF("text", NULL, MCF_ALIASOK,
428c2aa98e2SPeter Wemm 		map_parseargs, text_map_open, null_map_close,
429c2aa98e2SPeter Wemm 		text_map_lookup, null_map_store);
430c2aa98e2SPeter Wemm 
431c2aa98e2SPeter Wemm 	MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
432c2aa98e2SPeter Wemm 		map_parseargs, stab_map_open, null_map_close,
433c2aa98e2SPeter Wemm 		stab_map_lookup, stab_map_store);
434c2aa98e2SPeter Wemm 
435c2aa98e2SPeter Wemm 	MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE,
436c2aa98e2SPeter Wemm 		map_parseargs, impl_map_open, impl_map_close,
437c2aa98e2SPeter Wemm 		impl_map_lookup, impl_map_store);
438c2aa98e2SPeter Wemm 
439c2aa98e2SPeter Wemm 	/* access to system passwd file */
440c2aa98e2SPeter Wemm 	MAPDEF("user", NULL, MCF_OPTFILE,
441c2aa98e2SPeter Wemm 		map_parseargs, user_map_open, null_map_close,
442c2aa98e2SPeter Wemm 		user_map_lookup, null_map_store);
443c2aa98e2SPeter Wemm 
444c2aa98e2SPeter Wemm 	/* dequote map */
445c2aa98e2SPeter Wemm 	MAPDEF("dequote", NULL, 0,
446c2aa98e2SPeter Wemm 		dequote_init, null_map_open, null_map_close,
447c2aa98e2SPeter Wemm 		dequote_map, null_map_store);
448c2aa98e2SPeter Wemm 
449c2aa98e2SPeter Wemm #ifdef MAP_REGEX
450c2aa98e2SPeter Wemm 	MAPDEF("regex", NULL, 0,
451c2aa98e2SPeter Wemm 		regex_map_init, null_map_open, null_map_close,
452c2aa98e2SPeter Wemm 		regex_map_lookup, null_map_store);
453c2aa98e2SPeter Wemm #endif
454c2aa98e2SPeter Wemm 
455c2aa98e2SPeter Wemm #if USERDB
456c2aa98e2SPeter Wemm 	/* user database */
457c2aa98e2SPeter Wemm 	MAPDEF("userdb", ".db", 0,
458c2aa98e2SPeter Wemm 		map_parseargs, null_map_open, null_map_close,
459c2aa98e2SPeter Wemm 		udb_map_lookup, null_map_store);
460c2aa98e2SPeter Wemm #endif
461c2aa98e2SPeter Wemm 
462c2aa98e2SPeter Wemm 	/* arbitrary programs */
463c2aa98e2SPeter Wemm 	MAPDEF("program", NULL, MCF_ALIASOK,
464c2aa98e2SPeter Wemm 		map_parseargs, null_map_open, null_map_close,
465c2aa98e2SPeter Wemm 		prog_map_lookup, null_map_store);
466c2aa98e2SPeter Wemm 
467c2aa98e2SPeter Wemm 	/* sequenced maps */
468c2aa98e2SPeter Wemm 	MAPDEF("sequence", NULL, MCF_ALIASOK,
469c2aa98e2SPeter Wemm 		seq_map_parse, null_map_open, null_map_close,
470c2aa98e2SPeter Wemm 		seq_map_lookup, seq_map_store);
471c2aa98e2SPeter Wemm 
472c2aa98e2SPeter Wemm 	/* switched interface to sequenced maps */
473c2aa98e2SPeter Wemm 	MAPDEF("switch", NULL, MCF_ALIASOK,
474c2aa98e2SPeter Wemm 		map_parseargs, switch_map_open, null_map_close,
475c2aa98e2SPeter Wemm 		seq_map_lookup, seq_map_store);
476c2aa98e2SPeter Wemm 
477c2aa98e2SPeter Wemm 	/* null map lookup -- really for internal use only */
478c2aa98e2SPeter Wemm 	MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
479c2aa98e2SPeter Wemm 		map_parseargs, null_map_open, null_map_close,
480c2aa98e2SPeter Wemm 		null_map_lookup, null_map_store);
481c2aa98e2SPeter Wemm 
482c2aa98e2SPeter Wemm #if _FFR_MAP_SYSLOG
483c2aa98e2SPeter Wemm 	/* syslog map -- logs information to syslog */
484c2aa98e2SPeter Wemm 	MAPDEF("syslog", NULL, 0,
485c2aa98e2SPeter Wemm 	       syslog_map_parseargs, null_map_open, null_map_close,
486c2aa98e2SPeter Wemm 	       syslog_map_lookup, null_map_store);
487c2aa98e2SPeter Wemm #endif
488c2aa98e2SPeter Wemm }
489c2aa98e2SPeter Wemm 
490c2aa98e2SPeter Wemm #undef MAPDEF
491c2aa98e2SPeter Wemm /*
492c2aa98e2SPeter Wemm **  INITHOSTMAPS -- initial host-dependent maps
493c2aa98e2SPeter Wemm **
494c2aa98e2SPeter Wemm **	This should act as an interface to any local service switch
495c2aa98e2SPeter Wemm **	provided by the host operating system.
496c2aa98e2SPeter Wemm **
497c2aa98e2SPeter Wemm **	Parameters:
498c2aa98e2SPeter Wemm **		none
499c2aa98e2SPeter Wemm **
500c2aa98e2SPeter Wemm **	Returns:
501c2aa98e2SPeter Wemm **		none
502c2aa98e2SPeter Wemm **
503c2aa98e2SPeter Wemm **	Side Effects:
504c2aa98e2SPeter Wemm **		Should define maps "host" and "users" as necessary
505c2aa98e2SPeter Wemm **		for this OS.  If they are not defined, they will get
506c2aa98e2SPeter Wemm **		a default value later.  It should check to make sure
507c2aa98e2SPeter Wemm **		they are not defined first, since it's possible that
508c2aa98e2SPeter Wemm **		the config file has provided an override.
509c2aa98e2SPeter Wemm */
510c2aa98e2SPeter Wemm 
511c2aa98e2SPeter Wemm void
512c2aa98e2SPeter Wemm inithostmaps()
513c2aa98e2SPeter Wemm {
514c2aa98e2SPeter Wemm 	register int i;
515c2aa98e2SPeter Wemm 	int nmaps;
516c2aa98e2SPeter Wemm 	char *maptype[MAXMAPSTACK];
517c2aa98e2SPeter Wemm 	short mapreturn[MAXMAPACTIONS];
518c2aa98e2SPeter Wemm 	char buf[MAXLINE];
519c2aa98e2SPeter Wemm 
520c2aa98e2SPeter Wemm 	/*
521c2aa98e2SPeter Wemm 	**  Set up default hosts maps.
522c2aa98e2SPeter Wemm 	*/
523c2aa98e2SPeter Wemm 
524c2aa98e2SPeter Wemm #if 0
525c2aa98e2SPeter Wemm 	nmaps = switch_map_find("hosts", maptype, mapreturn);
526c2aa98e2SPeter Wemm 	for (i = 0; i < nmaps; i++)
527c2aa98e2SPeter Wemm 	{
528c2aa98e2SPeter Wemm 		if (strcmp(maptype[i], "files") == 0 &&
529c2aa98e2SPeter Wemm 		    stab("hosts.files", ST_MAP, ST_FIND) == NULL)
530c2aa98e2SPeter Wemm 		{
531c2aa98e2SPeter Wemm 			strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts");
532c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
533c2aa98e2SPeter Wemm 		}
534c2aa98e2SPeter Wemm #if NAMED_BIND
535c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "dns") == 0 &&
536c2aa98e2SPeter Wemm 		    stab("hosts.dns", ST_MAP, ST_FIND) == NULL)
537c2aa98e2SPeter Wemm 		{
538c2aa98e2SPeter Wemm 			strcpy(buf, "hosts.dns dns A");
539c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
540c2aa98e2SPeter Wemm 		}
541c2aa98e2SPeter Wemm #endif
542c2aa98e2SPeter Wemm #ifdef NISPLUS
543c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "nisplus") == 0 &&
544c2aa98e2SPeter Wemm 		    stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL)
545c2aa98e2SPeter Wemm 		{
546c2aa98e2SPeter Wemm 			strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir");
547c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
548c2aa98e2SPeter Wemm 		}
549c2aa98e2SPeter Wemm #endif
550c2aa98e2SPeter Wemm #ifdef NIS
551c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "nis") == 0 &&
552c2aa98e2SPeter Wemm 		    stab("hosts.nis", ST_MAP, ST_FIND) == NULL)
553c2aa98e2SPeter Wemm 		{
554c2aa98e2SPeter Wemm 			strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname");
555c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
556c2aa98e2SPeter Wemm 		}
557c2aa98e2SPeter Wemm #endif
558c2aa98e2SPeter Wemm #if NETINFO
559c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "netinfo") == 0) &&
560c2aa98e2SPeter Wemm 		    stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL)
561c2aa98e2SPeter Wemm 		{
562c2aa98e2SPeter Wemm 			strcpy(buf, "hosts.netinfo netinfo -v name /machines");
563c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
564c2aa98e2SPeter Wemm 		}
565c2aa98e2SPeter Wemm #endif
566c2aa98e2SPeter Wemm 	}
567c2aa98e2SPeter Wemm #endif
568c2aa98e2SPeter Wemm 
569c2aa98e2SPeter Wemm 	/*
570c2aa98e2SPeter Wemm 	**  Make sure we have a host map.
571c2aa98e2SPeter Wemm 	*/
572c2aa98e2SPeter Wemm 
573c2aa98e2SPeter Wemm 	if (stab("host", ST_MAP, ST_FIND) == NULL)
574c2aa98e2SPeter Wemm 	{
575c2aa98e2SPeter Wemm 		/* user didn't initialize: set up host map */
576c2aa98e2SPeter Wemm 		strcpy(buf, "host host");
577c2aa98e2SPeter Wemm #if NAMED_BIND
578c2aa98e2SPeter Wemm 		if (ConfigLevel >= 2)
579c2aa98e2SPeter Wemm 			strcat(buf, " -a.");
580c2aa98e2SPeter Wemm #endif
581c2aa98e2SPeter Wemm 		(void) makemapentry(buf);
582c2aa98e2SPeter Wemm 	}
583c2aa98e2SPeter Wemm 
584c2aa98e2SPeter Wemm 	/*
585c2aa98e2SPeter Wemm 	**  Set up default aliases maps
586c2aa98e2SPeter Wemm 	*/
587c2aa98e2SPeter Wemm 
588c2aa98e2SPeter Wemm 	nmaps = switch_map_find("aliases", maptype, mapreturn);
589c2aa98e2SPeter Wemm 	for (i = 0; i < nmaps; i++)
590c2aa98e2SPeter Wemm 	{
591c2aa98e2SPeter Wemm 		if (strcmp(maptype[i], "files") == 0 &&
592c2aa98e2SPeter Wemm 		    stab("aliases.files", ST_MAP, ST_FIND) == NULL)
593c2aa98e2SPeter Wemm 		{
594c2aa98e2SPeter Wemm 			strcpy(buf, "aliases.files null");
595c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
596c2aa98e2SPeter Wemm 		}
597c2aa98e2SPeter Wemm #ifdef NISPLUS
598c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "nisplus") == 0 &&
599c2aa98e2SPeter Wemm 		    stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
600c2aa98e2SPeter Wemm 		{
601c2aa98e2SPeter Wemm 			strcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion -d mail_aliases.org_dir");
602c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
603c2aa98e2SPeter Wemm 		}
604c2aa98e2SPeter Wemm #endif
605c2aa98e2SPeter Wemm #ifdef NIS
606c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "nis") == 0 &&
607c2aa98e2SPeter Wemm 		    stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
608c2aa98e2SPeter Wemm 		{
609c2aa98e2SPeter Wemm 			strcpy(buf, "aliases.nis nis -d mail.aliases");
610c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
611c2aa98e2SPeter Wemm 		}
612c2aa98e2SPeter Wemm #endif
613c2aa98e2SPeter Wemm #ifdef NETINFO
614c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "netinfo") == 0 &&
615c2aa98e2SPeter Wemm 		    stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
616c2aa98e2SPeter Wemm 		{
617c2aa98e2SPeter Wemm 			strcpy(buf, "aliases.netinfo netinfo -z, /aliases");
618c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
619c2aa98e2SPeter Wemm 		}
620c2aa98e2SPeter Wemm #endif
621c2aa98e2SPeter Wemm #ifdef HESIOD
622c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "hesiod") == 0 &&
623c2aa98e2SPeter Wemm 		    stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
624c2aa98e2SPeter Wemm 		{
625c2aa98e2SPeter Wemm 			strcpy(buf, "aliases.hesiod hesiod aliases");
626c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
627c2aa98e2SPeter Wemm 		}
628c2aa98e2SPeter Wemm #endif
629c2aa98e2SPeter Wemm 	}
630c2aa98e2SPeter Wemm 	if (stab("aliases", ST_MAP, ST_FIND) == NULL)
631c2aa98e2SPeter Wemm 	{
632c2aa98e2SPeter Wemm 		strcpy(buf, "aliases switch aliases");
633c2aa98e2SPeter Wemm 		(void) makemapentry(buf);
634c2aa98e2SPeter Wemm 	}
635c2aa98e2SPeter Wemm 
636c2aa98e2SPeter Wemm #if 0		/* "user" map class is a better choice */
637c2aa98e2SPeter Wemm 	/*
638c2aa98e2SPeter Wemm 	**  Set up default users maps.
639c2aa98e2SPeter Wemm 	*/
640c2aa98e2SPeter Wemm 
641c2aa98e2SPeter Wemm 	nmaps = switch_map_find("passwd", maptype, mapreturn);
642c2aa98e2SPeter Wemm 	for (i = 0; i < nmaps; i++)
643c2aa98e2SPeter Wemm 	{
644c2aa98e2SPeter Wemm 		if (strcmp(maptype[i], "files") == 0 &&
645c2aa98e2SPeter Wemm 		    stab("users.files", ST_MAP, ST_FIND) == NULL)
646c2aa98e2SPeter Wemm 		{
647c2aa98e2SPeter Wemm 			strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd");
648c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
649c2aa98e2SPeter Wemm 		}
650c2aa98e2SPeter Wemm #ifdef NISPLUS
651c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "nisplus") == 0 &&
652c2aa98e2SPeter Wemm 		    stab("users.nisplus", ST_MAP, ST_FIND) == NULL)
653c2aa98e2SPeter Wemm 		{
654c2aa98e2SPeter Wemm 			strcpy(buf, "users.nisplus nisplus -m -kname -vhome -d passwd.org_dir");
655c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
656c2aa98e2SPeter Wemm 		}
657c2aa98e2SPeter Wemm #endif
658c2aa98e2SPeter Wemm #ifdef NIS
659c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "nis") == 0 &&
660c2aa98e2SPeter Wemm 		    stab("users.nis", ST_MAP, ST_FIND) == NULL)
661c2aa98e2SPeter Wemm 		{
662c2aa98e2SPeter Wemm 			strcpy(buf, "users.nis nis -m -d passwd.byname");
663c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
664c2aa98e2SPeter Wemm 		}
665c2aa98e2SPeter Wemm #endif
666c2aa98e2SPeter Wemm #ifdef HESIOD
667c2aa98e2SPeter Wemm 		else if (strcmp(maptype[i], "hesiod") == 0) &&
668c2aa98e2SPeter Wemm 		    stab("users.hesiod", ST_MAP, ST_FIND) == NULL)
669c2aa98e2SPeter Wemm 		{
670c2aa98e2SPeter Wemm 			strcpy(buf, "users.hesiod hesiod");
671c2aa98e2SPeter Wemm 			(void) makemapentry(buf);
672c2aa98e2SPeter Wemm 		}
673c2aa98e2SPeter Wemm #endif
674c2aa98e2SPeter Wemm 	}
675c2aa98e2SPeter Wemm 	if (stab("users", ST_MAP, ST_FIND) == NULL)
676c2aa98e2SPeter Wemm 	{
677c2aa98e2SPeter Wemm 		strcpy(buf, "users switch -m passwd");
678c2aa98e2SPeter Wemm 		(void) makemapentry(buf);
679c2aa98e2SPeter Wemm 	}
680c2aa98e2SPeter Wemm #endif
681c2aa98e2SPeter Wemm }
682c2aa98e2SPeter Wemm /*
683c2aa98e2SPeter Wemm **  SWITCH_MAP_FIND -- find the list of types associated with a map
684c2aa98e2SPeter Wemm **
685c2aa98e2SPeter Wemm **	This is the system-dependent interface to the service switch.
686c2aa98e2SPeter Wemm **
687c2aa98e2SPeter Wemm **	Parameters:
688c2aa98e2SPeter Wemm **		service -- the name of the service of interest.
689c2aa98e2SPeter Wemm **		maptype -- an out-array of strings containing the types
690c2aa98e2SPeter Wemm **			of access to use for this service.  There can
691c2aa98e2SPeter Wemm **			be at most MAXMAPSTACK types for a single service.
692c2aa98e2SPeter Wemm **		mapreturn -- an out-array of return information bitmaps
693c2aa98e2SPeter Wemm **			for the map.
694c2aa98e2SPeter Wemm **
695c2aa98e2SPeter Wemm **	Returns:
696c2aa98e2SPeter Wemm **		The number of map types filled in, or -1 for failure.
697c2aa98e2SPeter Wemm */
698c2aa98e2SPeter Wemm 
699c2aa98e2SPeter Wemm #if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
700c2aa98e2SPeter Wemm # define _USE_SUN_NSSWITCH_
701c2aa98e2SPeter Wemm #endif
702c2aa98e2SPeter Wemm 
703c2aa98e2SPeter Wemm #ifdef _USE_SUN_NSSWITCH_
704c2aa98e2SPeter Wemm # include <nsswitch.h>
705c2aa98e2SPeter Wemm #endif
706c2aa98e2SPeter Wemm 
707c2aa98e2SPeter Wemm #if defined(ultrix) || (defined(__osf__) && defined(__alpha))
708c2aa98e2SPeter Wemm # define _USE_DEC_SVC_CONF_
709c2aa98e2SPeter Wemm #endif
710c2aa98e2SPeter Wemm 
711c2aa98e2SPeter Wemm #ifdef _USE_DEC_SVC_CONF_
712c2aa98e2SPeter Wemm # include <sys/svcinfo.h>
713c2aa98e2SPeter Wemm #endif
714c2aa98e2SPeter Wemm 
715c2aa98e2SPeter Wemm int
716c2aa98e2SPeter Wemm switch_map_find(service, maptype, mapreturn)
717c2aa98e2SPeter Wemm 	char *service;
718c2aa98e2SPeter Wemm 	char *maptype[MAXMAPSTACK];
719c2aa98e2SPeter Wemm 	short mapreturn[MAXMAPACTIONS];
720c2aa98e2SPeter Wemm {
721c2aa98e2SPeter Wemm 	int svcno;
722c2aa98e2SPeter Wemm 
723c2aa98e2SPeter Wemm #ifdef _USE_SUN_NSSWITCH_
724c2aa98e2SPeter Wemm 	struct __nsw_switchconfig *nsw_conf;
725c2aa98e2SPeter Wemm 	enum __nsw_parse_err pserr;
726c2aa98e2SPeter Wemm 	struct __nsw_lookup *lk;
727c2aa98e2SPeter Wemm 	static struct __nsw_lookup lkp0 =
728c2aa98e2SPeter Wemm 		{ "files", {1, 0, 0, 0}, NULL, NULL };
729c2aa98e2SPeter Wemm 	static struct __nsw_switchconfig lkp_default =
730c2aa98e2SPeter Wemm 		{ 0, "sendmail", 3, &lkp0 };
731c2aa98e2SPeter Wemm 
732c2aa98e2SPeter Wemm 	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
733c2aa98e2SPeter Wemm 		mapreturn[svcno] = 0;
734c2aa98e2SPeter Wemm 
735c2aa98e2SPeter Wemm 	if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
736c2aa98e2SPeter Wemm 		lk = lkp_default.lookups;
737c2aa98e2SPeter Wemm 	else
738c2aa98e2SPeter Wemm 		lk = nsw_conf->lookups;
739c2aa98e2SPeter Wemm 	svcno = 0;
740c2aa98e2SPeter Wemm 	while (lk != NULL)
741c2aa98e2SPeter Wemm 	{
742c2aa98e2SPeter Wemm 		maptype[svcno] = lk->service_name;
743c2aa98e2SPeter Wemm 		if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
744c2aa98e2SPeter Wemm 			mapreturn[MA_NOTFOUND] |= 1 << svcno;
745c2aa98e2SPeter Wemm 		if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
746c2aa98e2SPeter Wemm 			mapreturn[MA_TRYAGAIN] |= 1 << svcno;
747c2aa98e2SPeter Wemm 		if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
748c2aa98e2SPeter Wemm 			mapreturn[MA_TRYAGAIN] |= 1 << svcno;
749c2aa98e2SPeter Wemm 		svcno++;
750c2aa98e2SPeter Wemm 		lk = lk->next;
751c2aa98e2SPeter Wemm 	}
752c2aa98e2SPeter Wemm 	return svcno;
753c2aa98e2SPeter Wemm #endif
754c2aa98e2SPeter Wemm 
755c2aa98e2SPeter Wemm #ifdef _USE_DEC_SVC_CONF_
756c2aa98e2SPeter Wemm 	struct svcinfo *svcinfo;
757c2aa98e2SPeter Wemm 	int svc;
758c2aa98e2SPeter Wemm 
759c2aa98e2SPeter Wemm 	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
760c2aa98e2SPeter Wemm 		mapreturn[svcno] = 0;
761c2aa98e2SPeter Wemm 
762c2aa98e2SPeter Wemm 	svcinfo = getsvc();
763c2aa98e2SPeter Wemm 	if (svcinfo == NULL)
764c2aa98e2SPeter Wemm 		goto punt;
765c2aa98e2SPeter Wemm 	if (strcmp(service, "hosts") == 0)
766c2aa98e2SPeter Wemm 		svc = SVC_HOSTS;
767c2aa98e2SPeter Wemm 	else if (strcmp(service, "aliases") == 0)
768c2aa98e2SPeter Wemm 		svc = SVC_ALIASES;
769c2aa98e2SPeter Wemm 	else if (strcmp(service, "passwd") == 0)
770c2aa98e2SPeter Wemm 		svc = SVC_PASSWD;
771c2aa98e2SPeter Wemm 	else
772c2aa98e2SPeter Wemm 		return -1;
773c2aa98e2SPeter Wemm 	for (svcno = 0; svcno < SVC_PATHSIZE; svcno++)
774c2aa98e2SPeter Wemm 	{
775c2aa98e2SPeter Wemm 		switch (svcinfo->svcpath[svc][svcno])
776c2aa98e2SPeter Wemm 		{
777c2aa98e2SPeter Wemm 		  case SVC_LOCAL:
778c2aa98e2SPeter Wemm 			maptype[svcno] = "files";
779c2aa98e2SPeter Wemm 			break;
780c2aa98e2SPeter Wemm 
781c2aa98e2SPeter Wemm 		  case SVC_YP:
782c2aa98e2SPeter Wemm 			maptype[svcno] = "nis";
783c2aa98e2SPeter Wemm 			break;
784c2aa98e2SPeter Wemm 
785c2aa98e2SPeter Wemm 		  case SVC_BIND:
786c2aa98e2SPeter Wemm 			maptype[svcno] = "dns";
787c2aa98e2SPeter Wemm 			break;
788c2aa98e2SPeter Wemm 
789c2aa98e2SPeter Wemm #ifdef SVC_HESIOD
790c2aa98e2SPeter Wemm 		  case SVC_HESIOD:
791c2aa98e2SPeter Wemm 			maptype[svcno] = "hesiod";
792c2aa98e2SPeter Wemm 			break;
793c2aa98e2SPeter Wemm #endif
794c2aa98e2SPeter Wemm 
795c2aa98e2SPeter Wemm 		  case SVC_LAST:
796c2aa98e2SPeter Wemm 			return svcno;
797c2aa98e2SPeter Wemm 		}
798c2aa98e2SPeter Wemm 	}
799c2aa98e2SPeter Wemm 	return svcno;
800c2aa98e2SPeter Wemm #endif
801c2aa98e2SPeter Wemm 
802c2aa98e2SPeter Wemm #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
803c2aa98e2SPeter Wemm 	/*
804c2aa98e2SPeter Wemm 	**  Fall-back mechanism.
805c2aa98e2SPeter Wemm 	*/
806c2aa98e2SPeter Wemm 
807c2aa98e2SPeter Wemm 	STAB *st;
808c2aa98e2SPeter Wemm 	time_t now = curtime();
809c2aa98e2SPeter Wemm 
810c2aa98e2SPeter Wemm 	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
811c2aa98e2SPeter Wemm 		mapreturn[svcno] = 0;
812c2aa98e2SPeter Wemm 
813c2aa98e2SPeter Wemm 	if ((now - ServiceCacheTime) > (time_t) ServiceCacheMaxAge)
814c2aa98e2SPeter Wemm 	{
815c2aa98e2SPeter Wemm 		/* (re)read service switch */
816c2aa98e2SPeter Wemm 		register FILE *fp;
817c2aa98e2SPeter Wemm 		int sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK;
818c2aa98e2SPeter Wemm 
819c2aa98e2SPeter Wemm 		if (!bitset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR, DontBlameSendmail))
820c2aa98e2SPeter Wemm 			sff |= SFF_NOWLINK;
821c2aa98e2SPeter Wemm 
822c2aa98e2SPeter Wemm 		if (ConfigFileRead)
823c2aa98e2SPeter Wemm 			ServiceCacheTime = now;
824c2aa98e2SPeter Wemm 		fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff);
825c2aa98e2SPeter Wemm 		if (fp != NULL)
826c2aa98e2SPeter Wemm 		{
827c2aa98e2SPeter Wemm 			char buf[MAXLINE];
828c2aa98e2SPeter Wemm 
829c2aa98e2SPeter Wemm 			while (fgets(buf, sizeof buf, fp) != NULL)
830c2aa98e2SPeter Wemm 			{
831c2aa98e2SPeter Wemm 				register char *p;
832c2aa98e2SPeter Wemm 
833c2aa98e2SPeter Wemm 				p = strpbrk(buf, "#\n");
834c2aa98e2SPeter Wemm 				if (p != NULL)
835c2aa98e2SPeter Wemm 					*p = '\0';
836c2aa98e2SPeter Wemm 				p = strpbrk(buf, " \t");
837c2aa98e2SPeter Wemm 				if (p != NULL)
838c2aa98e2SPeter Wemm 					*p++ = '\0';
839c2aa98e2SPeter Wemm 				if (buf[0] == '\0')
840c2aa98e2SPeter Wemm 					continue;
84176b7bf71SPeter Wemm 				if (p == NULL)
84276b7bf71SPeter Wemm 				{
84376b7bf71SPeter Wemm 					sm_syslog(LOG_ERR, NOQID,
84476b7bf71SPeter Wemm 						  "Bad line on %.100s: %.100s",
84576b7bf71SPeter Wemm 						  ServiceSwitchFile,
84676b7bf71SPeter Wemm 						  buf);
84776b7bf71SPeter Wemm 					continue;
84876b7bf71SPeter Wemm 				}
849c2aa98e2SPeter Wemm 				while (isspace(*p))
850c2aa98e2SPeter Wemm 					p++;
851c2aa98e2SPeter Wemm 				if (*p == '\0')
852c2aa98e2SPeter Wemm 					continue;
853c2aa98e2SPeter Wemm 
854c2aa98e2SPeter Wemm 				/*
855c2aa98e2SPeter Wemm 				**  Find/allocate space for this service entry.
856c2aa98e2SPeter Wemm 				**	Space for all of the service strings
857c2aa98e2SPeter Wemm 				**	are allocated at once.  This means
858c2aa98e2SPeter Wemm 				**	that we only have to free the first
859c2aa98e2SPeter Wemm 				**	one to free all of them.
860c2aa98e2SPeter Wemm 				*/
861c2aa98e2SPeter Wemm 
862c2aa98e2SPeter Wemm 				st = stab(buf, ST_SERVICE, ST_ENTER);
863c2aa98e2SPeter Wemm 				if (st->s_service[0] != NULL)
864c2aa98e2SPeter Wemm 					free((void *) st->s_service[0]);
865c2aa98e2SPeter Wemm 				p = newstr(p);
866c2aa98e2SPeter Wemm 				for (svcno = 0; svcno < MAXMAPSTACK; )
867c2aa98e2SPeter Wemm 				{
868c2aa98e2SPeter Wemm 					if (*p == '\0')
869c2aa98e2SPeter Wemm 						break;
870c2aa98e2SPeter Wemm 					st->s_service[svcno++] = p;
871c2aa98e2SPeter Wemm 					p = strpbrk(p, " \t");
872c2aa98e2SPeter Wemm 					if (p == NULL)
873c2aa98e2SPeter Wemm 						break;
874c2aa98e2SPeter Wemm 					*p++ = '\0';
875c2aa98e2SPeter Wemm 					while (isspace(*p))
876c2aa98e2SPeter Wemm 						p++;
877c2aa98e2SPeter Wemm 				}
878c2aa98e2SPeter Wemm 				if (svcno < MAXMAPSTACK)
879c2aa98e2SPeter Wemm 					st->s_service[svcno] = NULL;
880c2aa98e2SPeter Wemm 			}
881c2aa98e2SPeter Wemm 			fclose(fp);
882c2aa98e2SPeter Wemm 		}
883c2aa98e2SPeter Wemm 	}
884c2aa98e2SPeter Wemm 
885c2aa98e2SPeter Wemm 	/* look up entry in cache */
886c2aa98e2SPeter Wemm 	st = stab(service, ST_SERVICE, ST_FIND);
887c2aa98e2SPeter Wemm 	if (st != NULL && st->s_service[0] != NULL)
888c2aa98e2SPeter Wemm 	{
889c2aa98e2SPeter Wemm 		/* extract data */
890c2aa98e2SPeter Wemm 		svcno = 0;
891c2aa98e2SPeter Wemm 		while (svcno < MAXMAPSTACK)
892c2aa98e2SPeter Wemm 		{
893c2aa98e2SPeter Wemm 			maptype[svcno] = st->s_service[svcno];
894c2aa98e2SPeter Wemm 			if (maptype[svcno++] == NULL)
895c2aa98e2SPeter Wemm 				break;
896c2aa98e2SPeter Wemm 		}
897c2aa98e2SPeter Wemm 		return --svcno;
898c2aa98e2SPeter Wemm 	}
899c2aa98e2SPeter Wemm #endif
900c2aa98e2SPeter Wemm 
901c2aa98e2SPeter Wemm #if !defined(_USE_SUN_NSSWITCH_)
902c2aa98e2SPeter Wemm 	/* if the service file doesn't work, use an absolute fallback */
903c2aa98e2SPeter Wemm # ifdef _USE_DEC_SVC_CONF_
904c2aa98e2SPeter Wemm   punt:
905c2aa98e2SPeter Wemm # endif
906c2aa98e2SPeter Wemm 	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
907c2aa98e2SPeter Wemm 		mapreturn[svcno] = 0;
908c2aa98e2SPeter Wemm 	svcno = 0;
909c2aa98e2SPeter Wemm 	if (strcmp(service, "aliases") == 0)
910c2aa98e2SPeter Wemm 	{
911c2aa98e2SPeter Wemm 		maptype[svcno++] = "files";
912c2aa98e2SPeter Wemm # ifdef AUTO_NIS_ALIASES
913c2aa98e2SPeter Wemm #  ifdef NISPLUS
914c2aa98e2SPeter Wemm 		maptype[svcno++] = "nisplus";
915c2aa98e2SPeter Wemm #  endif
916c2aa98e2SPeter Wemm #  ifdef NIS
917c2aa98e2SPeter Wemm 		maptype[svcno++] = "nis";
918c2aa98e2SPeter Wemm #  endif
919c2aa98e2SPeter Wemm # endif
920c2aa98e2SPeter Wemm 		return svcno;
921c2aa98e2SPeter Wemm 	}
922c2aa98e2SPeter Wemm 	if (strcmp(service, "hosts") == 0)
923c2aa98e2SPeter Wemm 	{
924c2aa98e2SPeter Wemm #  if NAMED_BIND
925c2aa98e2SPeter Wemm 		maptype[svcno++] = "dns";
926c2aa98e2SPeter Wemm #  else
927c2aa98e2SPeter Wemm #   if defined(sun) && !defined(BSD)
928c2aa98e2SPeter Wemm 		/* SunOS */
929c2aa98e2SPeter Wemm 		maptype[svcno++] = "nis";
930c2aa98e2SPeter Wemm #   endif
931c2aa98e2SPeter Wemm #  endif
932c2aa98e2SPeter Wemm 		maptype[svcno++] = "files";
933c2aa98e2SPeter Wemm 		return svcno;
934c2aa98e2SPeter Wemm 	}
935c2aa98e2SPeter Wemm 	return -1;
936c2aa98e2SPeter Wemm #endif
937c2aa98e2SPeter Wemm }
938c2aa98e2SPeter Wemm /*
939c2aa98e2SPeter Wemm **  USERNAME -- return the user id of the logged in user.
940c2aa98e2SPeter Wemm **
941c2aa98e2SPeter Wemm **	Parameters:
942c2aa98e2SPeter Wemm **		none.
943c2aa98e2SPeter Wemm **
944c2aa98e2SPeter Wemm **	Returns:
945c2aa98e2SPeter Wemm **		The login name of the logged in user.
946c2aa98e2SPeter Wemm **
947c2aa98e2SPeter Wemm **	Side Effects:
948c2aa98e2SPeter Wemm **		none.
949c2aa98e2SPeter Wemm **
950c2aa98e2SPeter Wemm **	Notes:
951c2aa98e2SPeter Wemm **		The return value is statically allocated.
952c2aa98e2SPeter Wemm */
953c2aa98e2SPeter Wemm 
954c2aa98e2SPeter Wemm char *
955c2aa98e2SPeter Wemm username()
956c2aa98e2SPeter Wemm {
957c2aa98e2SPeter Wemm 	static char *myname = NULL;
958c2aa98e2SPeter Wemm 	extern char *getlogin();
959c2aa98e2SPeter Wemm 	register struct passwd *pw;
960c2aa98e2SPeter Wemm 
961c2aa98e2SPeter Wemm 	/* cache the result */
962c2aa98e2SPeter Wemm 	if (myname == NULL)
963c2aa98e2SPeter Wemm 	{
964c2aa98e2SPeter Wemm 		myname = getlogin();
965c2aa98e2SPeter Wemm 		if (myname == NULL || myname[0] == '\0')
966c2aa98e2SPeter Wemm 		{
967c2aa98e2SPeter Wemm 			pw = sm_getpwuid(RealUid);
968c2aa98e2SPeter Wemm 			if (pw != NULL)
969c2aa98e2SPeter Wemm 				myname = newstr(pw->pw_name);
970c2aa98e2SPeter Wemm 		}
971c2aa98e2SPeter Wemm 		else
972c2aa98e2SPeter Wemm 		{
973c2aa98e2SPeter Wemm 			uid_t uid = RealUid;
974c2aa98e2SPeter Wemm 
975c2aa98e2SPeter Wemm 			myname = newstr(myname);
976c2aa98e2SPeter Wemm 			if ((pw = sm_getpwnam(myname)) == NULL ||
977c2aa98e2SPeter Wemm 			      (uid != 0 && uid != pw->pw_uid))
978c2aa98e2SPeter Wemm 			{
979c2aa98e2SPeter Wemm 				pw = sm_getpwuid(uid);
980c2aa98e2SPeter Wemm 				if (pw != NULL)
981c2aa98e2SPeter Wemm 					myname = newstr(pw->pw_name);
982c2aa98e2SPeter Wemm 			}
983c2aa98e2SPeter Wemm 		}
984c2aa98e2SPeter Wemm 		if (myname == NULL || myname[0] == '\0')
985c2aa98e2SPeter Wemm 		{
986c2aa98e2SPeter Wemm 			syserr("554 Who are you?");
987c2aa98e2SPeter Wemm 			myname = "postmaster";
988c2aa98e2SPeter Wemm 		}
989c2aa98e2SPeter Wemm 	}
990c2aa98e2SPeter Wemm 
991c2aa98e2SPeter Wemm 	return (myname);
992c2aa98e2SPeter Wemm }
993c2aa98e2SPeter Wemm /*
994c2aa98e2SPeter Wemm **  TTYPATH -- Get the path of the user's tty
995c2aa98e2SPeter Wemm **
996c2aa98e2SPeter Wemm **	Returns the pathname of the user's tty.  Returns NULL if
997c2aa98e2SPeter Wemm **	the user is not logged in or if s/he has write permission
998c2aa98e2SPeter Wemm **	denied.
999c2aa98e2SPeter Wemm **
1000c2aa98e2SPeter Wemm **	Parameters:
1001c2aa98e2SPeter Wemm **		none
1002c2aa98e2SPeter Wemm **
1003c2aa98e2SPeter Wemm **	Returns:
1004c2aa98e2SPeter Wemm **		pathname of the user's tty.
1005c2aa98e2SPeter Wemm **		NULL if not logged in or write permission denied.
1006c2aa98e2SPeter Wemm **
1007c2aa98e2SPeter Wemm **	Side Effects:
1008c2aa98e2SPeter Wemm **		none.
1009c2aa98e2SPeter Wemm **
1010c2aa98e2SPeter Wemm **	WARNING:
1011c2aa98e2SPeter Wemm **		Return value is in a local buffer.
1012c2aa98e2SPeter Wemm **
1013c2aa98e2SPeter Wemm **	Called By:
1014c2aa98e2SPeter Wemm **		savemail
1015c2aa98e2SPeter Wemm */
1016c2aa98e2SPeter Wemm 
1017c2aa98e2SPeter Wemm char *
1018c2aa98e2SPeter Wemm ttypath()
1019c2aa98e2SPeter Wemm {
1020c2aa98e2SPeter Wemm 	struct stat stbuf;
1021c2aa98e2SPeter Wemm 	register char *pathn;
1022c2aa98e2SPeter Wemm 	extern char *ttyname();
1023c2aa98e2SPeter Wemm 	extern char *getlogin();
1024c2aa98e2SPeter Wemm 
1025c2aa98e2SPeter Wemm 	/* compute the pathname of the controlling tty */
1026c2aa98e2SPeter Wemm 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
1027c2aa98e2SPeter Wemm 	    (pathn = ttyname(0)) == NULL)
1028c2aa98e2SPeter Wemm 	{
1029c2aa98e2SPeter Wemm 		errno = 0;
1030c2aa98e2SPeter Wemm 		return (NULL);
1031c2aa98e2SPeter Wemm 	}
1032c2aa98e2SPeter Wemm 
1033c2aa98e2SPeter Wemm 	/* see if we have write permission */
1034c2aa98e2SPeter Wemm 	if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode))
1035c2aa98e2SPeter Wemm 	{
1036c2aa98e2SPeter Wemm 		errno = 0;
1037c2aa98e2SPeter Wemm 		return (NULL);
1038c2aa98e2SPeter Wemm 	}
1039c2aa98e2SPeter Wemm 
1040c2aa98e2SPeter Wemm 	/* see if the user is logged in */
1041c2aa98e2SPeter Wemm 	if (getlogin() == NULL)
1042c2aa98e2SPeter Wemm 		return (NULL);
1043c2aa98e2SPeter Wemm 
1044c2aa98e2SPeter Wemm 	/* looks good */
1045c2aa98e2SPeter Wemm 	return (pathn);
1046c2aa98e2SPeter Wemm }
1047c2aa98e2SPeter Wemm /*
1048c2aa98e2SPeter Wemm **  CHECKCOMPAT -- check for From and To person compatible.
1049c2aa98e2SPeter Wemm **
1050c2aa98e2SPeter Wemm **	This routine can be supplied on a per-installation basis
1051c2aa98e2SPeter Wemm **	to determine whether a person is allowed to send a message.
1052c2aa98e2SPeter Wemm **	This allows restriction of certain types of internet
1053c2aa98e2SPeter Wemm **	forwarding or registration of users.
1054c2aa98e2SPeter Wemm **
1055c2aa98e2SPeter Wemm **	If the hosts are found to be incompatible, an error
1056c2aa98e2SPeter Wemm **	message should be given using "usrerr" and an EX_ code
1057c2aa98e2SPeter Wemm **	should be returned.  You can also set to->q_status to
1058c2aa98e2SPeter Wemm **	a DSN-style status code.
1059c2aa98e2SPeter Wemm **
1060c2aa98e2SPeter Wemm **	EF_NO_BODY_RETN can be set in e->e_flags to suppress the
1061c2aa98e2SPeter Wemm **	body during the return-to-sender function; this should be done
1062c2aa98e2SPeter Wemm **	on huge messages.  This bit may already be set by the ESMTP
1063c2aa98e2SPeter Wemm **	protocol.
1064c2aa98e2SPeter Wemm **
1065c2aa98e2SPeter Wemm **	Parameters:
1066c2aa98e2SPeter Wemm **		to -- the person being sent to.
1067c2aa98e2SPeter Wemm **
1068c2aa98e2SPeter Wemm **	Returns:
1069c2aa98e2SPeter Wemm **		an exit status
1070c2aa98e2SPeter Wemm **
1071c2aa98e2SPeter Wemm **	Side Effects:
1072c2aa98e2SPeter Wemm **		none (unless you include the usrerr stuff)
1073c2aa98e2SPeter Wemm */
1074c2aa98e2SPeter Wemm 
1075c2aa98e2SPeter Wemm int
1076c2aa98e2SPeter Wemm checkcompat(to, e)
1077c2aa98e2SPeter Wemm 	register ADDRESS *to;
1078c2aa98e2SPeter Wemm 	register ENVELOPE *e;
1079c2aa98e2SPeter Wemm {
1080c2aa98e2SPeter Wemm # ifdef lint
1081c2aa98e2SPeter Wemm 	if (to == NULL)
1082c2aa98e2SPeter Wemm 		to++;
1083c2aa98e2SPeter Wemm # endif /* lint */
1084c2aa98e2SPeter Wemm 
1085c2aa98e2SPeter Wemm 	if (tTd(49, 1))
1086c2aa98e2SPeter Wemm 		printf("checkcompat(to=%s, from=%s)\n",
1087c2aa98e2SPeter Wemm 			to->q_paddr, e->e_from.q_paddr);
1088c2aa98e2SPeter Wemm 
1089c2aa98e2SPeter Wemm # ifdef EXAMPLE_CODE
1090c2aa98e2SPeter Wemm 	/* this code is intended as an example only */
1091c2aa98e2SPeter Wemm 	register STAB *s;
1092c2aa98e2SPeter Wemm 
1093c2aa98e2SPeter Wemm 	s = stab("arpa", ST_MAILER, ST_FIND);
1094c2aa98e2SPeter Wemm 	if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
1095c2aa98e2SPeter Wemm 	    to->q_mailer == s->s_mailer)
1096c2aa98e2SPeter Wemm 	{
1097c2aa98e2SPeter Wemm 		usrerr("553 No ARPA mail through this machine: see your system administration");
1098c2aa98e2SPeter Wemm 		/* e->e_flags |= EF_NO_BODY_RETN; to supress body on return */
1099c2aa98e2SPeter Wemm 		to->q_status = "5.7.1";
1100c2aa98e2SPeter Wemm 		return (EX_UNAVAILABLE);
1101c2aa98e2SPeter Wemm 	}
1102c2aa98e2SPeter Wemm # endif /* EXAMPLE_CODE */
1103c2aa98e2SPeter Wemm 	return (EX_OK);
1104c2aa98e2SPeter Wemm }
1105c2aa98e2SPeter Wemm /*
1106c2aa98e2SPeter Wemm **  SETSIGNAL -- set a signal handler
1107c2aa98e2SPeter Wemm **
1108c2aa98e2SPeter Wemm **	This is essentially old BSD "signal(3)".
1109c2aa98e2SPeter Wemm */
1110c2aa98e2SPeter Wemm 
1111c2aa98e2SPeter Wemm sigfunc_t
1112c2aa98e2SPeter Wemm setsignal(sig, handler)
1113c2aa98e2SPeter Wemm 	int sig;
1114c2aa98e2SPeter Wemm 	sigfunc_t handler;
1115c2aa98e2SPeter Wemm {
1116c2aa98e2SPeter Wemm #if defined(SYS5SIGNALS) || defined(BSD4_3)
1117c2aa98e2SPeter Wemm # ifdef BSD4_3
1118c2aa98e2SPeter Wemm 	return signal(sig, handler);
1119c2aa98e2SPeter Wemm # else
1120c2aa98e2SPeter Wemm 	return sigset(sig, handler);
1121c2aa98e2SPeter Wemm # endif
1122c2aa98e2SPeter Wemm #else
1123c2aa98e2SPeter Wemm 	struct sigaction n, o;
1124c2aa98e2SPeter Wemm 
1125c2aa98e2SPeter Wemm 	bzero(&n, sizeof n);
1126c2aa98e2SPeter Wemm # if USE_SA_SIGACTION
1127c2aa98e2SPeter Wemm 	n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler;
1128c2aa98e2SPeter Wemm 	n.sa_flags = SA_RESTART|SA_SIGINFO;
1129c2aa98e2SPeter Wemm # else
1130c2aa98e2SPeter Wemm 	n.sa_handler = handler;
1131c2aa98e2SPeter Wemm #  ifdef SA_RESTART
1132c2aa98e2SPeter Wemm 	n.sa_flags = SA_RESTART;
1133c2aa98e2SPeter Wemm #  endif
1134c2aa98e2SPeter Wemm # endif
1135c2aa98e2SPeter Wemm 	if (sigaction(sig, &n, &o) < 0)
1136c2aa98e2SPeter Wemm 		return SIG_ERR;
1137c2aa98e2SPeter Wemm 	return o.sa_handler;
1138c2aa98e2SPeter Wemm #endif
1139c2aa98e2SPeter Wemm }
1140c2aa98e2SPeter Wemm /*
1141c2aa98e2SPeter Wemm **  BLOCKSIGNAL -- hold a signal to prevent delivery
1142c2aa98e2SPeter Wemm **
1143c2aa98e2SPeter Wemm **	Parameters:
1144c2aa98e2SPeter Wemm **		sig -- the signal to block.
1145c2aa98e2SPeter Wemm **
1146c2aa98e2SPeter Wemm **	Returns:
1147c2aa98e2SPeter Wemm **		1 signal was previously blocked
1148c2aa98e2SPeter Wemm **		0 signal was not previously blocked
1149c2aa98e2SPeter Wemm **		-1 on failure.
1150c2aa98e2SPeter Wemm */
1151c2aa98e2SPeter Wemm 
1152c2aa98e2SPeter Wemm int
1153c2aa98e2SPeter Wemm blocksignal(sig)
1154c2aa98e2SPeter Wemm 	int sig;
1155c2aa98e2SPeter Wemm {
1156c2aa98e2SPeter Wemm #ifdef BSD4_3
1157c2aa98e2SPeter Wemm # ifndef sigmask
1158c2aa98e2SPeter Wemm #  define sigmask(s)	(1 << ((s) - 1))
1159c2aa98e2SPeter Wemm # endif
1160c2aa98e2SPeter Wemm 	return (sigblock(sigmask(sig)) & sigmask(sig)) != 0;
1161c2aa98e2SPeter Wemm #else
1162c2aa98e2SPeter Wemm # ifdef ALTOS_SYSTEM_V
1163c2aa98e2SPeter Wemm 	sigfunc_t handler;
1164c2aa98e2SPeter Wemm 
1165c2aa98e2SPeter Wemm 	handler = sigset(sig, SIG_HOLD);
1166c2aa98e2SPeter Wemm 	if (handler == SIG_ERR)
1167c2aa98e2SPeter Wemm 		return -1;
1168c2aa98e2SPeter Wemm 	else
1169c2aa98e2SPeter Wemm 		return handler == SIG_HOLD;
1170c2aa98e2SPeter Wemm # else
1171c2aa98e2SPeter Wemm 	sigset_t sset, oset;
1172c2aa98e2SPeter Wemm 
1173c2aa98e2SPeter Wemm 	sigemptyset(&sset);
1174c2aa98e2SPeter Wemm 	sigaddset(&sset, sig);
1175c2aa98e2SPeter Wemm 	if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0)
1176c2aa98e2SPeter Wemm 		return -1;
1177c2aa98e2SPeter Wemm 	else
1178c2aa98e2SPeter Wemm 		return sigismember(&oset, sig);
1179c2aa98e2SPeter Wemm # endif
1180c2aa98e2SPeter Wemm #endif
1181c2aa98e2SPeter Wemm }
1182c2aa98e2SPeter Wemm /*
1183c2aa98e2SPeter Wemm **  RELEASESIGNAL -- release a held signal
1184c2aa98e2SPeter Wemm **
1185c2aa98e2SPeter Wemm **	Parameters:
1186c2aa98e2SPeter Wemm **		sig -- the signal to release.
1187c2aa98e2SPeter Wemm **
1188c2aa98e2SPeter Wemm **	Returns:
1189c2aa98e2SPeter Wemm **		1 signal was previously blocked
1190c2aa98e2SPeter Wemm **		0 signal was not previously blocked
1191c2aa98e2SPeter Wemm **		-1 on failure.
1192c2aa98e2SPeter Wemm */
1193c2aa98e2SPeter Wemm 
1194c2aa98e2SPeter Wemm int
1195c2aa98e2SPeter Wemm releasesignal(sig)
1196c2aa98e2SPeter Wemm 	int sig;
1197c2aa98e2SPeter Wemm {
1198c2aa98e2SPeter Wemm #ifdef BSD4_3
1199c2aa98e2SPeter Wemm 	return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0;
1200c2aa98e2SPeter Wemm #else
1201c2aa98e2SPeter Wemm # ifdef ALTOS_SYSTEM_V
1202c2aa98e2SPeter Wemm 	sigfunc_t handler;
1203c2aa98e2SPeter Wemm 
1204c2aa98e2SPeter Wemm 	handler = sigset(sig, SIG_HOLD);
1205c2aa98e2SPeter Wemm 	if (sigrelse(sig) < 0)
1206c2aa98e2SPeter Wemm 		return -1;
1207c2aa98e2SPeter Wemm 	else
1208c2aa98e2SPeter Wemm 		return handler == SIG_HOLD;
1209c2aa98e2SPeter Wemm # else
1210c2aa98e2SPeter Wemm 	sigset_t sset, oset;
1211c2aa98e2SPeter Wemm 
1212c2aa98e2SPeter Wemm 	sigemptyset(&sset);
1213c2aa98e2SPeter Wemm 	sigaddset(&sset, sig);
1214c2aa98e2SPeter Wemm 	if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0)
1215c2aa98e2SPeter Wemm 		return -1;
1216c2aa98e2SPeter Wemm 	else
1217c2aa98e2SPeter Wemm 		return sigismember(&oset, sig);
1218c2aa98e2SPeter Wemm # endif
1219c2aa98e2SPeter Wemm #endif
1220c2aa98e2SPeter Wemm }
1221c2aa98e2SPeter Wemm /*
1222c2aa98e2SPeter Wemm **  HOLDSIGS -- arrange to hold all signals
1223c2aa98e2SPeter Wemm **
1224c2aa98e2SPeter Wemm **	Parameters:
1225c2aa98e2SPeter Wemm **		none.
1226c2aa98e2SPeter Wemm **
1227c2aa98e2SPeter Wemm **	Returns:
1228c2aa98e2SPeter Wemm **		none.
1229c2aa98e2SPeter Wemm **
1230c2aa98e2SPeter Wemm **	Side Effects:
1231c2aa98e2SPeter Wemm **		Arranges that signals are held.
1232c2aa98e2SPeter Wemm */
1233c2aa98e2SPeter Wemm 
1234c2aa98e2SPeter Wemm void
1235c2aa98e2SPeter Wemm holdsigs()
1236c2aa98e2SPeter Wemm {
1237c2aa98e2SPeter Wemm }
1238c2aa98e2SPeter Wemm /*
1239c2aa98e2SPeter Wemm **  RLSESIGS -- arrange to release all signals
1240c2aa98e2SPeter Wemm **
1241c2aa98e2SPeter Wemm **	This undoes the effect of holdsigs.
1242c2aa98e2SPeter Wemm **
1243c2aa98e2SPeter Wemm **	Parameters:
1244c2aa98e2SPeter Wemm **		none.
1245c2aa98e2SPeter Wemm **
1246c2aa98e2SPeter Wemm **	Returns:
1247c2aa98e2SPeter Wemm **		none.
1248c2aa98e2SPeter Wemm **
1249c2aa98e2SPeter Wemm **	Side Effects:
1250c2aa98e2SPeter Wemm **		Arranges that signals are released.
1251c2aa98e2SPeter Wemm */
1252c2aa98e2SPeter Wemm 
1253c2aa98e2SPeter Wemm void
1254c2aa98e2SPeter Wemm rlsesigs()
1255c2aa98e2SPeter Wemm {
1256c2aa98e2SPeter Wemm }
1257c2aa98e2SPeter Wemm /*
1258c2aa98e2SPeter Wemm **  INIT_MD -- do machine dependent initializations
1259c2aa98e2SPeter Wemm **
1260c2aa98e2SPeter Wemm **	Systems that have global modes that should be set should do
1261c2aa98e2SPeter Wemm **	them here rather than in main.
1262c2aa98e2SPeter Wemm */
1263c2aa98e2SPeter Wemm 
1264c2aa98e2SPeter Wemm #ifdef _AUX_SOURCE
1265c2aa98e2SPeter Wemm # include <compat.h>
1266c2aa98e2SPeter Wemm #endif
1267c2aa98e2SPeter Wemm 
1268c2aa98e2SPeter Wemm #if SHARE_V1
1269c2aa98e2SPeter Wemm # include <shares.h>
1270c2aa98e2SPeter Wemm #endif
1271c2aa98e2SPeter Wemm 
1272c2aa98e2SPeter Wemm void
1273c2aa98e2SPeter Wemm init_md(argc, argv)
1274c2aa98e2SPeter Wemm 	int argc;
1275c2aa98e2SPeter Wemm 	char **argv;
1276c2aa98e2SPeter Wemm {
1277c2aa98e2SPeter Wemm #ifdef _AUX_SOURCE
1278c2aa98e2SPeter Wemm 	setcompat(getcompat() | COMPAT_BSDPROT);
1279c2aa98e2SPeter Wemm #endif
1280c2aa98e2SPeter Wemm 
1281c2aa98e2SPeter Wemm #ifdef SUN_EXTENSIONS
1282c2aa98e2SPeter Wemm 	init_md_sun();
1283c2aa98e2SPeter Wemm #endif
1284c2aa98e2SPeter Wemm 
1285c2aa98e2SPeter Wemm #if _CONVEX_SOURCE
1286c2aa98e2SPeter Wemm 	/* keep gethostby*() from stripping the local domain name */
1287c2aa98e2SPeter Wemm 	set_domain_trim_off();
1288c2aa98e2SPeter Wemm #endif
1289c2aa98e2SPeter Wemm #ifdef __QNX__
1290c2aa98e2SPeter Wemm 	/*
1291c2aa98e2SPeter Wemm 	**  Due to QNX's network distributed nature, you can target a tcpip
1292c2aa98e2SPeter Wemm 	**  stack on a different node in the qnx network; this patch lets
1293c2aa98e2SPeter Wemm 	**  this feature work.  The __sock_locate() must be done before the
1294c2aa98e2SPeter Wemm 	**  environment is clear.
1295c2aa98e2SPeter Wemm 	*/
1296c2aa98e2SPeter Wemm 	__sock_locate();
1297c2aa98e2SPeter Wemm #endif
1298c2aa98e2SPeter Wemm #if SECUREWARE || defined(_SCO_unix_)
1299c2aa98e2SPeter Wemm 	set_auth_parameters(argc, argv);
1300c2aa98e2SPeter Wemm 
1301c2aa98e2SPeter Wemm # ifdef _SCO_unix_
1302c2aa98e2SPeter Wemm 	/*
1303c2aa98e2SPeter Wemm 	**  This is required for highest security levels (the kernel
1304c2aa98e2SPeter Wemm 	**  won't let it call set*uid() or run setuid binaries without
1305c2aa98e2SPeter Wemm 	**  it).  It may be necessary on other SECUREWARE systems.
1306c2aa98e2SPeter Wemm 	*/
1307c2aa98e2SPeter Wemm 
1308c2aa98e2SPeter Wemm 	if (getluid() == -1)
1309c2aa98e2SPeter Wemm 		setluid(0);
1310c2aa98e2SPeter Wemm # endif
1311c2aa98e2SPeter Wemm #endif
1312c2aa98e2SPeter Wemm 
1313c2aa98e2SPeter Wemm #ifdef VENDOR_DEFAULT
1314c2aa98e2SPeter Wemm 	VendorCode = VENDOR_DEFAULT;
1315c2aa98e2SPeter Wemm #else
1316c2aa98e2SPeter Wemm 	VendorCode = VENDOR_BERKELEY;
1317c2aa98e2SPeter Wemm #endif
1318c2aa98e2SPeter Wemm }
1319c2aa98e2SPeter Wemm /*
1320c2aa98e2SPeter Wemm **  INIT_VENDOR_MACROS -- vendor-dependent macro initializations
1321c2aa98e2SPeter Wemm **
1322c2aa98e2SPeter Wemm **	Called once, on startup.
1323c2aa98e2SPeter Wemm **
1324c2aa98e2SPeter Wemm **	Parameters:
1325c2aa98e2SPeter Wemm **		e -- the global envelope.
1326c2aa98e2SPeter Wemm **
1327c2aa98e2SPeter Wemm **	Returns:
1328c2aa98e2SPeter Wemm **		none.
1329c2aa98e2SPeter Wemm **
1330c2aa98e2SPeter Wemm **	Side Effects:
1331c2aa98e2SPeter Wemm **		vendor-dependent.
1332c2aa98e2SPeter Wemm */
1333c2aa98e2SPeter Wemm 
1334c2aa98e2SPeter Wemm void
1335c2aa98e2SPeter Wemm init_vendor_macros(e)
1336c2aa98e2SPeter Wemm 	register ENVELOPE *e;
1337c2aa98e2SPeter Wemm {
1338c2aa98e2SPeter Wemm }
1339c2aa98e2SPeter Wemm /*
1340c2aa98e2SPeter Wemm **  GETLA -- get the current load average
1341c2aa98e2SPeter Wemm **
1342c2aa98e2SPeter Wemm **	This code stolen from la.c.
1343c2aa98e2SPeter Wemm **
1344c2aa98e2SPeter Wemm **	Parameters:
1345c2aa98e2SPeter Wemm **		none.
1346c2aa98e2SPeter Wemm **
1347c2aa98e2SPeter Wemm **	Returns:
1348c2aa98e2SPeter Wemm **		The current load average as an integer.
1349c2aa98e2SPeter Wemm **
1350c2aa98e2SPeter Wemm **	Side Effects:
1351c2aa98e2SPeter Wemm **		none.
1352c2aa98e2SPeter Wemm */
1353c2aa98e2SPeter Wemm 
1354c2aa98e2SPeter Wemm /* try to guess what style of load average we have */
1355c2aa98e2SPeter Wemm #define LA_ZERO		1	/* always return load average as zero */
1356c2aa98e2SPeter Wemm #define LA_INT		2	/* read kmem for avenrun; interpret as long */
1357c2aa98e2SPeter Wemm #define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
1358c2aa98e2SPeter Wemm #define LA_SUBR		4	/* call getloadavg */
1359c2aa98e2SPeter Wemm #define LA_MACH		5	/* MACH load averages (as on NeXT boxes) */
1360c2aa98e2SPeter Wemm #define LA_SHORT	6	/* read kmem for avenrun; interpret as short */
1361c2aa98e2SPeter Wemm #define LA_PROCSTR	7	/* read string ("1.17") from /proc/loadavg */
1362c2aa98e2SPeter Wemm #define LA_READKSYM	8	/* SVR4: use MIOC_READKSYM ioctl call */
1363c2aa98e2SPeter Wemm #define LA_DGUX		9	/* special DGUX implementation */
1364c2aa98e2SPeter Wemm #define LA_HPUX		10	/* special HPUX implementation */
1365c2aa98e2SPeter Wemm #define LA_IRIX6	11	/* special IRIX 6.2 implementation */
1366c2aa98e2SPeter Wemm #define LA_KSTAT	12	/* special Solaris kstat(3k) implementation */
1367c2aa98e2SPeter Wemm #define LA_DEVSHORT	13	/* read short from a device */
1368c2aa98e2SPeter Wemm #define LA_ALPHAOSF	14	/* Digital UNIX (OSF/1 on Alpha) table() call */
1369c2aa98e2SPeter Wemm 
1370c2aa98e2SPeter Wemm /* do guesses based on general OS type */
1371c2aa98e2SPeter Wemm #ifndef LA_TYPE
1372c2aa98e2SPeter Wemm # define LA_TYPE	LA_ZERO
1373c2aa98e2SPeter Wemm #endif
1374c2aa98e2SPeter Wemm 
1375c2aa98e2SPeter Wemm #ifndef FSHIFT
1376c2aa98e2SPeter Wemm # if defined(unixpc)
1377c2aa98e2SPeter Wemm #  define FSHIFT	5
1378c2aa98e2SPeter Wemm # endif
1379c2aa98e2SPeter Wemm 
1380c2aa98e2SPeter Wemm # if defined(__alpha) || defined(IRIX)
1381c2aa98e2SPeter Wemm #  define FSHIFT	10
1382c2aa98e2SPeter Wemm # endif
1383c2aa98e2SPeter Wemm 
1384c2aa98e2SPeter Wemm #endif
1385c2aa98e2SPeter Wemm 
1386c2aa98e2SPeter Wemm #ifndef FSHIFT
1387c2aa98e2SPeter Wemm # define FSHIFT		8
1388c2aa98e2SPeter Wemm #endif
1389c2aa98e2SPeter Wemm 
1390c2aa98e2SPeter Wemm #ifndef FSCALE
1391c2aa98e2SPeter Wemm # define FSCALE		(1 << FSHIFT)
1392c2aa98e2SPeter Wemm #endif
1393c2aa98e2SPeter Wemm 
1394c2aa98e2SPeter Wemm #ifndef LA_AVENRUN
1395c2aa98e2SPeter Wemm # ifdef SYSTEM5
1396c2aa98e2SPeter Wemm #  define LA_AVENRUN	"avenrun"
1397c2aa98e2SPeter Wemm # else
1398c2aa98e2SPeter Wemm #  define LA_AVENRUN	"_avenrun"
1399c2aa98e2SPeter Wemm # endif
1400c2aa98e2SPeter Wemm #endif
1401c2aa98e2SPeter Wemm 
1402c2aa98e2SPeter Wemm /* _PATH_KMEM should be defined in <paths.h> */
1403c2aa98e2SPeter Wemm #ifndef _PATH_KMEM
1404c2aa98e2SPeter Wemm # define _PATH_KMEM	"/dev/kmem"
1405c2aa98e2SPeter Wemm #endif
1406c2aa98e2SPeter Wemm 
1407c2aa98e2SPeter Wemm #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT)
1408c2aa98e2SPeter Wemm 
1409c2aa98e2SPeter Wemm #include <nlist.h>
1410c2aa98e2SPeter Wemm 
1411c2aa98e2SPeter Wemm /* _PATH_UNIX should be defined in <paths.h> */
1412c2aa98e2SPeter Wemm #ifndef _PATH_UNIX
1413c2aa98e2SPeter Wemm # if defined(SYSTEM5)
1414c2aa98e2SPeter Wemm #  define _PATH_UNIX	"/unix"
1415c2aa98e2SPeter Wemm # else
1416c2aa98e2SPeter Wemm #  define _PATH_UNIX	"/vmunix"
1417c2aa98e2SPeter Wemm # endif
1418c2aa98e2SPeter Wemm #endif
1419c2aa98e2SPeter Wemm 
1420c2aa98e2SPeter Wemm #ifdef _AUX_SOURCE
1421c2aa98e2SPeter Wemm struct nlist	Nl[2];
1422c2aa98e2SPeter Wemm #else
1423c2aa98e2SPeter Wemm struct nlist	Nl[] =
1424c2aa98e2SPeter Wemm {
1425c2aa98e2SPeter Wemm 	{ LA_AVENRUN },
1426c2aa98e2SPeter Wemm 	{ 0 },
1427c2aa98e2SPeter Wemm };
1428c2aa98e2SPeter Wemm #endif
1429c2aa98e2SPeter Wemm #define	X_AVENRUN	0
1430c2aa98e2SPeter Wemm 
1431c2aa98e2SPeter Wemm int
1432c2aa98e2SPeter Wemm getla()
1433c2aa98e2SPeter Wemm {
1434c2aa98e2SPeter Wemm 	static int kmem = -1;
1435c2aa98e2SPeter Wemm #if LA_TYPE == LA_INT
1436c2aa98e2SPeter Wemm 	long avenrun[3];
1437c2aa98e2SPeter Wemm #else
1438c2aa98e2SPeter Wemm # if LA_TYPE == LA_SHORT
1439c2aa98e2SPeter Wemm 	short avenrun[3];
1440c2aa98e2SPeter Wemm # else
1441c2aa98e2SPeter Wemm 	double avenrun[3];
1442c2aa98e2SPeter Wemm # endif
1443c2aa98e2SPeter Wemm #endif
1444c2aa98e2SPeter Wemm 	extern int errno;
1445c2aa98e2SPeter Wemm 	extern off_t lseek();
1446c2aa98e2SPeter Wemm 
1447c2aa98e2SPeter Wemm 	if (kmem < 0)
1448c2aa98e2SPeter Wemm 	{
1449c2aa98e2SPeter Wemm #ifdef _AUX_SOURCE
1450c2aa98e2SPeter Wemm 		strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN);
1451c2aa98e2SPeter Wemm 		Nl[1].n_name[0] = '\0';
1452c2aa98e2SPeter Wemm #endif
1453c2aa98e2SPeter Wemm 
1454c2aa98e2SPeter Wemm #if defined(_AIX3) || defined(_AIX4)
1455c2aa98e2SPeter Wemm 		if (knlist(Nl, 1, sizeof Nl[0]) < 0)
1456c2aa98e2SPeter Wemm #else
1457c2aa98e2SPeter Wemm 		if (nlist(_PATH_UNIX, Nl) < 0)
1458c2aa98e2SPeter Wemm #endif
1459c2aa98e2SPeter Wemm 		{
1460c2aa98e2SPeter Wemm 			if (tTd(3, 1))
1461c2aa98e2SPeter Wemm 				printf("getla: nlist(%s): %s\n", _PATH_UNIX,
1462c2aa98e2SPeter Wemm 					errstring(errno));
1463c2aa98e2SPeter Wemm 			return (-1);
1464c2aa98e2SPeter Wemm 		}
1465c2aa98e2SPeter Wemm 		if (Nl[X_AVENRUN].n_value == 0)
1466c2aa98e2SPeter Wemm 		{
1467c2aa98e2SPeter Wemm 			if (tTd(3, 1))
1468c2aa98e2SPeter Wemm 				printf("getla: nlist(%s, %s) ==> 0\n",
1469c2aa98e2SPeter Wemm 					_PATH_UNIX, LA_AVENRUN);
1470c2aa98e2SPeter Wemm 			return (-1);
1471c2aa98e2SPeter Wemm 		}
1472c2aa98e2SPeter Wemm #ifdef NAMELISTMASK
1473c2aa98e2SPeter Wemm 		Nl[X_AVENRUN].n_value &= NAMELISTMASK;
1474c2aa98e2SPeter Wemm #endif
1475c2aa98e2SPeter Wemm 
1476c2aa98e2SPeter Wemm 		kmem = open(_PATH_KMEM, 0, 0);
1477c2aa98e2SPeter Wemm 		if (kmem < 0)
1478c2aa98e2SPeter Wemm 		{
1479c2aa98e2SPeter Wemm 			if (tTd(3, 1))
1480c2aa98e2SPeter Wemm 				printf("getla: open(/dev/kmem): %s\n",
1481c2aa98e2SPeter Wemm 					errstring(errno));
1482c2aa98e2SPeter Wemm 			return (-1);
1483c2aa98e2SPeter Wemm 		}
1484c2aa98e2SPeter Wemm 		(void) fcntl(kmem, F_SETFD, 1);
1485c2aa98e2SPeter Wemm 	}
1486c2aa98e2SPeter Wemm 	if (tTd(3, 20))
1487c2aa98e2SPeter Wemm 		printf("getla: symbol address = %#lx\n",
1488c2aa98e2SPeter Wemm 			(u_long) Nl[X_AVENRUN].n_value);
1489c2aa98e2SPeter Wemm 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 ||
1490c2aa98e2SPeter Wemm 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
1491c2aa98e2SPeter Wemm 	{
1492c2aa98e2SPeter Wemm 		/* thank you Ian */
1493c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1494c2aa98e2SPeter Wemm 			printf("getla: lseek or read: %s\n", errstring(errno));
1495c2aa98e2SPeter Wemm 		return (-1);
1496c2aa98e2SPeter Wemm 	}
1497c2aa98e2SPeter Wemm # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
1498c2aa98e2SPeter Wemm 	if (tTd(3, 5))
1499c2aa98e2SPeter Wemm 	{
1500c2aa98e2SPeter Wemm #  if LA_TYPE == LA_SHORT
1501c2aa98e2SPeter Wemm 		printf("getla: avenrun = %d", avenrun[0]);
1502c2aa98e2SPeter Wemm 		if (tTd(3, 15))
1503c2aa98e2SPeter Wemm 			printf(", %d, %d", avenrun[1], avenrun[2]);
1504c2aa98e2SPeter Wemm #  else
1505c2aa98e2SPeter Wemm 		printf("getla: avenrun = %ld", avenrun[0]);
1506c2aa98e2SPeter Wemm 		if (tTd(3, 15))
1507c2aa98e2SPeter Wemm 			printf(", %ld, %ld", avenrun[1], avenrun[2]);
1508c2aa98e2SPeter Wemm #  endif
1509c2aa98e2SPeter Wemm 		printf("\n");
1510c2aa98e2SPeter Wemm 	}
1511c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1512c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1513c2aa98e2SPeter Wemm 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1514c2aa98e2SPeter Wemm # else /* LA_TYPE == LA_FLOAT */
1515c2aa98e2SPeter Wemm 	if (tTd(3, 5))
1516c2aa98e2SPeter Wemm 	{
1517c2aa98e2SPeter Wemm 		printf("getla: avenrun = %g", avenrun[0]);
1518c2aa98e2SPeter Wemm 		if (tTd(3, 15))
1519c2aa98e2SPeter Wemm 			printf(", %g, %g", avenrun[1], avenrun[2]);
1520c2aa98e2SPeter Wemm 		printf("\n");
1521c2aa98e2SPeter Wemm 	}
1522c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1523c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (avenrun[0] +0.5));
1524c2aa98e2SPeter Wemm 	return ((int) (avenrun[0] + 0.5));
1525c2aa98e2SPeter Wemm # endif
1526c2aa98e2SPeter Wemm }
1527c2aa98e2SPeter Wemm 
1528c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_INT or LA_SHORT or LA_FLOAT */
1529c2aa98e2SPeter Wemm 
1530c2aa98e2SPeter Wemm #if LA_TYPE == LA_READKSYM
1531c2aa98e2SPeter Wemm 
1532c2aa98e2SPeter Wemm # include <sys/ksym.h>
1533c2aa98e2SPeter Wemm 
1534c2aa98e2SPeter Wemm getla()
1535c2aa98e2SPeter Wemm {
1536c2aa98e2SPeter Wemm 	static int kmem = -1;
1537c2aa98e2SPeter Wemm 	long avenrun[3];
1538c2aa98e2SPeter Wemm 	extern int errno;
1539c2aa98e2SPeter Wemm 	struct mioc_rksym mirk;
1540c2aa98e2SPeter Wemm 
1541c2aa98e2SPeter Wemm 	if (kmem < 0)
1542c2aa98e2SPeter Wemm 	{
1543c2aa98e2SPeter Wemm 		kmem = open("/dev/kmem", 0, 0);
1544c2aa98e2SPeter Wemm 		if (kmem < 0)
1545c2aa98e2SPeter Wemm 		{
1546c2aa98e2SPeter Wemm 			if (tTd(3, 1))
1547c2aa98e2SPeter Wemm 				printf("getla: open(/dev/kmem): %s\n",
1548c2aa98e2SPeter Wemm 					errstring(errno));
1549c2aa98e2SPeter Wemm 			return (-1);
1550c2aa98e2SPeter Wemm 		}
1551c2aa98e2SPeter Wemm 		(void) fcntl(kmem, F_SETFD, 1);
1552c2aa98e2SPeter Wemm 	}
1553c2aa98e2SPeter Wemm 	mirk.mirk_symname = LA_AVENRUN;
1554c2aa98e2SPeter Wemm 	mirk.mirk_buf = avenrun;
1555c2aa98e2SPeter Wemm 	mirk.mirk_buflen = sizeof(avenrun);
1556c2aa98e2SPeter Wemm 	if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
1557c2aa98e2SPeter Wemm 	{
1558c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1559c2aa98e2SPeter Wemm 			printf("getla: ioctl(MIOC_READKSYM) failed: %s\n",
1560c2aa98e2SPeter Wemm 				errstring(errno));
1561c2aa98e2SPeter Wemm 		return -1;
1562c2aa98e2SPeter Wemm 	}
1563c2aa98e2SPeter Wemm 	if (tTd(3, 5))
1564c2aa98e2SPeter Wemm 	{
1565c2aa98e2SPeter Wemm 		printf("getla: avenrun = %d", avenrun[0]);
1566c2aa98e2SPeter Wemm 		if (tTd(3, 15))
1567c2aa98e2SPeter Wemm 			printf(", %d, %d", avenrun[1], avenrun[2]);
1568c2aa98e2SPeter Wemm 		printf("\n");
1569c2aa98e2SPeter Wemm 	}
1570c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1571c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1572c2aa98e2SPeter Wemm 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1573c2aa98e2SPeter Wemm }
1574c2aa98e2SPeter Wemm 
1575c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_READKSYM */
1576c2aa98e2SPeter Wemm 
1577c2aa98e2SPeter Wemm #if LA_TYPE == LA_DGUX
1578c2aa98e2SPeter Wemm 
1579c2aa98e2SPeter Wemm # include <sys/dg_sys_info.h>
1580c2aa98e2SPeter Wemm 
1581c2aa98e2SPeter Wemm int
1582c2aa98e2SPeter Wemm getla()
1583c2aa98e2SPeter Wemm {
1584c2aa98e2SPeter Wemm 	struct dg_sys_info_load_info load_info;
1585c2aa98e2SPeter Wemm 
1586c2aa98e2SPeter Wemm 	dg_sys_info((long *)&load_info,
1587c2aa98e2SPeter Wemm 		DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
1588c2aa98e2SPeter Wemm 
1589c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1590c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (load_info.one_minute + 0.5));
1591c2aa98e2SPeter Wemm 
1592c2aa98e2SPeter Wemm 	return((int) (load_info.one_minute + 0.5));
1593c2aa98e2SPeter Wemm }
1594c2aa98e2SPeter Wemm 
1595c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_DGUX */
1596c2aa98e2SPeter Wemm 
1597c2aa98e2SPeter Wemm #if LA_TYPE == LA_HPUX
1598c2aa98e2SPeter Wemm 
1599c2aa98e2SPeter Wemm /* forward declarations to keep gcc from complaining */
1600c2aa98e2SPeter Wemm struct pst_dynamic;
1601c2aa98e2SPeter Wemm struct pst_status;
1602c2aa98e2SPeter Wemm struct pst_static;
1603c2aa98e2SPeter Wemm struct pst_vminfo;
1604c2aa98e2SPeter Wemm struct pst_diskinfo;
1605c2aa98e2SPeter Wemm struct pst_processor;
1606c2aa98e2SPeter Wemm struct pst_lv;
1607c2aa98e2SPeter Wemm struct pst_swapinfo;
1608c2aa98e2SPeter Wemm 
1609c2aa98e2SPeter Wemm # include <sys/param.h>
1610c2aa98e2SPeter Wemm # include <sys/pstat.h>
1611c2aa98e2SPeter Wemm 
1612c2aa98e2SPeter Wemm int
1613c2aa98e2SPeter Wemm getla()
1614c2aa98e2SPeter Wemm {
1615c2aa98e2SPeter Wemm 	struct pst_dynamic pstd;
1616c2aa98e2SPeter Wemm 
1617c2aa98e2SPeter Wemm 	if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
1618c2aa98e2SPeter Wemm 			     (size_t) 1, 0) == -1)
1619c2aa98e2SPeter Wemm 		return 0;
1620c2aa98e2SPeter Wemm 
1621c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1622c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
1623c2aa98e2SPeter Wemm 
1624c2aa98e2SPeter Wemm 	return (int) (pstd.psd_avg_1_min + 0.5);
1625c2aa98e2SPeter Wemm }
1626c2aa98e2SPeter Wemm 
1627c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_HPUX */
1628c2aa98e2SPeter Wemm 
1629c2aa98e2SPeter Wemm #if LA_TYPE == LA_SUBR
1630c2aa98e2SPeter Wemm 
1631c2aa98e2SPeter Wemm int
1632c2aa98e2SPeter Wemm getla()
1633c2aa98e2SPeter Wemm {
1634c2aa98e2SPeter Wemm 	double avenrun[3];
1635c2aa98e2SPeter Wemm 
1636c2aa98e2SPeter Wemm 	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
1637c2aa98e2SPeter Wemm 	{
1638c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1639c2aa98e2SPeter Wemm 			perror("getla: getloadavg failed:");
1640c2aa98e2SPeter Wemm 		return (-1);
1641c2aa98e2SPeter Wemm 	}
1642c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1643c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (avenrun[0] +0.5));
1644c2aa98e2SPeter Wemm 	return ((int) (avenrun[0] + 0.5));
1645c2aa98e2SPeter Wemm }
1646c2aa98e2SPeter Wemm 
1647c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_SUBR */
1648c2aa98e2SPeter Wemm 
1649c2aa98e2SPeter Wemm #if LA_TYPE == LA_MACH
1650c2aa98e2SPeter Wemm 
1651c2aa98e2SPeter Wemm /*
1652c2aa98e2SPeter Wemm **  This has been tested on NEXTSTEP release 2.1/3.X.
1653c2aa98e2SPeter Wemm */
1654c2aa98e2SPeter Wemm 
1655c2aa98e2SPeter Wemm #if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
1656c2aa98e2SPeter Wemm # include <mach/mach.h>
1657c2aa98e2SPeter Wemm #else
1658c2aa98e2SPeter Wemm # include <mach.h>
1659c2aa98e2SPeter Wemm #endif
1660c2aa98e2SPeter Wemm 
1661c2aa98e2SPeter Wemm int
1662c2aa98e2SPeter Wemm getla()
1663c2aa98e2SPeter Wemm {
1664c2aa98e2SPeter Wemm 	processor_set_t default_set;
1665c2aa98e2SPeter Wemm 	kern_return_t error;
1666c2aa98e2SPeter Wemm 	unsigned int info_count;
1667c2aa98e2SPeter Wemm 	struct processor_set_basic_info info;
1668c2aa98e2SPeter Wemm 	host_t host;
1669c2aa98e2SPeter Wemm 
1670c2aa98e2SPeter Wemm 	error = processor_set_default(host_self(), &default_set);
1671c2aa98e2SPeter Wemm 	if (error != KERN_SUCCESS)
1672c2aa98e2SPeter Wemm 	{
1673c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1674c2aa98e2SPeter Wemm 			perror("getla: processor_set_default failed:");
1675c2aa98e2SPeter Wemm 		return -1;
1676c2aa98e2SPeter Wemm 	}
1677c2aa98e2SPeter Wemm 	info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
1678c2aa98e2SPeter Wemm 	if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
1679c2aa98e2SPeter Wemm 			       &host, (processor_set_info_t)&info,
1680c2aa98e2SPeter Wemm 			       &info_count) != KERN_SUCCESS)
1681c2aa98e2SPeter Wemm 	{
1682c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1683c2aa98e2SPeter Wemm 			perror("getla: processor_set_info failed:");
1684c2aa98e2SPeter Wemm 		return -1;
1685c2aa98e2SPeter Wemm 	}
1686c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1687c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE);
1688c2aa98e2SPeter Wemm 	return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
1689c2aa98e2SPeter Wemm }
1690c2aa98e2SPeter Wemm 
1691c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_MACH */
1692c2aa98e2SPeter Wemm 
1693c2aa98e2SPeter Wemm #if LA_TYPE == LA_PROCSTR
1694c2aa98e2SPeter Wemm 
1695c2aa98e2SPeter Wemm /*
1696c2aa98e2SPeter Wemm **  Read /proc/loadavg for the load average.  This is assumed to be
1697c2aa98e2SPeter Wemm **  in a format like "0.15 0.12 0.06".
1698c2aa98e2SPeter Wemm **
1699c2aa98e2SPeter Wemm **	Initially intended for Linux.  This has been in the kernel
1700c2aa98e2SPeter Wemm **	since at least 0.99.15.
1701c2aa98e2SPeter Wemm */
1702c2aa98e2SPeter Wemm 
1703c2aa98e2SPeter Wemm # ifndef _PATH_LOADAVG
1704c2aa98e2SPeter Wemm #  define _PATH_LOADAVG	"/proc/loadavg"
1705c2aa98e2SPeter Wemm # endif
1706c2aa98e2SPeter Wemm 
1707c2aa98e2SPeter Wemm int
1708c2aa98e2SPeter Wemm getla()
1709c2aa98e2SPeter Wemm {
1710c2aa98e2SPeter Wemm 	double avenrun;
1711c2aa98e2SPeter Wemm 	register int result;
1712c2aa98e2SPeter Wemm 	FILE *fp;
1713c2aa98e2SPeter Wemm 
1714c2aa98e2SPeter Wemm 	fp = fopen(_PATH_LOADAVG, "r");
1715c2aa98e2SPeter Wemm 	if (fp == NULL)
1716c2aa98e2SPeter Wemm 	{
1717c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1718c2aa98e2SPeter Wemm 			printf("getla: fopen(%s): %s\n",
1719c2aa98e2SPeter Wemm 				_PATH_LOADAVG, errstring(errno));
1720c2aa98e2SPeter Wemm 		return -1;
1721c2aa98e2SPeter Wemm 	}
1722c2aa98e2SPeter Wemm 	result = fscanf(fp, "%lf", &avenrun);
1723c2aa98e2SPeter Wemm 	fclose(fp);
1724c2aa98e2SPeter Wemm 	if (result != 1)
1725c2aa98e2SPeter Wemm 	{
1726c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1727c2aa98e2SPeter Wemm 			printf("getla: fscanf() = %d: %s\n",
1728c2aa98e2SPeter Wemm 				result, errstring(errno));
1729c2aa98e2SPeter Wemm 		return -1;
1730c2aa98e2SPeter Wemm 	}
1731c2aa98e2SPeter Wemm 
1732c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1733c2aa98e2SPeter Wemm 		printf("getla(): %.2f\n", avenrun);
1734c2aa98e2SPeter Wemm 
1735c2aa98e2SPeter Wemm 	return ((int) (avenrun + 0.5));
1736c2aa98e2SPeter Wemm }
1737c2aa98e2SPeter Wemm 
1738c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_PROCSTR */
1739c2aa98e2SPeter Wemm 
1740c2aa98e2SPeter Wemm #if LA_TYPE == LA_IRIX6
1741c2aa98e2SPeter Wemm #include <sys/sysmp.h>
1742c2aa98e2SPeter Wemm 
1743c2aa98e2SPeter Wemm int getla(void)
1744c2aa98e2SPeter Wemm {
1745c2aa98e2SPeter Wemm 	static int kmem = -1;
1746c2aa98e2SPeter Wemm 	int avenrun[3];
1747c2aa98e2SPeter Wemm 
1748c2aa98e2SPeter Wemm 	if (kmem < 0)
1749c2aa98e2SPeter Wemm 	{
1750c2aa98e2SPeter Wemm 		kmem = open(_PATH_KMEM, 0, 0);
1751c2aa98e2SPeter Wemm 		if (kmem < 0)
1752c2aa98e2SPeter Wemm 		{
1753c2aa98e2SPeter Wemm 			if (tTd(3, 1))
1754c2aa98e2SPeter Wemm 				printf("getla: open(%s): %s\n", _PATH_KMEM,
1755c2aa98e2SPeter Wemm 					errstring(errno));
1756c2aa98e2SPeter Wemm 			return -1;
1757c2aa98e2SPeter Wemm 		}
1758c2aa98e2SPeter Wemm 		(void) fcntl(kmem, F_SETFD, 1);
1759c2aa98e2SPeter Wemm 	}
1760c2aa98e2SPeter Wemm 
1761c2aa98e2SPeter Wemm 	if (lseek(kmem, (sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff), SEEK_SET) == -1 ||
1762c2aa98e2SPeter Wemm 	    read(kmem, (char *)avenrun, sizeof(avenrun)) < sizeof(avenrun))
1763c2aa98e2SPeter Wemm 	{
1764c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1765c2aa98e2SPeter Wemm 			printf("getla: lseek or read: %s\n",
1766c2aa98e2SPeter Wemm 			       errstring(errno));
1767c2aa98e2SPeter Wemm 		return -1;
1768c2aa98e2SPeter Wemm 	}
1769c2aa98e2SPeter Wemm 	if (tTd(3, 5))
1770c2aa98e2SPeter Wemm 	{
1771c2aa98e2SPeter Wemm 		printf("getla: avenrun = %ld", (long int) avenrun[0]);
1772c2aa98e2SPeter Wemm 		if (tTd(3, 15))
1773c2aa98e2SPeter Wemm 			printf(", %ld, %ld",
1774c2aa98e2SPeter Wemm 			       (long int) avenrun[1], (long int) avenrun[2]);
1775c2aa98e2SPeter Wemm 		printf("\n");
1776c2aa98e2SPeter Wemm 	}
1777c2aa98e2SPeter Wemm 
1778c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1779c2aa98e2SPeter Wemm 		printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1780c2aa98e2SPeter Wemm 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1781c2aa98e2SPeter Wemm 
1782c2aa98e2SPeter Wemm }
1783c2aa98e2SPeter Wemm #endif
1784c2aa98e2SPeter Wemm 
1785c2aa98e2SPeter Wemm #if LA_TYPE == LA_KSTAT
1786c2aa98e2SPeter Wemm 
1787c2aa98e2SPeter Wemm #include <kstat.h>
1788c2aa98e2SPeter Wemm 
1789c2aa98e2SPeter Wemm int
1790c2aa98e2SPeter Wemm getla()
1791c2aa98e2SPeter Wemm {
1792c2aa98e2SPeter Wemm 	static kstat_ctl_t *kc = NULL;
1793c2aa98e2SPeter Wemm 	static kstat_t *ksp = NULL;
1794c2aa98e2SPeter Wemm 	kstat_named_t *ksn;
1795c2aa98e2SPeter Wemm 	int la;
1796c2aa98e2SPeter Wemm 
1797c2aa98e2SPeter Wemm 	if (kc == NULL)		/* if not initialized before */
1798c2aa98e2SPeter Wemm 		kc = kstat_open();
1799c2aa98e2SPeter Wemm 	if (kc == NULL)
1800c2aa98e2SPeter Wemm 	{
1801c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1802c2aa98e2SPeter Wemm 			printf("getla: kstat_open(): %s\n",
1803c2aa98e2SPeter Wemm 				errstring(errno));
1804c2aa98e2SPeter Wemm 		return -1;
1805c2aa98e2SPeter Wemm 	}
1806c2aa98e2SPeter Wemm 	if (ksp == NULL)
1807c2aa98e2SPeter Wemm 		ksp = kstat_lookup(kc, "unix", 0, "system_misc");
1808c2aa98e2SPeter Wemm 	if (ksp == NULL)
1809c2aa98e2SPeter Wemm 	{
1810c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1811c2aa98e2SPeter Wemm 			printf("getla: kstat_lookup(): %s\n",
1812c2aa98e2SPeter Wemm 				errstring(errno));
1813c2aa98e2SPeter Wemm 		return -1;
1814c2aa98e2SPeter Wemm 	}
1815c2aa98e2SPeter Wemm 	if (kstat_read(kc, ksp, NULL) < 0)
1816c2aa98e2SPeter Wemm 	{
1817c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1818c2aa98e2SPeter Wemm 			printf("getla: kstat_read(): %s\n",
1819c2aa98e2SPeter Wemm 				errstring(errno));
1820c2aa98e2SPeter Wemm 		return -1;
1821c2aa98e2SPeter Wemm 	}
1822c2aa98e2SPeter Wemm 	ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
1823c2aa98e2SPeter Wemm 	la = ((double)ksn->value.ul + FSCALE/2) / FSCALE;
1824c2aa98e2SPeter Wemm 	/* kstat_close(kc); /o do not close for fast access */
1825c2aa98e2SPeter Wemm 	return la;
1826c2aa98e2SPeter Wemm }
1827c2aa98e2SPeter Wemm 
1828c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_KSTAT */
1829c2aa98e2SPeter Wemm 
1830c2aa98e2SPeter Wemm #if LA_TYPE == LA_DEVSHORT
1831c2aa98e2SPeter Wemm 
1832c2aa98e2SPeter Wemm /*
1833c2aa98e2SPeter Wemm **  Read /dev/table/avenrun for the load average.  This should contain
1834c2aa98e2SPeter Wemm **  three shorts for the 1, 5, and 15 minute loads.  We only read the
1835c2aa98e2SPeter Wemm **  first, since that's all we care about.
1836c2aa98e2SPeter Wemm **
1837c2aa98e2SPeter Wemm **	Intended for SCO OpenServer 5.
1838c2aa98e2SPeter Wemm */
1839c2aa98e2SPeter Wemm 
1840c2aa98e2SPeter Wemm # ifndef _PATH_AVENRUN
1841c2aa98e2SPeter Wemm #  define _PATH_AVENRUN	"/dev/table/avenrun"
1842c2aa98e2SPeter Wemm # endif
1843c2aa98e2SPeter Wemm 
1844c2aa98e2SPeter Wemm int
1845c2aa98e2SPeter Wemm getla()
1846c2aa98e2SPeter Wemm {
1847c2aa98e2SPeter Wemm 	static int afd = -1;
1848c2aa98e2SPeter Wemm 	short avenrun;
1849c2aa98e2SPeter Wemm 	int loadav;
1850c2aa98e2SPeter Wemm 	int r;
1851c2aa98e2SPeter Wemm 
1852c2aa98e2SPeter Wemm 	errno = EBADF;
1853c2aa98e2SPeter Wemm 
1854c2aa98e2SPeter Wemm 	if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
1855c2aa98e2SPeter Wemm 	{
1856c2aa98e2SPeter Wemm 		if (errno != EBADF)
1857c2aa98e2SPeter Wemm 			return -1;
1858c2aa98e2SPeter Wemm 		afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
1859c2aa98e2SPeter Wemm 		if (afd < 0)
1860c2aa98e2SPeter Wemm 		{
1861c2aa98e2SPeter Wemm 			sm_syslog(LOG_ERR, NOQID,
1862c2aa98e2SPeter Wemm 				"can't open %s: %m",
1863c2aa98e2SPeter Wemm 				_PATH_AVENRUN);
1864c2aa98e2SPeter Wemm 			return -1;
1865c2aa98e2SPeter Wemm 		}
1866c2aa98e2SPeter Wemm 	}
1867c2aa98e2SPeter Wemm 
1868c2aa98e2SPeter Wemm 	r = read(afd, &avenrun, sizeof avenrun);
1869c2aa98e2SPeter Wemm 
1870c2aa98e2SPeter Wemm 	if (tTd(3, 5))
1871c2aa98e2SPeter Wemm 		printf("getla: avenrun = %d\n", avenrun);
1872c2aa98e2SPeter Wemm 	loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
1873c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1874c2aa98e2SPeter Wemm 		printf("getla: %d\n", loadav);
1875c2aa98e2SPeter Wemm 	return loadav;
1876c2aa98e2SPeter Wemm }
1877c2aa98e2SPeter Wemm 
1878c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_DEVSHORT */
1879c2aa98e2SPeter Wemm 
1880c2aa98e2SPeter Wemm #if LA_TYPE == LA_ALPHAOSF
1881c2aa98e2SPeter Wemm struct rtentry;
1882c2aa98e2SPeter Wemm struct mbuf;
1883c2aa98e2SPeter Wemm # include <sys/table.h>
1884c2aa98e2SPeter Wemm 
1885c2aa98e2SPeter Wemm int getla()
1886c2aa98e2SPeter Wemm {
1887c2aa98e2SPeter Wemm 	int ave = 0;
1888c2aa98e2SPeter Wemm 	struct tbl_loadavg tab;
1889c2aa98e2SPeter Wemm 
1890c2aa98e2SPeter Wemm 	if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1)
1891c2aa98e2SPeter Wemm 	{
1892c2aa98e2SPeter Wemm 		if (tTd(3, 1))
1893c2aa98e2SPeter Wemm 			printf("getla: table %s\n", errstring(errno));
1894c2aa98e2SPeter Wemm 		return (-1);
1895c2aa98e2SPeter Wemm 	}
1896c2aa98e2SPeter Wemm 
1897c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1898c2aa98e2SPeter Wemm 		printf("getla: scale = %d\n", tab.tl_lscale);
1899c2aa98e2SPeter Wemm 
1900c2aa98e2SPeter Wemm 	if (tab.tl_lscale)
1901c2aa98e2SPeter Wemm 		ave = (tab.tl_avenrun.l[0] + (tab.tl_lscale/2)) / tab.tl_lscale;
1902c2aa98e2SPeter Wemm 	else
1903c2aa98e2SPeter Wemm 		ave = (int) (tab.tl_avenrun.d[0] + 0.5);
1904c2aa98e2SPeter Wemm 
1905c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1906c2aa98e2SPeter Wemm 		printf("getla: %d\n", ave);
1907c2aa98e2SPeter Wemm 
1908c2aa98e2SPeter Wemm 	return ave;
1909c2aa98e2SPeter Wemm }
1910c2aa98e2SPeter Wemm 
1911c2aa98e2SPeter Wemm #endif
1912c2aa98e2SPeter Wemm 
1913c2aa98e2SPeter Wemm #if LA_TYPE == LA_ZERO
1914c2aa98e2SPeter Wemm 
1915c2aa98e2SPeter Wemm int
1916c2aa98e2SPeter Wemm getla()
1917c2aa98e2SPeter Wemm {
1918c2aa98e2SPeter Wemm 	if (tTd(3, 1))
1919c2aa98e2SPeter Wemm 		printf("getla: ZERO\n");
1920c2aa98e2SPeter Wemm 	return (0);
1921c2aa98e2SPeter Wemm }
1922c2aa98e2SPeter Wemm 
1923c2aa98e2SPeter Wemm #endif /* LA_TYPE == LA_ZERO */
1924c2aa98e2SPeter Wemm 
1925c2aa98e2SPeter Wemm /*
1926c2aa98e2SPeter Wemm  * Copyright 1989 Massachusetts Institute of Technology
1927c2aa98e2SPeter Wemm  *
1928c2aa98e2SPeter Wemm  * Permission to use, copy, modify, distribute, and sell this software and its
1929c2aa98e2SPeter Wemm  * documentation for any purpose is hereby granted without fee, provided that
1930c2aa98e2SPeter Wemm  * the above copyright notice appear in all copies and that both that
1931c2aa98e2SPeter Wemm  * copyright notice and this permission notice appear in supporting
1932c2aa98e2SPeter Wemm  * documentation, and that the name of M.I.T. not be used in advertising or
1933c2aa98e2SPeter Wemm  * publicity pertaining to distribution of the software without specific,
1934c2aa98e2SPeter Wemm  * written prior permission.  M.I.T. makes no representations about the
1935c2aa98e2SPeter Wemm  * suitability of this software for any purpose.  It is provided "as is"
1936c2aa98e2SPeter Wemm  * without express or implied warranty.
1937c2aa98e2SPeter Wemm  *
1938c2aa98e2SPeter Wemm  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
1939c2aa98e2SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
1940c2aa98e2SPeter Wemm  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1941c2aa98e2SPeter Wemm  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
1942c2aa98e2SPeter Wemm  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1943c2aa98e2SPeter Wemm  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1944c2aa98e2SPeter Wemm  *
1945c2aa98e2SPeter Wemm  * Authors:  Many and varied...
1946c2aa98e2SPeter Wemm  */
1947c2aa98e2SPeter Wemm 
1948c2aa98e2SPeter Wemm /* Non Apollo stuff removed by Don Lewis 11/15/93 */
1949c2aa98e2SPeter Wemm #ifndef lint
1950c2aa98e2SPeter Wemm static char  rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
1951c2aa98e2SPeter Wemm #endif /* !lint */
1952c2aa98e2SPeter Wemm 
1953c2aa98e2SPeter Wemm #ifdef apollo
1954c2aa98e2SPeter Wemm # undef volatile
1955c2aa98e2SPeter Wemm #    include <apollo/base.h>
1956c2aa98e2SPeter Wemm 
1957c2aa98e2SPeter Wemm /* ARGSUSED */
1958c2aa98e2SPeter Wemm int getloadavg( call_data )
1959c2aa98e2SPeter Wemm      caddr_t	call_data;	/* pointer to (double) return value */
1960c2aa98e2SPeter Wemm {
1961c2aa98e2SPeter Wemm      double *avenrun = (double *) call_data;
1962c2aa98e2SPeter Wemm      int i;
1963c2aa98e2SPeter Wemm      status_$t      st;
1964c2aa98e2SPeter Wemm      long loadav[3];
1965c2aa98e2SPeter Wemm      proc1_$get_loadav(loadav, &st);
1966c2aa98e2SPeter Wemm      *avenrun = loadav[0] / (double) (1 << 16);
1967c2aa98e2SPeter Wemm      return(0);
1968c2aa98e2SPeter Wemm }
1969c2aa98e2SPeter Wemm #   endif /* apollo */
1970c2aa98e2SPeter Wemm /*
1971c2aa98e2SPeter Wemm **  SHOULDQUEUE -- should this message be queued or sent?
1972c2aa98e2SPeter Wemm **
1973c2aa98e2SPeter Wemm **	Compares the message cost to the load average to decide.
1974c2aa98e2SPeter Wemm **
1975c2aa98e2SPeter Wemm **	Parameters:
1976c2aa98e2SPeter Wemm **		pri -- the priority of the message in question.
1977c2aa98e2SPeter Wemm **		ctime -- the message creation time.
1978c2aa98e2SPeter Wemm **
1979c2aa98e2SPeter Wemm **	Returns:
1980c2aa98e2SPeter Wemm **		TRUE -- if this message should be queued up for the
1981c2aa98e2SPeter Wemm **			time being.
1982c2aa98e2SPeter Wemm **		FALSE -- if the load is low enough to send this message.
1983c2aa98e2SPeter Wemm **
1984c2aa98e2SPeter Wemm **	Side Effects:
1985c2aa98e2SPeter Wemm **		none.
1986c2aa98e2SPeter Wemm */
1987c2aa98e2SPeter Wemm 
1988c2aa98e2SPeter Wemm extern int	get_num_procs_online __P((void));
1989c2aa98e2SPeter Wemm 
1990c2aa98e2SPeter Wemm bool
1991c2aa98e2SPeter Wemm shouldqueue(pri, ctime)
1992c2aa98e2SPeter Wemm 	long pri;
1993c2aa98e2SPeter Wemm 	time_t ctime;
1994c2aa98e2SPeter Wemm {
1995c2aa98e2SPeter Wemm 	bool rval;
1996c2aa98e2SPeter Wemm 	int queuela = QueueLA * get_num_procs_online();
1997c2aa98e2SPeter Wemm 
1998c2aa98e2SPeter Wemm 	if (tTd(3, 30))
1999c2aa98e2SPeter Wemm 		printf("shouldqueue: CurrentLA=%d, pri=%ld: ", CurrentLA, pri);
2000c2aa98e2SPeter Wemm 	if (CurrentLA < queuela)
2001c2aa98e2SPeter Wemm 	{
2002c2aa98e2SPeter Wemm 		if (tTd(3, 30))
2003c2aa98e2SPeter Wemm 			printf("FALSE (CurrentLA < QueueLA)\n");
2004c2aa98e2SPeter Wemm 		return (FALSE);
2005c2aa98e2SPeter Wemm 	}
2006c2aa98e2SPeter Wemm #if 0	/* this code is reported to cause oscillation around RefuseLA */
2007c2aa98e2SPeter Wemm 	if (CurrentLA >= RefuseLA && QueueLA < RefuseLA)
2008c2aa98e2SPeter Wemm 	{
2009c2aa98e2SPeter Wemm 		if (tTd(3, 30))
2010c2aa98e2SPeter Wemm 			printf("TRUE (CurrentLA >= RefuseLA)\n");
2011c2aa98e2SPeter Wemm 		return (TRUE);
2012c2aa98e2SPeter Wemm 	}
2013c2aa98e2SPeter Wemm #endif
2014c2aa98e2SPeter Wemm 	rval = pri > (QueueFactor / (CurrentLA - queuela + 1));
2015c2aa98e2SPeter Wemm 	if (tTd(3, 30))
2016c2aa98e2SPeter Wemm 		printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE");
2017c2aa98e2SPeter Wemm 	return rval;
2018c2aa98e2SPeter Wemm }
2019c2aa98e2SPeter Wemm /*
2020c2aa98e2SPeter Wemm **  REFUSECONNECTIONS -- decide if connections should be refused
2021c2aa98e2SPeter Wemm **
2022c2aa98e2SPeter Wemm **	Parameters:
2023c2aa98e2SPeter Wemm **		port -- port number (for error messages only)
2024c2aa98e2SPeter Wemm **
2025c2aa98e2SPeter Wemm **	Returns:
2026c2aa98e2SPeter Wemm **		TRUE if incoming SMTP connections should be refused
2027c2aa98e2SPeter Wemm **			(for now).
2028c2aa98e2SPeter Wemm **		FALSE if we should accept new work.
2029c2aa98e2SPeter Wemm **
2030c2aa98e2SPeter Wemm **	Side Effects:
2031c2aa98e2SPeter Wemm **		Sets process title when it is rejecting connections.
2032c2aa98e2SPeter Wemm */
2033c2aa98e2SPeter Wemm 
2034c2aa98e2SPeter Wemm bool
2035c2aa98e2SPeter Wemm refuseconnections(port)
2036c2aa98e2SPeter Wemm 	int port;
2037c2aa98e2SPeter Wemm {
2038c2aa98e2SPeter Wemm 	int refusela = RefuseLA * get_num_procs_online();
2039c2aa98e2SPeter Wemm 	time_t now;
2040c2aa98e2SPeter Wemm 	static time_t lastconn = (time_t) 0;
2041c2aa98e2SPeter Wemm 	static int conncnt = 0;
2042c2aa98e2SPeter Wemm 	extern bool enoughdiskspace __P((long));
2043c2aa98e2SPeter Wemm 
2044c2aa98e2SPeter Wemm #ifdef XLA
2045c2aa98e2SPeter Wemm 	if (!xla_smtp_ok())
2046c2aa98e2SPeter Wemm 		return TRUE;
2047c2aa98e2SPeter Wemm #endif
2048c2aa98e2SPeter Wemm 
2049c2aa98e2SPeter Wemm 	now = curtime();
2050c2aa98e2SPeter Wemm 	if (now != lastconn)
2051c2aa98e2SPeter Wemm 	{
2052c2aa98e2SPeter Wemm 		lastconn = now;
2053c2aa98e2SPeter Wemm 		conncnt = 0;
2054c2aa98e2SPeter Wemm 	}
2055c2aa98e2SPeter Wemm 	else if (conncnt++ > ConnRateThrottle && ConnRateThrottle > 0)
2056c2aa98e2SPeter Wemm 	{
2057c2aa98e2SPeter Wemm 		/* sleep to flatten out connection load */
205876b7bf71SPeter Wemm 		sm_setproctitle(TRUE, "deferring connections on port %d: %d per second",
2059c2aa98e2SPeter Wemm 			port, ConnRateThrottle);
2060c2aa98e2SPeter Wemm 		if (LogLevel >= 14)
2061c2aa98e2SPeter Wemm 			sm_syslog(LOG_INFO, NOQID,
2062c2aa98e2SPeter Wemm 				"deferring connections on port %d: %d per second",
2063c2aa98e2SPeter Wemm 				port, ConnRateThrottle);
2064c2aa98e2SPeter Wemm 		sleep(1);
2065c2aa98e2SPeter Wemm 	}
2066c2aa98e2SPeter Wemm 
2067c2aa98e2SPeter Wemm 	CurrentLA = getla();
2068c2aa98e2SPeter Wemm 	if (CurrentLA >= refusela)
2069c2aa98e2SPeter Wemm 	{
207076b7bf71SPeter Wemm 		sm_setproctitle(TRUE, "rejecting connections on port %d: load average: %d",
2071c2aa98e2SPeter Wemm 			port, CurrentLA);
2072c2aa98e2SPeter Wemm 		if (LogLevel >= 14)
2073c2aa98e2SPeter Wemm 			sm_syslog(LOG_INFO, NOQID,
2074c2aa98e2SPeter Wemm 				"rejecting connections on port %d: load average: %d",
2075c2aa98e2SPeter Wemm 				port, CurrentLA);
2076c2aa98e2SPeter Wemm 		return TRUE;
2077c2aa98e2SPeter Wemm 	}
2078c2aa98e2SPeter Wemm 
2079c2aa98e2SPeter Wemm 	if (!enoughdiskspace(MinBlocksFree + 1))
2080c2aa98e2SPeter Wemm 	{
208176b7bf71SPeter Wemm 		sm_setproctitle(TRUE, "rejecting connections on port %d: min free: %d",
2082c2aa98e2SPeter Wemm 			port, MinBlocksFree);
2083c2aa98e2SPeter Wemm 		if (LogLevel >= 14)
2084c2aa98e2SPeter Wemm 			sm_syslog(LOG_INFO, NOQID,
2085c2aa98e2SPeter Wemm 				"rejecting connections on port %d: min free: %d",
2086c2aa98e2SPeter Wemm 				port, MinBlocksFree);
2087c2aa98e2SPeter Wemm 		return TRUE;
2088c2aa98e2SPeter Wemm 	}
2089c2aa98e2SPeter Wemm 
2090c2aa98e2SPeter Wemm 	if (MaxChildren > 0 && CurChildren >= MaxChildren)
2091c2aa98e2SPeter Wemm 	{
2092c2aa98e2SPeter Wemm 		proc_list_probe();
2093c2aa98e2SPeter Wemm 		if (CurChildren >= MaxChildren)
2094c2aa98e2SPeter Wemm 		{
209576b7bf71SPeter Wemm 			sm_setproctitle(TRUE, "rejecting connections on port %d: %d children, max %d",
2096c2aa98e2SPeter Wemm 				port, CurChildren, MaxChildren);
2097c2aa98e2SPeter Wemm 			if (LogLevel >= 14)
2098c2aa98e2SPeter Wemm 				sm_syslog(LOG_INFO, NOQID,
2099c2aa98e2SPeter Wemm 					"rejecting connections on port %d: %d children, max %d",
2100c2aa98e2SPeter Wemm 					port, CurChildren, MaxChildren);
2101c2aa98e2SPeter Wemm 			return TRUE;
2102c2aa98e2SPeter Wemm 		}
2103c2aa98e2SPeter Wemm 	}
2104c2aa98e2SPeter Wemm 
2105c2aa98e2SPeter Wemm 	return FALSE;
2106c2aa98e2SPeter Wemm }
2107c2aa98e2SPeter Wemm /*
2108c2aa98e2SPeter Wemm **  SETPROCTITLE -- set process title for ps
2109c2aa98e2SPeter Wemm **
2110c2aa98e2SPeter Wemm **	Parameters:
2111c2aa98e2SPeter Wemm **		fmt -- a printf style format string.
2112c2aa98e2SPeter Wemm **		a, b, c -- possible parameters to fmt.
2113c2aa98e2SPeter Wemm **
2114c2aa98e2SPeter Wemm **	Returns:
2115c2aa98e2SPeter Wemm **		none.
2116c2aa98e2SPeter Wemm **
2117c2aa98e2SPeter Wemm **	Side Effects:
2118c2aa98e2SPeter Wemm **		Clobbers argv of our main procedure so ps(1) will
2119c2aa98e2SPeter Wemm **		display the title.
2120c2aa98e2SPeter Wemm */
2121c2aa98e2SPeter Wemm 
2122c2aa98e2SPeter Wemm #define SPT_NONE	0	/* don't use it at all */
2123c2aa98e2SPeter Wemm #define SPT_REUSEARGV	1	/* cover argv with title information */
2124c2aa98e2SPeter Wemm #define SPT_BUILTIN	2	/* use libc builtin */
2125c2aa98e2SPeter Wemm #define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
2126c2aa98e2SPeter Wemm #define SPT_PSSTRINGS	4	/* use PS_STRINGS->... */
2127c2aa98e2SPeter Wemm #define SPT_SYSMIPS	5	/* use sysmips() supported by NEWS-OS 6 */
2128c2aa98e2SPeter Wemm #define SPT_SCO		6	/* write kernel u. area */
2129c2aa98e2SPeter Wemm #define SPT_CHANGEARGV	7	/* write our own strings into argv[] */
2130c2aa98e2SPeter Wemm 
2131c2aa98e2SPeter Wemm #ifndef SPT_TYPE
2132c2aa98e2SPeter Wemm # define SPT_TYPE	SPT_REUSEARGV
2133c2aa98e2SPeter Wemm #endif
2134c2aa98e2SPeter Wemm 
2135c2aa98e2SPeter Wemm #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
2136c2aa98e2SPeter Wemm 
2137c2aa98e2SPeter Wemm # if SPT_TYPE == SPT_PSTAT
2138c2aa98e2SPeter Wemm #  include <sys/pstat.h>
2139c2aa98e2SPeter Wemm # endif
2140c2aa98e2SPeter Wemm # if SPT_TYPE == SPT_PSSTRINGS
2141c2aa98e2SPeter Wemm #  include <machine/vmparam.h>
2142c2aa98e2SPeter Wemm #  include <sys/exec.h>
2143c2aa98e2SPeter Wemm #  ifndef PS_STRINGS	/* hmmmm....  apparently not available after all */
2144c2aa98e2SPeter Wemm #   undef SPT_TYPE
2145c2aa98e2SPeter Wemm #   define SPT_TYPE	SPT_REUSEARGV
2146c2aa98e2SPeter Wemm #  else
2147c2aa98e2SPeter Wemm #   ifndef NKPDE			/* FreeBSD 2.0 */
2148c2aa98e2SPeter Wemm #    define NKPDE 63
2149c2aa98e2SPeter Wemm typedef unsigned int	*pt_entry_t;
2150c2aa98e2SPeter Wemm #   endif
2151c2aa98e2SPeter Wemm #  endif
2152c2aa98e2SPeter Wemm # endif
2153c2aa98e2SPeter Wemm 
2154c2aa98e2SPeter Wemm # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
2155c2aa98e2SPeter Wemm #  define SETPROC_STATIC	static
2156c2aa98e2SPeter Wemm # else
2157c2aa98e2SPeter Wemm #  define SETPROC_STATIC
2158c2aa98e2SPeter Wemm # endif
2159c2aa98e2SPeter Wemm 
2160c2aa98e2SPeter Wemm # if SPT_TYPE == SPT_SYSMIPS
2161c2aa98e2SPeter Wemm #  include <sys/sysmips.h>
2162c2aa98e2SPeter Wemm #  include <sys/sysnews.h>
2163c2aa98e2SPeter Wemm # endif
2164c2aa98e2SPeter Wemm 
2165c2aa98e2SPeter Wemm # if SPT_TYPE == SPT_SCO
2166c2aa98e2SPeter Wemm #  include <sys/immu.h>
2167c2aa98e2SPeter Wemm #  include <sys/dir.h>
2168c2aa98e2SPeter Wemm #  include <sys/user.h>
2169c2aa98e2SPeter Wemm #  include <sys/fs/s5param.h>
2170c2aa98e2SPeter Wemm #  if PSARGSZ > MAXLINE
2171c2aa98e2SPeter Wemm #   define SPT_BUFSIZE	PSARGSZ
2172c2aa98e2SPeter Wemm #  endif
2173c2aa98e2SPeter Wemm # endif
2174c2aa98e2SPeter Wemm 
2175c2aa98e2SPeter Wemm # ifndef SPT_PADCHAR
2176c2aa98e2SPeter Wemm #  define SPT_PADCHAR	' '
2177c2aa98e2SPeter Wemm # endif
2178c2aa98e2SPeter Wemm 
217976b7bf71SPeter Wemm #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
218076b7bf71SPeter Wemm 
2181c2aa98e2SPeter Wemm # ifndef SPT_BUFSIZE
2182c2aa98e2SPeter Wemm #  define SPT_BUFSIZE	MAXLINE
2183c2aa98e2SPeter Wemm # endif
2184c2aa98e2SPeter Wemm 
2185c2aa98e2SPeter Wemm /*
2186c2aa98e2SPeter Wemm **  Pointers for setproctitle.
2187c2aa98e2SPeter Wemm **	This allows "ps" listings to give more useful information.
2188c2aa98e2SPeter Wemm */
2189c2aa98e2SPeter Wemm 
2190c2aa98e2SPeter Wemm char		**Argv = NULL;		/* pointer to argument vector */
2191c2aa98e2SPeter Wemm char		*LastArgv = NULL;	/* end of argv */
2192c2aa98e2SPeter Wemm 
2193c2aa98e2SPeter Wemm void
2194c2aa98e2SPeter Wemm initsetproctitle(argc, argv, envp)
2195c2aa98e2SPeter Wemm 	int argc;
2196c2aa98e2SPeter Wemm 	char **argv;
2197c2aa98e2SPeter Wemm 	char **envp;
2198c2aa98e2SPeter Wemm {
2199c2aa98e2SPeter Wemm 	register int i, envpsize = 0;
2200c2aa98e2SPeter Wemm 	extern char **environ;
2201c2aa98e2SPeter Wemm 
2202c2aa98e2SPeter Wemm 	/*
2203c2aa98e2SPeter Wemm 	**  Move the environment so setproctitle can use the space at
2204c2aa98e2SPeter Wemm 	**  the top of memory.
2205c2aa98e2SPeter Wemm 	*/
2206c2aa98e2SPeter Wemm 
2207c2aa98e2SPeter Wemm 	for (i = 0; envp[i] != NULL; i++)
2208c2aa98e2SPeter Wemm 		envpsize += strlen(envp[i]) + 1;
2209c2aa98e2SPeter Wemm 	environ = (char **) xalloc(sizeof (char *) * (i + 1));
2210c2aa98e2SPeter Wemm 	for (i = 0; envp[i] != NULL; i++)
2211c2aa98e2SPeter Wemm 		environ[i] = newstr(envp[i]);
2212c2aa98e2SPeter Wemm 	environ[i] = NULL;
2213c2aa98e2SPeter Wemm 
2214c2aa98e2SPeter Wemm 	/*
2215c2aa98e2SPeter Wemm 	**  Save start and extent of argv for setproctitle.
2216c2aa98e2SPeter Wemm 	*/
2217c2aa98e2SPeter Wemm 
2218c2aa98e2SPeter Wemm 	Argv = argv;
2219c2aa98e2SPeter Wemm 
2220c2aa98e2SPeter Wemm 	/*
2221c2aa98e2SPeter Wemm 	**  Determine how much space we can use for setproctitle.
2222c2aa98e2SPeter Wemm 	**  Use all contiguous argv and envp pointers starting at argv[0]
2223c2aa98e2SPeter Wemm  	*/
2224c2aa98e2SPeter Wemm 	for (i = 0; i < argc; i++)
2225c2aa98e2SPeter Wemm 	{
2226c2aa98e2SPeter Wemm 		if (i==0 || LastArgv + 1 == argv[i])
2227c2aa98e2SPeter Wemm 			LastArgv = argv[i] + strlen(argv[i]);
2228c2aa98e2SPeter Wemm 		else
2229c2aa98e2SPeter Wemm 			continue;
2230c2aa98e2SPeter Wemm 	}
2231c2aa98e2SPeter Wemm 	for (i=0; envp[i] != NULL; i++)
2232c2aa98e2SPeter Wemm 	{
2233c2aa98e2SPeter Wemm 		if (LastArgv + 1 == envp[i])
2234c2aa98e2SPeter Wemm 			LastArgv = envp[i] + strlen(envp[i]);
2235c2aa98e2SPeter Wemm 		else
2236c2aa98e2SPeter Wemm 			continue;
2237c2aa98e2SPeter Wemm 	}
2238c2aa98e2SPeter Wemm }
2239c2aa98e2SPeter Wemm 
2240c2aa98e2SPeter Wemm #if SPT_TYPE != SPT_BUILTIN
2241c2aa98e2SPeter Wemm 
2242c2aa98e2SPeter Wemm 
2243c2aa98e2SPeter Wemm /*VARARGS1*/
2244c2aa98e2SPeter Wemm void
2245c2aa98e2SPeter Wemm # ifdef __STDC__
2246c2aa98e2SPeter Wemm setproctitle(const char *fmt, ...)
2247c2aa98e2SPeter Wemm # else
2248c2aa98e2SPeter Wemm setproctitle(fmt, va_alist)
2249c2aa98e2SPeter Wemm 	const char *fmt;
2250c2aa98e2SPeter Wemm 	va_dcl
2251c2aa98e2SPeter Wemm # endif
2252c2aa98e2SPeter Wemm {
2253c2aa98e2SPeter Wemm # if SPT_TYPE != SPT_NONE
2254c2aa98e2SPeter Wemm 	register char *p;
2255c2aa98e2SPeter Wemm 	register int i;
2256c2aa98e2SPeter Wemm 	SETPROC_STATIC char buf[SPT_BUFSIZE];
2257c2aa98e2SPeter Wemm 	VA_LOCAL_DECL
2258c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_PSTAT
2259c2aa98e2SPeter Wemm 	union pstun pst;
2260c2aa98e2SPeter Wemm #  endif
2261c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_SCO
2262c2aa98e2SPeter Wemm 	off_t seek_off;
2263c2aa98e2SPeter Wemm 	static int kmem = -1;
2264c2aa98e2SPeter Wemm 	static int kmempid = -1;
2265c2aa98e2SPeter Wemm 	struct user u;
2266c2aa98e2SPeter Wemm #  endif
2267c2aa98e2SPeter Wemm 
2268c2aa98e2SPeter Wemm 	p = buf;
2269c2aa98e2SPeter Wemm 
2270c2aa98e2SPeter Wemm 	/* print sendmail: heading for grep */
2271c2aa98e2SPeter Wemm 	(void) strcpy(p, "sendmail: ");
2272c2aa98e2SPeter Wemm 	p += strlen(p);
2273c2aa98e2SPeter Wemm 
2274c2aa98e2SPeter Wemm 	/* print the argument string */
2275c2aa98e2SPeter Wemm 	VA_START(fmt);
2276c2aa98e2SPeter Wemm 	(void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
2277c2aa98e2SPeter Wemm 	VA_END;
2278c2aa98e2SPeter Wemm 
2279c2aa98e2SPeter Wemm 	i = strlen(buf);
2280c2aa98e2SPeter Wemm 
2281c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_PSTAT
2282c2aa98e2SPeter Wemm 	pst.pst_command = buf;
2283c2aa98e2SPeter Wemm 	pstat(PSTAT_SETCMD, pst, i, 0, 0);
2284c2aa98e2SPeter Wemm #  endif
2285c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_PSSTRINGS
2286c2aa98e2SPeter Wemm 	PS_STRINGS->ps_nargvstr = 1;
2287c2aa98e2SPeter Wemm 	PS_STRINGS->ps_argvstr = buf;
2288c2aa98e2SPeter Wemm #  endif
2289c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_SYSMIPS
2290c2aa98e2SPeter Wemm 	sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
2291c2aa98e2SPeter Wemm #  endif
2292c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_SCO
2293c2aa98e2SPeter Wemm 	if (kmem < 0 || kmempid != getpid())
2294c2aa98e2SPeter Wemm 	{
2295c2aa98e2SPeter Wemm 		if (kmem >= 0)
2296c2aa98e2SPeter Wemm 			close(kmem);
2297c2aa98e2SPeter Wemm 		kmem = open(_PATH_KMEM, O_RDWR, 0);
2298c2aa98e2SPeter Wemm 		if (kmem < 0)
2299c2aa98e2SPeter Wemm 			return;
2300c2aa98e2SPeter Wemm 		(void) fcntl(kmem, F_SETFD, 1);
2301c2aa98e2SPeter Wemm 		kmempid = getpid();
2302c2aa98e2SPeter Wemm 	}
2303c2aa98e2SPeter Wemm 	buf[PSARGSZ - 1] = '\0';
2304c2aa98e2SPeter Wemm 	seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
2305c2aa98e2SPeter Wemm 	if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
2306c2aa98e2SPeter Wemm 		(void) write(kmem, buf, PSARGSZ);
2307c2aa98e2SPeter Wemm #  endif
2308c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_REUSEARGV
2309c2aa98e2SPeter Wemm 	if (i > LastArgv - Argv[0] - 2)
2310c2aa98e2SPeter Wemm 	{
2311c2aa98e2SPeter Wemm 		i = LastArgv - Argv[0] - 2;
2312c2aa98e2SPeter Wemm 		buf[i] = '\0';
2313c2aa98e2SPeter Wemm 	}
2314c2aa98e2SPeter Wemm 	(void) strcpy(Argv[0], buf);
2315c2aa98e2SPeter Wemm 	p = &Argv[0][i];
2316c2aa98e2SPeter Wemm 	while (p < LastArgv)
2317c2aa98e2SPeter Wemm 		*p++ = SPT_PADCHAR;
2318c2aa98e2SPeter Wemm 	Argv[1] = NULL;
2319c2aa98e2SPeter Wemm #  endif
2320c2aa98e2SPeter Wemm #  if SPT_TYPE == SPT_CHANGEARGV
2321c2aa98e2SPeter Wemm 	Argv[0] = buf;
2322c2aa98e2SPeter Wemm 	Argv[1] = 0;
2323c2aa98e2SPeter Wemm #  endif
2324c2aa98e2SPeter Wemm # endif /* SPT_TYPE != SPT_NONE */
2325c2aa98e2SPeter Wemm }
2326c2aa98e2SPeter Wemm 
2327c2aa98e2SPeter Wemm #endif /* SPT_TYPE != SPT_BUILTIN */
2328c2aa98e2SPeter Wemm /*
232976b7bf71SPeter Wemm **  SM_SETPROCTITLE -- set process task and set process title for ps
233076b7bf71SPeter Wemm **
233176b7bf71SPeter Wemm **	Possibly set process status and call setproctitle() to
233276b7bf71SPeter Wemm **	change the ps display.
233376b7bf71SPeter Wemm **
233476b7bf71SPeter Wemm **	Parameters:
233576b7bf71SPeter Wemm **		status -- whether or not to store as process status
233676b7bf71SPeter Wemm **		fmt -- a printf style format string.
233776b7bf71SPeter Wemm **		a, b, c -- possible parameters to fmt.
233876b7bf71SPeter Wemm **
233976b7bf71SPeter Wemm **	Returns:
234076b7bf71SPeter Wemm **		none.
234176b7bf71SPeter Wemm */
234276b7bf71SPeter Wemm 
234376b7bf71SPeter Wemm /*VARARGS2*/
234476b7bf71SPeter Wemm void
234576b7bf71SPeter Wemm # ifdef __STDC__
234676b7bf71SPeter Wemm sm_setproctitle(bool status, const char *fmt, ...)
234776b7bf71SPeter Wemm # else
234876b7bf71SPeter Wemm sm_setproctitle(status, fmt, va_alist)
234976b7bf71SPeter Wemm 	bool status;
235076b7bf71SPeter Wemm 	const char *fmt;
235176b7bf71SPeter Wemm 	va_dcl
235276b7bf71SPeter Wemm #endif
235376b7bf71SPeter Wemm {
235476b7bf71SPeter Wemm 	char buf[SPT_BUFSIZE];
235576b7bf71SPeter Wemm 
235676b7bf71SPeter Wemm 	VA_LOCAL_DECL
235776b7bf71SPeter Wemm 	/* print the argument string */
235876b7bf71SPeter Wemm 	VA_START(fmt);
235976b7bf71SPeter Wemm 	(void) vsnprintf(buf, SPT_BUFSIZE, fmt, ap);
236076b7bf71SPeter Wemm 	VA_END;
236176b7bf71SPeter Wemm 
236276b7bf71SPeter Wemm 	if (status)
236376b7bf71SPeter Wemm 		proc_list_set(getpid(), buf);
236476b7bf71SPeter Wemm 	setproctitle("%s", buf);
236576b7bf71SPeter Wemm }
236676b7bf71SPeter Wemm /*
2367c2aa98e2SPeter Wemm **  WAITFOR -- wait for a particular process id.
2368c2aa98e2SPeter Wemm **
2369c2aa98e2SPeter Wemm **	Parameters:
2370c2aa98e2SPeter Wemm **		pid -- process id to wait for.
2371c2aa98e2SPeter Wemm **
2372c2aa98e2SPeter Wemm **	Returns:
2373c2aa98e2SPeter Wemm **		status of pid.
2374c2aa98e2SPeter Wemm **		-1 if pid never shows up.
2375c2aa98e2SPeter Wemm **
2376c2aa98e2SPeter Wemm **	Side Effects:
2377c2aa98e2SPeter Wemm **		none.
2378c2aa98e2SPeter Wemm */
2379c2aa98e2SPeter Wemm 
2380c2aa98e2SPeter Wemm int
2381c2aa98e2SPeter Wemm waitfor(pid)
2382c2aa98e2SPeter Wemm 	pid_t pid;
2383c2aa98e2SPeter Wemm {
2384c2aa98e2SPeter Wemm #ifdef WAITUNION
2385c2aa98e2SPeter Wemm 	union wait st;
2386c2aa98e2SPeter Wemm #else
2387c2aa98e2SPeter Wemm 	auto int st;
2388c2aa98e2SPeter Wemm #endif
2389c2aa98e2SPeter Wemm 	pid_t i;
2390c2aa98e2SPeter Wemm #if defined(ISC_UNIX) || defined(_SCO_unix_)
2391c2aa98e2SPeter Wemm 	int savesig;
2392c2aa98e2SPeter Wemm #endif
2393c2aa98e2SPeter Wemm 
2394c2aa98e2SPeter Wemm 	do
2395c2aa98e2SPeter Wemm 	{
2396c2aa98e2SPeter Wemm 		errno = 0;
2397c2aa98e2SPeter Wemm #if defined(ISC_UNIX) || defined(_SCO_unix_)
2398c2aa98e2SPeter Wemm 		savesig = releasesignal(SIGCHLD);
2399c2aa98e2SPeter Wemm #endif
2400c2aa98e2SPeter Wemm 		i = wait(&st);
2401c2aa98e2SPeter Wemm #if defined(ISC_UNIX) || defined(_SCO_unix_)
2402c2aa98e2SPeter Wemm 		if (savesig > 0)
2403c2aa98e2SPeter Wemm 			blocksignal(SIGCHLD);
2404c2aa98e2SPeter Wemm #endif
2405c2aa98e2SPeter Wemm 		if (i > 0)
2406c2aa98e2SPeter Wemm 			proc_list_drop(i);
2407c2aa98e2SPeter Wemm 	} while ((i >= 0 || errno == EINTR) && i != pid);
2408c2aa98e2SPeter Wemm 	if (i < 0)
2409c2aa98e2SPeter Wemm 		return -1;
2410c2aa98e2SPeter Wemm #ifdef WAITUNION
2411c2aa98e2SPeter Wemm 	return st.w_status;
2412c2aa98e2SPeter Wemm #else
2413c2aa98e2SPeter Wemm 	return st;
2414c2aa98e2SPeter Wemm #endif
2415c2aa98e2SPeter Wemm }
2416c2aa98e2SPeter Wemm /*
2417c2aa98e2SPeter Wemm **  REAPCHILD -- pick up the body of my child, lest it become a zombie
2418c2aa98e2SPeter Wemm **
2419c2aa98e2SPeter Wemm **	Parameters:
2420c2aa98e2SPeter Wemm **		sig -- the signal that got us here (unused).
2421c2aa98e2SPeter Wemm **
2422c2aa98e2SPeter Wemm **	Returns:
2423c2aa98e2SPeter Wemm **		none.
2424c2aa98e2SPeter Wemm **
2425c2aa98e2SPeter Wemm **	Side Effects:
2426c2aa98e2SPeter Wemm **		Picks up extant zombies.
2427c2aa98e2SPeter Wemm */
2428c2aa98e2SPeter Wemm 
2429c2aa98e2SPeter Wemm SIGFUNC_DECL
2430c2aa98e2SPeter Wemm reapchild(sig)
2431c2aa98e2SPeter Wemm 	int sig;
2432c2aa98e2SPeter Wemm {
2433c2aa98e2SPeter Wemm 	int olderrno = errno;
2434c2aa98e2SPeter Wemm 	pid_t pid;
2435c2aa98e2SPeter Wemm # ifdef HASWAITPID
2436c2aa98e2SPeter Wemm 	auto int status;
2437c2aa98e2SPeter Wemm 	int count;
2438c2aa98e2SPeter Wemm 
2439c2aa98e2SPeter Wemm 	count = 0;
2440c2aa98e2SPeter Wemm 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
2441c2aa98e2SPeter Wemm 	{
2442c2aa98e2SPeter Wemm 		if (count++ > 1000)
2443c2aa98e2SPeter Wemm 		{
2444c2aa98e2SPeter Wemm 			if (LogLevel > 0)
2445c2aa98e2SPeter Wemm 				sm_syslog(LOG_ALERT, NOQID,
2446c2aa98e2SPeter Wemm 					"reapchild: waitpid loop: pid=%d, status=%x",
2447c2aa98e2SPeter Wemm 					pid, status);
2448c2aa98e2SPeter Wemm 			break;
2449c2aa98e2SPeter Wemm 		}
2450c2aa98e2SPeter Wemm 		proc_list_drop(pid);
2451c2aa98e2SPeter Wemm 	}
2452c2aa98e2SPeter Wemm # else
2453c2aa98e2SPeter Wemm # ifdef WNOHANG
2454c2aa98e2SPeter Wemm 	union wait status;
2455c2aa98e2SPeter Wemm 
2456c2aa98e2SPeter Wemm 	while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
2457c2aa98e2SPeter Wemm 		proc_list_drop(pid);
2458c2aa98e2SPeter Wemm # else /* WNOHANG */
2459c2aa98e2SPeter Wemm 	auto int status;
2460c2aa98e2SPeter Wemm 
2461c2aa98e2SPeter Wemm 	/*
2462c2aa98e2SPeter Wemm 	**  Catch one zombie -- we will be re-invoked (we hope) if there
2463c2aa98e2SPeter Wemm 	**  are more.  Unreliable signals probably break this, but this
2464c2aa98e2SPeter Wemm 	**  is the "old system" situation -- waitpid or wait3 are to be
2465c2aa98e2SPeter Wemm 	**  strongly preferred.
2466c2aa98e2SPeter Wemm 	*/
2467c2aa98e2SPeter Wemm 
2468c2aa98e2SPeter Wemm 	if ((pid = wait(&status)) > 0)
2469c2aa98e2SPeter Wemm 		proc_list_drop(pid);
2470c2aa98e2SPeter Wemm # endif /* WNOHANG */
2471c2aa98e2SPeter Wemm # endif
2472c2aa98e2SPeter Wemm # ifdef SYS5SIGNALS
2473c2aa98e2SPeter Wemm 	(void) setsignal(SIGCHLD, reapchild);
2474c2aa98e2SPeter Wemm # endif
2475c2aa98e2SPeter Wemm 	errno = olderrno;
2476c2aa98e2SPeter Wemm 	return SIGFUNC_RETURN;
2477c2aa98e2SPeter Wemm }
2478c2aa98e2SPeter Wemm /*
2479c2aa98e2SPeter Wemm **  PUTENV -- emulation of putenv() in terms of setenv()
2480c2aa98e2SPeter Wemm **
2481c2aa98e2SPeter Wemm **	Not needed on Posix-compliant systems.
2482c2aa98e2SPeter Wemm **	This doesn't have full Posix semantics, but it's good enough
2483c2aa98e2SPeter Wemm **		for sendmail.
2484c2aa98e2SPeter Wemm **
2485c2aa98e2SPeter Wemm **	Parameter:
2486c2aa98e2SPeter Wemm **		env -- the environment to put.
2487c2aa98e2SPeter Wemm **
2488c2aa98e2SPeter Wemm **	Returns:
2489c2aa98e2SPeter Wemm **		none.
2490c2aa98e2SPeter Wemm */
2491c2aa98e2SPeter Wemm 
2492c2aa98e2SPeter Wemm #ifdef NEEDPUTENV
2493c2aa98e2SPeter Wemm 
2494c2aa98e2SPeter Wemm # if NEEDPUTENV == 2		/* no setenv(3) call available */
2495c2aa98e2SPeter Wemm 
2496c2aa98e2SPeter Wemm int
2497c2aa98e2SPeter Wemm putenv(str)
2498c2aa98e2SPeter Wemm 	char *str;
2499c2aa98e2SPeter Wemm {
2500c2aa98e2SPeter Wemm 	char **current;
2501c2aa98e2SPeter Wemm 	int matchlen, envlen=0;
2502c2aa98e2SPeter Wemm 	char *tmp;
2503c2aa98e2SPeter Wemm 	char **newenv;
2504c2aa98e2SPeter Wemm 	static int first=1;
2505c2aa98e2SPeter Wemm 	extern char **environ;
2506c2aa98e2SPeter Wemm 
2507c2aa98e2SPeter Wemm 	/*
2508c2aa98e2SPeter Wemm 	 * find out how much of str to match when searching
2509c2aa98e2SPeter Wemm 	 * for a string to replace.
2510c2aa98e2SPeter Wemm 	 */
2511c2aa98e2SPeter Wemm 	if ((tmp = strchr(str, '=')) == NULL || tmp == str)
2512c2aa98e2SPeter Wemm 		matchlen = strlen(str);
2513c2aa98e2SPeter Wemm 	else
2514c2aa98e2SPeter Wemm 		matchlen = (int) (tmp - str);
2515c2aa98e2SPeter Wemm 	++matchlen;
2516c2aa98e2SPeter Wemm 
2517c2aa98e2SPeter Wemm 	/*
2518c2aa98e2SPeter Wemm 	 * Search for an existing string in the environment and find the
2519c2aa98e2SPeter Wemm 	 * length of environ.  If found, replace and exit.
2520c2aa98e2SPeter Wemm 	 */
2521c2aa98e2SPeter Wemm 	for (current=environ; *current; current++) {
2522c2aa98e2SPeter Wemm 		++envlen;
2523c2aa98e2SPeter Wemm 
2524c2aa98e2SPeter Wemm 		if (strncmp(str, *current, matchlen) == 0) {
2525c2aa98e2SPeter Wemm 			/* found it, now insert the new version */
2526c2aa98e2SPeter Wemm 			*current = (char *)str;
2527c2aa98e2SPeter Wemm 			return(0);
2528c2aa98e2SPeter Wemm 		}
2529c2aa98e2SPeter Wemm 	}
2530c2aa98e2SPeter Wemm 
2531c2aa98e2SPeter Wemm 	/*
2532c2aa98e2SPeter Wemm 	 * There wasn't already a slot so add space for a new slot.
2533c2aa98e2SPeter Wemm 	 * If this is our first time through, use malloc(), else realloc().
2534c2aa98e2SPeter Wemm 	 */
2535c2aa98e2SPeter Wemm 	if (first) {
2536c2aa98e2SPeter Wemm 		newenv = (char **) malloc(sizeof(char *) * (envlen + 2));
2537c2aa98e2SPeter Wemm 		if (newenv == NULL)
2538c2aa98e2SPeter Wemm 			return(-1);
2539c2aa98e2SPeter Wemm 
2540c2aa98e2SPeter Wemm 		first=0;
2541c2aa98e2SPeter Wemm 		(void) memcpy(newenv, environ, sizeof(char *) * envlen);
2542c2aa98e2SPeter Wemm 	} else {
2543c2aa98e2SPeter Wemm 		newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2));
2544c2aa98e2SPeter Wemm 		if (newenv == NULL)
2545c2aa98e2SPeter Wemm 			return(-1);
2546c2aa98e2SPeter Wemm 	}
2547c2aa98e2SPeter Wemm 
2548c2aa98e2SPeter Wemm 	/* actually add in the new entry */
2549c2aa98e2SPeter Wemm 	environ = newenv;
2550c2aa98e2SPeter Wemm 	environ[envlen] = (char *)str;
2551c2aa98e2SPeter Wemm 	environ[envlen+1] = NULL;
2552c2aa98e2SPeter Wemm 
2553c2aa98e2SPeter Wemm 	return(0);
2554c2aa98e2SPeter Wemm }
2555c2aa98e2SPeter Wemm 
2556c2aa98e2SPeter Wemm #else			/* implement putenv() in terms of setenv() */
2557c2aa98e2SPeter Wemm 
2558c2aa98e2SPeter Wemm int
2559c2aa98e2SPeter Wemm putenv(env)
2560c2aa98e2SPeter Wemm 	char *env;
2561c2aa98e2SPeter Wemm {
2562c2aa98e2SPeter Wemm 	char *p;
2563c2aa98e2SPeter Wemm 	int l;
2564c2aa98e2SPeter Wemm 	char nbuf[100];
2565c2aa98e2SPeter Wemm 
2566c2aa98e2SPeter Wemm 	p = strchr(env, '=');
2567c2aa98e2SPeter Wemm 	if (p == NULL)
2568c2aa98e2SPeter Wemm 		return 0;
2569c2aa98e2SPeter Wemm 	l = p - env;
2570c2aa98e2SPeter Wemm 	if (l > sizeof nbuf - 1)
2571c2aa98e2SPeter Wemm 		l = sizeof nbuf - 1;
2572c2aa98e2SPeter Wemm 	bcopy(env, nbuf, l);
2573c2aa98e2SPeter Wemm 	nbuf[l] = '\0';
2574c2aa98e2SPeter Wemm 	return setenv(nbuf, ++p, 1);
2575c2aa98e2SPeter Wemm }
2576c2aa98e2SPeter Wemm 
2577c2aa98e2SPeter Wemm # endif
2578c2aa98e2SPeter Wemm #endif
2579c2aa98e2SPeter Wemm /*
2580c2aa98e2SPeter Wemm **  UNSETENV -- remove a variable from the environment
2581c2aa98e2SPeter Wemm **
2582c2aa98e2SPeter Wemm **	Not needed on newer systems.
2583c2aa98e2SPeter Wemm **
2584c2aa98e2SPeter Wemm **	Parameters:
2585c2aa98e2SPeter Wemm **		name -- the string name of the environment variable to be
2586c2aa98e2SPeter Wemm **			deleted from the current environment.
2587c2aa98e2SPeter Wemm **
2588c2aa98e2SPeter Wemm **	Returns:
2589c2aa98e2SPeter Wemm **		none.
2590c2aa98e2SPeter Wemm **
2591c2aa98e2SPeter Wemm **	Globals:
2592c2aa98e2SPeter Wemm **		environ -- a pointer to the current environment.
2593c2aa98e2SPeter Wemm **
2594c2aa98e2SPeter Wemm **	Side Effects:
2595c2aa98e2SPeter Wemm **		Modifies environ.
2596c2aa98e2SPeter Wemm */
2597c2aa98e2SPeter Wemm 
2598c2aa98e2SPeter Wemm #ifndef HASUNSETENV
2599c2aa98e2SPeter Wemm 
2600c2aa98e2SPeter Wemm void
2601c2aa98e2SPeter Wemm unsetenv(name)
2602c2aa98e2SPeter Wemm 	char *name;
2603c2aa98e2SPeter Wemm {
2604c2aa98e2SPeter Wemm 	extern char **environ;
2605c2aa98e2SPeter Wemm 	register char **pp;
2606c2aa98e2SPeter Wemm 	int len = strlen(name);
2607c2aa98e2SPeter Wemm 
2608c2aa98e2SPeter Wemm 	for (pp = environ; *pp != NULL; pp++)
2609c2aa98e2SPeter Wemm 	{
2610c2aa98e2SPeter Wemm 		if (strncmp(name, *pp, len) == 0 &&
2611c2aa98e2SPeter Wemm 		    ((*pp)[len] == '=' || (*pp)[len] == '\0'))
2612c2aa98e2SPeter Wemm 			break;
2613c2aa98e2SPeter Wemm 	}
2614c2aa98e2SPeter Wemm 
2615c2aa98e2SPeter Wemm 	for (; *pp != NULL; pp++)
2616c2aa98e2SPeter Wemm 		*pp = pp[1];
2617c2aa98e2SPeter Wemm }
2618c2aa98e2SPeter Wemm 
2619c2aa98e2SPeter Wemm #endif
2620c2aa98e2SPeter Wemm /*
2621c2aa98e2SPeter Wemm **  GETDTABLESIZE -- return number of file descriptors
2622c2aa98e2SPeter Wemm **
2623c2aa98e2SPeter Wemm **	Only on non-BSD systems
2624c2aa98e2SPeter Wemm **
2625c2aa98e2SPeter Wemm **	Parameters:
2626c2aa98e2SPeter Wemm **		none
2627c2aa98e2SPeter Wemm **
2628c2aa98e2SPeter Wemm **	Returns:
2629c2aa98e2SPeter Wemm **		size of file descriptor table
2630c2aa98e2SPeter Wemm **
2631c2aa98e2SPeter Wemm **	Side Effects:
2632c2aa98e2SPeter Wemm **		none
2633c2aa98e2SPeter Wemm */
2634c2aa98e2SPeter Wemm 
2635c2aa98e2SPeter Wemm #ifdef SOLARIS
2636c2aa98e2SPeter Wemm # include <sys/resource.h>
2637c2aa98e2SPeter Wemm #endif
2638c2aa98e2SPeter Wemm 
2639c2aa98e2SPeter Wemm int
2640c2aa98e2SPeter Wemm getdtsize()
2641c2aa98e2SPeter Wemm {
2642c2aa98e2SPeter Wemm #ifdef RLIMIT_NOFILE
2643c2aa98e2SPeter Wemm 	struct rlimit rl;
2644c2aa98e2SPeter Wemm 
2645c2aa98e2SPeter Wemm 	if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2646c2aa98e2SPeter Wemm 		return rl.rlim_cur;
2647c2aa98e2SPeter Wemm #endif
2648c2aa98e2SPeter Wemm 
2649c2aa98e2SPeter Wemm # ifdef HASGETDTABLESIZE
2650c2aa98e2SPeter Wemm 	return getdtablesize();
2651c2aa98e2SPeter Wemm # else
2652c2aa98e2SPeter Wemm #  ifdef _SC_OPEN_MAX
2653c2aa98e2SPeter Wemm 	return sysconf(_SC_OPEN_MAX);
2654c2aa98e2SPeter Wemm #  else
2655c2aa98e2SPeter Wemm 	return NOFILE;
2656c2aa98e2SPeter Wemm #  endif
2657c2aa98e2SPeter Wemm # endif
2658c2aa98e2SPeter Wemm }
2659c2aa98e2SPeter Wemm /*
2660c2aa98e2SPeter Wemm **  UNAME -- get the UUCP name of this system.
2661c2aa98e2SPeter Wemm */
2662c2aa98e2SPeter Wemm 
2663c2aa98e2SPeter Wemm #ifndef HASUNAME
2664c2aa98e2SPeter Wemm 
2665c2aa98e2SPeter Wemm int
2666c2aa98e2SPeter Wemm uname(name)
2667c2aa98e2SPeter Wemm 	struct utsname *name;
2668c2aa98e2SPeter Wemm {
2669c2aa98e2SPeter Wemm 	FILE *file;
2670c2aa98e2SPeter Wemm 	char *n;
2671c2aa98e2SPeter Wemm 
2672c2aa98e2SPeter Wemm 	name->nodename[0] = '\0';
2673c2aa98e2SPeter Wemm 
2674c2aa98e2SPeter Wemm 	/* try /etc/whoami -- one line with the node name */
2675c2aa98e2SPeter Wemm 	if ((file = fopen("/etc/whoami", "r")) != NULL)
2676c2aa98e2SPeter Wemm 	{
2677c2aa98e2SPeter Wemm 		(void) fgets(name->nodename, NODE_LENGTH + 1, file);
2678c2aa98e2SPeter Wemm 		(void) fclose(file);
2679c2aa98e2SPeter Wemm 		n = strchr(name->nodename, '\n');
2680c2aa98e2SPeter Wemm 		if (n != NULL)
2681c2aa98e2SPeter Wemm 			*n = '\0';
2682c2aa98e2SPeter Wemm 		if (name->nodename[0] != '\0')
2683c2aa98e2SPeter Wemm 			return (0);
2684c2aa98e2SPeter Wemm 	}
2685c2aa98e2SPeter Wemm 
2686c2aa98e2SPeter Wemm 	/* try /usr/include/whoami.h -- has a #define somewhere */
2687c2aa98e2SPeter Wemm 	if ((file = fopen("/usr/include/whoami.h", "r")) != NULL)
2688c2aa98e2SPeter Wemm 	{
2689c2aa98e2SPeter Wemm 		char buf[MAXLINE];
2690c2aa98e2SPeter Wemm 
2691c2aa98e2SPeter Wemm 		while (fgets(buf, MAXLINE, file) != NULL)
2692c2aa98e2SPeter Wemm 			if (sscanf(buf, "#define sysname \"%*[^\"]\"",
2693c2aa98e2SPeter Wemm 					NODE_LENGTH, name->nodename) > 0)
2694c2aa98e2SPeter Wemm 				break;
2695c2aa98e2SPeter Wemm 		(void) fclose(file);
2696c2aa98e2SPeter Wemm 		if (name->nodename[0] != '\0')
2697c2aa98e2SPeter Wemm 			return (0);
2698c2aa98e2SPeter Wemm 	}
2699c2aa98e2SPeter Wemm 
2700c2aa98e2SPeter Wemm #ifdef TRUST_POPEN
2701c2aa98e2SPeter Wemm 	/*
2702c2aa98e2SPeter Wemm 	**  Popen is known to have security holes.
2703c2aa98e2SPeter Wemm 	*/
2704c2aa98e2SPeter Wemm 
2705c2aa98e2SPeter Wemm 	/* try uuname -l to return local name */
2706c2aa98e2SPeter Wemm 	if ((file = popen("uuname -l", "r")) != NULL)
2707c2aa98e2SPeter Wemm 	{
2708c2aa98e2SPeter Wemm 		(void) fgets(name, NODE_LENGTH + 1, file);
2709c2aa98e2SPeter Wemm 		(void) pclose(file);
2710c2aa98e2SPeter Wemm 		n = strchr(name, '\n');
2711c2aa98e2SPeter Wemm 		if (n != NULL)
2712c2aa98e2SPeter Wemm 			*n = '\0';
2713c2aa98e2SPeter Wemm 		if (name->nodename[0] != '\0')
2714c2aa98e2SPeter Wemm 			return (0);
2715c2aa98e2SPeter Wemm 	}
2716c2aa98e2SPeter Wemm #endif
2717c2aa98e2SPeter Wemm 
2718c2aa98e2SPeter Wemm 	return (-1);
2719c2aa98e2SPeter Wemm }
2720c2aa98e2SPeter Wemm #endif /* HASUNAME */
2721c2aa98e2SPeter Wemm /*
2722c2aa98e2SPeter Wemm **  INITGROUPS -- initialize groups
2723c2aa98e2SPeter Wemm **
2724c2aa98e2SPeter Wemm **	Stub implementation for System V style systems
2725c2aa98e2SPeter Wemm */
2726c2aa98e2SPeter Wemm 
2727c2aa98e2SPeter Wemm #ifndef HASINITGROUPS
2728c2aa98e2SPeter Wemm 
2729c2aa98e2SPeter Wemm initgroups(name, basegid)
2730c2aa98e2SPeter Wemm 	char *name;
2731c2aa98e2SPeter Wemm 	int basegid;
2732c2aa98e2SPeter Wemm {
2733c2aa98e2SPeter Wemm 	return 0;
2734c2aa98e2SPeter Wemm }
2735c2aa98e2SPeter Wemm 
2736c2aa98e2SPeter Wemm #endif
2737c2aa98e2SPeter Wemm /*
2738c2aa98e2SPeter Wemm **  SETGROUPS -- set group list
2739c2aa98e2SPeter Wemm **
2740c2aa98e2SPeter Wemm **	Stub implementation for systems that don't have group lists
2741c2aa98e2SPeter Wemm */
2742c2aa98e2SPeter Wemm 
2743c2aa98e2SPeter Wemm #ifndef NGROUPS_MAX
2744c2aa98e2SPeter Wemm 
2745c2aa98e2SPeter Wemm int
2746c2aa98e2SPeter Wemm setgroups(ngroups, grouplist)
2747c2aa98e2SPeter Wemm 	int ngroups;
2748c2aa98e2SPeter Wemm 	GIDSET_T grouplist[];
2749c2aa98e2SPeter Wemm {
2750c2aa98e2SPeter Wemm 	return 0;
2751c2aa98e2SPeter Wemm }
2752c2aa98e2SPeter Wemm 
2753c2aa98e2SPeter Wemm #endif
2754c2aa98e2SPeter Wemm /*
2755c2aa98e2SPeter Wemm **  SETSID -- set session id (for non-POSIX systems)
2756c2aa98e2SPeter Wemm */
2757c2aa98e2SPeter Wemm 
2758c2aa98e2SPeter Wemm #ifndef HASSETSID
2759c2aa98e2SPeter Wemm 
2760c2aa98e2SPeter Wemm pid_t
2761c2aa98e2SPeter Wemm setsid __P ((void))
2762c2aa98e2SPeter Wemm {
2763c2aa98e2SPeter Wemm #ifdef TIOCNOTTY
2764c2aa98e2SPeter Wemm 	int fd;
2765c2aa98e2SPeter Wemm 
2766c2aa98e2SPeter Wemm 	fd = open("/dev/tty", O_RDWR, 0);
2767c2aa98e2SPeter Wemm 	if (fd >= 0)
2768c2aa98e2SPeter Wemm 	{
2769c2aa98e2SPeter Wemm 		(void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
2770c2aa98e2SPeter Wemm 		(void) close(fd);
2771c2aa98e2SPeter Wemm 	}
2772c2aa98e2SPeter Wemm #endif /* TIOCNOTTY */
2773c2aa98e2SPeter Wemm # ifdef SYS5SETPGRP
2774c2aa98e2SPeter Wemm 	return setpgrp();
2775c2aa98e2SPeter Wemm # else
2776c2aa98e2SPeter Wemm 	return setpgid(0, getpid());
2777c2aa98e2SPeter Wemm # endif
2778c2aa98e2SPeter Wemm }
2779c2aa98e2SPeter Wemm 
2780c2aa98e2SPeter Wemm #endif
2781c2aa98e2SPeter Wemm /*
2782c2aa98e2SPeter Wemm **  FSYNC -- dummy fsync
2783c2aa98e2SPeter Wemm */
2784c2aa98e2SPeter Wemm 
2785c2aa98e2SPeter Wemm #ifdef NEEDFSYNC
2786c2aa98e2SPeter Wemm 
2787c2aa98e2SPeter Wemm fsync(fd)
2788c2aa98e2SPeter Wemm 	int fd;
2789c2aa98e2SPeter Wemm {
2790c2aa98e2SPeter Wemm # ifdef O_SYNC
2791c2aa98e2SPeter Wemm 	return fcntl(fd, F_SETFL, O_SYNC);
2792c2aa98e2SPeter Wemm # else
2793c2aa98e2SPeter Wemm 	/* nothing we can do */
2794c2aa98e2SPeter Wemm 	return 0;
2795c2aa98e2SPeter Wemm # endif
2796c2aa98e2SPeter Wemm }
2797c2aa98e2SPeter Wemm 
2798c2aa98e2SPeter Wemm #endif
2799c2aa98e2SPeter Wemm /*
2800c2aa98e2SPeter Wemm **  DGUX_INET_ADDR -- inet_addr for DG/UX
2801c2aa98e2SPeter Wemm **
2802c2aa98e2SPeter Wemm **	Data General DG/UX version of inet_addr returns a struct in_addr
2803c2aa98e2SPeter Wemm **	instead of a long.  This patches things.  Only needed on versions
2804c2aa98e2SPeter Wemm **	prior to 5.4.3.
2805c2aa98e2SPeter Wemm */
2806c2aa98e2SPeter Wemm 
2807c2aa98e2SPeter Wemm #ifdef DGUX_5_4_2
2808c2aa98e2SPeter Wemm 
2809c2aa98e2SPeter Wemm #undef inet_addr
2810c2aa98e2SPeter Wemm 
2811c2aa98e2SPeter Wemm long
2812c2aa98e2SPeter Wemm dgux_inet_addr(host)
2813c2aa98e2SPeter Wemm 	char *host;
2814c2aa98e2SPeter Wemm {
2815c2aa98e2SPeter Wemm 	struct in_addr haddr;
2816c2aa98e2SPeter Wemm 
2817c2aa98e2SPeter Wemm 	haddr = inet_addr(host);
2818c2aa98e2SPeter Wemm 	return haddr.s_addr;
2819c2aa98e2SPeter Wemm }
2820c2aa98e2SPeter Wemm 
2821c2aa98e2SPeter Wemm #endif
2822c2aa98e2SPeter Wemm /*
2823c2aa98e2SPeter Wemm **  GETOPT -- for old systems or systems with bogus implementations
2824c2aa98e2SPeter Wemm */
2825c2aa98e2SPeter Wemm 
2826c2aa98e2SPeter Wemm #ifdef NEEDGETOPT
2827c2aa98e2SPeter Wemm 
2828c2aa98e2SPeter Wemm /*
2829c2aa98e2SPeter Wemm  * Copyright (c) 1985 Regents of the University of California.
2830c2aa98e2SPeter Wemm  * All rights reserved.  The Berkeley software License Agreement
2831c2aa98e2SPeter Wemm  * specifies the terms and conditions for redistribution.
2832c2aa98e2SPeter Wemm  */
2833c2aa98e2SPeter Wemm 
2834c2aa98e2SPeter Wemm 
2835c2aa98e2SPeter Wemm /*
2836c2aa98e2SPeter Wemm **  this version hacked to add `atend' flag to allow state machine
2837c2aa98e2SPeter Wemm **  to reset if invoked by the program to scan args for a 2nd time
2838c2aa98e2SPeter Wemm */
2839c2aa98e2SPeter Wemm 
2840c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint)
2841c2aa98e2SPeter Wemm static char sccsid[] = "@(#)getopt.c	4.3 (Berkeley) 3/9/86";
2842c2aa98e2SPeter Wemm #endif /* LIBC_SCCS and not lint */
2843c2aa98e2SPeter Wemm 
2844c2aa98e2SPeter Wemm #include <stdio.h>
2845c2aa98e2SPeter Wemm 
2846c2aa98e2SPeter Wemm /*
2847c2aa98e2SPeter Wemm  * get option letter from argument vector
2848c2aa98e2SPeter Wemm  */
2849c2aa98e2SPeter Wemm #ifdef _CONVEX_SOURCE
2850c2aa98e2SPeter Wemm extern int	optind, opterr, optopt;
2851c2aa98e2SPeter Wemm extern char	*optarg;
2852c2aa98e2SPeter Wemm #else
2853c2aa98e2SPeter Wemm int	opterr = 1;		/* if error message should be printed */
2854c2aa98e2SPeter Wemm int	optind = 1;		/* index into parent argv vector */
2855c2aa98e2SPeter Wemm int	optopt = 0;		/* character checked for validity */
2856c2aa98e2SPeter Wemm char	*optarg = NULL;		/* argument associated with option */
2857c2aa98e2SPeter Wemm #endif
2858c2aa98e2SPeter Wemm 
2859c2aa98e2SPeter Wemm #define BADCH	(int)'?'
2860c2aa98e2SPeter Wemm #define EMSG	""
2861c2aa98e2SPeter Wemm #define tell(s)	if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \
2862c2aa98e2SPeter Wemm 		fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
2863c2aa98e2SPeter Wemm 
2864c2aa98e2SPeter Wemm int
2865c2aa98e2SPeter Wemm getopt(nargc,nargv,ostr)
2866c2aa98e2SPeter Wemm 	int		nargc;
2867c2aa98e2SPeter Wemm 	char *const	*nargv;
2868c2aa98e2SPeter Wemm 	const char	*ostr;
2869c2aa98e2SPeter Wemm {
2870c2aa98e2SPeter Wemm 	static char	*place = EMSG;	/* option letter processing */
2871c2aa98e2SPeter Wemm 	static char	atend = 0;
2872c2aa98e2SPeter Wemm 	register char	*oli = NULL;	/* option letter list index */
2873c2aa98e2SPeter Wemm 
2874c2aa98e2SPeter Wemm 	if (atend) {
2875c2aa98e2SPeter Wemm 		atend = 0;
2876c2aa98e2SPeter Wemm 		place = EMSG;
2877c2aa98e2SPeter Wemm 	}
2878c2aa98e2SPeter Wemm 	if(!*place) {			/* update scanning pointer */
2879c2aa98e2SPeter Wemm 		if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
2880c2aa98e2SPeter Wemm 			atend++;
2881c2aa98e2SPeter Wemm 			return -1;
2882c2aa98e2SPeter Wemm 		}
2883c2aa98e2SPeter Wemm 		if (*place == '-') {	/* found "--" */
2884c2aa98e2SPeter Wemm 			++optind;
2885c2aa98e2SPeter Wemm 			atend++;
2886c2aa98e2SPeter Wemm 			return -1;
2887c2aa98e2SPeter Wemm 		}
2888c2aa98e2SPeter Wemm 	}				/* option letter okay? */
2889c2aa98e2SPeter Wemm 	if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
2890c2aa98e2SPeter Wemm 		if (!*place) ++optind;
2891c2aa98e2SPeter Wemm 		tell(": illegal option -- ");
2892c2aa98e2SPeter Wemm 	}
2893c2aa98e2SPeter Wemm 	if (oli && *++oli != ':') {		/* don't need argument */
2894c2aa98e2SPeter Wemm 		optarg = NULL;
2895c2aa98e2SPeter Wemm 		if (!*place) ++optind;
2896c2aa98e2SPeter Wemm 	}
2897c2aa98e2SPeter Wemm 	else {				/* need an argument */
2898c2aa98e2SPeter Wemm 		if (*place) optarg = place;	/* no white space */
2899c2aa98e2SPeter Wemm 		else if (nargc <= ++optind) {	/* no arg */
2900c2aa98e2SPeter Wemm 			place = EMSG;
2901c2aa98e2SPeter Wemm 			tell(": option requires an argument -- ");
2902c2aa98e2SPeter Wemm 		}
2903c2aa98e2SPeter Wemm 	 	else optarg = nargv[optind];	/* white space */
2904c2aa98e2SPeter Wemm 		place = EMSG;
2905c2aa98e2SPeter Wemm 		++optind;
2906c2aa98e2SPeter Wemm 	}
2907c2aa98e2SPeter Wemm 	return(optopt);			/* dump back option letter */
2908c2aa98e2SPeter Wemm }
2909c2aa98e2SPeter Wemm 
2910c2aa98e2SPeter Wemm #endif
2911c2aa98e2SPeter Wemm /*
2912c2aa98e2SPeter Wemm **  VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version
2913c2aa98e2SPeter Wemm */
2914c2aa98e2SPeter Wemm 
2915c2aa98e2SPeter Wemm #ifdef NEEDVPRINTF
2916c2aa98e2SPeter Wemm 
2917c2aa98e2SPeter Wemm #define MAXARG	16
2918c2aa98e2SPeter Wemm 
2919c2aa98e2SPeter Wemm vfprintf(fp, fmt, ap)
2920c2aa98e2SPeter Wemm 	FILE *fp;
2921c2aa98e2SPeter Wemm 	char *fmt;
2922c2aa98e2SPeter Wemm 	char **ap;
2923c2aa98e2SPeter Wemm {
2924c2aa98e2SPeter Wemm 	char *bp[MAXARG];
2925c2aa98e2SPeter Wemm 	int i = 0;
2926c2aa98e2SPeter Wemm 
2927c2aa98e2SPeter Wemm 	while (*ap && i < MAXARG)
2928c2aa98e2SPeter Wemm 		bp[i++] = *ap++;
2929c2aa98e2SPeter Wemm 	fprintf(fp, fmt, bp[0], bp[1], bp[2], bp[3],
2930c2aa98e2SPeter Wemm 			 bp[4], bp[5], bp[6], bp[7],
2931c2aa98e2SPeter Wemm 			 bp[8], bp[9], bp[10], bp[11],
2932c2aa98e2SPeter Wemm 			 bp[12], bp[13], bp[14], bp[15]);
2933c2aa98e2SPeter Wemm }
2934c2aa98e2SPeter Wemm 
2935c2aa98e2SPeter Wemm vsprintf(s, fmt, ap)
2936c2aa98e2SPeter Wemm 	char *s;
2937c2aa98e2SPeter Wemm 	char *fmt;
2938c2aa98e2SPeter Wemm 	char **ap;
2939c2aa98e2SPeter Wemm {
2940c2aa98e2SPeter Wemm 	char *bp[MAXARG];
2941c2aa98e2SPeter Wemm 	int i = 0;
2942c2aa98e2SPeter Wemm 
2943c2aa98e2SPeter Wemm 	while (*ap && i < MAXARG)
2944c2aa98e2SPeter Wemm 		bp[i++] = *ap++;
2945c2aa98e2SPeter Wemm 	sprintf(s, fmt, bp[0], bp[1], bp[2], bp[3],
2946c2aa98e2SPeter Wemm 			bp[4], bp[5], bp[6], bp[7],
2947c2aa98e2SPeter Wemm 			bp[8], bp[9], bp[10], bp[11],
2948c2aa98e2SPeter Wemm 			bp[12], bp[13], bp[14], bp[15]);
2949c2aa98e2SPeter Wemm }
2950c2aa98e2SPeter Wemm 
2951c2aa98e2SPeter Wemm #endif
2952c2aa98e2SPeter Wemm /*
2953c2aa98e2SPeter Wemm **  USERSHELLOK -- tell if a user's shell is ok for unrestricted use
2954c2aa98e2SPeter Wemm **
2955c2aa98e2SPeter Wemm **	Parameters:
2956c2aa98e2SPeter Wemm **		user -- the name of the user we are checking.
2957c2aa98e2SPeter Wemm **		shell -- the user's shell from /etc/passwd
2958c2aa98e2SPeter Wemm **
2959c2aa98e2SPeter Wemm **	Returns:
2960c2aa98e2SPeter Wemm **		TRUE -- if it is ok to use this for unrestricted access.
2961c2aa98e2SPeter Wemm **		FALSE -- if the shell is restricted.
2962c2aa98e2SPeter Wemm */
2963c2aa98e2SPeter Wemm 
2964c2aa98e2SPeter Wemm #if !HASGETUSERSHELL
2965c2aa98e2SPeter Wemm 
2966c2aa98e2SPeter Wemm # ifndef _PATH_SHELLS
2967c2aa98e2SPeter Wemm #  define _PATH_SHELLS	"/etc/shells"
2968c2aa98e2SPeter Wemm # endif
2969c2aa98e2SPeter Wemm 
2970c2aa98e2SPeter Wemm # if defined(_AIX3) || defined(_AIX4)
2971c2aa98e2SPeter Wemm #  include <userconf.h>
2972c2aa98e2SPeter Wemm #  if _AIX4 >= 40200
2973c2aa98e2SPeter Wemm #   include <userpw.h>
2974c2aa98e2SPeter Wemm #  endif
2975c2aa98e2SPeter Wemm #  include <usersec.h>
2976c2aa98e2SPeter Wemm # endif
2977c2aa98e2SPeter Wemm 
2978c2aa98e2SPeter Wemm char	*DefaultUserShells[] =
2979c2aa98e2SPeter Wemm {
2980c2aa98e2SPeter Wemm 	"/bin/sh",		/* standard shell */
2981c2aa98e2SPeter Wemm 	"/usr/bin/sh",
2982c2aa98e2SPeter Wemm 	"/bin/csh",		/* C shell */
2983c2aa98e2SPeter Wemm 	"/usr/bin/csh",
2984c2aa98e2SPeter Wemm #ifdef __hpux
2985c2aa98e2SPeter Wemm # ifdef V4FS
2986c2aa98e2SPeter Wemm 	"/usr/bin/rsh",		/* restricted Bourne shell */
2987c2aa98e2SPeter Wemm 	"/usr/bin/ksh",		/* Korn shell */
2988c2aa98e2SPeter Wemm 	"/usr/bin/rksh",	/* restricted Korn shell */
2989c2aa98e2SPeter Wemm 	"/usr/bin/pam",
2990c2aa98e2SPeter Wemm 	"/usr/bin/keysh",	/* key shell (extended Korn shell) */
2991c2aa98e2SPeter Wemm 	"/usr/bin/posix/sh",
2992c2aa98e2SPeter Wemm # else
2993c2aa98e2SPeter Wemm 	"/bin/rsh",		/* restricted Bourne shell */
2994c2aa98e2SPeter Wemm 	"/bin/ksh",		/* Korn shell */
2995c2aa98e2SPeter Wemm 	"/bin/rksh",		/* restricted Korn shell */
2996c2aa98e2SPeter Wemm 	"/bin/pam",
2997c2aa98e2SPeter Wemm 	"/usr/bin/keysh",	/* key shell (extended Korn shell) */
2998c2aa98e2SPeter Wemm 	"/bin/posix/sh",
2999c2aa98e2SPeter Wemm # endif
3000c2aa98e2SPeter Wemm #endif
3001c2aa98e2SPeter Wemm #if defined(_AIX3) || defined(_AIX4)
3002c2aa98e2SPeter Wemm 	"/bin/ksh",		/* Korn shell */
3003c2aa98e2SPeter Wemm 	"/usr/bin/ksh",
3004c2aa98e2SPeter Wemm 	"/bin/tsh",		/* trusted shell */
3005c2aa98e2SPeter Wemm 	"/usr/bin/tsh",
3006c2aa98e2SPeter Wemm 	"/bin/bsh",		/* Bourne shell */
3007c2aa98e2SPeter Wemm 	"/usr/bin/bsh",
3008c2aa98e2SPeter Wemm #endif
300976b7bf71SPeter Wemm #if defined(__svr4__) || defined(__svr5__)
3010c2aa98e2SPeter Wemm 	"/bin/ksh",		/* Korn shell */
3011c2aa98e2SPeter Wemm 	"/usr/bin/ksh",
3012c2aa98e2SPeter Wemm #endif
3013c2aa98e2SPeter Wemm #ifdef sgi
3014c2aa98e2SPeter Wemm 	"/sbin/sh",		/* SGI's shells really live in /sbin */
3015c2aa98e2SPeter Wemm 	"/sbin/csh",
3016c2aa98e2SPeter Wemm 	"/bin/ksh",		/* Korn shell */
3017c2aa98e2SPeter Wemm 	"/sbin/ksh",
3018c2aa98e2SPeter Wemm 	"/usr/bin/ksh",
3019c2aa98e2SPeter Wemm 	"/bin/tcsh",		/* Extended csh */
3020c2aa98e2SPeter Wemm 	"/usr/bin/tcsh",
3021c2aa98e2SPeter Wemm #endif
3022c2aa98e2SPeter Wemm 	NULL
3023c2aa98e2SPeter Wemm };
3024c2aa98e2SPeter Wemm 
3025c2aa98e2SPeter Wemm #endif
3026c2aa98e2SPeter Wemm 
3027c2aa98e2SPeter Wemm #define WILDCARD_SHELL	"/SENDMAIL/ANY/SHELL/"
3028c2aa98e2SPeter Wemm 
3029c2aa98e2SPeter Wemm bool
3030c2aa98e2SPeter Wemm usershellok(user, shell)
3031c2aa98e2SPeter Wemm 	char *user;
3032c2aa98e2SPeter Wemm 	char *shell;
3033c2aa98e2SPeter Wemm {
3034c2aa98e2SPeter Wemm #if HASGETUSERSHELL
3035c2aa98e2SPeter Wemm 	register char *p;
3036c2aa98e2SPeter Wemm 	extern char *getusershell();
3037c2aa98e2SPeter Wemm 
3038c2aa98e2SPeter Wemm 	if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
3039c2aa98e2SPeter Wemm 	    ConfigLevel <= 1)
3040c2aa98e2SPeter Wemm 		return TRUE;
3041c2aa98e2SPeter Wemm 
3042c2aa98e2SPeter Wemm 	setusershell();
3043c2aa98e2SPeter Wemm 	while ((p = getusershell()) != NULL)
3044c2aa98e2SPeter Wemm 		if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
3045c2aa98e2SPeter Wemm 			break;
3046c2aa98e2SPeter Wemm 	endusershell();
3047c2aa98e2SPeter Wemm 	return p != NULL;
3048c2aa98e2SPeter Wemm #else
3049c2aa98e2SPeter Wemm # if USEGETCONFATTR
3050c2aa98e2SPeter Wemm 	auto char *v;
3051c2aa98e2SPeter Wemm # endif
3052c2aa98e2SPeter Wemm 	register FILE *shellf;
3053c2aa98e2SPeter Wemm 	char buf[MAXLINE];
3054c2aa98e2SPeter Wemm 
3055c2aa98e2SPeter Wemm 	if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
3056c2aa98e2SPeter Wemm 	    ConfigLevel <= 1)
3057c2aa98e2SPeter Wemm 		return TRUE;
3058c2aa98e2SPeter Wemm 
3059c2aa98e2SPeter Wemm # if USEGETCONFATTR
3060c2aa98e2SPeter Wemm 	/*
3061c2aa98e2SPeter Wemm 	**  Naturally IBM has a "better" idea.....
3062c2aa98e2SPeter Wemm 	**
3063c2aa98e2SPeter Wemm 	**	What a crock.  This interface isn't documented, it is
3064c2aa98e2SPeter Wemm 	**	considered part of the security library (-ls), and it
3065c2aa98e2SPeter Wemm 	**	only works if you are running as root (since the list
3066c2aa98e2SPeter Wemm 	**	of valid shells is obviously a source of great concern).
3067c2aa98e2SPeter Wemm 	**	I recommend that you do NOT define USEGETCONFATTR,
3068c2aa98e2SPeter Wemm 	**	especially since you are going to have to set up an
3069c2aa98e2SPeter Wemm 	**	/etc/shells anyhow to handle the cases where getconfattr
3070c2aa98e2SPeter Wemm 	**	fails.
3071c2aa98e2SPeter Wemm 	*/
3072c2aa98e2SPeter Wemm 
3073c2aa98e2SPeter Wemm 	if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
3074c2aa98e2SPeter Wemm 	{
3075c2aa98e2SPeter Wemm 		while (*v != '\0')
3076c2aa98e2SPeter Wemm 		{
3077c2aa98e2SPeter Wemm 			if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
3078c2aa98e2SPeter Wemm 				return TRUE;
3079c2aa98e2SPeter Wemm 			v += strlen(v) + 1;
3080c2aa98e2SPeter Wemm 		}
3081c2aa98e2SPeter Wemm 		return FALSE;
3082c2aa98e2SPeter Wemm 	}
3083c2aa98e2SPeter Wemm # endif
3084c2aa98e2SPeter Wemm 
3085c2aa98e2SPeter Wemm 	shellf = fopen(_PATH_SHELLS, "r");
3086c2aa98e2SPeter Wemm 	if (shellf == NULL)
3087c2aa98e2SPeter Wemm 	{
3088c2aa98e2SPeter Wemm 		/* no /etc/shells; see if it is one of the std shells */
3089c2aa98e2SPeter Wemm 		char **d;
3090c2aa98e2SPeter Wemm 
3091c2aa98e2SPeter Wemm 		if (errno != ENOENT && LogLevel > 3)
3092c2aa98e2SPeter Wemm 			sm_syslog(LOG_ERR, NOQID,
3093c2aa98e2SPeter Wemm 				  "usershellok: cannot open %s: %s",
3094c2aa98e2SPeter Wemm 				  _PATH_SHELLS, errstring(errno));
3095c2aa98e2SPeter Wemm 
3096c2aa98e2SPeter Wemm 		for (d = DefaultUserShells; *d != NULL; d++)
3097c2aa98e2SPeter Wemm 		{
3098c2aa98e2SPeter Wemm 			if (strcmp(shell, *d) == 0)
3099c2aa98e2SPeter Wemm 				return TRUE;
3100c2aa98e2SPeter Wemm 		}
3101c2aa98e2SPeter Wemm 		return FALSE;
3102c2aa98e2SPeter Wemm 	}
3103c2aa98e2SPeter Wemm 
3104c2aa98e2SPeter Wemm 	while (fgets(buf, sizeof buf, shellf) != NULL)
3105c2aa98e2SPeter Wemm 	{
3106c2aa98e2SPeter Wemm 		register char *p, *q;
3107c2aa98e2SPeter Wemm 
3108c2aa98e2SPeter Wemm 		p = buf;
3109c2aa98e2SPeter Wemm 		while (*p != '\0' && *p != '#' && *p != '/')
3110c2aa98e2SPeter Wemm 			p++;
3111c2aa98e2SPeter Wemm 		if (*p == '#' || *p == '\0')
3112c2aa98e2SPeter Wemm 			continue;
3113c2aa98e2SPeter Wemm 		q = p;
3114c2aa98e2SPeter Wemm 		while (*p != '\0' && *p != '#' && !(isascii(*p) && isspace(*p)))
3115c2aa98e2SPeter Wemm 			p++;
3116c2aa98e2SPeter Wemm 		*p = '\0';
3117c2aa98e2SPeter Wemm 		if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
3118c2aa98e2SPeter Wemm 		{
3119c2aa98e2SPeter Wemm 			fclose(shellf);
3120c2aa98e2SPeter Wemm 			return TRUE;
3121c2aa98e2SPeter Wemm 		}
3122c2aa98e2SPeter Wemm 	}
3123c2aa98e2SPeter Wemm 	fclose(shellf);
3124c2aa98e2SPeter Wemm 	return FALSE;
3125c2aa98e2SPeter Wemm #endif
3126c2aa98e2SPeter Wemm }
3127c2aa98e2SPeter Wemm /*
3128c2aa98e2SPeter Wemm **  FREEDISKSPACE -- see how much free space is on the queue filesystem
3129c2aa98e2SPeter Wemm **
3130c2aa98e2SPeter Wemm **	Only implemented if you have statfs.
3131c2aa98e2SPeter Wemm **
3132c2aa98e2SPeter Wemm **	Parameters:
3133c2aa98e2SPeter Wemm **		dir -- the directory in question.
3134c2aa98e2SPeter Wemm **		bsize -- a variable into which the filesystem
3135c2aa98e2SPeter Wemm **			block size is stored.
3136c2aa98e2SPeter Wemm **
3137c2aa98e2SPeter Wemm **	Returns:
3138c2aa98e2SPeter Wemm **		The number of bytes free on the queue filesystem.
3139c2aa98e2SPeter Wemm **		-1 if the statfs call fails.
3140c2aa98e2SPeter Wemm **
3141c2aa98e2SPeter Wemm **	Side effects:
3142c2aa98e2SPeter Wemm **		Puts the filesystem block size into bsize.
3143c2aa98e2SPeter Wemm */
3144c2aa98e2SPeter Wemm 
3145c2aa98e2SPeter Wemm /* statfs types */
3146c2aa98e2SPeter Wemm #define SFS_NONE	0	/* no statfs implementation */
3147c2aa98e2SPeter Wemm #define SFS_USTAT	1	/* use ustat */
3148c2aa98e2SPeter Wemm #define SFS_4ARGS	2	/* use four-argument statfs call */
3149c2aa98e2SPeter Wemm #define SFS_VFS		3	/* use <sys/vfs.h> implementation */
3150c2aa98e2SPeter Wemm #define SFS_MOUNT	4	/* use <sys/mount.h> implementation */
3151c2aa98e2SPeter Wemm #define SFS_STATFS	5	/* use <sys/statfs.h> implementation */
3152c2aa98e2SPeter Wemm #define SFS_STATVFS	6	/* use <sys/statvfs.h> implementation */
3153c2aa98e2SPeter Wemm 
3154c2aa98e2SPeter Wemm #ifndef SFS_TYPE
3155c2aa98e2SPeter Wemm # define SFS_TYPE	SFS_NONE
3156c2aa98e2SPeter Wemm #endif
3157c2aa98e2SPeter Wemm 
3158c2aa98e2SPeter Wemm #if SFS_TYPE == SFS_USTAT
3159c2aa98e2SPeter Wemm # include <ustat.h>
3160c2aa98e2SPeter Wemm #endif
3161c2aa98e2SPeter Wemm #if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
3162c2aa98e2SPeter Wemm # include <sys/statfs.h>
3163c2aa98e2SPeter Wemm #endif
3164c2aa98e2SPeter Wemm #if SFS_TYPE == SFS_VFS
3165c2aa98e2SPeter Wemm # include <sys/vfs.h>
3166c2aa98e2SPeter Wemm #endif
3167c2aa98e2SPeter Wemm #if SFS_TYPE == SFS_MOUNT
3168c2aa98e2SPeter Wemm # include <sys/mount.h>
3169c2aa98e2SPeter Wemm #endif
3170c2aa98e2SPeter Wemm #if SFS_TYPE == SFS_STATVFS
3171c2aa98e2SPeter Wemm # include <sys/statvfs.h>
3172c2aa98e2SPeter Wemm #endif
3173c2aa98e2SPeter Wemm 
3174c2aa98e2SPeter Wemm long
3175c2aa98e2SPeter Wemm freediskspace(dir, bsize)
3176c2aa98e2SPeter Wemm 	char *dir;
3177c2aa98e2SPeter Wemm 	long *bsize;
3178c2aa98e2SPeter Wemm {
3179c2aa98e2SPeter Wemm #if SFS_TYPE != SFS_NONE
3180c2aa98e2SPeter Wemm # if SFS_TYPE == SFS_USTAT
3181c2aa98e2SPeter Wemm 	struct ustat fs;
3182c2aa98e2SPeter Wemm 	struct stat statbuf;
3183c2aa98e2SPeter Wemm #  define FSBLOCKSIZE	DEV_BSIZE
3184c2aa98e2SPeter Wemm #  define SFS_BAVAIL	f_tfree
3185c2aa98e2SPeter Wemm # else
3186c2aa98e2SPeter Wemm #  if defined(ultrix)
3187c2aa98e2SPeter Wemm 	struct fs_data fs;
3188c2aa98e2SPeter Wemm #   define SFS_BAVAIL	fd_bfreen
3189c2aa98e2SPeter Wemm #   define FSBLOCKSIZE	1024L
3190c2aa98e2SPeter Wemm #  else
3191c2aa98e2SPeter Wemm #   if SFS_TYPE == SFS_STATVFS
3192c2aa98e2SPeter Wemm 	struct statvfs fs;
3193c2aa98e2SPeter Wemm #    define FSBLOCKSIZE	fs.f_frsize
3194c2aa98e2SPeter Wemm #   else
3195c2aa98e2SPeter Wemm 	struct statfs fs;
3196c2aa98e2SPeter Wemm #    define FSBLOCKSIZE	fs.f_bsize
3197c2aa98e2SPeter Wemm #   endif
3198c2aa98e2SPeter Wemm #  endif
3199c2aa98e2SPeter Wemm # endif
3200c2aa98e2SPeter Wemm # ifndef SFS_BAVAIL
3201c2aa98e2SPeter Wemm #  define SFS_BAVAIL f_bavail
3202c2aa98e2SPeter Wemm # endif
3203c2aa98e2SPeter Wemm 
3204c2aa98e2SPeter Wemm # if SFS_TYPE == SFS_USTAT
3205c2aa98e2SPeter Wemm 	if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
3206c2aa98e2SPeter Wemm # else
3207c2aa98e2SPeter Wemm #  if SFS_TYPE == SFS_4ARGS
3208c2aa98e2SPeter Wemm 	if (statfs(dir, &fs, sizeof fs, 0) == 0)
3209c2aa98e2SPeter Wemm #  else
3210c2aa98e2SPeter Wemm #   if SFS_TYPE == SFS_STATVFS
3211c2aa98e2SPeter Wemm 	if (statvfs(dir, &fs) == 0)
3212c2aa98e2SPeter Wemm #   else
3213c2aa98e2SPeter Wemm #    if defined(ultrix)
3214c2aa98e2SPeter Wemm 	if (statfs(dir, &fs) > 0)
3215c2aa98e2SPeter Wemm #    else
3216c2aa98e2SPeter Wemm 	if (statfs(dir, &fs) == 0)
3217c2aa98e2SPeter Wemm #    endif
3218c2aa98e2SPeter Wemm #   endif
3219c2aa98e2SPeter Wemm #  endif
3220c2aa98e2SPeter Wemm # endif
3221c2aa98e2SPeter Wemm 	{
3222c2aa98e2SPeter Wemm 		if (bsize != NULL)
3223c2aa98e2SPeter Wemm 			*bsize = FSBLOCKSIZE;
3224c2aa98e2SPeter Wemm 		if (fs.SFS_BAVAIL <= 0)
3225c2aa98e2SPeter Wemm 			return 0;
3226c2aa98e2SPeter Wemm 		else if (fs.SFS_BAVAIL > LONG_MAX)
3227c2aa98e2SPeter Wemm 			return LONG_MAX;
3228c2aa98e2SPeter Wemm 		else
3229c2aa98e2SPeter Wemm 			return (long) fs.SFS_BAVAIL;
3230c2aa98e2SPeter Wemm 	}
3231c2aa98e2SPeter Wemm #endif
3232c2aa98e2SPeter Wemm 	return (-1);
3233c2aa98e2SPeter Wemm }
3234c2aa98e2SPeter Wemm /*
3235c2aa98e2SPeter Wemm **  ENOUGHDISKSPACE -- is there enough free space on the queue fs?
3236c2aa98e2SPeter Wemm **
3237c2aa98e2SPeter Wemm **	Only implemented if you have statfs.
3238c2aa98e2SPeter Wemm **
3239c2aa98e2SPeter Wemm **	Parameters:
3240c2aa98e2SPeter Wemm **		msize -- the size to check against.  If zero, we don't yet
3241c2aa98e2SPeter Wemm **		know how big the message will be, so just check for
3242c2aa98e2SPeter Wemm **		a "reasonable" amount.
3243c2aa98e2SPeter Wemm **
3244c2aa98e2SPeter Wemm **	Returns:
3245c2aa98e2SPeter Wemm **		TRUE if there is enough space.
3246c2aa98e2SPeter Wemm **		FALSE otherwise.
3247c2aa98e2SPeter Wemm */
3248c2aa98e2SPeter Wemm 
3249c2aa98e2SPeter Wemm bool
3250c2aa98e2SPeter Wemm enoughdiskspace(msize)
3251c2aa98e2SPeter Wemm 	long msize;
3252c2aa98e2SPeter Wemm {
3253c2aa98e2SPeter Wemm 	long bfree, bsize;
3254c2aa98e2SPeter Wemm 
3255c2aa98e2SPeter Wemm 	if (MinBlocksFree <= 0 && msize <= 0)
3256c2aa98e2SPeter Wemm 	{
3257c2aa98e2SPeter Wemm 		if (tTd(4, 80))
3258c2aa98e2SPeter Wemm 			printf("enoughdiskspace: no threshold\n");
3259c2aa98e2SPeter Wemm 		return TRUE;
3260c2aa98e2SPeter Wemm 	}
3261c2aa98e2SPeter Wemm 
3262c2aa98e2SPeter Wemm 	if ((bfree = freediskspace(QueueDir, &bsize)) >= 0)
3263c2aa98e2SPeter Wemm 	{
3264c2aa98e2SPeter Wemm 		if (tTd(4, 80))
3265c2aa98e2SPeter Wemm 			printf("enoughdiskspace: bavail=%ld, need=%ld\n",
3266c2aa98e2SPeter Wemm 				bfree, msize);
3267c2aa98e2SPeter Wemm 
3268c2aa98e2SPeter Wemm 		/* convert msize to block count */
3269c2aa98e2SPeter Wemm 		msize = msize / bsize + 1;
3270c2aa98e2SPeter Wemm 		if (MinBlocksFree >= 0)
3271c2aa98e2SPeter Wemm 			msize += MinBlocksFree;
3272c2aa98e2SPeter Wemm 
3273c2aa98e2SPeter Wemm 		if (bfree < msize)
3274c2aa98e2SPeter Wemm 		{
3275c2aa98e2SPeter Wemm 			if (LogLevel > 0)
3276c2aa98e2SPeter Wemm 				sm_syslog(LOG_ALERT, CurEnv->e_id,
3277c2aa98e2SPeter Wemm 					"low on space (have %ld, %s needs %ld in %s)",
3278c2aa98e2SPeter Wemm 					bfree,
3279c2aa98e2SPeter Wemm 					CurHostName == NULL ? "SMTP-DAEMON" : CurHostName,
3280c2aa98e2SPeter Wemm 					msize, QueueDir);
3281c2aa98e2SPeter Wemm 			return FALSE;
3282c2aa98e2SPeter Wemm 		}
3283c2aa98e2SPeter Wemm 	}
3284c2aa98e2SPeter Wemm 	else if (tTd(4, 80))
3285c2aa98e2SPeter Wemm 		printf("enoughdiskspace failure: min=%ld, need=%ld: %s\n",
3286c2aa98e2SPeter Wemm 			MinBlocksFree, msize, errstring(errno));
3287c2aa98e2SPeter Wemm 	return TRUE;
3288c2aa98e2SPeter Wemm }
3289c2aa98e2SPeter Wemm /*
3290c2aa98e2SPeter Wemm **  TRANSIENTERROR -- tell if an error code indicates a transient failure
3291c2aa98e2SPeter Wemm **
3292c2aa98e2SPeter Wemm **	This looks at an errno value and tells if this is likely to
3293c2aa98e2SPeter Wemm **	go away if retried later.
3294c2aa98e2SPeter Wemm **
3295c2aa98e2SPeter Wemm **	Parameters:
3296c2aa98e2SPeter Wemm **		err -- the errno code to classify.
3297c2aa98e2SPeter Wemm **
3298c2aa98e2SPeter Wemm **	Returns:
3299c2aa98e2SPeter Wemm **		TRUE if this is probably transient.
3300c2aa98e2SPeter Wemm **		FALSE otherwise.
3301c2aa98e2SPeter Wemm */
3302c2aa98e2SPeter Wemm 
3303c2aa98e2SPeter Wemm bool
3304c2aa98e2SPeter Wemm transienterror(err)
3305c2aa98e2SPeter Wemm 	int err;
3306c2aa98e2SPeter Wemm {
3307c2aa98e2SPeter Wemm 	switch (err)
3308c2aa98e2SPeter Wemm 	{
3309c2aa98e2SPeter Wemm 	  case EIO:			/* I/O error */
3310c2aa98e2SPeter Wemm 	  case ENXIO:			/* Device not configured */
3311c2aa98e2SPeter Wemm 	  case EAGAIN:			/* Resource temporarily unavailable */
3312c2aa98e2SPeter Wemm 	  case ENOMEM:			/* Cannot allocate memory */
3313c2aa98e2SPeter Wemm 	  case ENODEV:			/* Operation not supported by device */
3314c2aa98e2SPeter Wemm 	  case ENFILE:			/* Too many open files in system */
3315c2aa98e2SPeter Wemm 	  case EMFILE:			/* Too many open files */
3316c2aa98e2SPeter Wemm 	  case ENOSPC:			/* No space left on device */
3317c2aa98e2SPeter Wemm #ifdef ETIMEDOUT
3318c2aa98e2SPeter Wemm 	  case ETIMEDOUT:		/* Connection timed out */
3319c2aa98e2SPeter Wemm #endif
3320c2aa98e2SPeter Wemm #ifdef ESTALE
3321c2aa98e2SPeter Wemm 	  case ESTALE:			/* Stale NFS file handle */
3322c2aa98e2SPeter Wemm #endif
3323c2aa98e2SPeter Wemm #ifdef ENETDOWN
3324c2aa98e2SPeter Wemm 	  case ENETDOWN:		/* Network is down */
3325c2aa98e2SPeter Wemm #endif
3326c2aa98e2SPeter Wemm #ifdef ENETUNREACH
3327c2aa98e2SPeter Wemm 	  case ENETUNREACH:		/* Network is unreachable */
3328c2aa98e2SPeter Wemm #endif
3329c2aa98e2SPeter Wemm #ifdef ENETRESET
3330c2aa98e2SPeter Wemm 	  case ENETRESET:		/* Network dropped connection on reset */
3331c2aa98e2SPeter Wemm #endif
3332c2aa98e2SPeter Wemm #ifdef ECONNABORTED
3333c2aa98e2SPeter Wemm 	  case ECONNABORTED:		/* Software caused connection abort */
3334c2aa98e2SPeter Wemm #endif
3335c2aa98e2SPeter Wemm #ifdef ECONNRESET
3336c2aa98e2SPeter Wemm 	  case ECONNRESET:		/* Connection reset by peer */
3337c2aa98e2SPeter Wemm #endif
3338c2aa98e2SPeter Wemm #ifdef ENOBUFS
3339c2aa98e2SPeter Wemm 	  case ENOBUFS:			/* No buffer space available */
3340c2aa98e2SPeter Wemm #endif
3341c2aa98e2SPeter Wemm #ifdef ESHUTDOWN
3342c2aa98e2SPeter Wemm 	  case ESHUTDOWN:		/* Can't send after socket shutdown */
3343c2aa98e2SPeter Wemm #endif
3344c2aa98e2SPeter Wemm #ifdef ECONNREFUSED
3345c2aa98e2SPeter Wemm 	  case ECONNREFUSED:		/* Connection refused */
3346c2aa98e2SPeter Wemm #endif
3347c2aa98e2SPeter Wemm #ifdef EHOSTDOWN
3348c2aa98e2SPeter Wemm 	  case EHOSTDOWN:		/* Host is down */
3349c2aa98e2SPeter Wemm #endif
3350c2aa98e2SPeter Wemm #ifdef EHOSTUNREACH
3351c2aa98e2SPeter Wemm 	  case EHOSTUNREACH:		/* No route to host */
3352c2aa98e2SPeter Wemm #endif
3353c2aa98e2SPeter Wemm #ifdef EDQUOT
3354c2aa98e2SPeter Wemm 	  case EDQUOT:			/* Disc quota exceeded */
3355c2aa98e2SPeter Wemm #endif
3356c2aa98e2SPeter Wemm #ifdef EPROCLIM
3357c2aa98e2SPeter Wemm 	  case EPROCLIM:		/* Too many processes */
3358c2aa98e2SPeter Wemm #endif
3359c2aa98e2SPeter Wemm #ifdef EUSERS
3360c2aa98e2SPeter Wemm 	  case EUSERS:			/* Too many users */
3361c2aa98e2SPeter Wemm #endif
3362c2aa98e2SPeter Wemm #ifdef EDEADLK
3363c2aa98e2SPeter Wemm 	  case EDEADLK:			/* Resource deadlock avoided */
3364c2aa98e2SPeter Wemm #endif
3365c2aa98e2SPeter Wemm #ifdef EISCONN
3366c2aa98e2SPeter Wemm 	  case EISCONN:			/* Socket already connected */
3367c2aa98e2SPeter Wemm #endif
3368c2aa98e2SPeter Wemm #ifdef EINPROGRESS
3369c2aa98e2SPeter Wemm 	  case EINPROGRESS:		/* Operation now in progress */
3370c2aa98e2SPeter Wemm #endif
3371c2aa98e2SPeter Wemm #ifdef EALREADY
3372c2aa98e2SPeter Wemm 	  case EALREADY:		/* Operation already in progress */
3373c2aa98e2SPeter Wemm #endif
3374c2aa98e2SPeter Wemm #ifdef EADDRINUSE
3375c2aa98e2SPeter Wemm 	  case EADDRINUSE:		/* Address already in use */
3376c2aa98e2SPeter Wemm #endif
3377c2aa98e2SPeter Wemm #ifdef EADDRNOTAVAIL
3378c2aa98e2SPeter Wemm 	  case EADDRNOTAVAIL:		/* Can't assign requested address */
3379c2aa98e2SPeter Wemm #endif
3380c2aa98e2SPeter Wemm #ifdef ETXTBSY
3381c2aa98e2SPeter Wemm 	  case ETXTBSY:			/* (Apollo) file locked */
3382c2aa98e2SPeter Wemm #endif
3383c2aa98e2SPeter Wemm #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
3384c2aa98e2SPeter Wemm 	  case ENOSR:			/* Out of streams resources */
3385c2aa98e2SPeter Wemm #endif
3386c2aa98e2SPeter Wemm 	  case E_SM_OPENTIMEOUT:	/* PSEUDO: open timed out */
3387c2aa98e2SPeter Wemm 		return TRUE;
3388c2aa98e2SPeter Wemm 	}
3389c2aa98e2SPeter Wemm 
3390c2aa98e2SPeter Wemm 	/* nope, must be permanent */
3391c2aa98e2SPeter Wemm 	return FALSE;
3392c2aa98e2SPeter Wemm }
3393c2aa98e2SPeter Wemm /*
3394c2aa98e2SPeter Wemm **  LOCKFILE -- lock a file using flock or (shudder) fcntl locking
3395c2aa98e2SPeter Wemm **
3396c2aa98e2SPeter Wemm **	Parameters:
3397c2aa98e2SPeter Wemm **		fd -- the file descriptor of the file.
3398c2aa98e2SPeter Wemm **		filename -- the file name (for error messages).
3399c2aa98e2SPeter Wemm **		ext -- the filename extension.
3400c2aa98e2SPeter Wemm **		type -- type of the lock.  Bits can be:
3401c2aa98e2SPeter Wemm **			LOCK_EX -- exclusive lock.
3402c2aa98e2SPeter Wemm **			LOCK_NB -- non-blocking.
3403c2aa98e2SPeter Wemm **
3404c2aa98e2SPeter Wemm **	Returns:
3405c2aa98e2SPeter Wemm **		TRUE if the lock was acquired.
3406c2aa98e2SPeter Wemm **		FALSE otherwise.
3407c2aa98e2SPeter Wemm */
3408c2aa98e2SPeter Wemm 
3409c2aa98e2SPeter Wemm bool
3410c2aa98e2SPeter Wemm lockfile(fd, filename, ext, type)
3411c2aa98e2SPeter Wemm 	int fd;
3412c2aa98e2SPeter Wemm 	char *filename;
3413c2aa98e2SPeter Wemm 	char *ext;
3414c2aa98e2SPeter Wemm 	int type;
3415c2aa98e2SPeter Wemm {
3416c2aa98e2SPeter Wemm 	int i;
3417c2aa98e2SPeter Wemm 	int save_errno;
3418c2aa98e2SPeter Wemm # if !HASFLOCK
3419c2aa98e2SPeter Wemm 	int action;
3420c2aa98e2SPeter Wemm 	struct flock lfd;
3421c2aa98e2SPeter Wemm 
3422c2aa98e2SPeter Wemm 	if (ext == NULL)
3423c2aa98e2SPeter Wemm 		ext = "";
3424c2aa98e2SPeter Wemm 
3425c2aa98e2SPeter Wemm 	bzero(&lfd, sizeof lfd);
3426c2aa98e2SPeter Wemm 	if (bitset(LOCK_UN, type))
3427c2aa98e2SPeter Wemm 		lfd.l_type = F_UNLCK;
3428c2aa98e2SPeter Wemm 	else if (bitset(LOCK_EX, type))
3429c2aa98e2SPeter Wemm 		lfd.l_type = F_WRLCK;
3430c2aa98e2SPeter Wemm 	else
3431c2aa98e2SPeter Wemm 		lfd.l_type = F_RDLCK;
3432c2aa98e2SPeter Wemm 
3433c2aa98e2SPeter Wemm 	if (bitset(LOCK_NB, type))
3434c2aa98e2SPeter Wemm 		action = F_SETLK;
3435c2aa98e2SPeter Wemm 	else
3436c2aa98e2SPeter Wemm 		action = F_SETLKW;
3437c2aa98e2SPeter Wemm 
3438c2aa98e2SPeter Wemm 	if (tTd(55, 60))
3439c2aa98e2SPeter Wemm 		printf("lockfile(%s%s, action=%d, type=%d): ",
3440c2aa98e2SPeter Wemm 			filename, ext, action, lfd.l_type);
3441c2aa98e2SPeter Wemm 
3442c2aa98e2SPeter Wemm 	while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
3443c2aa98e2SPeter Wemm 		continue;
3444c2aa98e2SPeter Wemm 	if (i >= 0)
3445c2aa98e2SPeter Wemm 	{
3446c2aa98e2SPeter Wemm 		if (tTd(55, 60))
3447c2aa98e2SPeter Wemm 			printf("SUCCESS\n");
3448c2aa98e2SPeter Wemm 		return TRUE;
3449c2aa98e2SPeter Wemm 	}
3450c2aa98e2SPeter Wemm 	save_errno = errno;
3451c2aa98e2SPeter Wemm 
3452c2aa98e2SPeter Wemm 	if (tTd(55, 60))
3453c2aa98e2SPeter Wemm 		printf("(%s) ", errstring(save_errno));
3454c2aa98e2SPeter Wemm 
3455c2aa98e2SPeter Wemm 	/*
3456c2aa98e2SPeter Wemm 	**  On SunOS, if you are testing using -oQ/tmp/mqueue or
3457c2aa98e2SPeter Wemm 	**  -oA/tmp/aliases or anything like that, and /tmp is mounted
3458c2aa98e2SPeter Wemm 	**  as type "tmp" (that is, served from swap space), the
3459c2aa98e2SPeter Wemm 	**  previous fcntl will fail with "Invalid argument" errors.
3460c2aa98e2SPeter Wemm 	**  Since this is fairly common during testing, we will assume
3461c2aa98e2SPeter Wemm 	**  that this indicates that the lock is successfully grabbed.
3462c2aa98e2SPeter Wemm 	*/
3463c2aa98e2SPeter Wemm 
3464c2aa98e2SPeter Wemm 	if (save_errno == EINVAL)
3465c2aa98e2SPeter Wemm 	{
3466c2aa98e2SPeter Wemm 		if (tTd(55, 60))
3467c2aa98e2SPeter Wemm 			printf("SUCCESS\n");
3468c2aa98e2SPeter Wemm 		return TRUE;
3469c2aa98e2SPeter Wemm 	}
3470c2aa98e2SPeter Wemm 
3471c2aa98e2SPeter Wemm 	if (!bitset(LOCK_NB, type) || (save_errno != EACCES && save_errno != EAGAIN))
3472c2aa98e2SPeter Wemm 	{
3473c2aa98e2SPeter Wemm 		int omode = -1;
3474c2aa98e2SPeter Wemm #  ifdef F_GETFL
3475c2aa98e2SPeter Wemm 		(void) fcntl(fd, F_GETFL, &omode);
3476c2aa98e2SPeter Wemm 		errno = save_errno;
3477c2aa98e2SPeter Wemm #  endif
3478c2aa98e2SPeter Wemm 		syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
3479c2aa98e2SPeter Wemm 			filename, ext, fd, type, omode, geteuid());
3480c2aa98e2SPeter Wemm 		dumpfd(fd, TRUE, TRUE);
3481c2aa98e2SPeter Wemm 	}
3482c2aa98e2SPeter Wemm # else
3483c2aa98e2SPeter Wemm 	if (ext == NULL)
3484c2aa98e2SPeter Wemm 		ext = "";
3485c2aa98e2SPeter Wemm 
3486c2aa98e2SPeter Wemm 	if (tTd(55, 60))
3487c2aa98e2SPeter Wemm 		printf("lockfile(%s%s, type=%o): ", filename, ext, type);
3488c2aa98e2SPeter Wemm 
3489c2aa98e2SPeter Wemm 	while ((i = flock(fd, type)) < 0 && errno == EINTR)
3490c2aa98e2SPeter Wemm 		continue;
3491c2aa98e2SPeter Wemm 	if (i >= 0)
3492c2aa98e2SPeter Wemm 	{
3493c2aa98e2SPeter Wemm 		if (tTd(55, 60))
3494c2aa98e2SPeter Wemm 			printf("SUCCESS\n");
3495c2aa98e2SPeter Wemm 		return TRUE;
3496c2aa98e2SPeter Wemm 	}
3497c2aa98e2SPeter Wemm 	save_errno = errno;
3498c2aa98e2SPeter Wemm 
3499c2aa98e2SPeter Wemm 	if (tTd(55, 60))
3500c2aa98e2SPeter Wemm 		printf("(%s) ", errstring(save_errno));
3501c2aa98e2SPeter Wemm 
3502c2aa98e2SPeter Wemm 	if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK)
3503c2aa98e2SPeter Wemm 	{
3504c2aa98e2SPeter Wemm 		int omode = -1;
3505c2aa98e2SPeter Wemm #  ifdef F_GETFL
3506c2aa98e2SPeter Wemm 		(void) fcntl(fd, F_GETFL, &omode);
3507c2aa98e2SPeter Wemm 		errno = save_errno;
3508c2aa98e2SPeter Wemm #  endif
3509c2aa98e2SPeter Wemm 		syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
3510c2aa98e2SPeter Wemm 			filename, ext, fd, type, omode, geteuid());
3511c2aa98e2SPeter Wemm 		dumpfd(fd, TRUE, TRUE);
3512c2aa98e2SPeter Wemm 	}
3513c2aa98e2SPeter Wemm # endif
3514c2aa98e2SPeter Wemm 	if (tTd(55, 60))
3515c2aa98e2SPeter Wemm 		printf("FAIL\n");
3516c2aa98e2SPeter Wemm 	errno = save_errno;
3517c2aa98e2SPeter Wemm 	return FALSE;
3518c2aa98e2SPeter Wemm }
3519c2aa98e2SPeter Wemm /*
3520c2aa98e2SPeter Wemm **  CHOWNSAFE -- tell if chown is "safe" (executable only by root)
3521c2aa98e2SPeter Wemm **
3522c2aa98e2SPeter Wemm **	Unfortunately, given that we can't predict other systems on which
3523c2aa98e2SPeter Wemm **	a remote mounted (NFS) filesystem will be mounted, the answer is
3524c2aa98e2SPeter Wemm **	almost always that this is unsafe.
3525c2aa98e2SPeter Wemm **
3526c2aa98e2SPeter Wemm **	Note also that many operating systems have non-compliant
3527c2aa98e2SPeter Wemm **	implementations of the _POSIX_CHOWN_RESTRICTED variable and the
3528c2aa98e2SPeter Wemm **	fpathconf() routine.  According to IEEE 1003.1-1990, if
3529c2aa98e2SPeter Wemm **	_POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
3530c2aa98e2SPeter Wemm **	no non-root process can give away the file.  However, vendors
3531c2aa98e2SPeter Wemm **	don't take NFS into account, so a comfortable value of
3532c2aa98e2SPeter Wemm **	_POSIX_CHOWN_RESTRICTED tells us nothing.
3533c2aa98e2SPeter Wemm **
3534c2aa98e2SPeter Wemm **	Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
3535c2aa98e2SPeter Wemm **	even on files where chown is not restricted.  Many systems get
3536c2aa98e2SPeter Wemm **	this wrong on NFS-based filesystems (that is, they say that chown
3537c2aa98e2SPeter Wemm **	is restricted [safe] on NFS filesystems where it may not be, since
3538c2aa98e2SPeter Wemm **	other systems can access the same filesystem and do file giveaway;
3539c2aa98e2SPeter Wemm **	only the NFS server knows for sure!)  Hence, it is important to
3540c2aa98e2SPeter Wemm **	get the value of SAFENFSPATHCONF correct -- it should be defined
3541c2aa98e2SPeter Wemm **	_only_ after testing (see test/t_pathconf.c) a system on an unsafe
3542c2aa98e2SPeter Wemm **	NFS-based filesystem to ensure that you can get meaningful results.
3543c2aa98e2SPeter Wemm **	If in doubt, assume unsafe!
3544c2aa98e2SPeter Wemm **
3545c2aa98e2SPeter Wemm **	You may also need to tweak IS_SAFE_CHOWN -- it should be a
3546c2aa98e2SPeter Wemm **	condition indicating whether the return from pathconf indicates
3547c2aa98e2SPeter Wemm **	that chown is safe (typically either > 0 or >= 0 -- there isn't
3548c2aa98e2SPeter Wemm **	even any agreement about whether a zero return means that a file
3549c2aa98e2SPeter Wemm **	is or is not safe).  It defaults to "> 0".
3550c2aa98e2SPeter Wemm **
3551c2aa98e2SPeter Wemm **	If the parent directory is safe (writable only by owner back
3552c2aa98e2SPeter Wemm **	to the root) then we can relax slightly and trust fpathconf
3553c2aa98e2SPeter Wemm **	in more circumstances.  This is really a crock -- if this is an
3554c2aa98e2SPeter Wemm **	NFS mounted filesystem then we really know nothing about the
3555c2aa98e2SPeter Wemm **	underlying implementation.  However, most systems pessimize and
3556c2aa98e2SPeter Wemm **	return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
3557c2aa98e2SPeter Wemm **	we interpret as unsafe, as we should.  Thus, this heuristic gets
3558c2aa98e2SPeter Wemm **	us into a possible problem only on systems that have a broken
3559c2aa98e2SPeter Wemm **	pathconf implementation and which are also poorly configured
3560c2aa98e2SPeter Wemm **	(have :include: files in group- or world-writable directories).
3561c2aa98e2SPeter Wemm **
3562c2aa98e2SPeter Wemm **	Parameters:
3563c2aa98e2SPeter Wemm **		fd -- the file descriptor to check.
3564c2aa98e2SPeter Wemm **		safedir -- set if the parent directory is safe.
3565c2aa98e2SPeter Wemm **
3566c2aa98e2SPeter Wemm **	Returns:
3567c2aa98e2SPeter Wemm **		TRUE -- if the chown(2) operation is "safe" -- that is,
3568c2aa98e2SPeter Wemm **			only root can chown the file to an arbitrary user.
3569c2aa98e2SPeter Wemm **		FALSE -- if an arbitrary user can give away a file.
3570c2aa98e2SPeter Wemm */
3571c2aa98e2SPeter Wemm 
3572c2aa98e2SPeter Wemm #ifndef IS_SAFE_CHOWN
3573c2aa98e2SPeter Wemm # define IS_SAFE_CHOWN	> 0
3574c2aa98e2SPeter Wemm #endif
3575c2aa98e2SPeter Wemm 
3576c2aa98e2SPeter Wemm bool
3577c2aa98e2SPeter Wemm chownsafe(fd, safedir)
3578c2aa98e2SPeter Wemm 	int fd;
3579c2aa98e2SPeter Wemm 	bool safedir;
3580c2aa98e2SPeter Wemm {
3581c2aa98e2SPeter Wemm #if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \
3582c2aa98e2SPeter Wemm     (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H))
3583c2aa98e2SPeter Wemm 	int rval;
3584c2aa98e2SPeter Wemm 
3585c2aa98e2SPeter Wemm 	/* give the system administrator a chance to override */
3586c2aa98e2SPeter Wemm 	if (bitset(DBS_ASSUMESAFECHOWN, DontBlameSendmail))
3587c2aa98e2SPeter Wemm 		return TRUE;
3588c2aa98e2SPeter Wemm 
3589c2aa98e2SPeter Wemm 	/*
3590c2aa98e2SPeter Wemm 	**  Some systems (e.g., SunOS) seem to have the call and the
3591c2aa98e2SPeter Wemm 	**  #define _PC_CHOWN_RESTRICTED, but don't actually implement
3592c2aa98e2SPeter Wemm 	**  the call.  This heuristic checks for that.
3593c2aa98e2SPeter Wemm 	*/
3594c2aa98e2SPeter Wemm 
3595c2aa98e2SPeter Wemm 	errno = 0;
3596c2aa98e2SPeter Wemm 	rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
3597c2aa98e2SPeter Wemm # if SAFENFSPATHCONF
3598c2aa98e2SPeter Wemm 	return errno == 0 && rval IS_SAFE_CHOWN;
3599c2aa98e2SPeter Wemm # else
3600c2aa98e2SPeter Wemm 	return safedir && errno == 0 && rval IS_SAFE_CHOWN;
3601c2aa98e2SPeter Wemm # endif
3602c2aa98e2SPeter Wemm #else
3603c2aa98e2SPeter Wemm 	return bitset(DBS_ASSUMESAFECHOWN, DontBlameSendmail);
3604c2aa98e2SPeter Wemm #endif
3605c2aa98e2SPeter Wemm }
3606c2aa98e2SPeter Wemm /*
3607c2aa98e2SPeter Wemm **  RESETLIMITS -- reset system controlled resource limits
3608c2aa98e2SPeter Wemm **
3609c2aa98e2SPeter Wemm **	This is to avoid denial-of-service attacks
3610c2aa98e2SPeter Wemm **
3611c2aa98e2SPeter Wemm **	Parameters:
3612c2aa98e2SPeter Wemm **		none
3613c2aa98e2SPeter Wemm **
3614c2aa98e2SPeter Wemm **	Returns:
3615c2aa98e2SPeter Wemm **		none
3616c2aa98e2SPeter Wemm */
3617c2aa98e2SPeter Wemm 
3618c2aa98e2SPeter Wemm #if HASSETRLIMIT
3619c2aa98e2SPeter Wemm # ifdef RLIMIT_NEEDS_SYS_TIME_H
3620c2aa98e2SPeter Wemm #  include <sys/time.h>
3621c2aa98e2SPeter Wemm # endif
3622c2aa98e2SPeter Wemm # include <sys/resource.h>
3623c2aa98e2SPeter Wemm #endif
3624c2aa98e2SPeter Wemm #ifndef FD_SETSIZE
3625c2aa98e2SPeter Wemm # define FD_SETSIZE	256
3626c2aa98e2SPeter Wemm #endif
3627c2aa98e2SPeter Wemm 
3628c2aa98e2SPeter Wemm void
3629c2aa98e2SPeter Wemm resetlimits()
3630c2aa98e2SPeter Wemm {
3631c2aa98e2SPeter Wemm #if HASSETRLIMIT
3632c2aa98e2SPeter Wemm 	struct rlimit lim;
3633c2aa98e2SPeter Wemm 
3634c2aa98e2SPeter Wemm 	lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
3635c2aa98e2SPeter Wemm 	(void) setrlimit(RLIMIT_CPU, &lim);
3636c2aa98e2SPeter Wemm 	(void) setrlimit(RLIMIT_FSIZE, &lim);
3637c2aa98e2SPeter Wemm # ifdef RLIMIT_NOFILE
3638c2aa98e2SPeter Wemm 	lim.rlim_cur = lim.rlim_max = FD_SETSIZE;
3639c2aa98e2SPeter Wemm 	(void) setrlimit(RLIMIT_NOFILE, &lim);
3640c2aa98e2SPeter Wemm # endif
3641c2aa98e2SPeter Wemm #else
3642c2aa98e2SPeter Wemm # if HASULIMIT
3643c2aa98e2SPeter Wemm 	(void) ulimit(2, 0x3fffff);
3644c2aa98e2SPeter Wemm 	(void) ulimit(4, FD_SETSIZE);
3645c2aa98e2SPeter Wemm # endif
3646c2aa98e2SPeter Wemm #endif
3647c2aa98e2SPeter Wemm 	errno = 0;
3648c2aa98e2SPeter Wemm }
3649c2aa98e2SPeter Wemm /*
3650c2aa98e2SPeter Wemm **  GETCFNAME -- return the name of the .cf file.
3651c2aa98e2SPeter Wemm **
3652c2aa98e2SPeter Wemm **	Some systems (e.g., NeXT) determine this dynamically.
3653c2aa98e2SPeter Wemm */
3654c2aa98e2SPeter Wemm 
3655c2aa98e2SPeter Wemm char *
3656c2aa98e2SPeter Wemm getcfname()
3657c2aa98e2SPeter Wemm {
3658c2aa98e2SPeter Wemm 
3659c2aa98e2SPeter Wemm 	if (ConfFile != NULL)
3660c2aa98e2SPeter Wemm 		return ConfFile;
3661c2aa98e2SPeter Wemm #if NETINFO
3662c2aa98e2SPeter Wemm 	{
3663c2aa98e2SPeter Wemm 		extern char *ni_propval __P((char *, char *, char *, char *, int));
3664c2aa98e2SPeter Wemm 		char *cflocation;
3665c2aa98e2SPeter Wemm 
3666c2aa98e2SPeter Wemm 		cflocation = ni_propval("/locations", NULL, "sendmail",
3667c2aa98e2SPeter Wemm 					"sendmail.cf", '\0');
3668c2aa98e2SPeter Wemm 		if (cflocation != NULL)
3669c2aa98e2SPeter Wemm 			return cflocation;
3670c2aa98e2SPeter Wemm 	}
3671c2aa98e2SPeter Wemm #endif
3672c2aa98e2SPeter Wemm 
3673c2aa98e2SPeter Wemm 	return _PATH_SENDMAILCF;
3674c2aa98e2SPeter Wemm }
3675c2aa98e2SPeter Wemm /*
3676c2aa98e2SPeter Wemm **  SETVENDOR -- process vendor code from V configuration line
3677c2aa98e2SPeter Wemm **
3678c2aa98e2SPeter Wemm **	Parameters:
3679c2aa98e2SPeter Wemm **		vendor -- string representation of vendor.
3680c2aa98e2SPeter Wemm **
3681c2aa98e2SPeter Wemm **	Returns:
3682c2aa98e2SPeter Wemm **		TRUE -- if ok.
3683c2aa98e2SPeter Wemm **		FALSE -- if vendor code could not be processed.
3684c2aa98e2SPeter Wemm **
3685c2aa98e2SPeter Wemm **	Side Effects:
3686c2aa98e2SPeter Wemm **		It is reasonable to set mode flags here to tweak
3687c2aa98e2SPeter Wemm **		processing in other parts of the code if necessary.
3688c2aa98e2SPeter Wemm **		For example, if you are a vendor that uses $%y to
3689c2aa98e2SPeter Wemm **		indicate YP lookups, you could enable that here.
3690c2aa98e2SPeter Wemm */
3691c2aa98e2SPeter Wemm 
3692c2aa98e2SPeter Wemm bool
3693c2aa98e2SPeter Wemm setvendor(vendor)
3694c2aa98e2SPeter Wemm 	char *vendor;
3695c2aa98e2SPeter Wemm {
3696c2aa98e2SPeter Wemm 	if (strcasecmp(vendor, "Berkeley") == 0)
3697c2aa98e2SPeter Wemm 	{
3698c2aa98e2SPeter Wemm 		VendorCode = VENDOR_BERKELEY;
3699c2aa98e2SPeter Wemm 		return TRUE;
3700c2aa98e2SPeter Wemm 	}
3701c2aa98e2SPeter Wemm 
3702c2aa98e2SPeter Wemm 	/* add vendor extensions here */
3703c2aa98e2SPeter Wemm 
3704c2aa98e2SPeter Wemm #ifdef SUN_EXTENSIONS
3705c2aa98e2SPeter Wemm 	if (strcasecmp(vendor, "Sun") == 0)
3706c2aa98e2SPeter Wemm 	{
3707c2aa98e2SPeter Wemm 		VendorCode = VENDOR_SUN;
3708c2aa98e2SPeter Wemm 		return TRUE;
3709c2aa98e2SPeter Wemm 	}
3710c2aa98e2SPeter Wemm #endif
3711c2aa98e2SPeter Wemm 
371276b7bf71SPeter Wemm #if defined(VENDOR_NAME) && defined(VENDOR_CODE)
371376b7bf71SPeter Wemm 	if (strcasecmp(vendor, VENDOR_NAME) == 0)
371476b7bf71SPeter Wemm 	{
371576b7bf71SPeter Wemm 		VendorCode = VENDOR_CODE;
371676b7bf71SPeter Wemm 		return TRUE;
371776b7bf71SPeter Wemm 	}
371876b7bf71SPeter Wemm #endif
371976b7bf71SPeter Wemm 
3720c2aa98e2SPeter Wemm 	return FALSE;
3721c2aa98e2SPeter Wemm }
3722c2aa98e2SPeter Wemm /*
372376b7bf71SPeter Wemm **  GETVENDOR -- return vendor name based on vendor code
372476b7bf71SPeter Wemm **
372576b7bf71SPeter Wemm **	Parameters:
372676b7bf71SPeter Wemm **		vendorcode -- numeric representation of vendor.
372776b7bf71SPeter Wemm **
372876b7bf71SPeter Wemm **	Returns:
372976b7bf71SPeter Wemm **		string containing vendor name.
373076b7bf71SPeter Wemm */
373176b7bf71SPeter Wemm 
373276b7bf71SPeter Wemm char *
373376b7bf71SPeter Wemm getvendor(vendorcode)
373476b7bf71SPeter Wemm 	int vendorcode;
373576b7bf71SPeter Wemm {
373676b7bf71SPeter Wemm #if defined(VENDOR_NAME) && defined(VENDOR_CODE)
373776b7bf71SPeter Wemm 	/*
373876b7bf71SPeter Wemm 	**  Can't have the same switch case twice so need to
373976b7bf71SPeter Wemm 	**  handle VENDOR_CODE outside of switch.  It might
374076b7bf71SPeter Wemm 	**  match one of the existing VENDOR_* codes.
374176b7bf71SPeter Wemm 	*/
374276b7bf71SPeter Wemm 
374376b7bf71SPeter Wemm 	if (vendorcode == VENDOR_CODE)
374476b7bf71SPeter Wemm 		return VENDOR_NAME;
374576b7bf71SPeter Wemm #endif
374676b7bf71SPeter Wemm 
374776b7bf71SPeter Wemm 	switch (vendorcode)
374876b7bf71SPeter Wemm 	{
374976b7bf71SPeter Wemm 		case VENDOR_BERKELEY:
375076b7bf71SPeter Wemm 			return "Berkeley";
375176b7bf71SPeter Wemm 
375276b7bf71SPeter Wemm 		case VENDOR_SUN:
375376b7bf71SPeter Wemm 			return "Sun";
375476b7bf71SPeter Wemm 
375576b7bf71SPeter Wemm 		case VENDOR_HP:
375676b7bf71SPeter Wemm 			return "HP";
375776b7bf71SPeter Wemm 
375876b7bf71SPeter Wemm 		case VENDOR_IBM:
375976b7bf71SPeter Wemm 			return "IBM";
376076b7bf71SPeter Wemm 
376176b7bf71SPeter Wemm 		case VENDOR_SENDMAIL:
376276b7bf71SPeter Wemm 			return "Sendmail";
376376b7bf71SPeter Wemm 
376476b7bf71SPeter Wemm 		default:
376576b7bf71SPeter Wemm 			return "Unknown";
376676b7bf71SPeter Wemm 	}
376776b7bf71SPeter Wemm }
376876b7bf71SPeter Wemm /*
3769c2aa98e2SPeter Wemm **  VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
3770c2aa98e2SPeter Wemm **
3771c2aa98e2SPeter Wemm **	Vendor_pre_defaults is called before reading the configuration
3772c2aa98e2SPeter Wemm **	file; vendor_post_defaults is called immediately after.
3773c2aa98e2SPeter Wemm **
3774c2aa98e2SPeter Wemm **	Parameters:
3775c2aa98e2SPeter Wemm **		e -- the global environment to initialize.
3776c2aa98e2SPeter Wemm **
3777c2aa98e2SPeter Wemm **	Returns:
3778c2aa98e2SPeter Wemm **		none.
3779c2aa98e2SPeter Wemm */
3780c2aa98e2SPeter Wemm 
3781c2aa98e2SPeter Wemm #if SHARE_V1
3782c2aa98e2SPeter Wemm int	DefShareUid;	/* default share uid to run as -- unused??? */
3783c2aa98e2SPeter Wemm #endif
3784c2aa98e2SPeter Wemm 
3785c2aa98e2SPeter Wemm void
3786c2aa98e2SPeter Wemm vendor_pre_defaults(e)
3787c2aa98e2SPeter Wemm 	ENVELOPE *e;
3788c2aa98e2SPeter Wemm {
3789c2aa98e2SPeter Wemm #if SHARE_V1
3790c2aa98e2SPeter Wemm 	/* OTHERUID is defined in shares.h, do not be alarmed */
3791c2aa98e2SPeter Wemm 	DefShareUid = OTHERUID;
3792c2aa98e2SPeter Wemm #endif
3793c2aa98e2SPeter Wemm #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
3794c2aa98e2SPeter Wemm 	sun_pre_defaults(e);
3795c2aa98e2SPeter Wemm #endif
3796c2aa98e2SPeter Wemm #ifdef apollo
3797c2aa98e2SPeter Wemm 	/* stupid domain/os can't even open /etc/sendmail.cf without this */
3798c2aa98e2SPeter Wemm 	setuserenv("ISP", NULL);
3799c2aa98e2SPeter Wemm 	setuserenv("SYSTYPE", NULL);
3800c2aa98e2SPeter Wemm #endif
3801c2aa98e2SPeter Wemm }
3802c2aa98e2SPeter Wemm 
3803c2aa98e2SPeter Wemm 
3804c2aa98e2SPeter Wemm void
3805c2aa98e2SPeter Wemm vendor_post_defaults(e)
3806c2aa98e2SPeter Wemm 	ENVELOPE *e;
3807c2aa98e2SPeter Wemm {
3808c2aa98e2SPeter Wemm #ifdef __QNX__
3809c2aa98e2SPeter Wemm 	char *p;
3810c2aa98e2SPeter Wemm 
3811c2aa98e2SPeter Wemm 	/* Makes sure the SOCK environment variable remains */
3812c2aa98e2SPeter Wemm 	if (p = getextenv("SOCK"))
3813c2aa98e2SPeter Wemm 		setuserenv("SOCK", p);
3814c2aa98e2SPeter Wemm #endif
3815c2aa98e2SPeter Wemm #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
3816c2aa98e2SPeter Wemm 	sun_post_defaults(e);
3817c2aa98e2SPeter Wemm #endif
3818c2aa98e2SPeter Wemm }
3819c2aa98e2SPeter Wemm /*
3820c2aa98e2SPeter Wemm **  VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
3821c2aa98e2SPeter Wemm */
3822c2aa98e2SPeter Wemm 
3823c2aa98e2SPeter Wemm void
3824c2aa98e2SPeter Wemm vendor_daemon_setup(e)
3825c2aa98e2SPeter Wemm 	ENVELOPE *e;
3826c2aa98e2SPeter Wemm {
3827c2aa98e2SPeter Wemm #if SECUREWARE
3828c2aa98e2SPeter Wemm 	if (getluid() != -1)
3829c2aa98e2SPeter Wemm 	{
3830c2aa98e2SPeter Wemm 		usrerr("Daemon cannot have LUID");
383176b7bf71SPeter Wemm 		finis(FALSE, EX_USAGE);
3832c2aa98e2SPeter Wemm 	}
3833c2aa98e2SPeter Wemm #endif /* SECUREWARE */
3834c2aa98e2SPeter Wemm }
3835c2aa98e2SPeter Wemm /*
3836c2aa98e2SPeter Wemm **  VENDOR_SET_UID -- do setup for setting a user id
3837c2aa98e2SPeter Wemm **
3838c2aa98e2SPeter Wemm **	This is called when we are still root.
3839c2aa98e2SPeter Wemm **
3840c2aa98e2SPeter Wemm **	Parameters:
3841c2aa98e2SPeter Wemm **		uid -- the uid we are about to become.
3842c2aa98e2SPeter Wemm **
3843c2aa98e2SPeter Wemm **	Returns:
3844c2aa98e2SPeter Wemm **		none.
3845c2aa98e2SPeter Wemm */
3846c2aa98e2SPeter Wemm 
3847c2aa98e2SPeter Wemm void
3848c2aa98e2SPeter Wemm vendor_set_uid(uid)
3849c2aa98e2SPeter Wemm 	UID_T uid;
3850c2aa98e2SPeter Wemm {
3851c2aa98e2SPeter Wemm 	/*
3852c2aa98e2SPeter Wemm 	**  We need to setup the share groups (lnodes)
3853c2aa98e2SPeter Wemm 	**  and and auditing inforation (luid's)
3854c2aa98e2SPeter Wemm 	**  before we loose our ``root''ness.
3855c2aa98e2SPeter Wemm 	*/
3856c2aa98e2SPeter Wemm #if SHARE_V1
3857c2aa98e2SPeter Wemm 	if (setupshares(uid, syserr) != 0)
3858c2aa98e2SPeter Wemm 		syserr("Unable to set up shares");
3859c2aa98e2SPeter Wemm #endif
3860c2aa98e2SPeter Wemm #if SECUREWARE
3861c2aa98e2SPeter Wemm 	(void) setup_secure(uid);
3862c2aa98e2SPeter Wemm #endif
3863c2aa98e2SPeter Wemm }
3864c2aa98e2SPeter Wemm /*
3865c2aa98e2SPeter Wemm **  VALIDATE_CONNECTION -- check connection for rationality
3866c2aa98e2SPeter Wemm **
3867c2aa98e2SPeter Wemm **	If the connection is rejected, this routine should log an
3868c2aa98e2SPeter Wemm **	appropriate message -- but should never issue any SMTP protocol.
3869c2aa98e2SPeter Wemm **
3870c2aa98e2SPeter Wemm **	Parameters:
3871c2aa98e2SPeter Wemm **		sap -- a pointer to a SOCKADDR naming the peer.
3872c2aa98e2SPeter Wemm **		hostname -- the name corresponding to sap.
3873c2aa98e2SPeter Wemm **		e -- the current envelope.
3874c2aa98e2SPeter Wemm **
3875c2aa98e2SPeter Wemm **	Returns:
3876c2aa98e2SPeter Wemm **		error message from rejection.
3877c2aa98e2SPeter Wemm **		NULL if not rejected.
3878c2aa98e2SPeter Wemm */
3879c2aa98e2SPeter Wemm 
3880c2aa98e2SPeter Wemm #if TCPWRAPPERS
3881c2aa98e2SPeter Wemm # include <tcpd.h>
3882c2aa98e2SPeter Wemm 
3883c2aa98e2SPeter Wemm /* tcpwrappers does no logging, but you still have to declare these -- ugh */
3884c2aa98e2SPeter Wemm int	allow_severity	= LOG_INFO;
3885c2aa98e2SPeter Wemm int	deny_severity	= LOG_NOTICE;
3886c2aa98e2SPeter Wemm #endif
3887c2aa98e2SPeter Wemm 
3888c2aa98e2SPeter Wemm #if DAEMON
3889c2aa98e2SPeter Wemm char *
3890c2aa98e2SPeter Wemm validate_connection(sap, hostname, e)
3891c2aa98e2SPeter Wemm 	SOCKADDR *sap;
3892c2aa98e2SPeter Wemm 	char *hostname;
3893c2aa98e2SPeter Wemm 	ENVELOPE *e;
3894c2aa98e2SPeter Wemm {
3895c2aa98e2SPeter Wemm #if TCPWRAPPERS
3896c2aa98e2SPeter Wemm 	char *host;
3897c2aa98e2SPeter Wemm #endif
3898c2aa98e2SPeter Wemm 
3899c2aa98e2SPeter Wemm 	if (tTd(48, 3))
3900c2aa98e2SPeter Wemm 		printf("validate_connection(%s, %s)\n",
3901c2aa98e2SPeter Wemm 			hostname, anynet_ntoa(sap));
3902c2aa98e2SPeter Wemm 
3903c2aa98e2SPeter Wemm 	if (rscheck("check_relay", hostname, anynet_ntoa(sap), e) != EX_OK)
3904c2aa98e2SPeter Wemm 	{
3905c2aa98e2SPeter Wemm 		static char reject[BUFSIZ*2];
3906c2aa98e2SPeter Wemm 		extern char MsgBuf[];
3907c2aa98e2SPeter Wemm 
3908c2aa98e2SPeter Wemm 		if (tTd(48, 4))
3909c2aa98e2SPeter Wemm 			printf("  ... validate_connection: BAD (rscheck)\n");
3910c2aa98e2SPeter Wemm 
3911c2aa98e2SPeter Wemm 		if (strlen(MsgBuf) > 5)
3912c2aa98e2SPeter Wemm 		{
3913c2aa98e2SPeter Wemm 			if (isascii(MsgBuf[0]) && isdigit(MsgBuf[0]) &&
3914c2aa98e2SPeter Wemm 			    isascii(MsgBuf[1]) && isdigit(MsgBuf[1]) &&
3915c2aa98e2SPeter Wemm 			    isascii(MsgBuf[2]) && isdigit(MsgBuf[2]))
3916c2aa98e2SPeter Wemm 				strcpy(reject, &MsgBuf[4]);
3917c2aa98e2SPeter Wemm 			else
3918c2aa98e2SPeter Wemm 				strcpy(reject, MsgBuf);
3919c2aa98e2SPeter Wemm 		}
3920c2aa98e2SPeter Wemm 		else
3921c2aa98e2SPeter Wemm 			strcpy(reject, "Access denied");
3922c2aa98e2SPeter Wemm 
3923c2aa98e2SPeter Wemm 		return reject;
3924c2aa98e2SPeter Wemm 	}
3925c2aa98e2SPeter Wemm 
3926c2aa98e2SPeter Wemm #if TCPWRAPPERS
3927c2aa98e2SPeter Wemm 	if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']')
3928c2aa98e2SPeter Wemm 		host = "unknown";
3929c2aa98e2SPeter Wemm 	else
3930c2aa98e2SPeter Wemm 		host = hostname;
3931c2aa98e2SPeter Wemm 	if (!hosts_ctl("sendmail", host, anynet_ntoa(sap), STRING_UNKNOWN))
3932c2aa98e2SPeter Wemm 	{
3933c2aa98e2SPeter Wemm 		if (tTd(48, 4))
3934c2aa98e2SPeter Wemm 			printf("  ... validate_connection: BAD (tcpwrappers)\n");
3935c2aa98e2SPeter Wemm 		if (LogLevel >= 4)
3936c2aa98e2SPeter Wemm 			sm_syslog(LOG_NOTICE, NOQID,
3937c2aa98e2SPeter Wemm 				"tcpwrappers (%s, %s) rejection",
3938c2aa98e2SPeter Wemm 				host, anynet_ntoa(sap));
3939c2aa98e2SPeter Wemm 		return "Access denied";
3940c2aa98e2SPeter Wemm 	}
3941c2aa98e2SPeter Wemm #endif
3942c2aa98e2SPeter Wemm 	if (tTd(48, 4))
3943c2aa98e2SPeter Wemm 		printf("  ... validate_connection: OK\n");
3944c2aa98e2SPeter Wemm 	return NULL;
3945c2aa98e2SPeter Wemm }
3946c2aa98e2SPeter Wemm 
3947c2aa98e2SPeter Wemm #endif
3948c2aa98e2SPeter Wemm /*
3949c2aa98e2SPeter Wemm **  STRTOL -- convert string to long integer
3950c2aa98e2SPeter Wemm **
3951c2aa98e2SPeter Wemm **	For systems that don't have it in the C library.
3952c2aa98e2SPeter Wemm **
3953c2aa98e2SPeter Wemm **	This is taken verbatim from the 4.4-Lite C library.
3954c2aa98e2SPeter Wemm */
3955c2aa98e2SPeter Wemm 
3956c2aa98e2SPeter Wemm #ifdef NEEDSTRTOL
3957c2aa98e2SPeter Wemm 
3958c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint)
3959c2aa98e2SPeter Wemm static char sccsid[] = "@(#)strtol.c	8.1 (Berkeley) 6/4/93";
3960c2aa98e2SPeter Wemm #endif /* LIBC_SCCS and not lint */
3961c2aa98e2SPeter Wemm 
3962c2aa98e2SPeter Wemm /*
3963c2aa98e2SPeter Wemm  * Convert a string to a long integer.
3964c2aa98e2SPeter Wemm  *
3965c2aa98e2SPeter Wemm  * Ignores `locale' stuff.  Assumes that the upper and lower case
3966c2aa98e2SPeter Wemm  * alphabets and digits are each contiguous.
3967c2aa98e2SPeter Wemm  */
3968c2aa98e2SPeter Wemm 
3969c2aa98e2SPeter Wemm long
3970c2aa98e2SPeter Wemm strtol(nptr, endptr, base)
3971c2aa98e2SPeter Wemm 	const char *nptr;
3972c2aa98e2SPeter Wemm 	char **endptr;
3973c2aa98e2SPeter Wemm 	register int base;
3974c2aa98e2SPeter Wemm {
3975c2aa98e2SPeter Wemm 	register const char *s = nptr;
3976c2aa98e2SPeter Wemm 	register unsigned long acc;
3977c2aa98e2SPeter Wemm 	register int c;
3978c2aa98e2SPeter Wemm 	register unsigned long cutoff;
3979c2aa98e2SPeter Wemm 	register int neg = 0, any, cutlim;
3980c2aa98e2SPeter Wemm 
3981c2aa98e2SPeter Wemm 	/*
3982c2aa98e2SPeter Wemm 	 * Skip white space and pick up leading +/- sign if any.
3983c2aa98e2SPeter Wemm 	 * If base is 0, allow 0x for hex and 0 for octal, else
3984c2aa98e2SPeter Wemm 	 * assume decimal; if base is already 16, allow 0x.
3985c2aa98e2SPeter Wemm 	 */
3986c2aa98e2SPeter Wemm 	do {
3987c2aa98e2SPeter Wemm 		c = *s++;
3988c2aa98e2SPeter Wemm 	} while (isspace(c));
3989c2aa98e2SPeter Wemm 	if (c == '-') {
3990c2aa98e2SPeter Wemm 		neg = 1;
3991c2aa98e2SPeter Wemm 		c = *s++;
3992c2aa98e2SPeter Wemm 	} else if (c == '+')
3993c2aa98e2SPeter Wemm 		c = *s++;
3994c2aa98e2SPeter Wemm 	if ((base == 0 || base == 16) &&
3995c2aa98e2SPeter Wemm 	    c == '0' && (*s == 'x' || *s == 'X')) {
3996c2aa98e2SPeter Wemm 		c = s[1];
3997c2aa98e2SPeter Wemm 		s += 2;
3998c2aa98e2SPeter Wemm 		base = 16;
3999c2aa98e2SPeter Wemm 	}
4000c2aa98e2SPeter Wemm 	if (base == 0)
4001c2aa98e2SPeter Wemm 		base = c == '0' ? 8 : 10;
4002c2aa98e2SPeter Wemm 
4003c2aa98e2SPeter Wemm 	/*
4004c2aa98e2SPeter Wemm 	 * Compute the cutoff value between legal numbers and illegal
4005c2aa98e2SPeter Wemm 	 * numbers.  That is the largest legal value, divided by the
4006c2aa98e2SPeter Wemm 	 * base.  An input number that is greater than this value, if
4007c2aa98e2SPeter Wemm 	 * followed by a legal input character, is too big.  One that
4008c2aa98e2SPeter Wemm 	 * is equal to this value may be valid or not; the limit
4009c2aa98e2SPeter Wemm 	 * between valid and invalid numbers is then based on the last
4010c2aa98e2SPeter Wemm 	 * digit.  For instance, if the range for longs is
4011c2aa98e2SPeter Wemm 	 * [-2147483648..2147483647] and the input base is 10,
4012c2aa98e2SPeter Wemm 	 * cutoff will be set to 214748364 and cutlim to either
4013c2aa98e2SPeter Wemm 	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
4014c2aa98e2SPeter Wemm 	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
4015c2aa98e2SPeter Wemm 	 * the number is too big, and we will return a range error.
4016c2aa98e2SPeter Wemm 	 *
4017c2aa98e2SPeter Wemm 	 * Set any if any `digits' consumed; make it negative to indicate
4018c2aa98e2SPeter Wemm 	 * overflow.
4019c2aa98e2SPeter Wemm 	 */
4020c2aa98e2SPeter Wemm 	cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
4021c2aa98e2SPeter Wemm 	cutlim = cutoff % (unsigned long)base;
4022c2aa98e2SPeter Wemm 	cutoff /= (unsigned long)base;
4023c2aa98e2SPeter Wemm 	for (acc = 0, any = 0;; c = *s++) {
4024c2aa98e2SPeter Wemm 		if (isdigit(c))
4025c2aa98e2SPeter Wemm 			c -= '0';
4026c2aa98e2SPeter Wemm 		else if (isalpha(c))
4027c2aa98e2SPeter Wemm 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
4028c2aa98e2SPeter Wemm 		else
4029c2aa98e2SPeter Wemm 			break;
4030c2aa98e2SPeter Wemm 		if (c >= base)
4031c2aa98e2SPeter Wemm 			break;
4032c2aa98e2SPeter Wemm 		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
4033c2aa98e2SPeter Wemm 			any = -1;
4034c2aa98e2SPeter Wemm 		else {
4035c2aa98e2SPeter Wemm 			any = 1;
4036c2aa98e2SPeter Wemm 			acc *= base;
4037c2aa98e2SPeter Wemm 			acc += c;
4038c2aa98e2SPeter Wemm 		}
4039c2aa98e2SPeter Wemm 	}
4040c2aa98e2SPeter Wemm 	if (any < 0) {
4041c2aa98e2SPeter Wemm 		acc = neg ? LONG_MIN : LONG_MAX;
4042c2aa98e2SPeter Wemm 		errno = ERANGE;
4043c2aa98e2SPeter Wemm 	} else if (neg)
4044c2aa98e2SPeter Wemm 		acc = -acc;
4045c2aa98e2SPeter Wemm 	if (endptr != 0)
4046c2aa98e2SPeter Wemm 		*endptr = (char *)(any ? s - 1 : nptr);
4047c2aa98e2SPeter Wemm 	return (acc);
4048c2aa98e2SPeter Wemm }
4049c2aa98e2SPeter Wemm 
4050c2aa98e2SPeter Wemm #endif
4051c2aa98e2SPeter Wemm /*
4052c2aa98e2SPeter Wemm **  STRSTR -- find first substring in string
4053c2aa98e2SPeter Wemm **
4054c2aa98e2SPeter Wemm **	Parameters:
4055c2aa98e2SPeter Wemm **		big -- the big (full) string.
4056c2aa98e2SPeter Wemm **		little -- the little (sub) string.
4057c2aa98e2SPeter Wemm **
4058c2aa98e2SPeter Wemm **	Returns:
4059c2aa98e2SPeter Wemm **		A pointer to the first instance of little in big.
4060c2aa98e2SPeter Wemm **		big if little is the null string.
4061c2aa98e2SPeter Wemm **		NULL if little is not contained in big.
4062c2aa98e2SPeter Wemm */
4063c2aa98e2SPeter Wemm 
4064c2aa98e2SPeter Wemm #ifdef NEEDSTRSTR
4065c2aa98e2SPeter Wemm 
4066c2aa98e2SPeter Wemm char *
4067c2aa98e2SPeter Wemm strstr(big, little)
4068c2aa98e2SPeter Wemm 	char *big;
4069c2aa98e2SPeter Wemm 	char *little;
4070c2aa98e2SPeter Wemm {
4071c2aa98e2SPeter Wemm 	register char *p = big;
4072c2aa98e2SPeter Wemm 	int l;
4073c2aa98e2SPeter Wemm 
4074c2aa98e2SPeter Wemm 	if (*little == '\0')
4075c2aa98e2SPeter Wemm 		return big;
4076c2aa98e2SPeter Wemm 	l = strlen(little);
4077c2aa98e2SPeter Wemm 
4078c2aa98e2SPeter Wemm 	while ((p = strchr(p, *little)) != NULL)
4079c2aa98e2SPeter Wemm 	{
4080c2aa98e2SPeter Wemm 		if (strncmp(p, little, l) == 0)
4081c2aa98e2SPeter Wemm 			return p;
4082c2aa98e2SPeter Wemm 		p++;
4083c2aa98e2SPeter Wemm 	}
4084c2aa98e2SPeter Wemm 	return NULL;
4085c2aa98e2SPeter Wemm }
4086c2aa98e2SPeter Wemm 
4087c2aa98e2SPeter Wemm #endif
4088c2aa98e2SPeter Wemm /*
4089c2aa98e2SPeter Wemm **  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
4090c2aa98e2SPeter Wemm **
4091c2aa98e2SPeter Wemm **	Some operating systems have wierd problems with the gethostbyXXX
4092c2aa98e2SPeter Wemm **	routines.  For example, Solaris versions at least through 2.3
4093c2aa98e2SPeter Wemm **	don't properly deliver a canonical h_name field.  This tries to
4094c2aa98e2SPeter Wemm **	work around these problems.
4095c2aa98e2SPeter Wemm */
4096c2aa98e2SPeter Wemm 
4097c2aa98e2SPeter Wemm struct hostent *
4098c2aa98e2SPeter Wemm sm_gethostbyname(name)
4099c2aa98e2SPeter Wemm 	char *name;
4100c2aa98e2SPeter Wemm {
4101c2aa98e2SPeter Wemm 	struct hostent *h;
4102c2aa98e2SPeter Wemm #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
4103c2aa98e2SPeter Wemm # if SOLARIS == 20300 || SOLARIS == 203
4104c2aa98e2SPeter Wemm 	static struct hostent hp;
4105c2aa98e2SPeter Wemm 	static char buf[1000];
4106c2aa98e2SPeter Wemm 	extern struct hostent *_switch_gethostbyname_r();
4107c2aa98e2SPeter Wemm 
4108c2aa98e2SPeter Wemm 	if (tTd(61, 10))
4109c2aa98e2SPeter Wemm 		printf("_switch_gethostbyname_r(%s)... ", name);
4110c2aa98e2SPeter Wemm 	h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
4111c2aa98e2SPeter Wemm # else
4112c2aa98e2SPeter Wemm 	extern struct hostent *__switch_gethostbyname();
4113c2aa98e2SPeter Wemm 
4114c2aa98e2SPeter Wemm 	if (tTd(61, 10))
4115c2aa98e2SPeter Wemm 		printf("__switch_gethostbyname(%s)... ", name);
4116c2aa98e2SPeter Wemm 	h = __switch_gethostbyname(name);
4117c2aa98e2SPeter Wemm # endif
4118c2aa98e2SPeter Wemm #else
4119c2aa98e2SPeter Wemm 	int nmaps;
4120c2aa98e2SPeter Wemm 	char *maptype[MAXMAPSTACK];
4121c2aa98e2SPeter Wemm 	short mapreturn[MAXMAPACTIONS];
4122c2aa98e2SPeter Wemm 	char hbuf[MAXNAME];
4123c2aa98e2SPeter Wemm 
4124c2aa98e2SPeter Wemm 	if (tTd(61, 10))
4125c2aa98e2SPeter Wemm 		printf("gethostbyname(%s)... ", name);
4126c2aa98e2SPeter Wemm 	h = gethostbyname(name);
4127c2aa98e2SPeter Wemm 	if (h == NULL)
4128c2aa98e2SPeter Wemm 	{
4129c2aa98e2SPeter Wemm 		if (tTd(61, 10))
4130c2aa98e2SPeter Wemm 			printf("failure\n");
4131c2aa98e2SPeter Wemm 
4132c2aa98e2SPeter Wemm 		nmaps = switch_map_find("hosts", maptype, mapreturn);
4133c2aa98e2SPeter Wemm 		while (--nmaps >= 0)
4134c2aa98e2SPeter Wemm 			if (strcmp(maptype[nmaps], "nis") == 0 ||
4135c2aa98e2SPeter Wemm 			    strcmp(maptype[nmaps], "files") == 0)
4136c2aa98e2SPeter Wemm 				break;
4137c2aa98e2SPeter Wemm 		if (nmaps >= 0)
4138c2aa98e2SPeter Wemm 		{
4139c2aa98e2SPeter Wemm 			/* try short name */
4140c2aa98e2SPeter Wemm 			if (strlen(name) > (SIZE_T) sizeof hbuf - 1)
4141c2aa98e2SPeter Wemm 				return NULL;
4142c2aa98e2SPeter Wemm 			strcpy(hbuf, name);
4143c2aa98e2SPeter Wemm 			shorten_hostname(hbuf);
4144c2aa98e2SPeter Wemm 
4145c2aa98e2SPeter Wemm 			/* if it hasn't been shortened, there's no point */
4146c2aa98e2SPeter Wemm 			if (strcmp(hbuf, name) != 0)
4147c2aa98e2SPeter Wemm 			{
4148c2aa98e2SPeter Wemm 				if (tTd(61, 10))
4149c2aa98e2SPeter Wemm 					printf("gethostbyname(%s)... ", hbuf);
4150c2aa98e2SPeter Wemm 				h = gethostbyname(hbuf);
4151c2aa98e2SPeter Wemm 			}
4152c2aa98e2SPeter Wemm 		}
4153c2aa98e2SPeter Wemm 	}
4154c2aa98e2SPeter Wemm #endif
4155c2aa98e2SPeter Wemm 	if (tTd(61, 10))
4156c2aa98e2SPeter Wemm 	{
4157c2aa98e2SPeter Wemm 		if (h == NULL)
4158c2aa98e2SPeter Wemm 			printf("failure\n");
4159c2aa98e2SPeter Wemm 		else
4160c2aa98e2SPeter Wemm 			printf("%s\n", h->h_name);
4161c2aa98e2SPeter Wemm 	}
4162c2aa98e2SPeter Wemm 	return h;
4163c2aa98e2SPeter Wemm }
4164c2aa98e2SPeter Wemm 
4165c2aa98e2SPeter Wemm struct hostent *
4166c2aa98e2SPeter Wemm sm_gethostbyaddr(addr, len, type)
4167c2aa98e2SPeter Wemm 	char *addr;
4168c2aa98e2SPeter Wemm 	int len;
4169c2aa98e2SPeter Wemm 	int type;
4170c2aa98e2SPeter Wemm {
4171c2aa98e2SPeter Wemm #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
4172c2aa98e2SPeter Wemm # if SOLARIS == 20300 || SOLARIS == 203
4173c2aa98e2SPeter Wemm 	static struct hostent hp;
4174c2aa98e2SPeter Wemm 	static char buf[1000];
4175c2aa98e2SPeter Wemm 	extern struct hostent *_switch_gethostbyaddr_r();
4176c2aa98e2SPeter Wemm 
4177c2aa98e2SPeter Wemm 	return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno);
4178c2aa98e2SPeter Wemm # else
4179c2aa98e2SPeter Wemm 	extern struct hostent *__switch_gethostbyaddr();
4180c2aa98e2SPeter Wemm 
4181c2aa98e2SPeter Wemm 	return __switch_gethostbyaddr(addr, len, type);
4182c2aa98e2SPeter Wemm # endif
4183c2aa98e2SPeter Wemm #else
4184c2aa98e2SPeter Wemm 	return gethostbyaddr(addr, len, type);
4185c2aa98e2SPeter Wemm #endif
4186c2aa98e2SPeter Wemm }
4187c2aa98e2SPeter Wemm /*
4188c2aa98e2SPeter Wemm **  SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
4189c2aa98e2SPeter Wemm */
4190c2aa98e2SPeter Wemm 
4191c2aa98e2SPeter Wemm struct passwd *
4192c2aa98e2SPeter Wemm sm_getpwnam(user)
4193c2aa98e2SPeter Wemm 	char *user;
4194c2aa98e2SPeter Wemm {
4195c2aa98e2SPeter Wemm #ifdef _AIX4
4196c2aa98e2SPeter Wemm 	extern struct passwd *_getpwnam_shadow(const char *, const int);
4197c2aa98e2SPeter Wemm 
4198c2aa98e2SPeter Wemm 	return _getpwnam_shadow(user, 0);
4199c2aa98e2SPeter Wemm #else
4200c2aa98e2SPeter Wemm 	return getpwnam(user);
4201c2aa98e2SPeter Wemm #endif
4202c2aa98e2SPeter Wemm }
4203c2aa98e2SPeter Wemm 
4204c2aa98e2SPeter Wemm struct passwd *
4205c2aa98e2SPeter Wemm sm_getpwuid(uid)
4206c2aa98e2SPeter Wemm 	UID_T uid;
4207c2aa98e2SPeter Wemm {
4208c2aa98e2SPeter Wemm #if defined(_AIX4) && 0
4209c2aa98e2SPeter Wemm 	extern struct passwd *_getpwuid_shadow(const int, const int);
4210c2aa98e2SPeter Wemm 
4211c2aa98e2SPeter Wemm 	return _getpwuid_shadow(uid,0);
4212c2aa98e2SPeter Wemm #else
4213c2aa98e2SPeter Wemm 	return getpwuid(uid);
4214c2aa98e2SPeter Wemm #endif
4215c2aa98e2SPeter Wemm }
4216c2aa98e2SPeter Wemm /*
4217c2aa98e2SPeter Wemm **  SECUREWARE_SETUP_SECURE -- Convex SecureWare setup
4218c2aa98e2SPeter Wemm **
4219c2aa98e2SPeter Wemm **	Set up the trusted computing environment for C2 level security
4220c2aa98e2SPeter Wemm **	under SecureWare.
4221c2aa98e2SPeter Wemm **
4222c2aa98e2SPeter Wemm **	Parameters:
4223c2aa98e2SPeter Wemm **		uid -- uid of the user to initialize in the TCB
4224c2aa98e2SPeter Wemm **
4225c2aa98e2SPeter Wemm **	Returns:
4226c2aa98e2SPeter Wemm **		none
4227c2aa98e2SPeter Wemm **
4228c2aa98e2SPeter Wemm **	Side Effects:
4229c2aa98e2SPeter Wemm **		Initialized the user in the trusted computing base
4230c2aa98e2SPeter Wemm */
4231c2aa98e2SPeter Wemm 
4232c2aa98e2SPeter Wemm #if SECUREWARE
4233c2aa98e2SPeter Wemm 
4234c2aa98e2SPeter Wemm # include <sys/security.h>
4235c2aa98e2SPeter Wemm # include <prot.h>
4236c2aa98e2SPeter Wemm 
4237c2aa98e2SPeter Wemm void
4238c2aa98e2SPeter Wemm secureware_setup_secure(uid)
4239c2aa98e2SPeter Wemm 	UID_T uid;
4240c2aa98e2SPeter Wemm {
4241c2aa98e2SPeter Wemm 	int rc;
4242c2aa98e2SPeter Wemm 
4243c2aa98e2SPeter Wemm 	if (getluid() != -1)
4244c2aa98e2SPeter Wemm 		return;
4245c2aa98e2SPeter Wemm 
4246c2aa98e2SPeter Wemm 	if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN)
4247c2aa98e2SPeter Wemm 	{
4248c2aa98e2SPeter Wemm 		switch (rc)
4249c2aa98e2SPeter Wemm 		{
4250c2aa98e2SPeter Wemm 		  case SSI_NO_PRPW_ENTRY:
4251c2aa98e2SPeter Wemm 			syserr("No protected passwd entry, uid = %d", uid);
4252c2aa98e2SPeter Wemm 			break;
4253c2aa98e2SPeter Wemm 
4254c2aa98e2SPeter Wemm 		  case SSI_LOCKED:
4255c2aa98e2SPeter Wemm 			syserr("Account has been disabled, uid = %d", uid);
4256c2aa98e2SPeter Wemm 			break;
4257c2aa98e2SPeter Wemm 
4258c2aa98e2SPeter Wemm 		  case SSI_RETIRED:
4259c2aa98e2SPeter Wemm 			syserr("Account has been retired, uid = %d", uid);
4260c2aa98e2SPeter Wemm 			break;
4261c2aa98e2SPeter Wemm 
4262c2aa98e2SPeter Wemm 		  case SSI_BAD_SET_LUID:
4263c2aa98e2SPeter Wemm 			syserr("Could not set LUID, uid = %d", uid);
4264c2aa98e2SPeter Wemm 			break;
4265c2aa98e2SPeter Wemm 
4266c2aa98e2SPeter Wemm 		  case SSI_BAD_SET_PRIVS:
4267c2aa98e2SPeter Wemm 			syserr("Could not set kernel privs, uid = %d", uid);
4268c2aa98e2SPeter Wemm 
4269c2aa98e2SPeter Wemm 		  default:
4270c2aa98e2SPeter Wemm 			syserr("Unknown return code (%d) from set_secure_info(%d)",
4271c2aa98e2SPeter Wemm 				rc, uid);
4272c2aa98e2SPeter Wemm 			break;
4273c2aa98e2SPeter Wemm 		}
427476b7bf71SPeter Wemm 		finis(FALSE, EX_NOPERM);
4275c2aa98e2SPeter Wemm 	}
4276c2aa98e2SPeter Wemm }
4277c2aa98e2SPeter Wemm #endif /* SECUREWARE */
4278c2aa98e2SPeter Wemm /*
427976b7bf71SPeter Wemm **  ADD_LOCAL_HOST_NAMES -- Add a hostname to class 'w' based on IP address
428076b7bf71SPeter Wemm **
428176b7bf71SPeter Wemm **	Add hostnames to class 'w' based on the IP address read from
428276b7bf71SPeter Wemm **	the network interface.
428376b7bf71SPeter Wemm **
428476b7bf71SPeter Wemm **	Parameters:
428576b7bf71SPeter Wemm **		sa -- a pointer to a SOCKADDR containing the address
428676b7bf71SPeter Wemm **
428776b7bf71SPeter Wemm **	Returns:
428876b7bf71SPeter Wemm **		0 if successful, -1 if host lookup fails.
428976b7bf71SPeter Wemm */
429076b7bf71SPeter Wemm 
429176b7bf71SPeter Wemm int
429276b7bf71SPeter Wemm add_hostnames(sa)
429376b7bf71SPeter Wemm 	SOCKADDR *sa;
429476b7bf71SPeter Wemm {
429576b7bf71SPeter Wemm 	struct hostent *hp;
429676b7bf71SPeter Wemm 
429776b7bf71SPeter Wemm 	/* lookup name with IP address */
429876b7bf71SPeter Wemm 	switch (sa->sa.sa_family)
429976b7bf71SPeter Wemm 	{
430076b7bf71SPeter Wemm 		case AF_INET:
430176b7bf71SPeter Wemm 			hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr,
430276b7bf71SPeter Wemm 				sizeof(sa->sin.sin_addr), sa->sa.sa_family);
430376b7bf71SPeter Wemm 			break;
430476b7bf71SPeter Wemm 
430576b7bf71SPeter Wemm 		default:
430676b7bf71SPeter Wemm #if _FFR_LOG_UNSUPPORTED_FAMILIES
430776b7bf71SPeter Wemm 			/* XXX: Give warning about unsupported family */
430876b7bf71SPeter Wemm 			if (LogLevel > 3)
430976b7bf71SPeter Wemm 				sm_syslog(LOG_WARNING, NOQID,
431076b7bf71SPeter Wemm 					  "Unsupported address family %d: %.100s",
431176b7bf71SPeter Wemm 					  sa->sa.sa_family, anynet_ntoa(sa));
431276b7bf71SPeter Wemm #endif
431376b7bf71SPeter Wemm 			return -1;
431476b7bf71SPeter Wemm 	}
431576b7bf71SPeter Wemm 
431676b7bf71SPeter Wemm 	if (hp == NULL)
431776b7bf71SPeter Wemm 	{
431876b7bf71SPeter Wemm 		int save_errno = errno;
431976b7bf71SPeter Wemm 
432076b7bf71SPeter Wemm 		if (LogLevel > 3)
432176b7bf71SPeter Wemm 			sm_syslog(LOG_WARNING, NOQID,
432276b7bf71SPeter Wemm 				"gethostbyaddr(%.100s) failed: %d\n",
432376b7bf71SPeter Wemm 				anynet_ntoa(sa),
432476b7bf71SPeter Wemm #if NAMED_BIND
432576b7bf71SPeter Wemm 				h_errno
432676b7bf71SPeter Wemm #else
432776b7bf71SPeter Wemm 				-1
432876b7bf71SPeter Wemm #endif
432976b7bf71SPeter Wemm 				);
433076b7bf71SPeter Wemm 		errno = save_errno;
433176b7bf71SPeter Wemm 		return -1;
433276b7bf71SPeter Wemm 	}
433376b7bf71SPeter Wemm 
433476b7bf71SPeter Wemm 	/* save its cname */
433576b7bf71SPeter Wemm 	if (!wordinclass((char *) hp->h_name, 'w'))
433676b7bf71SPeter Wemm 	{
433776b7bf71SPeter Wemm 		setclass('w', (char *) hp->h_name);
433876b7bf71SPeter Wemm 		if (tTd(0, 4))
433976b7bf71SPeter Wemm 			printf("\ta.k.a.: %s\n", hp->h_name);
434076b7bf71SPeter Wemm 	}
434176b7bf71SPeter Wemm 
434276b7bf71SPeter Wemm 	/* save all it aliases name */
434376b7bf71SPeter Wemm 	while (*hp->h_aliases)
434476b7bf71SPeter Wemm 	{
434576b7bf71SPeter Wemm 		if (!wordinclass(*hp->h_aliases, 'w'))
434676b7bf71SPeter Wemm 		{
434776b7bf71SPeter Wemm 			setclass('w', *hp->h_aliases);
434876b7bf71SPeter Wemm 			if (tTd(0, 4))
434976b7bf71SPeter Wemm 				printf("\ta.k.a.: %s\n", *hp->h_aliases);
435076b7bf71SPeter Wemm 		}
435176b7bf71SPeter Wemm 		hp->h_aliases++;
435276b7bf71SPeter Wemm 	}
435376b7bf71SPeter Wemm 	return 0;
435476b7bf71SPeter Wemm }
435576b7bf71SPeter Wemm /*
4356c2aa98e2SPeter Wemm **  LOAD_IF_NAMES -- load interface-specific names into $=w
4357c2aa98e2SPeter Wemm **
4358c2aa98e2SPeter Wemm **	Parameters:
4359c2aa98e2SPeter Wemm **		none.
4360c2aa98e2SPeter Wemm **
4361c2aa98e2SPeter Wemm **	Returns:
4362c2aa98e2SPeter Wemm **		none.
4363c2aa98e2SPeter Wemm **
4364c2aa98e2SPeter Wemm **	Side Effects:
4365c2aa98e2SPeter Wemm **		Loads $=w with the names of all the interfaces.
4366c2aa98e2SPeter Wemm */
4367c2aa98e2SPeter Wemm 
4368c2aa98e2SPeter Wemm #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
4369c2aa98e2SPeter Wemm struct rtentry;
4370c2aa98e2SPeter Wemm struct mbuf;
4371c2aa98e2SPeter Wemm # include <arpa/inet.h>
4372c2aa98e2SPeter Wemm # ifndef SUNOS403
4373c2aa98e2SPeter Wemm #  include <sys/time.h>
4374c2aa98e2SPeter Wemm # endif
4375c2aa98e2SPeter Wemm # if _AIX4 >= 40300
4376c2aa98e2SPeter Wemm #  undef __P
4377c2aa98e2SPeter Wemm # endif
4378c2aa98e2SPeter Wemm # include <net/if.h>
4379c2aa98e2SPeter Wemm #endif
4380c2aa98e2SPeter Wemm 
4381c2aa98e2SPeter Wemm void
4382c2aa98e2SPeter Wemm load_if_names()
4383c2aa98e2SPeter Wemm {
4384c2aa98e2SPeter Wemm #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
4385c2aa98e2SPeter Wemm 	int s;
4386c2aa98e2SPeter Wemm 	int i;
4387c2aa98e2SPeter Wemm 	struct ifconf ifc;
4388c2aa98e2SPeter Wemm 	int numifs;
4389c2aa98e2SPeter Wemm 
4390c2aa98e2SPeter Wemm 	s = socket(AF_INET, SOCK_DGRAM, 0);
4391c2aa98e2SPeter Wemm 	if (s == -1)
4392c2aa98e2SPeter Wemm 		return;
4393c2aa98e2SPeter Wemm 
4394c2aa98e2SPeter Wemm 	/* get the list of known IP address from the kernel */
4395c2aa98e2SPeter Wemm # if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN
4396c2aa98e2SPeter Wemm 	if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
4397c2aa98e2SPeter Wemm 	{
4398c2aa98e2SPeter Wemm 		/* can't get number of interfaces -- fall back */
4399c2aa98e2SPeter Wemm 		if (tTd(0, 4))
4400c2aa98e2SPeter Wemm 			printf("SIOCGIFNUM failed: %s\n", errstring(errno));
4401c2aa98e2SPeter Wemm 		numifs = -1;
4402c2aa98e2SPeter Wemm 	}
4403c2aa98e2SPeter Wemm 	else if (tTd(0, 42))
4404c2aa98e2SPeter Wemm 		printf("system has %d interfaces\n", numifs);
4405c2aa98e2SPeter Wemm 	if (numifs < 0)
4406c2aa98e2SPeter Wemm # endif
4407c2aa98e2SPeter Wemm 		numifs = 512;
4408c2aa98e2SPeter Wemm 
4409c2aa98e2SPeter Wemm 	if (numifs <= 0)
4410c2aa98e2SPeter Wemm 	{
4411c2aa98e2SPeter Wemm 		close(s);
4412c2aa98e2SPeter Wemm 		return;
4413c2aa98e2SPeter Wemm 	}
4414c2aa98e2SPeter Wemm 	ifc.ifc_len = numifs * sizeof (struct ifreq);
4415c2aa98e2SPeter Wemm 	ifc.ifc_buf = xalloc(ifc.ifc_len);
4416c2aa98e2SPeter Wemm 	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
4417c2aa98e2SPeter Wemm 	{
4418c2aa98e2SPeter Wemm 		if (tTd(0, 4))
4419c2aa98e2SPeter Wemm 			printf("SIOGIFCONF failed: %s\n", errstring(errno));
4420c2aa98e2SPeter Wemm 		close(s);
4421c2aa98e2SPeter Wemm 		return;
4422c2aa98e2SPeter Wemm 	}
4423c2aa98e2SPeter Wemm 
4424c2aa98e2SPeter Wemm 	/* scan the list of IP address */
4425c2aa98e2SPeter Wemm 	if (tTd(0, 40))
4426c2aa98e2SPeter Wemm 		printf("scanning for interface specific names, ifc_len=%d\n",
4427c2aa98e2SPeter Wemm 			ifc.ifc_len);
4428c2aa98e2SPeter Wemm 
4429c2aa98e2SPeter Wemm 	for (i = 0; i < ifc.ifc_len; )
4430c2aa98e2SPeter Wemm 	{
4431c2aa98e2SPeter Wemm 		struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
443276b7bf71SPeter Wemm 		SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr;
4433c2aa98e2SPeter Wemm 		struct in_addr ia;
4434c2aa98e2SPeter Wemm #ifdef SIOCGIFFLAGS
4435c2aa98e2SPeter Wemm 		struct ifreq ifrf;
4436c2aa98e2SPeter Wemm #endif
4437c2aa98e2SPeter Wemm 		char ip_addr[256];
4438c2aa98e2SPeter Wemm 		extern char *inet_ntoa();
4439c2aa98e2SPeter Wemm 
4440c2aa98e2SPeter Wemm #ifdef BSD4_4_SOCKADDR
444176b7bf71SPeter Wemm 		if (sa->sa.sa_len > sizeof ifr->ifr_addr)
444276b7bf71SPeter Wemm 			i += sizeof ifr->ifr_name + sa->sa.sa_len;
4443c2aa98e2SPeter Wemm 		else
4444c2aa98e2SPeter Wemm #endif
4445c2aa98e2SPeter Wemm 			i += sizeof *ifr;
4446c2aa98e2SPeter Wemm 
4447c2aa98e2SPeter Wemm 		if (tTd(0, 20))
444876b7bf71SPeter Wemm 			printf("%s\n", anynet_ntoa(sa));
4449c2aa98e2SPeter Wemm 
4450c2aa98e2SPeter Wemm 		if (ifr->ifr_addr.sa_family != AF_INET)
4451c2aa98e2SPeter Wemm 			continue;
4452c2aa98e2SPeter Wemm 
4453c2aa98e2SPeter Wemm #ifdef SIOCGIFFLAGS
4454c2aa98e2SPeter Wemm 		bzero(&ifrf, sizeof(struct ifreq));
4455c2aa98e2SPeter Wemm 		strncpy(ifrf.ifr_name, ifr->ifr_name, sizeof(ifrf.ifr_name));
4456c2aa98e2SPeter Wemm 		ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
4457c2aa98e2SPeter Wemm 		if (tTd(0, 41))
4458c2aa98e2SPeter Wemm 			printf("\tflags: %x\n", ifrf.ifr_flags);
4459c2aa98e2SPeter Wemm # define IFRFREF ifrf
4460c2aa98e2SPeter Wemm #else
4461c2aa98e2SPeter Wemm # define IFRFREF (*ifr)
4462c2aa98e2SPeter Wemm #endif
4463c2aa98e2SPeter Wemm 		if (!bitset(IFF_UP, IFRFREF.ifr_flags))
4464c2aa98e2SPeter Wemm 			continue;
4465c2aa98e2SPeter Wemm 
4466c2aa98e2SPeter Wemm 		/* extract IP address from the list*/
446776b7bf71SPeter Wemm 		ia = sa->sin.sin_addr;
4468c2aa98e2SPeter Wemm 		if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE)
4469c2aa98e2SPeter Wemm 		{
4470c2aa98e2SPeter Wemm 			message("WARNING: interface %s is UP with %s address",
4471c2aa98e2SPeter Wemm 				ifr->ifr_name, inet_ntoa(ia));
4472c2aa98e2SPeter Wemm 			continue;
4473c2aa98e2SPeter Wemm 		}
4474c2aa98e2SPeter Wemm 
4475c2aa98e2SPeter Wemm 		/* save IP address in text from */
4476c2aa98e2SPeter Wemm 		(void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]",
44771ec86adfSBruce Evans 			(int)sizeof ip_addr - 3,
4478c2aa98e2SPeter Wemm 			inet_ntoa(ia));
4479c2aa98e2SPeter Wemm 		if (!wordinclass(ip_addr, 'w'))
4480c2aa98e2SPeter Wemm 		{
4481c2aa98e2SPeter Wemm 			setclass('w', ip_addr);
4482c2aa98e2SPeter Wemm 			if (tTd(0, 4))
4483c2aa98e2SPeter Wemm 				printf("\ta.k.a.: %s\n", ip_addr);
4484c2aa98e2SPeter Wemm 		}
4485c2aa98e2SPeter Wemm 
4486c2aa98e2SPeter Wemm 		/* skip "loopback" interface "lo" */
4487c2aa98e2SPeter Wemm 		if (bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
4488c2aa98e2SPeter Wemm 			continue;
4489c2aa98e2SPeter Wemm 
449076b7bf71SPeter Wemm 		(void) add_hostnames(sa);
4491c2aa98e2SPeter Wemm 	}
4492c2aa98e2SPeter Wemm 	free(ifc.ifc_buf);
4493c2aa98e2SPeter Wemm 	close(s);
4494c2aa98e2SPeter Wemm # undef IFRFREF
4495c2aa98e2SPeter Wemm #endif
4496c2aa98e2SPeter Wemm }
4497c2aa98e2SPeter Wemm /*
4498c2aa98e2SPeter Wemm **  GET_NUM_PROCS_ONLINE -- return the number of processors currently online
4499c2aa98e2SPeter Wemm **
4500c2aa98e2SPeter Wemm **	Parameters:
4501c2aa98e2SPeter Wemm **		none.
4502c2aa98e2SPeter Wemm **
4503c2aa98e2SPeter Wemm **	Returns:
4504c2aa98e2SPeter Wemm **		The number of processors online.
4505c2aa98e2SPeter Wemm */
4506c2aa98e2SPeter Wemm 
4507c2aa98e2SPeter Wemm int
4508c2aa98e2SPeter Wemm get_num_procs_online()
4509c2aa98e2SPeter Wemm {
4510c2aa98e2SPeter Wemm 	int nproc = 0;
4511c2aa98e2SPeter Wemm 
4512c2aa98e2SPeter Wemm #if _FFR_SCALE_LA_BY_NUM_PROCS
4513c2aa98e2SPeter Wemm #ifdef _SC_NPROCESSORS_ONLN
4514c2aa98e2SPeter Wemm 	nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
4515c2aa98e2SPeter Wemm #endif
4516c2aa98e2SPeter Wemm #endif
4517c2aa98e2SPeter Wemm 	if (nproc <= 0)
4518c2aa98e2SPeter Wemm 		nproc = 1;
4519c2aa98e2SPeter Wemm 	return nproc;
4520c2aa98e2SPeter Wemm }
4521c2aa98e2SPeter Wemm /*
4522c2aa98e2SPeter Wemm **  SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
4523c2aa98e2SPeter Wemm **
4524c2aa98e2SPeter Wemm **	Parameters:
4525c2aa98e2SPeter Wemm **		level -- syslog level
4526c2aa98e2SPeter Wemm **		id -- envelope ID or NULL (NOQUEUE)
4527c2aa98e2SPeter Wemm **		fmt -- format string
4528c2aa98e2SPeter Wemm **		arg... -- arguments as implied by fmt.
4529c2aa98e2SPeter Wemm **
4530c2aa98e2SPeter Wemm **	Returns:
4531c2aa98e2SPeter Wemm **		none
4532c2aa98e2SPeter Wemm */
4533c2aa98e2SPeter Wemm 
4534c2aa98e2SPeter Wemm /* VARARGS3 */
4535c2aa98e2SPeter Wemm void
4536c2aa98e2SPeter Wemm # ifdef __STDC__
4537c2aa98e2SPeter Wemm sm_syslog(int level, const char *id, const char *fmt, ...)
4538c2aa98e2SPeter Wemm # else
4539c2aa98e2SPeter Wemm sm_syslog(level, id, fmt, va_alist)
4540c2aa98e2SPeter Wemm 	int level;
4541c2aa98e2SPeter Wemm 	const char *id;
4542c2aa98e2SPeter Wemm 	const char *fmt;
4543c2aa98e2SPeter Wemm 	va_dcl
4544c2aa98e2SPeter Wemm #endif
4545c2aa98e2SPeter Wemm {
4546c2aa98e2SPeter Wemm 	static char *buf = NULL;
4547c2aa98e2SPeter Wemm 	static size_t bufsize = MAXLINE;
4548c2aa98e2SPeter Wemm 	char *begin, *end;
4549c2aa98e2SPeter Wemm 	int seq = 1;
4550c2aa98e2SPeter Wemm 	int idlen;
4551c2aa98e2SPeter Wemm 	extern int SnprfOverflow;
4552c2aa98e2SPeter Wemm 	extern int SyslogErrno;
4553c2aa98e2SPeter Wemm 	extern char *DoprEnd;
4554c2aa98e2SPeter Wemm 	VA_LOCAL_DECL
455576b7bf71SPeter Wemm 	extern void sm_dopr __P((char *, const char *, va_list));
4556c2aa98e2SPeter Wemm 
4557c2aa98e2SPeter Wemm 	SyslogErrno = errno;
4558c2aa98e2SPeter Wemm 	if (id == NULL)
4559c2aa98e2SPeter Wemm 	{
4560c2aa98e2SPeter Wemm 		id = "NOQUEUE";
4561c2aa98e2SPeter Wemm 		idlen = 9;
4562c2aa98e2SPeter Wemm 	}
4563c2aa98e2SPeter Wemm 	else if (strcmp(id, NOQID) == 0)
4564c2aa98e2SPeter Wemm 	{
4565c2aa98e2SPeter Wemm 		id = "";
4566c2aa98e2SPeter Wemm 		idlen = 0;
4567c2aa98e2SPeter Wemm 	}
4568c2aa98e2SPeter Wemm 	else
4569c2aa98e2SPeter Wemm 		idlen = strlen(id + 2);
4570c2aa98e2SPeter Wemm bufalloc:
4571c2aa98e2SPeter Wemm 	if (buf == NULL)
4572c2aa98e2SPeter Wemm 		buf = (char *) xalloc(sizeof(char) * bufsize);
4573c2aa98e2SPeter Wemm 
4574c2aa98e2SPeter Wemm 	/* do a virtual vsnprintf into buf */
4575c2aa98e2SPeter Wemm 	VA_START(fmt);
4576c2aa98e2SPeter Wemm 	buf[0] = 0;
4577c2aa98e2SPeter Wemm 	DoprEnd = buf + bufsize - 1;
4578c2aa98e2SPeter Wemm 	SnprfOverflow = 0;
4579c2aa98e2SPeter Wemm 	sm_dopr(buf, fmt, ap);
4580c2aa98e2SPeter Wemm 	*DoprEnd = '\0';
4581c2aa98e2SPeter Wemm 	VA_END;
4582c2aa98e2SPeter Wemm 	/* end of virtual vsnprintf */
4583c2aa98e2SPeter Wemm 
4584c2aa98e2SPeter Wemm 	if (SnprfOverflow)
4585c2aa98e2SPeter Wemm 	{
4586c2aa98e2SPeter Wemm 		/* String too small, redo with correct size */
4587c2aa98e2SPeter Wemm 		bufsize += SnprfOverflow + 1;
4588c2aa98e2SPeter Wemm 		free(buf);
4589c2aa98e2SPeter Wemm 		buf = NULL;
4590c2aa98e2SPeter Wemm 		goto bufalloc;
4591c2aa98e2SPeter Wemm 	}
4592c2aa98e2SPeter Wemm 	if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE)
4593c2aa98e2SPeter Wemm 	{
4594c2aa98e2SPeter Wemm #if LOG
4595c2aa98e2SPeter Wemm 		if (*id == '\0')
4596c2aa98e2SPeter Wemm 			syslog(level, "%s", buf);
4597c2aa98e2SPeter Wemm 		else
4598c2aa98e2SPeter Wemm 			syslog(level, "%s: %s", id, buf);
4599c2aa98e2SPeter Wemm #else
4600c2aa98e2SPeter Wemm 		/*XXX should do something more sensible */
4601c2aa98e2SPeter Wemm 		if (*id == '\0')
4602c2aa98e2SPeter Wemm 			fprintf(stderr, "%s\n", buf);
4603c2aa98e2SPeter Wemm 		else
4604c2aa98e2SPeter Wemm 			fprintf(stderr, "%s: %s\n", id, buf);
4605c2aa98e2SPeter Wemm #endif
4606c2aa98e2SPeter Wemm 		return;
4607c2aa98e2SPeter Wemm 	}
4608c2aa98e2SPeter Wemm 
4609c2aa98e2SPeter Wemm 	begin = buf;
4610c2aa98e2SPeter Wemm 	while (*begin != '\0' &&
4611c2aa98e2SPeter Wemm 	       (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE)
4612c2aa98e2SPeter Wemm 	{
4613c2aa98e2SPeter Wemm 		char save;
4614c2aa98e2SPeter Wemm 
4615c2aa98e2SPeter Wemm 		if (seq == 999)
4616c2aa98e2SPeter Wemm 		{
4617c2aa98e2SPeter Wemm 			/* Too many messages */
4618c2aa98e2SPeter Wemm 			break;
4619c2aa98e2SPeter Wemm 		}
4620c2aa98e2SPeter Wemm 		end = begin + SYSLOG_BUFSIZE - idlen - 12;
4621c2aa98e2SPeter Wemm 		while (end > begin)
4622c2aa98e2SPeter Wemm 		{
4623c2aa98e2SPeter Wemm 			/* Break on comma or space */
4624c2aa98e2SPeter Wemm 			if (*end == ',' || *end == ' ')
4625c2aa98e2SPeter Wemm 			{
4626c2aa98e2SPeter Wemm 				end++;	  /* Include separator */
4627c2aa98e2SPeter Wemm 				break;
4628c2aa98e2SPeter Wemm 			}
4629c2aa98e2SPeter Wemm 			end--;
4630c2aa98e2SPeter Wemm 		}
4631c2aa98e2SPeter Wemm 		/* No separator, break midstring... */
4632c2aa98e2SPeter Wemm 		if (end == begin)
4633c2aa98e2SPeter Wemm 			end = begin + SYSLOG_BUFSIZE - idlen - 12;
4634c2aa98e2SPeter Wemm 		save = *end;
4635c2aa98e2SPeter Wemm 		*end = 0;
4636c2aa98e2SPeter Wemm #if LOG
4637c2aa98e2SPeter Wemm 		syslog(level, "%s[%d]: %s ...", id, seq++, begin);
4638c2aa98e2SPeter Wemm #else
4639c2aa98e2SPeter Wemm 		fprintf(stderr, "%s[%d]: %s ...\n", id, seq++, begin);
4640c2aa98e2SPeter Wemm #endif
4641c2aa98e2SPeter Wemm 		*end = save;
4642c2aa98e2SPeter Wemm 		begin = end;
4643c2aa98e2SPeter Wemm 	}
4644c2aa98e2SPeter Wemm 	if (seq == 999)
4645c2aa98e2SPeter Wemm #if LOG
4646c2aa98e2SPeter Wemm 		syslog(level, "%s[%d]: log terminated, too many parts", id, seq);
4647c2aa98e2SPeter Wemm #else
4648c2aa98e2SPeter Wemm 		fprintf(stderr, "%s[%d]: log terminated, too many parts\n", id, seq);
4649c2aa98e2SPeter Wemm #endif
4650c2aa98e2SPeter Wemm 	else if (*begin != '\0')
4651c2aa98e2SPeter Wemm #if LOG
4652c2aa98e2SPeter Wemm 		syslog(level, "%s[%d]: %s", id, seq, begin);
4653c2aa98e2SPeter Wemm #else
4654c2aa98e2SPeter Wemm 		fprintf(stderr, "%s[%d]: %s\n", id, seq, begin);
4655c2aa98e2SPeter Wemm #endif
4656c2aa98e2SPeter Wemm }
4657c2aa98e2SPeter Wemm /*
4658c2aa98e2SPeter Wemm **  HARD_SYSLOG -- call syslog repeatedly until it works
4659c2aa98e2SPeter Wemm **
4660c2aa98e2SPeter Wemm **	Needed on HP-UX, which apparently doesn't guarantee that
4661c2aa98e2SPeter Wemm **	syslog succeeds during interrupt handlers.
4662c2aa98e2SPeter Wemm */
4663c2aa98e2SPeter Wemm 
4664c2aa98e2SPeter Wemm #if defined(__hpux) && !defined(HPUX11)
4665c2aa98e2SPeter Wemm 
4666c2aa98e2SPeter Wemm # define MAXSYSLOGTRIES	100
4667c2aa98e2SPeter Wemm # undef syslog
4668c2aa98e2SPeter Wemm # ifdef V4FS
4669c2aa98e2SPeter Wemm #  define XCNST	const
4670c2aa98e2SPeter Wemm #  define CAST	(const char *)
4671c2aa98e2SPeter Wemm # else
4672c2aa98e2SPeter Wemm #  define XCNST
4673c2aa98e2SPeter Wemm #  define CAST
4674c2aa98e2SPeter Wemm # endif
4675c2aa98e2SPeter Wemm 
4676c2aa98e2SPeter Wemm void
4677c2aa98e2SPeter Wemm # ifdef __STDC__
4678c2aa98e2SPeter Wemm hard_syslog(int pri, XCNST char *msg, ...)
4679c2aa98e2SPeter Wemm # else
4680c2aa98e2SPeter Wemm hard_syslog(pri, msg, va_alist)
4681c2aa98e2SPeter Wemm 	int pri;
4682c2aa98e2SPeter Wemm 	XCNST char *msg;
4683c2aa98e2SPeter Wemm 	va_dcl
4684c2aa98e2SPeter Wemm # endif
4685c2aa98e2SPeter Wemm {
4686c2aa98e2SPeter Wemm 	int i;
4687c2aa98e2SPeter Wemm 	char buf[SYSLOG_BUFSIZE];
4688c2aa98e2SPeter Wemm 	VA_LOCAL_DECL;
4689c2aa98e2SPeter Wemm 
4690c2aa98e2SPeter Wemm 	VA_START(msg);
4691c2aa98e2SPeter Wemm 	vsnprintf(buf, sizeof buf, msg, ap);
4692c2aa98e2SPeter Wemm 	VA_END;
4693c2aa98e2SPeter Wemm 
4694c2aa98e2SPeter Wemm 	for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
4695c2aa98e2SPeter Wemm 		continue;
4696c2aa98e2SPeter Wemm }
4697c2aa98e2SPeter Wemm 
4698c2aa98e2SPeter Wemm # undef CAST
4699c2aa98e2SPeter Wemm #endif
4700c2aa98e2SPeter Wemm /*
4701c2aa98e2SPeter Wemm **  LOCAL_HOSTNAME_LENGTH
4702c2aa98e2SPeter Wemm **
4703c2aa98e2SPeter Wemm **	This is required to get sendmail to compile against BIND 4.9.x
4704c2aa98e2SPeter Wemm **	on Ultrix.
4705c2aa98e2SPeter Wemm */
4706c2aa98e2SPeter Wemm 
4707c2aa98e2SPeter Wemm #if defined(ultrix) && NAMED_BIND
4708c2aa98e2SPeter Wemm 
4709c2aa98e2SPeter Wemm # include <resolv.h>
4710c2aa98e2SPeter Wemm # if __RES >= 19931104 && __RES < 19950621
4711c2aa98e2SPeter Wemm 
4712c2aa98e2SPeter Wemm int
4713c2aa98e2SPeter Wemm local_hostname_length(hostname)
4714c2aa98e2SPeter Wemm 	char *hostname;
4715c2aa98e2SPeter Wemm {
4716c2aa98e2SPeter Wemm 	int len_host, len_domain;
4717c2aa98e2SPeter Wemm 
4718c2aa98e2SPeter Wemm 	if (!*_res.defdname)
4719c2aa98e2SPeter Wemm 		res_init();
4720c2aa98e2SPeter Wemm 	len_host = strlen(hostname);
4721c2aa98e2SPeter Wemm 	len_domain = strlen(_res.defdname);
4722c2aa98e2SPeter Wemm 	if (len_host > len_domain &&
4723c2aa98e2SPeter Wemm 	    (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) &&
4724c2aa98e2SPeter Wemm 	    hostname[len_host - len_domain - 1] == '.')
4725c2aa98e2SPeter Wemm 		return len_host - len_domain - 1;
4726c2aa98e2SPeter Wemm 	else
4727c2aa98e2SPeter Wemm 		return 0;
4728c2aa98e2SPeter Wemm }
4729c2aa98e2SPeter Wemm 
4730c2aa98e2SPeter Wemm # endif
4731c2aa98e2SPeter Wemm #endif
4732c2aa98e2SPeter Wemm /*
4733c2aa98e2SPeter Wemm **  Compile-Time options
4734c2aa98e2SPeter Wemm */
4735c2aa98e2SPeter Wemm 
4736c2aa98e2SPeter Wemm char	*CompileOptions[] =
4737c2aa98e2SPeter Wemm {
4738c2aa98e2SPeter Wemm #ifdef HESIOD
4739c2aa98e2SPeter Wemm 	"HESIOD",
4740c2aa98e2SPeter Wemm #endif
4741c2aa98e2SPeter Wemm #if HES_GETMAILHOST
4742c2aa98e2SPeter Wemm 	"HES_GETMAILHOST",
4743c2aa98e2SPeter Wemm #endif
4744c2aa98e2SPeter Wemm #ifdef LDAPMAP
4745c2aa98e2SPeter Wemm 	"LDAPMAP",
4746c2aa98e2SPeter Wemm #endif
4747c2aa98e2SPeter Wemm #ifdef MAP_REGEX
4748c2aa98e2SPeter Wemm 	"MAP_REGEX",
4749c2aa98e2SPeter Wemm #endif
4750c2aa98e2SPeter Wemm #if LOG
4751c2aa98e2SPeter Wemm 	"LOG",
4752c2aa98e2SPeter Wemm #endif
4753c2aa98e2SPeter Wemm #if MATCHGECOS
4754c2aa98e2SPeter Wemm 	"MATCHGECOS",
4755c2aa98e2SPeter Wemm #endif
4756c2aa98e2SPeter Wemm #if MIME7TO8
4757c2aa98e2SPeter Wemm 	"MIME7TO8",
4758c2aa98e2SPeter Wemm #endif
4759c2aa98e2SPeter Wemm #if MIME8TO7
4760c2aa98e2SPeter Wemm 	"MIME8TO7",
4761c2aa98e2SPeter Wemm #endif
4762c2aa98e2SPeter Wemm #if NAMED_BIND
4763c2aa98e2SPeter Wemm 	"NAMED_BIND",
4764c2aa98e2SPeter Wemm #endif
4765c2aa98e2SPeter Wemm #ifdef NDBM
4766c2aa98e2SPeter Wemm 	"NDBM",
4767c2aa98e2SPeter Wemm #endif
4768c2aa98e2SPeter Wemm #if NETINET
4769c2aa98e2SPeter Wemm 	"NETINET",
4770c2aa98e2SPeter Wemm #endif
4771c2aa98e2SPeter Wemm #if NETINFO
4772c2aa98e2SPeter Wemm 	"NETINFO",
4773c2aa98e2SPeter Wemm #endif
4774c2aa98e2SPeter Wemm #if NETISO
4775c2aa98e2SPeter Wemm 	"NETISO",
4776c2aa98e2SPeter Wemm #endif
4777c2aa98e2SPeter Wemm #if NETNS
4778c2aa98e2SPeter Wemm 	"NETNS",
4779c2aa98e2SPeter Wemm #endif
4780c2aa98e2SPeter Wemm #if NETUNIX
4781c2aa98e2SPeter Wemm 	"NETUNIX",
4782c2aa98e2SPeter Wemm #endif
4783c2aa98e2SPeter Wemm #if NETX25
4784c2aa98e2SPeter Wemm 	"NETX25",
4785c2aa98e2SPeter Wemm #endif
4786c2aa98e2SPeter Wemm #ifdef NEWDB
4787c2aa98e2SPeter Wemm 	"NEWDB",
4788c2aa98e2SPeter Wemm #endif
4789c2aa98e2SPeter Wemm #ifdef NIS
4790c2aa98e2SPeter Wemm 	"NIS",
4791c2aa98e2SPeter Wemm #endif
4792c2aa98e2SPeter Wemm #ifdef NISPLUS
4793c2aa98e2SPeter Wemm 	"NISPLUS",
4794c2aa98e2SPeter Wemm #endif
4795c2aa98e2SPeter Wemm #if QUEUE
4796c2aa98e2SPeter Wemm 	"QUEUE",
4797c2aa98e2SPeter Wemm #endif
4798c2aa98e2SPeter Wemm #if SCANF
4799c2aa98e2SPeter Wemm 	"SCANF",
4800c2aa98e2SPeter Wemm #endif
4801c2aa98e2SPeter Wemm #if SMTP
4802c2aa98e2SPeter Wemm 	"SMTP",
4803c2aa98e2SPeter Wemm #endif
4804c2aa98e2SPeter Wemm #if SMTPDEBUG
4805c2aa98e2SPeter Wemm 	"SMTPDEBUG",
4806c2aa98e2SPeter Wemm #endif
4807c2aa98e2SPeter Wemm #ifdef SUID_ROOT_FILES_OK
4808c2aa98e2SPeter Wemm 	"SUID_ROOT_FILES_OK",
4809c2aa98e2SPeter Wemm #endif
4810c2aa98e2SPeter Wemm #if TCPWRAPPERS
4811c2aa98e2SPeter Wemm 	"TCPWRAPPERS",
4812c2aa98e2SPeter Wemm #endif
4813c2aa98e2SPeter Wemm #if USERDB
4814c2aa98e2SPeter Wemm 	"USERDB",
4815c2aa98e2SPeter Wemm #endif
4816c2aa98e2SPeter Wemm #if XDEBUG
4817c2aa98e2SPeter Wemm 	"XDEBUG",
4818c2aa98e2SPeter Wemm #endif
4819c2aa98e2SPeter Wemm #ifdef XLA
4820c2aa98e2SPeter Wemm 	"XLA",
4821c2aa98e2SPeter Wemm #endif
4822c2aa98e2SPeter Wemm 	NULL
4823c2aa98e2SPeter Wemm };
4824c2aa98e2SPeter Wemm 
4825c2aa98e2SPeter Wemm 
4826c2aa98e2SPeter Wemm /*
4827c2aa98e2SPeter Wemm **  OS compile options.
4828c2aa98e2SPeter Wemm */
4829c2aa98e2SPeter Wemm 
4830c2aa98e2SPeter Wemm char	*OsCompileOptions[] =
4831c2aa98e2SPeter Wemm {
4832c2aa98e2SPeter Wemm #if BOGUS_O_EXCL
4833c2aa98e2SPeter Wemm 	"BOGUS_O_EXCL",
4834c2aa98e2SPeter Wemm #endif
4835c2aa98e2SPeter Wemm #if HASFCHMOD
4836c2aa98e2SPeter Wemm 	"HASFCHMOD",
4837c2aa98e2SPeter Wemm #endif
4838c2aa98e2SPeter Wemm #if HASFLOCK
4839c2aa98e2SPeter Wemm 	"HASFLOCK",
4840c2aa98e2SPeter Wemm #endif
4841c2aa98e2SPeter Wemm #if HASGETDTABLESIZE
4842c2aa98e2SPeter Wemm 	"HASGETDTABLESIZE",
4843c2aa98e2SPeter Wemm #endif
4844c2aa98e2SPeter Wemm #if HASGETUSERSHELL
4845c2aa98e2SPeter Wemm 	"HASGETUSERSHELL",
4846c2aa98e2SPeter Wemm #endif
4847c2aa98e2SPeter Wemm #if HASINITGROUPS
4848c2aa98e2SPeter Wemm 	"HASINITGROUPS",
4849c2aa98e2SPeter Wemm #endif
4850c2aa98e2SPeter Wemm #if HASLSTAT
4851c2aa98e2SPeter Wemm 	"HASLSTAT",
4852c2aa98e2SPeter Wemm #endif
4853c2aa98e2SPeter Wemm #if HASSETREUID
4854c2aa98e2SPeter Wemm 	"HASSETREUID",
4855c2aa98e2SPeter Wemm #endif
4856c2aa98e2SPeter Wemm #if HASSETRLIMIT
4857c2aa98e2SPeter Wemm 	"HASSETRLIMIT",
4858c2aa98e2SPeter Wemm #endif
4859c2aa98e2SPeter Wemm #if HASSETSID
4860c2aa98e2SPeter Wemm 	"HASSETSID",
4861c2aa98e2SPeter Wemm #endif
4862c2aa98e2SPeter Wemm #if HASSETUSERCONTEXT
4863c2aa98e2SPeter Wemm 	"HASSETUSERCONTEXT",
4864c2aa98e2SPeter Wemm #endif
4865c2aa98e2SPeter Wemm #if HASSETVBUF
4866c2aa98e2SPeter Wemm 	"HASSETVBUF",
4867c2aa98e2SPeter Wemm #endif
4868c2aa98e2SPeter Wemm #if HASSNPRINTF
4869c2aa98e2SPeter Wemm 	"HASSNPRINTF",
4870c2aa98e2SPeter Wemm #endif
4871c2aa98e2SPeter Wemm #if HAS_ST_GEN
4872c2aa98e2SPeter Wemm 	"HAS_ST_GEN",
4873c2aa98e2SPeter Wemm #endif
4874c2aa98e2SPeter Wemm #if HASSTRERROR
4875c2aa98e2SPeter Wemm 	"HASSTRERROR",
4876c2aa98e2SPeter Wemm #endif
4877c2aa98e2SPeter Wemm #if HASULIMIT
4878c2aa98e2SPeter Wemm 	"HASULIMIT",
4879c2aa98e2SPeter Wemm #endif
4880c2aa98e2SPeter Wemm #if HASUNAME
4881c2aa98e2SPeter Wemm 	"HASUNAME",
4882c2aa98e2SPeter Wemm #endif
4883c2aa98e2SPeter Wemm #if HASUNSETENV
4884c2aa98e2SPeter Wemm 	"HASUNSETENV",
4885c2aa98e2SPeter Wemm #endif
4886c2aa98e2SPeter Wemm #if HASWAITPID
4887c2aa98e2SPeter Wemm 	"HASWAITPID",
4888c2aa98e2SPeter Wemm #endif
4889c2aa98e2SPeter Wemm #if IDENTPROTO
4890c2aa98e2SPeter Wemm 	"IDENTPROTO",
4891c2aa98e2SPeter Wemm #endif
4892c2aa98e2SPeter Wemm #if IP_SRCROUTE
4893c2aa98e2SPeter Wemm 	"IP_SRCROUTE",
4894c2aa98e2SPeter Wemm #endif
4895c2aa98e2SPeter Wemm #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
4896c2aa98e2SPeter Wemm 	"LOCK_ON_OPEN",
4897c2aa98e2SPeter Wemm #endif
4898c2aa98e2SPeter Wemm #if NEEDFSYNC
4899c2aa98e2SPeter Wemm 	"NEEDFSYNC",
4900c2aa98e2SPeter Wemm #endif
4901c2aa98e2SPeter Wemm #if NOFTRUNCATE
4902c2aa98e2SPeter Wemm 	"NOFTRUNCATE",
4903c2aa98e2SPeter Wemm #endif
4904c2aa98e2SPeter Wemm #if RLIMIT_NEEDS_SYS_TIME_H
4905c2aa98e2SPeter Wemm 	"RLIMIT_NEEDS_SYS_TIME_H",
4906c2aa98e2SPeter Wemm #endif
4907c2aa98e2SPeter Wemm #if SAFENFSPATHCONF
4908c2aa98e2SPeter Wemm 	"SAFENFSPATHCONF",
4909c2aa98e2SPeter Wemm #endif
4910c2aa98e2SPeter Wemm #if SECUREWARE
4911c2aa98e2SPeter Wemm 	"SECUREWARE",
4912c2aa98e2SPeter Wemm #endif
4913c2aa98e2SPeter Wemm #if SHARE_V1
4914c2aa98e2SPeter Wemm 	"SHARE_V1",
4915c2aa98e2SPeter Wemm #endif
4916c2aa98e2SPeter Wemm #if SIOCGIFCONF_IS_BROKEN
4917c2aa98e2SPeter Wemm 	"SIOCGIFCONF_IS_BROKEN",
4918c2aa98e2SPeter Wemm #endif
4919c2aa98e2SPeter Wemm #if SIOCGIFNUM_IS_BROKEN
4920c2aa98e2SPeter Wemm 	"SIOCGIFNUM_IS_BROKEN",
4921c2aa98e2SPeter Wemm #endif
4922c2aa98e2SPeter Wemm #if SYS5SETPGRP
4923c2aa98e2SPeter Wemm 	"SYS5SETPGRP",
4924c2aa98e2SPeter Wemm #endif
4925c2aa98e2SPeter Wemm #if SYSTEM5
4926c2aa98e2SPeter Wemm 	"SYSTEM5",
4927c2aa98e2SPeter Wemm #endif
4928c2aa98e2SPeter Wemm #if USE_SA_SIGACTION
4929c2aa98e2SPeter Wemm 	"USE_SA_SIGACTION",
4930c2aa98e2SPeter Wemm #endif
4931c2aa98e2SPeter Wemm #if USE_SIGLONGJMP
4932c2aa98e2SPeter Wemm 	"USE_SIGLONGJMP",
4933c2aa98e2SPeter Wemm #endif
4934c2aa98e2SPeter Wemm #if USESETEUID
4935c2aa98e2SPeter Wemm 	"USESETEUID",
4936c2aa98e2SPeter Wemm #endif
4937c2aa98e2SPeter Wemm 	NULL
4938c2aa98e2SPeter Wemm };
4939