xref: /csrg-svn/usr.sbin/sendmail/src/util.c (revision 33724)
122717Sdist /*
222717Sdist **  Sendmail
322717Sdist **  Copyright (c) 1983  Eric P. Allman
422717Sdist **  Berkeley, California
522717Sdist **
622717Sdist **  Copyright (c) 1983 Regents of the University of California.
722717Sdist **  All rights reserved.  The Berkeley software License Agreement
822717Sdist **  specifies the terms and conditions for redistribution.
922717Sdist */
1022717Sdist 
1122717Sdist #ifndef lint
12*33724Sbostic static char	SccsId[] = "@(#)util.c	5.10 (Berkeley) 03/13/88";
1322717Sdist #endif not lint
1422717Sdist 
153151Seric # include <stdio.h>
164538Seric # include <sys/types.h>
174538Seric # include <sys/stat.h>
18298Seric # include <sysexits.h>
196890Seric # include <errno.h>
206890Seric # include "sendmail.h"
21298Seric 
22298Seric /*
23298Seric **  STRIPQUOTES -- Strip quotes & quote bits from a string.
24298Seric **
25298Seric **	Runs through a string and strips off unquoted quote
26298Seric **	characters and quote bits.  This is done in place.
27298Seric **
28298Seric **	Parameters:
29298Seric **		s -- the string to strip.
304101Seric **		qf -- if set, remove actual `` " '' characters
314101Seric **			as well as the quote bits.
32298Seric **
33298Seric **	Returns:
34298Seric **		none.
35298Seric **
36298Seric **	Side Effects:
37298Seric **		none.
38298Seric **
39298Seric **	Called By:
40298Seric **		deliver
41298Seric */
42298Seric 
434101Seric stripquotes(s, qf)
44298Seric 	char *s;
454101Seric 	bool qf;
46298Seric {
47298Seric 	register char *p;
48298Seric 	register char *q;
49298Seric 	register char c;
50298Seric 
514101Seric 	if (s == NULL)
524101Seric 		return;
534101Seric 
54298Seric 	for (p = q = s; (c = *p++) != '\0'; )
55298Seric 	{
564101Seric 		if (c != '"' || !qf)
57298Seric 			*q++ = c & 0177;
58298Seric 	}
59298Seric 	*q = '\0';
60298Seric }
61298Seric /*
629043Seric **  QSTRLEN -- give me the string length assuming 0200 bits add a char
639043Seric **
649043Seric **	Parameters:
659043Seric **		s -- the string to measure.
669043Seric **
679043Seric **	Reurns:
689043Seric **		The length of s, including space for backslash escapes.
699043Seric **
709043Seric **	Side Effects:
719043Seric **		none.
729043Seric */
739043Seric 
749043Seric qstrlen(s)
759043Seric 	register char *s;
769043Seric {
779043Seric 	register int l = 0;
789043Seric 	register char c;
799043Seric 
809043Seric 	while ((c = *s++) != '\0')
819043Seric 	{
829043Seric 		if (bitset(0200, c))
839043Seric 			l++;
849043Seric 		l++;
859043Seric 	}
869043Seric 	return (l);
879043Seric }
889043Seric /*
892900Seric **  CAPITALIZE -- return a copy of a string, properly capitalized.
902900Seric **
912900Seric **	Parameters:
922900Seric **		s -- the string to capitalize.
932900Seric **
942900Seric **	Returns:
952900Seric **		a pointer to a properly capitalized string.
962900Seric **
972900Seric **	Side Effects:
982900Seric **		none.
992900Seric */
1002900Seric 
1012900Seric char *
1022900Seric capitalize(s)
1032900Seric 	register char *s;
1042900Seric {
1052900Seric 	static char buf[50];
1062900Seric 	register char *p;
1072900Seric 
1082900Seric 	p = buf;
1092900Seric 
1102900Seric 	for (;;)
1112900Seric 	{
1122900Seric 		while (!isalpha(*s) && *s != '\0')
1132900Seric 			*p++ = *s++;
1142900Seric 		if (*s == '\0')
1152900Seric 			break;
1162900Seric 		*p++ = toupper(*s++);
1172900Seric 		while (isalpha(*s))
1182900Seric 			*p++ = *s++;
1192900Seric 	}
1202900Seric 
1212900Seric 	*p = '\0';
1222900Seric 	return (buf);
1232900Seric }
1242900Seric /*
125298Seric **  XALLOC -- Allocate memory and bitch wildly on failure.
126298Seric **
127298Seric **	THIS IS A CLUDGE.  This should be made to give a proper
128298Seric **	error -- but after all, what can we do?
129298Seric **
130298Seric **	Parameters:
131298Seric **		sz -- size of area to allocate.
132298Seric **
133298Seric **	Returns:
134298Seric **		pointer to data region.
135298Seric **
136298Seric **	Side Effects:
137298Seric **		Memory is allocated.
138298Seric */
139298Seric 
140298Seric char *
141298Seric xalloc(sz)
1427007Seric 	register int sz;
143298Seric {
144298Seric 	register char *p;
14523121Seric 	extern char *malloc();
146298Seric 
14723121Seric 	p = malloc((unsigned) sz);
148298Seric 	if (p == NULL)
149298Seric 	{
150298Seric 		syserr("Out of memory!!");
15110685Seric 		abort();
15210685Seric 		/* exit(EX_UNAVAILABLE); */
153298Seric 	}
154298Seric 	return (p);
155298Seric }
156298Seric /*
1573151Seric **  COPYPLIST -- copy list of pointers.
1583151Seric **
1593151Seric **	This routine is the equivalent of newstr for lists of
1603151Seric **	pointers.
1613151Seric **
1623151Seric **	Parameters:
1633151Seric **		list -- list of pointers to copy.
1643151Seric **			Must be NULL terminated.
1653151Seric **		copycont -- if TRUE, copy the contents of the vector
1663151Seric **			(which must be a string) also.
1673151Seric **
1683151Seric **	Returns:
1693151Seric **		a copy of 'list'.
1703151Seric **
1713151Seric **	Side Effects:
1723151Seric **		none.
1733151Seric */
1743151Seric 
1753151Seric char **
1763151Seric copyplist(list, copycont)
1773151Seric 	char **list;
1783151Seric 	bool copycont;
1793151Seric {
1803151Seric 	register char **vp;
1813151Seric 	register char **newvp;
1823151Seric 
1833151Seric 	for (vp = list; *vp != NULL; vp++)
1843151Seric 		continue;
1853151Seric 
1863151Seric 	vp++;
1873151Seric 
18816897Seric 	newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
18916897Seric 	bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp);
1903151Seric 
1913151Seric 	if (copycont)
1923151Seric 	{
1933151Seric 		for (vp = newvp; *vp != NULL; vp++)
1943151Seric 			*vp = newstr(*vp);
1953151Seric 	}
1963151Seric 
1973151Seric 	return (newvp);
1983151Seric }
1993151Seric /*
2003151Seric **  PRINTAV -- print argument vector.
2013151Seric **
2023151Seric **	Parameters:
2033151Seric **		av -- argument vector.
2043151Seric **
2053151Seric **	Returns:
2063151Seric **		none.
2073151Seric **
2083151Seric **	Side Effects:
2093151Seric **		prints av.
2103151Seric */
2113151Seric 
2123151Seric printav(av)
2133151Seric 	register char **av;
2143151Seric {
2153151Seric 	while (*av != NULL)
2163151Seric 	{
2178063Seric 		if (tTd(0, 44))
2188063Seric 			printf("\n\t%08x=", *av);
2198063Seric 		else
22023105Seric 			(void) putchar(' ');
2213151Seric 		xputs(*av++);
2223151Seric 	}
22323105Seric 	(void) putchar('\n');
2243151Seric }
2253151Seric /*
2263151Seric **  LOWER -- turn letter into lower case.
2273151Seric **
2283151Seric **	Parameters:
2293151Seric **		c -- character to turn into lower case.
2303151Seric **
2313151Seric **	Returns:
2323151Seric **		c, in lower case.
2333151Seric **
2343151Seric **	Side Effects:
2353151Seric **		none.
2363151Seric */
2373151Seric 
2383151Seric char
2393151Seric lower(c)
2403151Seric 	register char c;
2413151Seric {
242*33724Sbostic 	return(isascii(c) && isupper(c) ? tolower(c) : c);
2433151Seric }
2443151Seric /*
2453151Seric **  XPUTS -- put string doing control escapes.
2463151Seric **
2473151Seric **	Parameters:
2483151Seric **		s -- string to put.
2493151Seric **
2503151Seric **	Returns:
2513151Seric **		none.
2523151Seric **
2533151Seric **	Side Effects:
2543151Seric **		output to stdout
2553151Seric */
2563151Seric 
2573151Seric xputs(s)
2583151Seric 	register char *s;
2593151Seric {
2603151Seric 	register char c;
2613151Seric 
2628055Seric 	if (s == NULL)
2638055Seric 	{
2648055Seric 		printf("<null>");
2658055Seric 		return;
2668055Seric 	}
26723105Seric 	(void) putchar('"');
2683151Seric 	while ((c = *s++) != '\0')
2693151Seric 	{
2703151Seric 		if (!isascii(c))
2713151Seric 		{
27223105Seric 			(void) putchar('\\');
2733151Seric 			c &= 0177;
2743151Seric 		}
27510326Seric 		if (c < 040 || c >= 0177)
2763151Seric 		{
27723105Seric 			(void) putchar('^');
27810326Seric 			c ^= 0100;
2793151Seric 		}
28023105Seric 		(void) putchar(c);
2813151Seric 	}
28223105Seric 	(void) putchar('"');
2834086Seric 	(void) fflush(stdout);
2843151Seric }
2853151Seric /*
2863151Seric **  MAKELOWER -- Translate a line into lower case
2873151Seric **
2883151Seric **	Parameters:
2893151Seric **		p -- the string to translate.  If NULL, return is
2903151Seric **			immediate.
2913151Seric **
2923151Seric **	Returns:
2933151Seric **		none.
2943151Seric **
2953151Seric **	Side Effects:
2963151Seric **		String pointed to by p is translated to lower case.
2973151Seric **
2983151Seric **	Called By:
2993151Seric **		parse
3003151Seric */
3013151Seric 
3023151Seric makelower(p)
3033151Seric 	register char *p;
3043151Seric {
3053151Seric 	register char c;
3063151Seric 
3073151Seric 	if (p == NULL)
3083151Seric 		return;
3093151Seric 	for (; (c = *p) != '\0'; p++)
3103151Seric 		if (isascii(c) && isupper(c))
311*33724Sbostic 			*p = tolower(c);
3123151Seric }
3134059Seric /*
3145196Seric **  BUILDFNAME -- build full name from gecos style entry.
3154375Seric **
3165196Seric **	This routine interprets the strange entry that would appear
3175196Seric **	in the GECOS field of the password file.
3185196Seric **
3194375Seric **	Parameters:
3205196Seric **		p -- name to build.
3215196Seric **		login -- the login name of this user (for &).
3225196Seric **		buf -- place to put the result.
3234375Seric **
3244375Seric **	Returns:
3254375Seric **		none.
3264375Seric **
3274375Seric **	Side Effects:
3284375Seric **		none.
3294375Seric */
3304375Seric 
3315196Seric buildfname(p, login, buf)
3325196Seric 	register char *p;
3335196Seric 	char *login;
3344375Seric 	char *buf;
3354375Seric {
3364375Seric 	register char *bp = buf;
3374375Seric 
3384438Seric 	if (*p == '*')
3394438Seric 		p++;
3406278Seric 	while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
3414375Seric 	{
3424375Seric 		if (*p == '&')
3434375Seric 		{
3445196Seric 			(void) strcpy(bp, login);
3454375Seric 			*bp = toupper(*bp);
3464375Seric 			while (*bp != '\0')
3474375Seric 				bp++;
3484375Seric 			p++;
3494375Seric 		}
3504375Seric 		else
3514375Seric 			*bp++ = *p++;
3524375Seric 	}
3534375Seric 	*bp = '\0';
3544375Seric }
3554375Seric /*
3564538Seric **  SAFEFILE -- return true if a file exists and is safe for a user.
3574538Seric **
3584538Seric **	Parameters:
3594538Seric **		fn -- filename to check.
3604538Seric **		uid -- uid to compare against.
3614538Seric **		mode -- mode bits that must match.
3624538Seric **
3634538Seric **	Returns:
3644538Seric **		TRUE if fn exists, is owned by uid, and matches mode.
3654538Seric **		FALSE otherwise.
3664538Seric **
3674538Seric **	Side Effects:
3684538Seric **		none.
3694538Seric */
3704538Seric 
3714538Seric bool
3724538Seric safefile(fn, uid, mode)
3734538Seric 	char *fn;
3744538Seric 	int uid;
3754538Seric 	int mode;
3764538Seric {
3774538Seric 	struct stat stbuf;
3784538Seric 
3794538Seric 	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
3804538Seric 	    (stbuf.st_mode & mode) == mode)
3814538Seric 		return (TRUE);
38211936Seric 	errno = 0;
3834538Seric 	return (FALSE);
3844538Seric }
3854538Seric /*
3864557Seric **  FIXCRLF -- fix <CR><LF> in line.
3874557Seric **
3884557Seric **	Looks for the <CR><LF> combination and turns it into the
3894557Seric **	UNIX canonical <NL> character.  It only takes one line,
3904557Seric **	i.e., it is assumed that the first <NL> found is the end
3914557Seric **	of the line.
3924557Seric **
3934557Seric **	Parameters:
3944557Seric **		line -- the line to fix.
3954557Seric **		stripnl -- if true, strip the newline also.
3964557Seric **
3974557Seric **	Returns:
3984557Seric **		none.
3994557Seric **
4004557Seric **	Side Effects:
4014557Seric **		line is changed in place.
4024557Seric */
4034557Seric 
4044557Seric fixcrlf(line, stripnl)
4054557Seric 	char *line;
4064557Seric 	bool stripnl;
4074557Seric {
4084557Seric 	register char *p;
4094557Seric 
4104557Seric 	p = index(line, '\n');
4114557Seric 	if (p == NULL)
4124557Seric 		return;
4134794Seric 	if (p[-1] == '\r')
4144557Seric 		p--;
4154557Seric 	if (!stripnl)
4164557Seric 		*p++ = '\n';
4174557Seric 	*p = '\0';
4184557Seric }
4194557Seric /*
4206890Seric **  DFOPEN -- determined file open
4216890Seric **
4226890Seric **	This routine has the semantics of fopen, except that it will
4236890Seric **	keep trying a few times to make this happen.  The idea is that
4246890Seric **	on very loaded systems, we may run out of resources (inodes,
4256890Seric **	whatever), so this tries to get around it.
4266890Seric */
4276890Seric 
4286890Seric FILE *
4296890Seric dfopen(filename, mode)
4306890Seric 	char *filename;
4316890Seric 	char *mode;
4326890Seric {
4336890Seric 	register int tries;
4346890Seric 	register FILE *fp;
4356890Seric 
4366890Seric 	for (tries = 0; tries < 10; tries++)
4376890Seric 	{
43825618Seric 		sleep((unsigned) (10 * tries));
4396890Seric 		errno = 0;
4406890Seric 		fp = fopen(filename, mode);
4419376Seric 		if (fp != NULL)
4426890Seric 			break;
4439376Seric 		if (errno != ENFILE && errno != EINTR)
4449376Seric 			break;
4456890Seric 	}
44611936Seric 	errno = 0;
4476890Seric 	return (fp);
4486890Seric }
4497124Seric /*
4507124Seric **  PUTLINE -- put a line like fputs obeying SMTP conventions
4517124Seric **
4527753Seric **	This routine always guarantees outputing a newline (or CRLF,
4537753Seric **	as appropriate) at the end of the string.
4547753Seric **
4557124Seric **	Parameters:
4567124Seric **		l -- line to put.
4577124Seric **		fp -- file to put it onto.
45810172Seric **		m -- the mailer used to control output.
4597124Seric **
4607124Seric **	Returns:
4617124Seric **		none
4627124Seric **
4637124Seric **	Side Effects:
4647124Seric **		output of l to fp.
4657124Seric */
4667124Seric 
4677753Seric # define SMTPLINELIM	990	/* maximum line length */
4687124Seric 
46910172Seric putline(l, fp, m)
4707753Seric 	register char *l;
4717124Seric 	FILE *fp;
47210172Seric 	MAILER *m;
4737124Seric {
4747124Seric 	register char *p;
4757753Seric 	char svchar;
4767124Seric 
47711275Seric 	/* strip out 0200 bits -- these can look like TELNET protocol */
47811275Seric 	if (bitnset(M_LIMITS, m->m_flags))
47911275Seric 	{
48011275Seric 		p = l;
48111275Seric 		while ((*p++ &= ~0200) != 0)
48211275Seric 			continue;
48311275Seric 	}
48411275Seric 
4857753Seric 	do
4867124Seric 	{
4877753Seric 		/* find the end of the line */
4887753Seric 		p = index(l, '\n');
4897753Seric 		if (p == NULL)
4907753Seric 			p = &l[strlen(l)];
4917124Seric 
4927753Seric 		/* check for line overflow */
49311275Seric 		while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags))
4947753Seric 		{
4957753Seric 			register char *q = &l[SMTPLINELIM - 1];
4967124Seric 
4977753Seric 			svchar = *q;
4987753Seric 			*q = '\0';
49910685Seric 			if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
50023105Seric 				(void) putc('.', fp);
5017753Seric 			fputs(l, fp);
50223105Seric 			(void) putc('!', fp);
50310326Seric 			fputs(m->m_eol, fp);
5047753Seric 			*q = svchar;
5057753Seric 			l = q;
5067753Seric 		}
5077124Seric 
5087753Seric 		/* output last part */
5097753Seric 		svchar = *p;
5107753Seric 		*p = '\0';
51110685Seric 		if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
51223105Seric 			(void) putc('.', fp);
5137124Seric 		fputs(l, fp);
51410326Seric 		fputs(m->m_eol, fp);
5157753Seric 		*p = svchar;
5167753Seric 		l = p;
5177753Seric 		if (*l == '\n')
5187753Seric 			l++;
5197753Seric 	} while (l[0] != '\0');
5207124Seric }
5217676Seric /*
5227676Seric **  XUNLINK -- unlink a file, doing logging as appropriate.
5237676Seric **
5247676Seric **	Parameters:
5257676Seric **		f -- name of file to unlink.
5267676Seric **
5277676Seric **	Returns:
5287676Seric **		none.
5297676Seric **
5307676Seric **	Side Effects:
5317676Seric **		f is unlinked.
5327676Seric */
5337676Seric 
5347676Seric xunlink(f)
5357676Seric 	char *f;
5367676Seric {
5377676Seric 	register int i;
5387676Seric 
5397676Seric # ifdef LOG
5407676Seric 	if (LogLevel > 20)
5417812Seric 		syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
5427676Seric # endif LOG
5437676Seric 
5447676Seric 	i = unlink(f);
5457676Seric # ifdef LOG
5467676Seric 	if (i < 0 && LogLevel > 21)
5477942Seric 		syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
5487676Seric # endif LOG
5497676Seric }
5507685Seric /*
55114885Seric **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
5527685Seric **
5537685Seric **	Parameters:
5547685Seric **		buf -- place to put the input line.
5557685Seric **		siz -- size of buf.
5567685Seric **		fp -- file to read from.
5577685Seric **
5587685Seric **	Returns:
55915533Seric **		NULL on error (including timeout).  This will also leave
56015533Seric **			buf containing a null string.
5617685Seric **		buf otherwise.
5627685Seric **
5637685Seric **	Side Effects:
5647685Seric **		none.
5657685Seric */
5667685Seric 
56714885Seric static jmp_buf	CtxReadTimeout;
5687685Seric 
56916138Seric #ifndef ETIMEDOUT
57016138Seric #define ETIMEDOUT	EINTR
57116138Seric #endif
57216138Seric 
5737685Seric char *
5747685Seric sfgets(buf, siz, fp)
5757685Seric 	char *buf;
5767685Seric 	int siz;
5777685Seric 	FILE *fp;
5787685Seric {
5797942Seric 	register EVENT *ev = NULL;
5807685Seric 	register char *p;
5817685Seric 	extern readtimeout();
5827685Seric 
58314885Seric 	/* set the timeout */
5847942Seric 	if (ReadTimeout != 0)
58514885Seric 	{
58614885Seric 		if (setjmp(CtxReadTimeout) != 0)
58714885Seric 		{
58816138Seric 			errno = ETIMEDOUT;
58925050Seric 			syserr("net timeout");
59019037Seric 			buf[0] = '\0';
59114885Seric 			return (NULL);
59214885Seric 		}
59316138Seric 		ev = setevent((time_t) ReadTimeout, readtimeout, 0);
59414885Seric 	}
59514885Seric 
59614885Seric 	/* try to read */
59715533Seric 	p = NULL;
59815533Seric 	while (p == NULL && !feof(fp) && !ferror(fp))
5997942Seric 	{
6007942Seric 		errno = 0;
6017942Seric 		p = fgets(buf, siz, fp);
60215533Seric 		if (errno == EINTR)
60315533Seric 			clearerr(fp);
60415533Seric 	}
60514885Seric 
60614885Seric 	/* clear the event if it has not sprung */
6077685Seric 	clrevent(ev);
60814885Seric 
60914885Seric 	/* clean up the books and exit */
6108055Seric 	LineNumber++;
61115533Seric 	if (p == NULL)
61216880Seric 	{
61315533Seric 		buf[0] = '\0';
61416880Seric 		return (NULL);
61516880Seric 	}
61616880Seric 	for (p = buf; *p != '\0'; p++)
61716880Seric 		*p &= ~0200;
61816880Seric 	return (buf);
6197685Seric }
6207685Seric 
6217685Seric static
6227685Seric readtimeout()
6237685Seric {
62414885Seric 	longjmp(CtxReadTimeout, 1);
6257685Seric }
6267786Seric /*
6277786Seric **  FGETFOLDED -- like fgets, but know about folded lines.
6287786Seric **
6297786Seric **	Parameters:
6307786Seric **		buf -- place to put result.
6317786Seric **		n -- bytes available.
6327786Seric **		f -- file to read from.
6337786Seric **
6347786Seric **	Returns:
6357786Seric **		buf on success, NULL on error or EOF.
6367786Seric **
6377786Seric **	Side Effects:
6387786Seric **		buf gets lines from f, with continuation lines (lines
6397786Seric **		with leading white space) appended.  CRLF's are mapped
6407786Seric **		into single newlines.  Any trailing NL is stripped.
6417786Seric */
6427786Seric 
6437786Seric char *
6447786Seric fgetfolded(buf, n, f)
6457786Seric 	char *buf;
6467786Seric 	register int n;
6477786Seric 	FILE *f;
6487786Seric {
6497786Seric 	register char *p = buf;
6507786Seric 	register int i;
6517786Seric 
6527786Seric 	n--;
65317350Seric 	while ((i = getc(f)) != EOF)
6547786Seric 	{
65517350Seric 		if (i == '\r')
65617350Seric 		{
65717350Seric 			i = getc(f);
65817350Seric 			if (i != '\n')
65917350Seric 			{
66017350Seric 				if (i != EOF)
66123105Seric 					(void) ungetc(i, f);
66217350Seric 				i = '\r';
66317350Seric 			}
66417350Seric 		}
66517350Seric 		if (--n > 0)
66617350Seric 			*p++ = i;
66717350Seric 		if (i == '\n')
66817350Seric 		{
66917350Seric 			LineNumber++;
67017350Seric 			i = getc(f);
67117350Seric 			if (i != EOF)
67223105Seric 				(void) ungetc(i, f);
67317350Seric 			if (i != ' ' && i != '\t')
67417350Seric 			{
67517350Seric 				*--p = '\0';
67617350Seric 				return (buf);
67717350Seric 			}
67817350Seric 		}
6797786Seric 	}
6807786Seric 	return (NULL);
6817786Seric }
6827860Seric /*
6837886Seric **  CURTIME -- return current time.
6847886Seric **
6857886Seric **	Parameters:
6867886Seric **		none.
6877886Seric **
6887886Seric **	Returns:
6897886Seric **		the current time.
6907886Seric **
6917886Seric **	Side Effects:
6927886Seric **		none.
6937886Seric */
6947886Seric 
6957886Seric time_t
6967886Seric curtime()
6977886Seric {
6987886Seric 	auto time_t t;
6997886Seric 
7007886Seric 	(void) time(&t);
7017886Seric 	return (t);
7027886Seric }
7038264Seric /*
7048264Seric **  ATOBOOL -- convert a string representation to boolean.
7058264Seric **
7068264Seric **	Defaults to "TRUE"
7078264Seric **
7088264Seric **	Parameters:
7098264Seric **		s -- string to convert.  Takes "tTyY" as true,
7108264Seric **			others as false.
7118264Seric **
7128264Seric **	Returns:
7138264Seric **		A boolean representation of the string.
7148264Seric **
7158264Seric **	Side Effects:
7168264Seric **		none.
7178264Seric */
7188264Seric 
7198264Seric bool
7208264Seric atobool(s)
7218264Seric 	register char *s;
7228264Seric {
7238264Seric 	if (*s == '\0' || index("tTyY", *s) != NULL)
7248264Seric 		return (TRUE);
7258264Seric 	return (FALSE);
7268264Seric }
7279048Seric /*
7289048Seric **  ATOOCT -- convert a string representation to octal.
7299048Seric **
7309048Seric **	Parameters:
7319048Seric **		s -- string to convert.
7329048Seric **
7339048Seric **	Returns:
7349048Seric **		An integer representing the string interpreted as an
7359048Seric **		octal number.
7369048Seric **
7379048Seric **	Side Effects:
7389048Seric **		none.
7399048Seric */
7409048Seric 
7419048Seric atooct(s)
7429048Seric 	register char *s;
7439048Seric {
7449048Seric 	register int i = 0;
7459048Seric 
7469048Seric 	while (*s >= '0' && *s <= '7')
7479048Seric 		i = (i << 3) | (*s++ - '0');
7489048Seric 	return (i);
7499048Seric }
7509376Seric /*
7519376Seric **  WAITFOR -- wait for a particular process id.
7529376Seric **
7539376Seric **	Parameters:
7549376Seric **		pid -- process id to wait for.
7559376Seric **
7569376Seric **	Returns:
7579376Seric **		status of pid.
7589376Seric **		-1 if pid never shows up.
7599376Seric **
7609376Seric **	Side Effects:
7619376Seric **		none.
7629376Seric */
7639376Seric 
7649376Seric waitfor(pid)
7659376Seric 	int pid;
7669376Seric {
7679376Seric 	auto int st;
7689376Seric 	int i;
7699376Seric 
7709376Seric 	do
7719376Seric 	{
7729376Seric 		errno = 0;
7739376Seric 		i = wait(&st);
7749376Seric 	} while ((i >= 0 || errno == EINTR) && i != pid);
7759376Seric 	if (i < 0)
7769376Seric 		st = -1;
7779376Seric 	return (st);
7789376Seric }
7799376Seric /*
78010685Seric **  BITINTERSECT -- tell if two bitmaps intersect
78110685Seric **
78210685Seric **	Parameters:
78310685Seric **		a, b -- the bitmaps in question
78410685Seric **
78510685Seric **	Returns:
78610685Seric **		TRUE if they have a non-null intersection
78710685Seric **		FALSE otherwise
78810685Seric **
78910685Seric **	Side Effects:
79010685Seric **		none.
79110685Seric */
79210685Seric 
79310685Seric bool
79410685Seric bitintersect(a, b)
79510685Seric 	BITMAP a;
79610685Seric 	BITMAP b;
79710685Seric {
79810685Seric 	int i;
79910685Seric 
80010685Seric 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
80110685Seric 		if ((a[i] & b[i]) != 0)
80210685Seric 			return (TRUE);
80310685Seric 	return (FALSE);
80410685Seric }
80510685Seric /*
80610685Seric **  BITZEROP -- tell if a bitmap is all zero
80710685Seric **
80810685Seric **	Parameters:
80910685Seric **		map -- the bit map to check
81010685Seric **
81110685Seric **	Returns:
81210685Seric **		TRUE if map is all zero.
81310685Seric **		FALSE if there are any bits set in map.
81410685Seric **
81510685Seric **	Side Effects:
81610685Seric **		none.
81710685Seric */
81810685Seric 
81910685Seric bool
82010685Seric bitzerop(map)
82110685Seric 	BITMAP map;
82210685Seric {
82310685Seric 	int i;
82410685Seric 
82510685Seric 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
82610685Seric 		if (map[i] != 0)
82710685Seric 			return (FALSE);
82810685Seric 	return (TRUE);
82910685Seric }
830