xref: /csrg-svn/usr.sbin/sendmail/src/util.c (revision 16897)
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*16897Seric SCCSID(@(#)util.c	4.8		08/11/84);
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!!");
13910685Seric 		abort();
14010685Seric 		/* exit(EX_UNAVAILABLE); */
141298Seric 	}
142298Seric 	return (p);
143298Seric }
144298Seric /*
1453151Seric **  COPYPLIST -- copy list of pointers.
1463151Seric **
1473151Seric **	This routine is the equivalent of newstr for lists of
1483151Seric **	pointers.
1493151Seric **
1503151Seric **	Parameters:
1513151Seric **		list -- list of pointers to copy.
1523151Seric **			Must be NULL terminated.
1533151Seric **		copycont -- if TRUE, copy the contents of the vector
1543151Seric **			(which must be a string) also.
1553151Seric **
1563151Seric **	Returns:
1573151Seric **		a copy of 'list'.
1583151Seric **
1593151Seric **	Side Effects:
1603151Seric **		none.
1613151Seric */
1623151Seric 
1633151Seric char **
1643151Seric copyplist(list, copycont)
1653151Seric 	char **list;
1663151Seric 	bool copycont;
1673151Seric {
1683151Seric 	register char **vp;
1693151Seric 	register char **newvp;
1703151Seric 
1713151Seric 	for (vp = list; *vp != NULL; vp++)
1723151Seric 		continue;
1733151Seric 
1743151Seric 	vp++;
1753151Seric 
176*16897Seric 	newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
177*16897Seric 	bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp);
1783151Seric 
1793151Seric 	if (copycont)
1803151Seric 	{
1813151Seric 		for (vp = newvp; *vp != NULL; vp++)
1823151Seric 			*vp = newstr(*vp);
1833151Seric 	}
1843151Seric 
1853151Seric 	return (newvp);
1863151Seric }
1873151Seric /*
1883151Seric **  PRINTAV -- print argument vector.
1893151Seric **
1903151Seric **	Parameters:
1913151Seric **		av -- argument vector.
1923151Seric **
1933151Seric **	Returns:
1943151Seric **		none.
1953151Seric **
1963151Seric **	Side Effects:
1973151Seric **		prints av.
1983151Seric */
1993151Seric 
2003151Seric # ifdef DEBUG
2013151Seric printav(av)
2023151Seric 	register char **av;
2033151Seric {
2043151Seric 	while (*av != NULL)
2053151Seric 	{
2068063Seric 		if (tTd(0, 44))
2078063Seric 			printf("\n\t%08x=", *av);
2088063Seric 		else
2098063Seric 			putchar(' ');
2103151Seric 		xputs(*av++);
2113151Seric 	}
2128063Seric 	putchar('\n');
2133151Seric }
2143151Seric # endif DEBUG
2153151Seric /*
2163151Seric **  LOWER -- turn letter into lower case.
2173151Seric **
2183151Seric **	Parameters:
2193151Seric **		c -- character to turn into lower case.
2203151Seric **
2213151Seric **	Returns:
2223151Seric **		c, in lower case.
2233151Seric **
2243151Seric **	Side Effects:
2253151Seric **		none.
2263151Seric */
2273151Seric 
2283151Seric char
2293151Seric lower(c)
2303151Seric 	register char c;
2313151Seric {
2323151Seric 	if (isascii(c) && isupper(c))
2333151Seric 		c = c - 'A' + 'a';
2343151Seric 	return (c);
2353151Seric }
2363151Seric /*
2373151Seric **  XPUTS -- put string doing control escapes.
2383151Seric **
2393151Seric **	Parameters:
2403151Seric **		s -- string to put.
2413151Seric **
2423151Seric **	Returns:
2433151Seric **		none.
2443151Seric **
2453151Seric **	Side Effects:
2463151Seric **		output to stdout
2473151Seric */
2483151Seric 
2493151Seric # ifdef DEBUG
2503151Seric xputs(s)
2513151Seric 	register char *s;
2523151Seric {
2533151Seric 	register char c;
2543151Seric 
2558055Seric 	if (s == NULL)
2568055Seric 	{
2578055Seric 		printf("<null>");
2588055Seric 		return;
2598055Seric 	}
2608063Seric 	putchar('"');
2613151Seric 	while ((c = *s++) != '\0')
2623151Seric 	{
2633151Seric 		if (!isascii(c))
2643151Seric 		{
2653151Seric 			putchar('\\');
2663151Seric 			c &= 0177;
2673151Seric 		}
26810326Seric 		if (c < 040 || c >= 0177)
2693151Seric 		{
2703151Seric 			putchar('^');
27110326Seric 			c ^= 0100;
2723151Seric 		}
2733151Seric 		putchar(c);
2743151Seric 	}
2758063Seric 	putchar('"');
2764086Seric 	(void) fflush(stdout);
2773151Seric }
2783151Seric # endif DEBUG
2793151Seric /*
2803151Seric **  MAKELOWER -- Translate a line into lower case
2813151Seric **
2823151Seric **	Parameters:
2833151Seric **		p -- the string to translate.  If NULL, return is
2843151Seric **			immediate.
2853151Seric **
2863151Seric **	Returns:
2873151Seric **		none.
2883151Seric **
2893151Seric **	Side Effects:
2903151Seric **		String pointed to by p is translated to lower case.
2913151Seric **
2923151Seric **	Called By:
2933151Seric **		parse
2943151Seric */
2953151Seric 
2963151Seric makelower(p)
2973151Seric 	register char *p;
2983151Seric {
2993151Seric 	register char c;
3003151Seric 
3013151Seric 	if (p == NULL)
3023151Seric 		return;
3033151Seric 	for (; (c = *p) != '\0'; p++)
3043151Seric 		if (isascii(c) && isupper(c))
3053151Seric 			*p = c - 'A' + 'a';
3063151Seric }
3074059Seric /*
3084059Seric **  SAMEWORD -- return TRUE if the words are the same
3094059Seric **
3104059Seric **	Ignores case.
3114059Seric **
3124059Seric **	Parameters:
3134059Seric **		a, b -- the words to compare.
3144059Seric **
3154059Seric **	Returns:
3164059Seric **		TRUE if a & b match exactly (modulo case)
3174059Seric **		FALSE otherwise.
3184059Seric **
3194059Seric **	Side Effects:
3204059Seric **		none.
3214059Seric */
3224059Seric 
3234059Seric bool
3244059Seric sameword(a, b)
3254059Seric 	register char *a, *b;
3264059Seric {
3274059Seric 	while (lower(*a) == lower(*b))
3284059Seric 	{
3294059Seric 		if (*a == '\0')
3304059Seric 			return (TRUE);
3314059Seric 		a++;
3324059Seric 		b++;
3334059Seric 	}
3344059Seric 	return (FALSE);
3354059Seric }
3364086Seric /*
3375196Seric **  BUILDFNAME -- build full name from gecos style entry.
3384375Seric **
3395196Seric **	This routine interprets the strange entry that would appear
3405196Seric **	in the GECOS field of the password file.
3415196Seric **
3424375Seric **	Parameters:
3435196Seric **		p -- name to build.
3445196Seric **		login -- the login name of this user (for &).
3455196Seric **		buf -- place to put the result.
3464375Seric **
3474375Seric **	Returns:
3484375Seric **		none.
3494375Seric **
3504375Seric **	Side Effects:
3514375Seric **		none.
3524375Seric */
3534375Seric 
3545196Seric buildfname(p, login, buf)
3555196Seric 	register char *p;
3565196Seric 	char *login;
3574375Seric 	char *buf;
3584375Seric {
3594375Seric 	register char *bp = buf;
3604375Seric 
3614438Seric 	if (*p == '*')
3624438Seric 		p++;
3636278Seric 	while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
3644375Seric 	{
3654375Seric 		if (*p == '&')
3664375Seric 		{
3675196Seric 			(void) strcpy(bp, login);
3684375Seric 			*bp = toupper(*bp);
3694375Seric 			while (*bp != '\0')
3704375Seric 				bp++;
3714375Seric 			p++;
3724375Seric 		}
3734375Seric 		else
3744375Seric 			*bp++ = *p++;
3754375Seric 	}
3764375Seric 	*bp = '\0';
3774375Seric }
3784375Seric /*
3794538Seric **  SAFEFILE -- return true if a file exists and is safe for a user.
3804538Seric **
3814538Seric **	Parameters:
3824538Seric **		fn -- filename to check.
3834538Seric **		uid -- uid to compare against.
3844538Seric **		mode -- mode bits that must match.
3854538Seric **
3864538Seric **	Returns:
3874538Seric **		TRUE if fn exists, is owned by uid, and matches mode.
3884538Seric **		FALSE otherwise.
3894538Seric **
3904538Seric **	Side Effects:
3914538Seric **		none.
3924538Seric */
3934538Seric 
3944538Seric bool
3954538Seric safefile(fn, uid, mode)
3964538Seric 	char *fn;
3974538Seric 	int uid;
3984538Seric 	int mode;
3994538Seric {
4004538Seric 	struct stat stbuf;
4014538Seric 
4024538Seric 	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
4034538Seric 	    (stbuf.st_mode & mode) == mode)
4044538Seric 		return (TRUE);
40511936Seric 	errno = 0;
4064538Seric 	return (FALSE);
4074538Seric }
4084538Seric /*
4094557Seric **  FIXCRLF -- fix <CR><LF> in line.
4104557Seric **
4114557Seric **	Looks for the <CR><LF> combination and turns it into the
4124557Seric **	UNIX canonical <NL> character.  It only takes one line,
4134557Seric **	i.e., it is assumed that the first <NL> found is the end
4144557Seric **	of the line.
4154557Seric **
4164557Seric **	Parameters:
4174557Seric **		line -- the line to fix.
4184557Seric **		stripnl -- if true, strip the newline also.
4194557Seric **
4204557Seric **	Returns:
4214557Seric **		none.
4224557Seric **
4234557Seric **	Side Effects:
4244557Seric **		line is changed in place.
4254557Seric */
4264557Seric 
4274557Seric fixcrlf(line, stripnl)
4284557Seric 	char *line;
4294557Seric 	bool stripnl;
4304557Seric {
4314557Seric 	register char *p;
4324557Seric 
4334557Seric 	p = index(line, '\n');
4344557Seric 	if (p == NULL)
4354557Seric 		return;
4364794Seric 	if (p[-1] == '\r')
4374557Seric 		p--;
4384557Seric 	if (!stripnl)
4394557Seric 		*p++ = '\n';
4404557Seric 	*p = '\0';
4414557Seric }
4424557Seric /*
4434086Seric **  SYSLOG -- fake entry to fool lint
4444086Seric */
4454086Seric 
4464086Seric # ifdef LOG
4474086Seric # ifdef lint
4484086Seric 
4494086Seric /*VARARGS2*/
4504086Seric syslog(pri, fmt, args)
4514086Seric 	int pri;
4524086Seric 	char *fmt;
4534086Seric {
4544086Seric 	pri = *fmt;
4554086Seric 	args = pri;
4564086Seric 	pri = args;
4574086Seric }
4584086Seric 
4594086Seric # endif lint
4604086Seric # endif LOG
4616890Seric /*
4626890Seric **  DFOPEN -- determined file open
4636890Seric **
4646890Seric **	This routine has the semantics of fopen, except that it will
4656890Seric **	keep trying a few times to make this happen.  The idea is that
4666890Seric **	on very loaded systems, we may run out of resources (inodes,
4676890Seric **	whatever), so this tries to get around it.
4686890Seric */
4696890Seric 
4706890Seric FILE *
4716890Seric dfopen(filename, mode)
4726890Seric 	char *filename;
4736890Seric 	char *mode;
4746890Seric {
4756890Seric 	register int tries;
4766890Seric 	register FILE *fp;
4776890Seric 
4786890Seric 	for (tries = 0; tries < 10; tries++)
4796890Seric 	{
4806890Seric 		sleep(10 * tries);
4816890Seric 		errno = 0;
4826890Seric 		fp = fopen(filename, mode);
4839376Seric 		if (fp != NULL)
4846890Seric 			break;
4859376Seric 		if (errno != ENFILE && errno != EINTR)
4869376Seric 			break;
4876890Seric 	}
48811936Seric 	errno = 0;
4896890Seric 	return (fp);
4906890Seric }
4917124Seric /*
4927124Seric **  PUTLINE -- put a line like fputs obeying SMTP conventions
4937124Seric **
4947753Seric **	This routine always guarantees outputing a newline (or CRLF,
4957753Seric **	as appropriate) at the end of the string.
4967753Seric **
4977124Seric **	Parameters:
4987124Seric **		l -- line to put.
4997124Seric **		fp -- file to put it onto.
50010172Seric **		m -- the mailer used to control output.
5017124Seric **
5027124Seric **	Returns:
5037124Seric **		none
5047124Seric **
5057124Seric **	Side Effects:
5067124Seric **		output of l to fp.
5077124Seric */
5087124Seric 
5097753Seric # define SMTPLINELIM	990	/* maximum line length */
5107124Seric 
51110172Seric putline(l, fp, m)
5127753Seric 	register char *l;
5137124Seric 	FILE *fp;
51410172Seric 	MAILER *m;
5157124Seric {
5167124Seric 	register char *p;
5177753Seric 	char svchar;
5187124Seric 
51911275Seric 	/* strip out 0200 bits -- these can look like TELNET protocol */
52011275Seric 	if (bitnset(M_LIMITS, m->m_flags))
52111275Seric 	{
52211275Seric 		p = l;
52311275Seric 		while ((*p++ &= ~0200) != 0)
52411275Seric 			continue;
52511275Seric 	}
52611275Seric 
5277753Seric 	do
5287124Seric 	{
5297753Seric 		/* find the end of the line */
5307753Seric 		p = index(l, '\n');
5317753Seric 		if (p == NULL)
5327753Seric 			p = &l[strlen(l)];
5337124Seric 
5347753Seric 		/* check for line overflow */
53511275Seric 		while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags))
5367753Seric 		{
5377753Seric 			register char *q = &l[SMTPLINELIM - 1];
5387124Seric 
5397753Seric 			svchar = *q;
5407753Seric 			*q = '\0';
54110685Seric 			if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
54210172Seric 				fputc('.', fp);
5437753Seric 			fputs(l, fp);
54410066Seric 			fputc('!', fp);
54510326Seric 			fputs(m->m_eol, fp);
5467753Seric 			*q = svchar;
5477753Seric 			l = q;
5487753Seric 		}
5497124Seric 
5507753Seric 		/* output last part */
5517753Seric 		svchar = *p;
5527753Seric 		*p = '\0';
55310685Seric 		if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
55410172Seric 			fputc('.', fp);
5557124Seric 		fputs(l, fp);
55610326Seric 		fputs(m->m_eol, fp);
5577753Seric 		*p = svchar;
5587753Seric 		l = p;
5597753Seric 		if (*l == '\n')
5607753Seric 			l++;
5617753Seric 	} while (l[0] != '\0');
5627124Seric }
5637676Seric /*
5647676Seric **  XUNLINK -- unlink a file, doing logging as appropriate.
5657676Seric **
5667676Seric **	Parameters:
5677676Seric **		f -- name of file to unlink.
5687676Seric **
5697676Seric **	Returns:
5707676Seric **		none.
5717676Seric **
5727676Seric **	Side Effects:
5737676Seric **		f is unlinked.
5747676Seric */
5757676Seric 
5767676Seric xunlink(f)
5777676Seric 	char *f;
5787676Seric {
5797676Seric 	register int i;
5807676Seric 
5817676Seric # ifdef LOG
5827676Seric 	if (LogLevel > 20)
5837812Seric 		syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
5847676Seric # endif LOG
5857676Seric 
5867676Seric 	i = unlink(f);
5877676Seric # ifdef LOG
5887676Seric 	if (i < 0 && LogLevel > 21)
5897942Seric 		syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
5907676Seric # endif LOG
5917676Seric }
5927685Seric /*
59314885Seric **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
5947685Seric **
5957685Seric **	Parameters:
5967685Seric **		buf -- place to put the input line.
5977685Seric **		siz -- size of buf.
5987685Seric **		fp -- file to read from.
5997685Seric **
6007685Seric **	Returns:
60115533Seric **		NULL on error (including timeout).  This will also leave
60215533Seric **			buf containing a null string.
6037685Seric **		buf otherwise.
6047685Seric **
6057685Seric **	Side Effects:
6067685Seric **		none.
6077685Seric */
6087685Seric 
60914885Seric static jmp_buf	CtxReadTimeout;
6107685Seric 
61116138Seric #ifndef ETIMEDOUT
61216138Seric #define ETIMEDOUT	EINTR
61316138Seric #endif
61416138Seric 
6157685Seric char *
6167685Seric sfgets(buf, siz, fp)
6177685Seric 	char *buf;
6187685Seric 	int siz;
6197685Seric 	FILE *fp;
6207685Seric {
6217942Seric 	register EVENT *ev = NULL;
6227685Seric 	register char *p;
6237685Seric 	extern readtimeout();
6247685Seric 
62514885Seric 	/* set the timeout */
6267942Seric 	if (ReadTimeout != 0)
62714885Seric 	{
62814885Seric 		if (setjmp(CtxReadTimeout) != 0)
62914885Seric 		{
63016138Seric 			errno = ETIMEDOUT;
63114885Seric 			syserr("sfgets: timeout on read (mailer may be hung)");
63214885Seric 			return (NULL);
63314885Seric 		}
63416138Seric 		ev = setevent((time_t) ReadTimeout, readtimeout, 0);
63514885Seric 	}
63614885Seric 
63714885Seric 	/* try to read */
63815533Seric 	p = NULL;
63915533Seric 	while (p == NULL && !feof(fp) && !ferror(fp))
6407942Seric 	{
6417942Seric 		errno = 0;
6427942Seric 		p = fgets(buf, siz, fp);
64315533Seric 		if (errno == EINTR)
64415533Seric 			clearerr(fp);
64515533Seric 	}
64614885Seric 
64714885Seric 	/* clear the event if it has not sprung */
6487685Seric 	clrevent(ev);
64914885Seric 
65014885Seric 	/* clean up the books and exit */
6518055Seric 	LineNumber++;
65215533Seric 	if (p == NULL)
65316880Seric 	{
65415533Seric 		buf[0] = '\0';
65516880Seric 		return (NULL);
65616880Seric 	}
65716880Seric 	for (p = buf; *p != '\0'; p++)
65816880Seric 		*p &= ~0200;
65916880Seric 	return (buf);
6607685Seric }
6617685Seric 
6627685Seric static
6637685Seric readtimeout()
6647685Seric {
66514885Seric 	longjmp(CtxReadTimeout, 1);
6667685Seric }
6677786Seric /*
6687786Seric **  FGETFOLDED -- like fgets, but know about folded lines.
6697786Seric **
6707786Seric **	Parameters:
6717786Seric **		buf -- place to put result.
6727786Seric **		n -- bytes available.
6737786Seric **		f -- file to read from.
6747786Seric **
6757786Seric **	Returns:
6767786Seric **		buf on success, NULL on error or EOF.
6777786Seric **
6787786Seric **	Side Effects:
6797786Seric **		buf gets lines from f, with continuation lines (lines
6807786Seric **		with leading white space) appended.  CRLF's are mapped
6817786Seric **		into single newlines.  Any trailing NL is stripped.
6827786Seric */
6837786Seric 
6847786Seric char *
6857786Seric fgetfolded(buf, n, f)
6867786Seric 	char *buf;
6877786Seric 	register int n;
6887786Seric 	FILE *f;
6897786Seric {
6907786Seric 	register char *p = buf;
6917786Seric 	register int i;
6927786Seric 
6937786Seric 	n--;
69410030Seric 	while (fgets(p, n, f) != NULL)
6957786Seric 	{
69610030Seric 		LineNumber++;
6977786Seric 		fixcrlf(p, TRUE);
6987786Seric 		i = fgetc(f);
6997786Seric 		if (i != EOF)
7007786Seric 			ungetc(i, f);
7017786Seric 		if (i != ' ' && i != '\t')
7027786Seric 			return (buf);
7037786Seric 		i = strlen(p);
7047786Seric 		p += i;
7057786Seric 		*p++ = '\n';
7067786Seric 		n -= i + 1;
7077786Seric 	}
7087786Seric 	return (NULL);
7097786Seric }
7107860Seric /*
7117886Seric **  CURTIME -- return current time.
7127886Seric **
7137886Seric **	Parameters:
7147886Seric **		none.
7157886Seric **
7167886Seric **	Returns:
7177886Seric **		the current time.
7187886Seric **
7197886Seric **	Side Effects:
7207886Seric **		none.
7217886Seric */
7227886Seric 
7237886Seric time_t
7247886Seric curtime()
7257886Seric {
7267886Seric 	auto time_t t;
7277886Seric 
7287886Seric 	(void) time(&t);
7297886Seric 	return (t);
7307886Seric }
7318264Seric /*
7328264Seric **  ATOBOOL -- convert a string representation to boolean.
7338264Seric **
7348264Seric **	Defaults to "TRUE"
7358264Seric **
7368264Seric **	Parameters:
7378264Seric **		s -- string to convert.  Takes "tTyY" as true,
7388264Seric **			others as false.
7398264Seric **
7408264Seric **	Returns:
7418264Seric **		A boolean representation of the string.
7428264Seric **
7438264Seric **	Side Effects:
7448264Seric **		none.
7458264Seric */
7468264Seric 
7478264Seric bool
7488264Seric atobool(s)
7498264Seric 	register char *s;
7508264Seric {
7518264Seric 	if (*s == '\0' || index("tTyY", *s) != NULL)
7528264Seric 		return (TRUE);
7538264Seric 	return (FALSE);
7548264Seric }
7559048Seric /*
7569048Seric **  ATOOCT -- convert a string representation to octal.
7579048Seric **
7589048Seric **	Parameters:
7599048Seric **		s -- string to convert.
7609048Seric **
7619048Seric **	Returns:
7629048Seric **		An integer representing the string interpreted as an
7639048Seric **		octal number.
7649048Seric **
7659048Seric **	Side Effects:
7669048Seric **		none.
7679048Seric */
7689048Seric 
7699048Seric atooct(s)
7709048Seric 	register char *s;
7719048Seric {
7729048Seric 	register int i = 0;
7739048Seric 
7749048Seric 	while (*s >= '0' && *s <= '7')
7759048Seric 		i = (i << 3) | (*s++ - '0');
7769048Seric 	return (i);
7779048Seric }
7789376Seric /*
7799376Seric **  WAITFOR -- wait for a particular process id.
7809376Seric **
7819376Seric **	Parameters:
7829376Seric **		pid -- process id to wait for.
7839376Seric **
7849376Seric **	Returns:
7859376Seric **		status of pid.
7869376Seric **		-1 if pid never shows up.
7879376Seric **
7889376Seric **	Side Effects:
7899376Seric **		none.
7909376Seric */
7919376Seric 
7929376Seric waitfor(pid)
7939376Seric 	int pid;
7949376Seric {
7959376Seric 	auto int st;
7969376Seric 	int i;
7979376Seric 
7989376Seric 	do
7999376Seric 	{
8009376Seric 		errno = 0;
8019376Seric 		i = wait(&st);
8029376Seric 	} while ((i >= 0 || errno == EINTR) && i != pid);
8039376Seric 	if (i < 0)
8049376Seric 		st = -1;
8059376Seric 	return (st);
8069376Seric }
8079376Seric /*
80810685Seric **  BITINTERSECT -- tell if two bitmaps intersect
80910685Seric **
81010685Seric **	Parameters:
81110685Seric **		a, b -- the bitmaps in question
81210685Seric **
81310685Seric **	Returns:
81410685Seric **		TRUE if they have a non-null intersection
81510685Seric **		FALSE otherwise
81610685Seric **
81710685Seric **	Side Effects:
81810685Seric **		none.
81910685Seric */
82010685Seric 
82110685Seric bool
82210685Seric bitintersect(a, b)
82310685Seric 	BITMAP a;
82410685Seric 	BITMAP b;
82510685Seric {
82610685Seric 	int i;
82710685Seric 
82810685Seric 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
82910685Seric 		if ((a[i] & b[i]) != 0)
83010685Seric 			return (TRUE);
83110685Seric 	return (FALSE);
83210685Seric }
83310685Seric /*
83410685Seric **  BITZEROP -- tell if a bitmap is all zero
83510685Seric **
83610685Seric **	Parameters:
83710685Seric **		map -- the bit map to check
83810685Seric **
83910685Seric **	Returns:
84010685Seric **		TRUE if map is all zero.
84110685Seric **		FALSE if there are any bits set in map.
84210685Seric **
84310685Seric **	Side Effects:
84410685Seric **		none.
84510685Seric */
84610685Seric 
84710685Seric bool
84810685Seric bitzerop(map)
84910685Seric 	BITMAP map;
85010685Seric {
85110685Seric 	int i;
85210685Seric 
85310685Seric 	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
85410685Seric 		if (map[i] != 0)
85510685Seric 			return (FALSE);
85610685Seric 	return (TRUE);
85710685Seric }
858