xref: /csrg-svn/usr.sbin/sendmail/src/util.c (revision 9043)
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*9043Seric SCCSID(@(#)util.c	3.33		11/03/82);
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 /*
51*9043Seric **  QSTRLEN -- give me the string length assuming 0200 bits add a char
52*9043Seric **
53*9043Seric **	Parameters:
54*9043Seric **		s -- the string to measure.
55*9043Seric **
56*9043Seric **	Reurns:
57*9043Seric **		The length of s, including space for backslash escapes.
58*9043Seric **
59*9043Seric **	Side Effects:
60*9043Seric **		none.
61*9043Seric */
62*9043Seric 
63*9043Seric qstrlen(s)
64*9043Seric 	register char *s;
65*9043Seric {
66*9043Seric 	register int l = 0;
67*9043Seric 	register char c;
68*9043Seric 
69*9043Seric 	while ((c = *s++) != '\0')
70*9043Seric 	{
71*9043Seric 		if (bitset(0200, c))
72*9043Seric 			l++;
73*9043Seric 		l++;
74*9043Seric 	}
75*9043Seric 	return (l);
76*9043Seric }
77*9043Seric /*
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 /*
1442900Seric **  NEWSTR -- make copy of string.
1452900Seric **
1462900Seric **	Space is allocated for it using xalloc.
1472900Seric **
1482900Seric **	Parameters:
1492900Seric **		string to copy.
1502900Seric **
1512900Seric **	Returns:
1522900Seric **		pointer to new string.
1532900Seric **
1542900Seric **	Side Effects:
1552900Seric **		none.
1562900Seric */
1572900Seric 
1582900Seric char *
1592900Seric newstr(s)
1602900Seric 	register char *s;
1612900Seric {
1622900Seric 	register char *p;
1632900Seric 
1647007Seric 	p = xalloc(strlen(s) + 1);
1657007Seric 	(void) strcpy(p, s);
1662900Seric 	return (p);
1672900Seric }
1683151Seric /*
1693151Seric **  COPYPLIST -- copy list of pointers.
1703151Seric **
1713151Seric **	This routine is the equivalent of newstr for lists of
1723151Seric **	pointers.
1733151Seric **
1743151Seric **	Parameters:
1753151Seric **		list -- list of pointers to copy.
1763151Seric **			Must be NULL terminated.
1773151Seric **		copycont -- if TRUE, copy the contents of the vector
1783151Seric **			(which must be a string) also.
1793151Seric **
1803151Seric **	Returns:
1813151Seric **		a copy of 'list'.
1823151Seric **
1833151Seric **	Side Effects:
1843151Seric **		none.
1853151Seric */
1863151Seric 
1873151Seric char **
1883151Seric copyplist(list, copycont)
1893151Seric 	char **list;
1903151Seric 	bool copycont;
1913151Seric {
1923151Seric 	register char **vp;
1933151Seric 	register char **newvp;
1943151Seric 
1953151Seric 	for (vp = list; *vp != NULL; vp++)
1963151Seric 		continue;
1973151Seric 
1983151Seric 	vp++;
1993151Seric 
2007007Seric 	newvp = (char **) xalloc((vp - list) * sizeof *vp);
2014086Seric 	bmove((char *) list, (char *) newvp, (vp - list) * sizeof *vp);
2023151Seric 
2033151Seric 	if (copycont)
2043151Seric 	{
2053151Seric 		for (vp = newvp; *vp != NULL; vp++)
2063151Seric 			*vp = newstr(*vp);
2073151Seric 	}
2083151Seric 
2093151Seric 	return (newvp);
2103151Seric }
2113151Seric /*
2123151Seric **  PRINTAV -- print argument vector.
2133151Seric **
2143151Seric **	Parameters:
2153151Seric **		av -- argument vector.
2163151Seric **
2173151Seric **	Returns:
2183151Seric **		none.
2193151Seric **
2203151Seric **	Side Effects:
2213151Seric **		prints av.
2223151Seric */
2233151Seric 
2243151Seric # ifdef DEBUG
2253151Seric printav(av)
2263151Seric 	register char **av;
2273151Seric {
2283151Seric 	while (*av != NULL)
2293151Seric 	{
2308063Seric 		if (tTd(0, 44))
2318063Seric 			printf("\n\t%08x=", *av);
2328063Seric 		else
2338063Seric 			putchar(' ');
2343151Seric 		xputs(*av++);
2353151Seric 	}
2368063Seric 	putchar('\n');
2373151Seric }
2383151Seric # endif DEBUG
2393151Seric /*
2403151Seric **  LOWER -- turn letter into lower case.
2413151Seric **
2423151Seric **	Parameters:
2433151Seric **		c -- character to turn into lower case.
2443151Seric **
2453151Seric **	Returns:
2463151Seric **		c, in lower case.
2473151Seric **
2483151Seric **	Side Effects:
2493151Seric **		none.
2503151Seric */
2513151Seric 
2523151Seric char
2533151Seric lower(c)
2543151Seric 	register char c;
2553151Seric {
2563151Seric 	if (isascii(c) && isupper(c))
2573151Seric 		c = c - 'A' + 'a';
2583151Seric 	return (c);
2593151Seric }
2603151Seric /*
2613151Seric **  XPUTS -- put string doing control escapes.
2623151Seric **
2633151Seric **	Parameters:
2643151Seric **		s -- string to put.
2653151Seric **
2663151Seric **	Returns:
2673151Seric **		none.
2683151Seric **
2693151Seric **	Side Effects:
2703151Seric **		output to stdout
2713151Seric */
2723151Seric 
2733151Seric # ifdef DEBUG
2743151Seric xputs(s)
2753151Seric 	register char *s;
2763151Seric {
2773151Seric 	register char c;
2783151Seric 
2798055Seric 	if (s == NULL)
2808055Seric 	{
2818055Seric 		printf("<null>");
2828055Seric 		return;
2838055Seric 	}
2848063Seric 	putchar('"');
2853151Seric 	while ((c = *s++) != '\0')
2863151Seric 	{
2873151Seric 		if (!isascii(c))
2883151Seric 		{
2893151Seric 			putchar('\\');
2903151Seric 			c &= 0177;
2913151Seric 		}
2923151Seric 		if (iscntrl(c))
2933151Seric 		{
2943151Seric 			putchar('^');
2953151Seric 			c |= 0100;
2963151Seric 		}
2973151Seric 		putchar(c);
2983151Seric 	}
2998063Seric 	putchar('"');
3004086Seric 	(void) fflush(stdout);
3013151Seric }
3023151Seric # endif DEBUG
3033151Seric /*
3043151Seric **  MAKELOWER -- Translate a line into lower case
3053151Seric **
3063151Seric **	Parameters:
3073151Seric **		p -- the string to translate.  If NULL, return is
3083151Seric **			immediate.
3093151Seric **
3103151Seric **	Returns:
3113151Seric **		none.
3123151Seric **
3133151Seric **	Side Effects:
3143151Seric **		String pointed to by p is translated to lower case.
3153151Seric **
3163151Seric **	Called By:
3173151Seric **		parse
3183151Seric */
3193151Seric 
3203151Seric makelower(p)
3213151Seric 	register char *p;
3223151Seric {
3233151Seric 	register char c;
3243151Seric 
3253151Seric 	if (p == NULL)
3263151Seric 		return;
3273151Seric 	for (; (c = *p) != '\0'; p++)
3283151Seric 		if (isascii(c) && isupper(c))
3293151Seric 			*p = c - 'A' + 'a';
3303151Seric }
3314059Seric /*
3324059Seric **  SAMEWORD -- return TRUE if the words are the same
3334059Seric **
3344059Seric **	Ignores case.
3354059Seric **
3364059Seric **	Parameters:
3374059Seric **		a, b -- the words to compare.
3384059Seric **
3394059Seric **	Returns:
3404059Seric **		TRUE if a & b match exactly (modulo case)
3414059Seric **		FALSE otherwise.
3424059Seric **
3434059Seric **	Side Effects:
3444059Seric **		none.
3454059Seric */
3464059Seric 
3474059Seric bool
3484059Seric sameword(a, b)
3494059Seric 	register char *a, *b;
3504059Seric {
3514059Seric 	while (lower(*a) == lower(*b))
3524059Seric 	{
3534059Seric 		if (*a == '\0')
3544059Seric 			return (TRUE);
3554059Seric 		a++;
3564059Seric 		b++;
3574059Seric 	}
3584059Seric 	return (FALSE);
3594059Seric }
3604086Seric /*
3614101Seric **  CLEAR -- clear a block of memory
3624101Seric **
3634101Seric **	Parameters:
3644101Seric **		p -- location to clear.
3654101Seric **		l -- number of bytes to clear.
3664101Seric **
3674101Seric **	Returns:
3684101Seric **		none.
3694101Seric **
3704101Seric **	Side Effects:
3714101Seric **		none.
3724101Seric */
3734101Seric 
3744101Seric clear(p, l)
3754101Seric 	register char *p;
3764101Seric 	register int l;
3774101Seric {
3784101Seric 	while (l-- > 0)
3794101Seric 		*p++ = 0;
3804101Seric }
3814101Seric /*
3825196Seric **  BUILDFNAME -- build full name from gecos style entry.
3834375Seric **
3845196Seric **	This routine interprets the strange entry that would appear
3855196Seric **	in the GECOS field of the password file.
3865196Seric **
3874375Seric **	Parameters:
3885196Seric **		p -- name to build.
3895196Seric **		login -- the login name of this user (for &).
3905196Seric **		buf -- place to put the result.
3914375Seric **
3924375Seric **	Returns:
3934375Seric **		none.
3944375Seric **
3954375Seric **	Side Effects:
3964375Seric **		none.
3974375Seric */
3984375Seric 
3995196Seric buildfname(p, login, buf)
4005196Seric 	register char *p;
4015196Seric 	char *login;
4024375Seric 	char *buf;
4034375Seric {
4044375Seric 	register char *bp = buf;
4054375Seric 
4064438Seric 	if (*p == '*')
4074438Seric 		p++;
4086278Seric 	while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
4094375Seric 	{
4104375Seric 		if (*p == '&')
4114375Seric 		{
4125196Seric 			(void) strcpy(bp, login);
4134375Seric 			*bp = toupper(*bp);
4144375Seric 			while (*bp != '\0')
4154375Seric 				bp++;
4164375Seric 			p++;
4174375Seric 		}
4184375Seric 		else
4194375Seric 			*bp++ = *p++;
4204375Seric 	}
4214375Seric 	*bp = '\0';
4224375Seric }
4234375Seric /*
4244538Seric **  SAFEFILE -- return true if a file exists and is safe for a user.
4254538Seric **
4264538Seric **	Parameters:
4274538Seric **		fn -- filename to check.
4284538Seric **		uid -- uid to compare against.
4294538Seric **		mode -- mode bits that must match.
4304538Seric **
4314538Seric **	Returns:
4324538Seric **		TRUE if fn exists, is owned by uid, and matches mode.
4334538Seric **		FALSE otherwise.
4344538Seric **
4354538Seric **	Side Effects:
4364538Seric **		none.
4374538Seric */
4384538Seric 
4394538Seric bool
4404538Seric safefile(fn, uid, mode)
4414538Seric 	char *fn;
4424538Seric 	int uid;
4434538Seric 	int mode;
4444538Seric {
4454538Seric 	struct stat stbuf;
4464538Seric 
4474538Seric 	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
4484538Seric 	    (stbuf.st_mode & mode) == mode)
4494538Seric 		return (TRUE);
4504538Seric 	return (FALSE);
4514538Seric }
4524538Seric /*
4534557Seric **  FIXCRLF -- fix <CR><LF> in line.
4544557Seric **
4554557Seric **	Looks for the <CR><LF> combination and turns it into the
4564557Seric **	UNIX canonical <NL> character.  It only takes one line,
4574557Seric **	i.e., it is assumed that the first <NL> found is the end
4584557Seric **	of the line.
4594557Seric **
4604557Seric **	Parameters:
4614557Seric **		line -- the line to fix.
4624557Seric **		stripnl -- if true, strip the newline also.
4634557Seric **
4644557Seric **	Returns:
4654557Seric **		none.
4664557Seric **
4674557Seric **	Side Effects:
4684557Seric **		line is changed in place.
4694557Seric */
4704557Seric 
4714557Seric fixcrlf(line, stripnl)
4724557Seric 	char *line;
4734557Seric 	bool stripnl;
4744557Seric {
4754557Seric 	register char *p;
4764557Seric 
4774557Seric 	p = index(line, '\n');
4784557Seric 	if (p == NULL)
4794557Seric 		return;
4804794Seric 	if (p[-1] == '\r')
4814557Seric 		p--;
4824557Seric 	if (!stripnl)
4834557Seric 		*p++ = '\n';
4844557Seric 	*p = '\0';
4854557Seric }
4864557Seric /*
4874086Seric **  SYSLOG -- fake entry to fool lint
4884086Seric */
4894086Seric 
4904086Seric # ifdef LOG
4914086Seric # ifdef lint
4924086Seric 
4934086Seric /*VARARGS2*/
4944086Seric syslog(pri, fmt, args)
4954086Seric 	int pri;
4964086Seric 	char *fmt;
4974086Seric {
4984086Seric 	pri = *fmt;
4994086Seric 	args = pri;
5004086Seric 	pri = args;
5014086Seric }
5024086Seric 
5034086Seric # endif lint
5044086Seric # endif LOG
5056890Seric /*
5066890Seric **  DFOPEN -- determined file open
5076890Seric **
5086890Seric **	This routine has the semantics of fopen, except that it will
5096890Seric **	keep trying a few times to make this happen.  The idea is that
5106890Seric **	on very loaded systems, we may run out of resources (inodes,
5116890Seric **	whatever), so this tries to get around it.
5126890Seric */
5136890Seric 
5146890Seric FILE *
5156890Seric dfopen(filename, mode)
5166890Seric 	char *filename;
5176890Seric 	char *mode;
5186890Seric {
5196890Seric 	register int tries;
5206890Seric 	register FILE *fp;
5216890Seric 	extern int errno;
5226890Seric 
5236890Seric 	for (tries = 0; tries < 10; tries++)
5246890Seric 	{
5256890Seric 		sleep(10 * tries);
5266890Seric 		errno = 0;
5276890Seric 		fp = fopen(filename, mode);
5286890Seric 		if (fp != NULL || errno != ENFILE)
5296890Seric 			break;
5306890Seric 	}
5316890Seric 	return (fp);
5326890Seric }
5337124Seric /*
5347124Seric **  PUTLINE -- put a line like fputs obeying SMTP conventions
5357124Seric **
5367753Seric **	This routine always guarantees outputing a newline (or CRLF,
5377753Seric **	as appropriate) at the end of the string.
5387753Seric **
5397124Seric **	Parameters:
5407124Seric **		l -- line to put.
5417124Seric **		fp -- file to put it onto.
5427124Seric **		fullsmtp -- if set, obey strictest SMTP conventions.
5437124Seric **
5447124Seric **	Returns:
5457124Seric **		none
5467124Seric **
5477124Seric **	Side Effects:
5487124Seric **		output of l to fp.
5497124Seric */
5507124Seric 
5517753Seric # define SMTPLINELIM	990	/* maximum line length */
5527124Seric 
5537124Seric putline(l, fp, fullsmtp)
5547753Seric 	register char *l;
5557124Seric 	FILE *fp;
5567124Seric 	bool fullsmtp;
5577124Seric {
5587124Seric 	register char *p;
5597753Seric 	char svchar;
5607124Seric 
5617753Seric 	do
5627124Seric 	{
5637753Seric 		/* find the end of the line */
5647753Seric 		p = index(l, '\n');
5657753Seric 		if (p == NULL)
5667753Seric 			p = &l[strlen(l)];
5677124Seric 
5687753Seric 		/* check for line overflow */
5697753Seric 		while (fullsmtp && (p - l) > SMTPLINELIM)
5707753Seric 		{
5717753Seric 			register char *q = &l[SMTPLINELIM - 1];
5727124Seric 
5737753Seric 			svchar = *q;
5747753Seric 			*q = '\0';
5757753Seric 			fputs(l, fp);
5767753Seric 			fputs("!\r\n", fp);
5777753Seric 			*q = svchar;
5787753Seric 			l = q;
5797753Seric 		}
5807124Seric 
5817753Seric 		/* output last part */
5827753Seric 		svchar = *p;
5837753Seric 		*p = '\0';
5847124Seric 		fputs(l, fp);
5857753Seric 		if (fullsmtp)
5867753Seric 			fputc('\r', fp);
5877753Seric 		fputc('\n', fp);
5887753Seric 		*p = svchar;
5897753Seric 		l = p;
5907753Seric 		if (*l == '\n')
5917753Seric 			l++;
5927753Seric 	} while (l[0] != '\0');
5937124Seric }
5947676Seric /*
5957676Seric **  XUNLINK -- unlink a file, doing logging as appropriate.
5967676Seric **
5977676Seric **	Parameters:
5987676Seric **		f -- name of file to unlink.
5997676Seric **
6007676Seric **	Returns:
6017676Seric **		none.
6027676Seric **
6037676Seric **	Side Effects:
6047676Seric **		f is unlinked.
6057676Seric */
6067676Seric 
6077676Seric xunlink(f)
6087676Seric 	char *f;
6097676Seric {
6107676Seric 	register int i;
6117676Seric 
6127676Seric # ifdef LOG
6137676Seric 	if (LogLevel > 20)
6147812Seric 		syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
6157676Seric # endif LOG
6167676Seric 
6177676Seric 	i = unlink(f);
6187676Seric # ifdef LOG
6197676Seric 	if (i < 0 && LogLevel > 21)
6207942Seric 		syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
6217676Seric # endif LOG
6227676Seric }
6237685Seric /*
6247685Seric **  SFGETS -- "safe" fgets -- times out.
6257685Seric **
6267685Seric **	Parameters:
6277685Seric **		buf -- place to put the input line.
6287685Seric **		siz -- size of buf.
6297685Seric **		fp -- file to read from.
6307685Seric **
6317685Seric **	Returns:
6327685Seric **		NULL on error (including timeout).
6337685Seric **		buf otherwise.
6347685Seric **
6357685Seric **	Side Effects:
6367685Seric **		none.
6377685Seric */
6387685Seric 
6397942Seric static bool	TimeoutFlag;
6407685Seric 
6417685Seric char *
6427685Seric sfgets(buf, siz, fp)
6437685Seric 	char *buf;
6447685Seric 	int siz;
6457685Seric 	FILE *fp;
6467685Seric {
6477942Seric 	register EVENT *ev = NULL;
6487685Seric 	register char *p;
6497685Seric 	extern readtimeout();
6507685Seric 
6517942Seric 	if (ReadTimeout != 0)
6527942Seric 		ev = setevent(ReadTimeout, readtimeout, 0);
6537942Seric 	TimeoutFlag = FALSE;
6547942Seric 	do
6557942Seric 	{
6567942Seric 		errno = 0;
6577942Seric 		p = fgets(buf, siz, fp);
6587942Seric 	} while (!(p != NULL || TimeoutFlag || errno != EINTR));
6597685Seric 	clrevent(ev);
6608055Seric 	LineNumber++;
6617685Seric 	return (p);
6627685Seric }
6637685Seric 
6647685Seric static
6657685Seric readtimeout()
6667685Seric {
6677942Seric 	TimeoutFlag = TRUE;
6687685Seric }
6697786Seric /*
6707786Seric **  FGETFOLDED -- like fgets, but know about folded lines.
6717786Seric **
6727786Seric **	Parameters:
6737786Seric **		buf -- place to put result.
6747786Seric **		n -- bytes available.
6757786Seric **		f -- file to read from.
6767786Seric **
6777786Seric **	Returns:
6787786Seric **		buf on success, NULL on error or EOF.
6797786Seric **
6807786Seric **	Side Effects:
6817786Seric **		buf gets lines from f, with continuation lines (lines
6827786Seric **		with leading white space) appended.  CRLF's are mapped
6837786Seric **		into single newlines.  Any trailing NL is stripped.
6847786Seric */
6857786Seric 
6867786Seric char *
6877786Seric fgetfolded(buf, n, f)
6887786Seric 	char *buf;
6897786Seric 	register int n;
6907786Seric 	FILE *f;
6917786Seric {
6927786Seric 	register char *p = buf;
6937786Seric 	register int i;
6947786Seric 
6957786Seric 	n--;
6968055Seric 	while (sfgets(p, n, f) != NULL)
6977786Seric 	{
6987786Seric 		fixcrlf(p, TRUE);
6997786Seric 		i = fgetc(f);
7007786Seric 		if (i != EOF)
7017786Seric 			ungetc(i, f);
7027786Seric 		if (i != ' ' && i != '\t')
7037786Seric 			return (buf);
7047786Seric 		i = strlen(p);
7057786Seric 		p += i;
7067786Seric 		*p++ = '\n';
7077786Seric 		n -= i + 1;
7087786Seric 	}
7097786Seric 	return (NULL);
7107786Seric }
7117860Seric /*
7127860Seric **  PINTVL -- produce printable version of a time interval
7137860Seric **
7147860Seric **	Parameters:
7157860Seric **		intvl -- the interval to be converted
7167860Seric **		brief -- if TRUE, print this in an extremely compact form
7177860Seric **			(basically used for logging).
7187860Seric **
7197860Seric **	Returns:
7207860Seric **		A pointer to a string version of intvl suitable for
7217860Seric **			printing or framing.
7227860Seric **
7237860Seric **	Side Effects:
7247860Seric **		none.
7257860Seric **
7267860Seric **	Warning:
7277860Seric **		The string returned is in a static buffer.
7287860Seric */
7297860Seric 
7307860Seric # define PLURAL(n)	((n) == 1 ? "" : "s")
7317860Seric 
7327860Seric char *
7337860Seric pintvl(intvl, brief)
7347860Seric 	time_t intvl;
7357860Seric 	bool brief;
7367860Seric {
7377860Seric 	static char buf[MAXNAME];
7387860Seric 	register char *p;
7397860Seric 	int wk, dy, hr, mi, se;
7407860Seric 
7417860Seric 	if (intvl == 0 && !brief)
7427860Seric 		return ("zero seconds");
7437860Seric 
7447860Seric 	/* decode the interval into weeks, days, hours, minutes, seconds */
7457860Seric 	se = intvl % 60;
7467860Seric 	intvl /= 60;
7477860Seric 	mi = intvl % 60;
7487860Seric 	intvl /= 60;
7497860Seric 	hr = intvl % 24;
7507860Seric 	intvl /= 24;
7517860Seric 	if (brief)
7527860Seric 		dy = intvl;
7537860Seric 	else
7547860Seric 	{
7557860Seric 		dy = intvl % 7;
7567860Seric 		intvl /= 7;
7577860Seric 		wk = intvl;
7587860Seric 	}
7597860Seric 
7607860Seric 	/* now turn it into a sexy form */
7617860Seric 	p = buf;
7627860Seric 	if (brief)
7637860Seric 	{
7647860Seric 		if (dy > 0)
7657860Seric 		{
7667860Seric 			(void) sprintf(p, "%d+", dy);
7677860Seric 			p += strlen(p);
7687860Seric 		}
7697860Seric 		(void) sprintf(p, "%02d:%02d:%02d", hr, mi, se);
7707860Seric 		return (buf);
7717860Seric 	}
7727860Seric 
7737860Seric 	/* use the verbose form */
7747860Seric 	if (wk > 0)
7757860Seric 	{
7767860Seric 		(void) sprintf(p, ", %d week%s", wk, PLURAL(wk));
7777860Seric 		p += strlen(p);
7787860Seric 	}
7797860Seric 	if (dy > 0)
7807860Seric 	{
7817860Seric 		(void) sprintf(p, ", %d day%s", dy, PLURAL(dy));
7827860Seric 		p += strlen(p);
7837860Seric 	}
7847860Seric 	if (hr > 0)
7857860Seric 	{
7867860Seric 		(void) sprintf(p, ", %d hour%s", hr, PLURAL(hr));
7877860Seric 		p += strlen(p);
7887860Seric 	}
7897860Seric 	if (mi > 0)
7907860Seric 	{
7917860Seric 		(void) sprintf(p, ", %d minute%s", mi, PLURAL(mi));
7927860Seric 		p += strlen(p);
7937860Seric 	}
7947860Seric 	if (se > 0)
7957860Seric 	{
7967860Seric 		(void) sprintf(p, ", %d second%s", se, PLURAL(se));
7977860Seric 		p += strlen(p);
7987860Seric 	}
7997860Seric 
8007860Seric 	return (buf + 2);
8017860Seric }
8027886Seric /*
8037886Seric **  CURTIME -- return current time.
8047886Seric **
8057886Seric **	Parameters:
8067886Seric **		none.
8077886Seric **
8087886Seric **	Returns:
8097886Seric **		the current time.
8107886Seric **
8117886Seric **	Side Effects:
8127886Seric **		none.
8137886Seric */
8147886Seric 
8157886Seric time_t
8167886Seric curtime()
8177886Seric {
8187886Seric 	auto time_t t;
8197886Seric 
8207886Seric 	(void) time(&t);
8217886Seric 	return (t);
8227886Seric }
8238264Seric /*
8248264Seric **  ATOBOOL -- convert a string representation to boolean.
8258264Seric **
8268264Seric **	Defaults to "TRUE"
8278264Seric **
8288264Seric **	Parameters:
8298264Seric **		s -- string to convert.  Takes "tTyY" as true,
8308264Seric **			others as false.
8318264Seric **
8328264Seric **	Returns:
8338264Seric **		A boolean representation of the string.
8348264Seric **
8358264Seric **	Side Effects:
8368264Seric **		none.
8378264Seric */
8388264Seric 
8398264Seric bool
8408264Seric atobool(s)
8418264Seric 	register char *s;
8428264Seric {
8438264Seric 	if (*s == '\0' || index("tTyY", *s) != NULL)
8448264Seric 		return (TRUE);
8458264Seric 	return (FALSE);
8468264Seric }
847