xref: /csrg-svn/usr.sbin/sendmail/src/util.c (revision 10326)
13151Seric # include <stdio.h>
24538Seric # include <sys/types.h>
34538Seric # include <sys/stat.h>
4298Seric # include <sysexits.h>
56890Seric # include <errno.h>
62900Seric # include <ctype.h>
76890Seric # include "sendmail.h"
8298Seric 
9*10326Seric SCCSID(@(#)util.c	3.41		01/16/83);
10409Seric 
11298Seric /*
12298Seric **  STRIPQUOTES -- Strip quotes & quote bits from a string.
13298Seric **
14298Seric **	Runs through a string and strips off unquoted quote
15298Seric **	characters and quote bits.  This is done in place.
16298Seric **
17298Seric **	Parameters:
18298Seric **		s -- the string to strip.
194101Seric **		qf -- if set, remove actual `` " '' characters
204101Seric **			as well as the quote bits.
21298Seric **
22298Seric **	Returns:
23298Seric **		none.
24298Seric **
25298Seric **	Side Effects:
26298Seric **		none.
27298Seric **
28298Seric **	Called By:
29298Seric **		deliver
30298Seric */
31298Seric 
324101Seric stripquotes(s, qf)
33298Seric 	char *s;
344101Seric 	bool qf;
35298Seric {
36298Seric 	register char *p;
37298Seric 	register char *q;
38298Seric 	register char c;
39298Seric 
404101Seric 	if (s == NULL)
414101Seric 		return;
424101Seric 
43298Seric 	for (p = q = s; (c = *p++) != '\0'; )
44298Seric 	{
454101Seric 		if (c != '"' || !qf)
46298Seric 			*q++ = c & 0177;
47298Seric 	}
48298Seric 	*q = '\0';
49298Seric }
50298Seric /*
519043Seric **  QSTRLEN -- give me the string length assuming 0200 bits add a char
529043Seric **
539043Seric **	Parameters:
549043Seric **		s -- the string to measure.
559043Seric **
569043Seric **	Reurns:
579043Seric **		The length of s, including space for backslash escapes.
589043Seric **
599043Seric **	Side Effects:
609043Seric **		none.
619043Seric */
629043Seric 
639043Seric qstrlen(s)
649043Seric 	register char *s;
659043Seric {
669043Seric 	register int l = 0;
679043Seric 	register char c;
689043Seric 
699043Seric 	while ((c = *s++) != '\0')
709043Seric 	{
719043Seric 		if (bitset(0200, c))
729043Seric 			l++;
739043Seric 		l++;
749043Seric 	}
759043Seric 	return (l);
769043Seric }
779043Seric /*
782900Seric **  CAPITALIZE -- return a copy of a string, properly capitalized.
792900Seric **
802900Seric **	Parameters:
812900Seric **		s -- the string to capitalize.
822900Seric **
832900Seric **	Returns:
842900Seric **		a pointer to a properly capitalized string.
852900Seric **
862900Seric **	Side Effects:
872900Seric **		none.
882900Seric */
892900Seric 
902900Seric char *
912900Seric capitalize(s)
922900Seric 	register char *s;
932900Seric {
942900Seric 	static char buf[50];
952900Seric 	register char *p;
962900Seric 
972900Seric 	p = buf;
982900Seric 
992900Seric 	for (;;)
1002900Seric 	{
1012900Seric 		while (!isalpha(*s) && *s != '\0')
1022900Seric 			*p++ = *s++;
1032900Seric 		if (*s == '\0')
1042900Seric 			break;
1052900Seric 		*p++ = toupper(*s++);
1062900Seric 		while (isalpha(*s))
1072900Seric 			*p++ = *s++;
1082900Seric 	}
1092900Seric 
1102900Seric 	*p = '\0';
1112900Seric 	return (buf);
1122900Seric }
1132900Seric /*
114298Seric **  XALLOC -- Allocate memory and bitch wildly on failure.
115298Seric **
116298Seric **	THIS IS A CLUDGE.  This should be made to give a proper
117298Seric **	error -- but after all, what can we do?
118298Seric **
119298Seric **	Parameters:
120298Seric **		sz -- size of area to allocate.
121298Seric **
122298Seric **	Returns:
123298Seric **		pointer to data region.
124298Seric **
125298Seric **	Side Effects:
126298Seric **		Memory is allocated.
127298Seric */
128298Seric 
129298Seric char *
130298Seric xalloc(sz)
1317007Seric 	register int sz;
132298Seric {
133298Seric 	register char *p;
134298Seric 
135298Seric 	p = malloc(sz);
136298Seric 	if (p == NULL)
137298Seric 	{
138298Seric 		syserr("Out of memory!!");
1391598Seric 		exit(EX_UNAVAILABLE);
140298Seric 	}
141298Seric 	return (p);
142298Seric }
143298Seric /*
1443151Seric **  COPYPLIST -- copy list of pointers.
1453151Seric **
1463151Seric **	This routine is the equivalent of newstr for lists of
1473151Seric **	pointers.
1483151Seric **
1493151Seric **	Parameters:
1503151Seric **		list -- list of pointers to copy.
1513151Seric **			Must be NULL terminated.
1523151Seric **		copycont -- if TRUE, copy the contents of the vector
1533151Seric **			(which must be a string) also.
1543151Seric **
1553151Seric **	Returns:
1563151Seric **		a copy of 'list'.
1573151Seric **
1583151Seric **	Side Effects:
1593151Seric **		none.
1603151Seric */
1613151Seric 
1623151Seric char **
1633151Seric copyplist(list, copycont)
1643151Seric 	char **list;
1653151Seric 	bool copycont;
1663151Seric {
1673151Seric 	register char **vp;
1683151Seric 	register char **newvp;
1693151Seric 
1703151Seric 	for (vp = list; *vp != NULL; vp++)
1713151Seric 		continue;
1723151Seric 
1733151Seric 	vp++;
1743151Seric 
1757007Seric 	newvp = (char **) xalloc((vp - list) * sizeof *vp);
1764086Seric 	bmove((char *) list, (char *) newvp, (vp - list) * sizeof *vp);
1773151Seric 
1783151Seric 	if (copycont)
1793151Seric 	{
1803151Seric 		for (vp = newvp; *vp != NULL; vp++)
1813151Seric 			*vp = newstr(*vp);
1823151Seric 	}
1833151Seric 
1843151Seric 	return (newvp);
1853151Seric }
1863151Seric /*
1873151Seric **  PRINTAV -- print argument vector.
1883151Seric **
1893151Seric **	Parameters:
1903151Seric **		av -- argument vector.
1913151Seric **
1923151Seric **	Returns:
1933151Seric **		none.
1943151Seric **
1953151Seric **	Side Effects:
1963151Seric **		prints av.
1973151Seric */
1983151Seric 
1993151Seric # ifdef DEBUG
2003151Seric printav(av)
2013151Seric 	register char **av;
2023151Seric {
2033151Seric 	while (*av != NULL)
2043151Seric 	{
2058063Seric 		if (tTd(0, 44))
2068063Seric 			printf("\n\t%08x=", *av);
2078063Seric 		else
2088063Seric 			putchar(' ');
2093151Seric 		xputs(*av++);
2103151Seric 	}
2118063Seric 	putchar('\n');
2123151Seric }
2133151Seric # endif DEBUG
2143151Seric /*
2153151Seric **  LOWER -- turn letter into lower case.
2163151Seric **
2173151Seric **	Parameters:
2183151Seric **		c -- character to turn into lower case.
2193151Seric **
2203151Seric **	Returns:
2213151Seric **		c, in lower case.
2223151Seric **
2233151Seric **	Side Effects:
2243151Seric **		none.
2253151Seric */
2263151Seric 
2273151Seric char
2283151Seric lower(c)
2293151Seric 	register char c;
2303151Seric {
2313151Seric 	if (isascii(c) && isupper(c))
2323151Seric 		c = c - 'A' + 'a';
2333151Seric 	return (c);
2343151Seric }
2353151Seric /*
2363151Seric **  XPUTS -- put string doing control escapes.
2373151Seric **
2383151Seric **	Parameters:
2393151Seric **		s -- string to put.
2403151Seric **
2413151Seric **	Returns:
2423151Seric **		none.
2433151Seric **
2443151Seric **	Side Effects:
2453151Seric **		output to stdout
2463151Seric */
2473151Seric 
2483151Seric # ifdef DEBUG
2493151Seric xputs(s)
2503151Seric 	register char *s;
2513151Seric {
2523151Seric 	register char c;
2533151Seric 
2548055Seric 	if (s == NULL)
2558055Seric 	{
2568055Seric 		printf("<null>");
2578055Seric 		return;
2588055Seric 	}
2598063Seric 	putchar('"');
2603151Seric 	while ((c = *s++) != '\0')
2613151Seric 	{
2623151Seric 		if (!isascii(c))
2633151Seric 		{
2643151Seric 			putchar('\\');
2653151Seric 			c &= 0177;
2663151Seric 		}
267*10326Seric 		if (c < 040 || c >= 0177)
2683151Seric 		{
2693151Seric 			putchar('^');
270*10326Seric 			c ^= 0100;
2713151Seric 		}
2723151Seric 		putchar(c);
2733151Seric 	}
2748063Seric 	putchar('"');
2754086Seric 	(void) fflush(stdout);
2763151Seric }
2773151Seric # endif DEBUG
2783151Seric /*
2793151Seric **  MAKELOWER -- Translate a line into lower case
2803151Seric **
2813151Seric **	Parameters:
2823151Seric **		p -- the string to translate.  If NULL, return is
2833151Seric **			immediate.
2843151Seric **
2853151Seric **	Returns:
2863151Seric **		none.
2873151Seric **
2883151Seric **	Side Effects:
2893151Seric **		String pointed to by p is translated to lower case.
2903151Seric **
2913151Seric **	Called By:
2923151Seric **		parse
2933151Seric */
2943151Seric 
2953151Seric makelower(p)
2963151Seric 	register char *p;
2973151Seric {
2983151Seric 	register char c;
2993151Seric 
3003151Seric 	if (p == NULL)
3013151Seric 		return;
3023151Seric 	for (; (c = *p) != '\0'; p++)
3033151Seric 		if (isascii(c) && isupper(c))
3043151Seric 			*p = c - 'A' + 'a';
3053151Seric }
3064059Seric /*
3074059Seric **  SAMEWORD -- return TRUE if the words are the same
3084059Seric **
3094059Seric **	Ignores case.
3104059Seric **
3114059Seric **	Parameters:
3124059Seric **		a, b -- the words to compare.
3134059Seric **
3144059Seric **	Returns:
3154059Seric **		TRUE if a & b match exactly (modulo case)
3164059Seric **		FALSE otherwise.
3174059Seric **
3184059Seric **	Side Effects:
3194059Seric **		none.
3204059Seric */
3214059Seric 
3224059Seric bool
3234059Seric sameword(a, b)
3244059Seric 	register char *a, *b;
3254059Seric {
3264059Seric 	while (lower(*a) == lower(*b))
3274059Seric 	{
3284059Seric 		if (*a == '\0')
3294059Seric 			return (TRUE);
3304059Seric 		a++;
3314059Seric 		b++;
3324059Seric 	}
3334059Seric 	return (FALSE);
3344059Seric }
3354086Seric /*
3364101Seric **  CLEAR -- clear a block of memory
3374101Seric **
3384101Seric **	Parameters:
3394101Seric **		p -- location to clear.
3404101Seric **		l -- number of bytes to clear.
3414101Seric **
3424101Seric **	Returns:
3434101Seric **		none.
3444101Seric **
3454101Seric **	Side Effects:
3464101Seric **		none.
3474101Seric */
3484101Seric 
3494101Seric clear(p, l)
3504101Seric 	register char *p;
3514101Seric 	register int l;
3524101Seric {
3534101Seric 	while (l-- > 0)
3544101Seric 		*p++ = 0;
3554101Seric }
3564101Seric /*
3575196Seric **  BUILDFNAME -- build full name from gecos style entry.
3584375Seric **
3595196Seric **	This routine interprets the strange entry that would appear
3605196Seric **	in the GECOS field of the password file.
3615196Seric **
3624375Seric **	Parameters:
3635196Seric **		p -- name to build.
3645196Seric **		login -- the login name of this user (for &).
3655196Seric **		buf -- place to put the result.
3664375Seric **
3674375Seric **	Returns:
3684375Seric **		none.
3694375Seric **
3704375Seric **	Side Effects:
3714375Seric **		none.
3724375Seric */
3734375Seric 
3745196Seric buildfname(p, login, buf)
3755196Seric 	register char *p;
3765196Seric 	char *login;
3774375Seric 	char *buf;
3784375Seric {
3794375Seric 	register char *bp = buf;
3804375Seric 
3814438Seric 	if (*p == '*')
3824438Seric 		p++;
3836278Seric 	while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
3844375Seric 	{
3854375Seric 		if (*p == '&')
3864375Seric 		{
3875196Seric 			(void) strcpy(bp, login);
3884375Seric 			*bp = toupper(*bp);
3894375Seric 			while (*bp != '\0')
3904375Seric 				bp++;
3914375Seric 			p++;
3924375Seric 		}
3934375Seric 		else
3944375Seric 			*bp++ = *p++;
3954375Seric 	}
3964375Seric 	*bp = '\0';
3974375Seric }
3984375Seric /*
3994538Seric **  SAFEFILE -- return true if a file exists and is safe for a user.
4004538Seric **
4014538Seric **	Parameters:
4024538Seric **		fn -- filename to check.
4034538Seric **		uid -- uid to compare against.
4044538Seric **		mode -- mode bits that must match.
4054538Seric **
4064538Seric **	Returns:
4074538Seric **		TRUE if fn exists, is owned by uid, and matches mode.
4084538Seric **		FALSE otherwise.
4094538Seric **
4104538Seric **	Side Effects:
4114538Seric **		none.
4124538Seric */
4134538Seric 
4144538Seric bool
4154538Seric safefile(fn, uid, mode)
4164538Seric 	char *fn;
4174538Seric 	int uid;
4184538Seric 	int mode;
4194538Seric {
4204538Seric 	struct stat stbuf;
4214538Seric 
4224538Seric 	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
4234538Seric 	    (stbuf.st_mode & mode) == mode)
4244538Seric 		return (TRUE);
4254538Seric 	return (FALSE);
4264538Seric }
4274538Seric /*
4284557Seric **  FIXCRLF -- fix <CR><LF> in line.
4294557Seric **
4304557Seric **	Looks for the <CR><LF> combination and turns it into the
4314557Seric **	UNIX canonical <NL> character.  It only takes one line,
4324557Seric **	i.e., it is assumed that the first <NL> found is the end
4334557Seric **	of the line.
4344557Seric **
4354557Seric **	Parameters:
4364557Seric **		line -- the line to fix.
4374557Seric **		stripnl -- if true, strip the newline also.
4384557Seric **
4394557Seric **	Returns:
4404557Seric **		none.
4414557Seric **
4424557Seric **	Side Effects:
4434557Seric **		line is changed in place.
4444557Seric */
4454557Seric 
4464557Seric fixcrlf(line, stripnl)
4474557Seric 	char *line;
4484557Seric 	bool stripnl;
4494557Seric {
4504557Seric 	register char *p;
4514557Seric 
4524557Seric 	p = index(line, '\n');
4534557Seric 	if (p == NULL)
4544557Seric 		return;
4554794Seric 	if (p[-1] == '\r')
4564557Seric 		p--;
4574557Seric 	if (!stripnl)
4584557Seric 		*p++ = '\n';
4594557Seric 	*p = '\0';
4604557Seric }
4614557Seric /*
4624086Seric **  SYSLOG -- fake entry to fool lint
4634086Seric */
4644086Seric 
4654086Seric # ifdef LOG
4664086Seric # ifdef lint
4674086Seric 
4684086Seric /*VARARGS2*/
4694086Seric syslog(pri, fmt, args)
4704086Seric 	int pri;
4714086Seric 	char *fmt;
4724086Seric {
4734086Seric 	pri = *fmt;
4744086Seric 	args = pri;
4754086Seric 	pri = args;
4764086Seric }
4774086Seric 
4784086Seric # endif lint
4794086Seric # endif LOG
4806890Seric /*
4816890Seric **  DFOPEN -- determined file open
4826890Seric **
4836890Seric **	This routine has the semantics of fopen, except that it will
4846890Seric **	keep trying a few times to make this happen.  The idea is that
4856890Seric **	on very loaded systems, we may run out of resources (inodes,
4866890Seric **	whatever), so this tries to get around it.
4876890Seric */
4886890Seric 
4896890Seric FILE *
4906890Seric dfopen(filename, mode)
4916890Seric 	char *filename;
4926890Seric 	char *mode;
4936890Seric {
4946890Seric 	register int tries;
4956890Seric 	register FILE *fp;
4966890Seric 
4976890Seric 	for (tries = 0; tries < 10; tries++)
4986890Seric 	{
4996890Seric 		sleep(10 * tries);
5006890Seric 		errno = 0;
5016890Seric 		fp = fopen(filename, mode);
5029376Seric 		if (fp != NULL)
5036890Seric 			break;
5049376Seric 		if (errno != ENFILE && errno != EINTR)
5059376Seric 			break;
5066890Seric 	}
5076890Seric 	return (fp);
5086890Seric }
5097124Seric /*
5107124Seric **  PUTLINE -- put a line like fputs obeying SMTP conventions
5117124Seric **
5127753Seric **	This routine always guarantees outputing a newline (or CRLF,
5137753Seric **	as appropriate) at the end of the string.
5147753Seric **
5157124Seric **	Parameters:
5167124Seric **		l -- line to put.
5177124Seric **		fp -- file to put it onto.
51810172Seric **		m -- the mailer used to control output.
5197124Seric **
5207124Seric **	Returns:
5217124Seric **		none
5227124Seric **
5237124Seric **	Side Effects:
5247124Seric **		output of l to fp.
5257124Seric */
5267124Seric 
5277753Seric # define SMTPLINELIM	990	/* maximum line length */
5287124Seric 
52910172Seric putline(l, fp, m)
5307753Seric 	register char *l;
5317124Seric 	FILE *fp;
53210172Seric 	MAILER *m;
5337124Seric {
5347124Seric 	register char *p;
5357753Seric 	char svchar;
5367124Seric 
5377753Seric 	do
5387124Seric 	{
5397753Seric 		/* find the end of the line */
5407753Seric 		p = index(l, '\n');
5417753Seric 		if (p == NULL)
5427753Seric 			p = &l[strlen(l)];
5437124Seric 
5447753Seric 		/* check for line overflow */
54510172Seric 		while (bitset(M_LIMITS, m->m_flags) && (p - l) > SMTPLINELIM)
5467753Seric 		{
5477753Seric 			register char *q = &l[SMTPLINELIM - 1];
5487124Seric 
5497753Seric 			svchar = *q;
5507753Seric 			*q = '\0';
55110172Seric 			if (l[0] == '.' && bitset(M_XDOT, m->m_flags))
55210172Seric 				fputc('.', fp);
5537753Seric 			fputs(l, fp);
55410066Seric 			fputc('!', fp);
555*10326Seric 			fputs(m->m_eol, fp);
5567753Seric 			*q = svchar;
5577753Seric 			l = q;
5587753Seric 		}
5597124Seric 
5607753Seric 		/* output last part */
5617753Seric 		svchar = *p;
5627753Seric 		*p = '\0';
56310172Seric 		if (l[0] == '.' && bitset(M_XDOT, m->m_flags))
56410172Seric 			fputc('.', fp);
5657124Seric 		fputs(l, fp);
566*10326Seric 		fputs(m->m_eol, fp);
5677753Seric 		*p = svchar;
5687753Seric 		l = p;
5697753Seric 		if (*l == '\n')
5707753Seric 			l++;
5717753Seric 	} while (l[0] != '\0');
5727124Seric }
5737676Seric /*
5747676Seric **  XUNLINK -- unlink a file, doing logging as appropriate.
5757676Seric **
5767676Seric **	Parameters:
5777676Seric **		f -- name of file to unlink.
5787676Seric **
5797676Seric **	Returns:
5807676Seric **		none.
5817676Seric **
5827676Seric **	Side Effects:
5837676Seric **		f is unlinked.
5847676Seric */
5857676Seric 
5867676Seric xunlink(f)
5877676Seric 	char *f;
5887676Seric {
5897676Seric 	register int i;
5907676Seric 
5917676Seric # ifdef LOG
5927676Seric 	if (LogLevel > 20)
5937812Seric 		syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
5947676Seric # endif LOG
5957676Seric 
5967676Seric 	i = unlink(f);
5977676Seric # ifdef LOG
5987676Seric 	if (i < 0 && LogLevel > 21)
5997942Seric 		syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
6007676Seric # endif LOG
6017676Seric }
6027685Seric /*
6037685Seric **  SFGETS -- "safe" fgets -- times out.
6047685Seric **
6057685Seric **	Parameters:
6067685Seric **		buf -- place to put the input line.
6077685Seric **		siz -- size of buf.
6087685Seric **		fp -- file to read from.
6097685Seric **
6107685Seric **	Returns:
6117685Seric **		NULL on error (including timeout).
6127685Seric **		buf otherwise.
6137685Seric **
6147685Seric **	Side Effects:
6157685Seric **		none.
6167685Seric */
6177685Seric 
6187942Seric static bool	TimeoutFlag;
6197685Seric 
6207685Seric char *
6217685Seric sfgets(buf, siz, fp)
6227685Seric 	char *buf;
6237685Seric 	int siz;
6247685Seric 	FILE *fp;
6257685Seric {
6267942Seric 	register EVENT *ev = NULL;
6277685Seric 	register char *p;
6287685Seric 	extern readtimeout();
6297685Seric 
6307942Seric 	if (ReadTimeout != 0)
6317942Seric 		ev = setevent(ReadTimeout, readtimeout, 0);
6327942Seric 	TimeoutFlag = FALSE;
6337942Seric 	do
6347942Seric 	{
6357942Seric 		errno = 0;
6367942Seric 		p = fgets(buf, siz, fp);
6377942Seric 	} while (!(p != NULL || TimeoutFlag || errno != EINTR));
6387685Seric 	clrevent(ev);
6398055Seric 	LineNumber++;
6409581Seric 	if (TimeoutFlag)
6419581Seric 		syserr("sfgets: timeout on read (mailer may be hung)");
6427685Seric 	return (p);
6437685Seric }
6447685Seric 
6457685Seric static
6467685Seric readtimeout()
6477685Seric {
6487942Seric 	TimeoutFlag = TRUE;
6497685Seric }
6507786Seric /*
6517786Seric **  FGETFOLDED -- like fgets, but know about folded lines.
6527786Seric **
6537786Seric **	Parameters:
6547786Seric **		buf -- place to put result.
6557786Seric **		n -- bytes available.
6567786Seric **		f -- file to read from.
6577786Seric **
6587786Seric **	Returns:
6597786Seric **		buf on success, NULL on error or EOF.
6607786Seric **
6617786Seric **	Side Effects:
6627786Seric **		buf gets lines from f, with continuation lines (lines
6637786Seric **		with leading white space) appended.  CRLF's are mapped
6647786Seric **		into single newlines.  Any trailing NL is stripped.
6657786Seric */
6667786Seric 
6677786Seric char *
6687786Seric fgetfolded(buf, n, f)
6697786Seric 	char *buf;
6707786Seric 	register int n;
6717786Seric 	FILE *f;
6727786Seric {
6737786Seric 	register char *p = buf;
6747786Seric 	register int i;
6757786Seric 
6767786Seric 	n--;
67710030Seric 	while (fgets(p, n, f) != NULL)
6787786Seric 	{
67910030Seric 		LineNumber++;
6807786Seric 		fixcrlf(p, TRUE);
6817786Seric 		i = fgetc(f);
6827786Seric 		if (i != EOF)
6837786Seric 			ungetc(i, f);
6847786Seric 		if (i != ' ' && i != '\t')
6857786Seric 			return (buf);
6867786Seric 		i = strlen(p);
6877786Seric 		p += i;
6887786Seric 		*p++ = '\n';
6897786Seric 		n -= i + 1;
6907786Seric 	}
6917786Seric 	return (NULL);
6927786Seric }
6937860Seric /*
6947886Seric **  CURTIME -- return current time.
6957886Seric **
6967886Seric **	Parameters:
6977886Seric **		none.
6987886Seric **
6997886Seric **	Returns:
7007886Seric **		the current time.
7017886Seric **
7027886Seric **	Side Effects:
7037886Seric **		none.
7047886Seric */
7057886Seric 
7067886Seric time_t
7077886Seric curtime()
7087886Seric {
7097886Seric 	auto time_t t;
7107886Seric 
7117886Seric 	(void) time(&t);
7127886Seric 	return (t);
7137886Seric }
7148264Seric /*
7158264Seric **  ATOBOOL -- convert a string representation to boolean.
7168264Seric **
7178264Seric **	Defaults to "TRUE"
7188264Seric **
7198264Seric **	Parameters:
7208264Seric **		s -- string to convert.  Takes "tTyY" as true,
7218264Seric **			others as false.
7228264Seric **
7238264Seric **	Returns:
7248264Seric **		A boolean representation of the string.
7258264Seric **
7268264Seric **	Side Effects:
7278264Seric **		none.
7288264Seric */
7298264Seric 
7308264Seric bool
7318264Seric atobool(s)
7328264Seric 	register char *s;
7338264Seric {
7348264Seric 	if (*s == '\0' || index("tTyY", *s) != NULL)
7358264Seric 		return (TRUE);
7368264Seric 	return (FALSE);
7378264Seric }
7389048Seric /*
7399048Seric **  ATOOCT -- convert a string representation to octal.
7409048Seric **
7419048Seric **	Parameters:
7429048Seric **		s -- string to convert.
7439048Seric **
7449048Seric **	Returns:
7459048Seric **		An integer representing the string interpreted as an
7469048Seric **		octal number.
7479048Seric **
7489048Seric **	Side Effects:
7499048Seric **		none.
7509048Seric */
7519048Seric 
7529048Seric atooct(s)
7539048Seric 	register char *s;
7549048Seric {
7559048Seric 	register int i = 0;
7569048Seric 
7579048Seric 	while (*s >= '0' && *s <= '7')
7589048Seric 		i = (i << 3) | (*s++ - '0');
7599048Seric 	return (i);
7609048Seric }
7619376Seric /*
7629376Seric **  WAITFOR -- wait for a particular process id.
7639376Seric **
7649376Seric **	Parameters:
7659376Seric **		pid -- process id to wait for.
7669376Seric **
7679376Seric **	Returns:
7689376Seric **		status of pid.
7699376Seric **		-1 if pid never shows up.
7709376Seric **
7719376Seric **	Side Effects:
7729376Seric **		none.
7739376Seric */
7749376Seric 
7759376Seric waitfor(pid)
7769376Seric 	int pid;
7779376Seric {
7789376Seric 	auto int st;
7799376Seric 	int i;
7809376Seric 
7819376Seric 	do
7829376Seric 	{
7839376Seric 		errno = 0;
7849376Seric 		i = wait(&st);
7859376Seric 	} while ((i >= 0 || errno == EINTR) && i != pid);
7869376Seric 	if (i < 0)
7879376Seric 		st = -1;
7889376Seric 	return (st);
7899376Seric }
7909376Seric /*
7919376Seric **  CLOSEALL -- close all extraneous file descriptors
7929376Seric **
7939376Seric **	Parameters:
7949376Seric **		none.
7959376Seric **
7969376Seric **	Returns:
7979376Seric **		none.
7989376Seric **
7999376Seric **	Side Effects:
8009376Seric **		Closes all file descriptors except zero, one, and two.
8019376Seric */
8029376Seric 
8039376Seric closeall()
8049376Seric {
8059376Seric 	int i;
8069376Seric 
8079376Seric 	for (i = 3; i < 50; i++)
8089376Seric 		(void) close(i);
8099376Seric }
810