xref: /csrg-svn/usr.sbin/sendmail/src/util.c (revision 5196)
13151Seric # include <stdio.h>
24538Seric # include <sys/types.h>
34538Seric # include <sys/stat.h>
4298Seric # include <sysexits.h>
5298Seric # include "useful.h"
62900Seric # include <ctype.h>
7298Seric 
8*5196Seric SCCSID(@(#)util.c	3.13		12/06/81);
9409Seric 
10298Seric /*
11298Seric **  STRIPQUOTES -- Strip quotes & quote bits from a string.
12298Seric **
13298Seric **	Runs through a string and strips off unquoted quote
14298Seric **	characters and quote bits.  This is done in place.
15298Seric **
16298Seric **	Parameters:
17298Seric **		s -- the string to strip.
184101Seric **		qf -- if set, remove actual `` " '' characters
194101Seric **			as well as the quote bits.
20298Seric **
21298Seric **	Returns:
22298Seric **		none.
23298Seric **
24298Seric **	Side Effects:
25298Seric **		none.
26298Seric **
27298Seric **	Called By:
28298Seric **		deliver
29298Seric */
30298Seric 
314101Seric stripquotes(s, qf)
32298Seric 	char *s;
334101Seric 	bool qf;
34298Seric {
35298Seric 	register char *p;
36298Seric 	register char *q;
37298Seric 	register char c;
38298Seric 
394101Seric 	if (s == NULL)
404101Seric 		return;
414101Seric 
42298Seric 	for (p = q = s; (c = *p++) != '\0'; )
43298Seric 	{
444101Seric 		if (c != '"' || !qf)
45298Seric 			*q++ = c & 0177;
46298Seric 	}
47298Seric 	*q = '\0';
48298Seric }
49298Seric /*
502900Seric **  CAPITALIZE -- return a copy of a string, properly capitalized.
512900Seric **
522900Seric **	Parameters:
532900Seric **		s -- the string to capitalize.
542900Seric **
552900Seric **	Returns:
562900Seric **		a pointer to a properly capitalized string.
572900Seric **
582900Seric **	Side Effects:
592900Seric **		none.
602900Seric */
612900Seric 
622900Seric char *
632900Seric capitalize(s)
642900Seric 	register char *s;
652900Seric {
662900Seric 	static char buf[50];
672900Seric 	register char *p;
682900Seric 
692900Seric 	p = buf;
702900Seric 
712900Seric 	for (;;)
722900Seric 	{
732900Seric 		while (!isalpha(*s) && *s != '\0')
742900Seric 			*p++ = *s++;
752900Seric 		if (*s == '\0')
762900Seric 			break;
772900Seric 		*p++ = toupper(*s++);
782900Seric 		while (isalpha(*s))
792900Seric 			*p++ = *s++;
802900Seric 	}
812900Seric 
822900Seric 	*p = '\0';
832900Seric 	return (buf);
842900Seric }
852900Seric /*
86298Seric **  XALLOC -- Allocate memory and bitch wildly on failure.
87298Seric **
88298Seric **	THIS IS A CLUDGE.  This should be made to give a proper
89298Seric **	error -- but after all, what can we do?
90298Seric **
91298Seric **	Parameters:
92298Seric **		sz -- size of area to allocate.
93298Seric **
94298Seric **	Returns:
95298Seric **		pointer to data region.
96298Seric **
97298Seric **	Side Effects:
98298Seric **		Memory is allocated.
99298Seric */
100298Seric 
101298Seric char *
102298Seric xalloc(sz)
103298Seric 	register unsigned int sz;
104298Seric {
105298Seric 	register char *p;
106298Seric 
107298Seric 	p = malloc(sz);
108298Seric 	if (p == NULL)
109298Seric 	{
110298Seric 		syserr("Out of memory!!");
1111598Seric 		exit(EX_UNAVAILABLE);
112298Seric 	}
113298Seric 	return (p);
114298Seric }
115298Seric /*
1162900Seric **  NEWSTR -- make copy of string.
1172900Seric **
1182900Seric **	Space is allocated for it using xalloc.
1192900Seric **
1202900Seric **	Parameters:
1212900Seric **		string to copy.
1222900Seric **
1232900Seric **	Returns:
1242900Seric **		pointer to new string.
1252900Seric **
1262900Seric **	Side Effects:
1272900Seric **		none.
1282900Seric */
1292900Seric 
1302900Seric char *
1312900Seric newstr(s)
1322900Seric 	register char *s;
1332900Seric {
1342900Seric 	register char *p;
1352900Seric 
1362992Seric 	p = xalloc((unsigned) (strlen(s) + 1));
1372900Seric 	strcpy(p, s);
1382900Seric 	return (p);
1392900Seric }
1403151Seric /*
1413151Seric **  COPYPLIST -- copy list of pointers.
1423151Seric **
1433151Seric **	This routine is the equivalent of newstr for lists of
1443151Seric **	pointers.
1453151Seric **
1463151Seric **	Parameters:
1473151Seric **		list -- list of pointers to copy.
1483151Seric **			Must be NULL terminated.
1493151Seric **		copycont -- if TRUE, copy the contents of the vector
1503151Seric **			(which must be a string) also.
1513151Seric **
1523151Seric **	Returns:
1533151Seric **		a copy of 'list'.
1543151Seric **
1553151Seric **	Side Effects:
1563151Seric **		none.
1573151Seric */
1583151Seric 
1593151Seric char **
1603151Seric copyplist(list, copycont)
1613151Seric 	char **list;
1623151Seric 	bool copycont;
1633151Seric {
1643151Seric 	register char **vp;
1653151Seric 	register char **newvp;
1663151Seric 
1673151Seric 	for (vp = list; *vp != NULL; vp++)
1683151Seric 		continue;
1693151Seric 
1703151Seric 	vp++;
1713151Seric 
1724086Seric 	newvp = (char **) xalloc((unsigned) (vp - list) * sizeof *vp);
1734086Seric 	bmove((char *) list, (char *) newvp, (vp - list) * sizeof *vp);
1743151Seric 
1753151Seric 	if (copycont)
1763151Seric 	{
1773151Seric 		for (vp = newvp; *vp != NULL; vp++)
1783151Seric 			*vp = newstr(*vp);
1793151Seric 	}
1803151Seric 
1813151Seric 	return (newvp);
1823151Seric }
1833151Seric /*
1843151Seric **  PRINTAV -- print argument vector.
1853151Seric **
1863151Seric **	Parameters:
1873151Seric **		av -- argument vector.
1883151Seric **
1893151Seric **	Returns:
1903151Seric **		none.
1913151Seric **
1923151Seric **	Side Effects:
1933151Seric **		prints av.
1943151Seric */
1953151Seric 
1963151Seric # ifdef DEBUG
1973151Seric printav(av)
1983151Seric 	register char **av;
1993151Seric {
2003151Seric 	while (*av != NULL)
2013151Seric 	{
2023151Seric 		printf("\t%08x=", *av);
2033151Seric 		xputs(*av++);
2043151Seric 		putchar('\n');
2053151Seric 	}
2063151Seric }
2073151Seric # endif DEBUG
2083151Seric /*
2093151Seric **  LOWER -- turn letter into lower case.
2103151Seric **
2113151Seric **	Parameters:
2123151Seric **		c -- character to turn into lower case.
2133151Seric **
2143151Seric **	Returns:
2153151Seric **		c, in lower case.
2163151Seric **
2173151Seric **	Side Effects:
2183151Seric **		none.
2193151Seric */
2203151Seric 
2213151Seric char
2223151Seric lower(c)
2233151Seric 	register char c;
2243151Seric {
2253151Seric 	if (isascii(c) && isupper(c))
2263151Seric 		c = c - 'A' + 'a';
2273151Seric 	return (c);
2283151Seric }
2293151Seric /*
2303151Seric **  XPUTS -- put string doing control escapes.
2313151Seric **
2323151Seric **	Parameters:
2333151Seric **		s -- string to put.
2343151Seric **
2353151Seric **	Returns:
2363151Seric **		none.
2373151Seric **
2383151Seric **	Side Effects:
2393151Seric **		output to stdout
2403151Seric */
2413151Seric 
2423151Seric # ifdef DEBUG
2433151Seric xputs(s)
2443151Seric 	register char *s;
2453151Seric {
2463151Seric 	register char c;
2473151Seric 
2483151Seric 	while ((c = *s++) != '\0')
2493151Seric 	{
2503151Seric 		if (!isascii(c))
2513151Seric 		{
2523151Seric 			putchar('\\');
2533151Seric 			c &= 0177;
2543151Seric 		}
2553151Seric 		if (iscntrl(c))
2563151Seric 		{
2573151Seric 			putchar('^');
2583151Seric 			c |= 0100;
2593151Seric 		}
2603151Seric 		putchar(c);
2613151Seric 	}
2624086Seric 	(void) fflush(stdout);
2633151Seric }
2643151Seric # endif DEBUG
2653151Seric /*
2663151Seric **  MAKELOWER -- Translate a line into lower case
2673151Seric **
2683151Seric **	Parameters:
2693151Seric **		p -- the string to translate.  If NULL, return is
2703151Seric **			immediate.
2713151Seric **
2723151Seric **	Returns:
2733151Seric **		none.
2743151Seric **
2753151Seric **	Side Effects:
2763151Seric **		String pointed to by p is translated to lower case.
2773151Seric **
2783151Seric **	Called By:
2793151Seric **		parse
2803151Seric */
2813151Seric 
2823151Seric makelower(p)
2833151Seric 	register char *p;
2843151Seric {
2853151Seric 	register char c;
2863151Seric 
2873151Seric 	if (p == NULL)
2883151Seric 		return;
2893151Seric 	for (; (c = *p) != '\0'; p++)
2903151Seric 		if (isascii(c) && isupper(c))
2913151Seric 			*p = c - 'A' + 'a';
2923151Seric }
2934059Seric /*
2944059Seric **  SAMEWORD -- return TRUE if the words are the same
2954059Seric **
2964059Seric **	Ignores case.
2974059Seric **
2984059Seric **	Parameters:
2994059Seric **		a, b -- the words to compare.
3004059Seric **
3014059Seric **	Returns:
3024059Seric **		TRUE if a & b match exactly (modulo case)
3034059Seric **		FALSE otherwise.
3044059Seric **
3054059Seric **	Side Effects:
3064059Seric **		none.
3074059Seric */
3084059Seric 
3094059Seric bool
3104059Seric sameword(a, b)
3114059Seric 	register char *a, *b;
3124059Seric {
3134059Seric 	while (lower(*a) == lower(*b))
3144059Seric 	{
3154059Seric 		if (*a == '\0')
3164059Seric 			return (TRUE);
3174059Seric 		a++;
3184059Seric 		b++;
3194059Seric 	}
3204059Seric 	return (FALSE);
3214059Seric }
3224086Seric /*
3234101Seric **  CLEAR -- clear a block of memory
3244101Seric **
3254101Seric **	Parameters:
3264101Seric **		p -- location to clear.
3274101Seric **		l -- number of bytes to clear.
3284101Seric **
3294101Seric **	Returns:
3304101Seric **		none.
3314101Seric **
3324101Seric **	Side Effects:
3334101Seric **		none.
3344101Seric */
3354101Seric 
3364101Seric clear(p, l)
3374101Seric 	register char *p;
3384101Seric 	register int l;
3394101Seric {
3404101Seric 	while (l-- > 0)
3414101Seric 		*p++ = 0;
3424101Seric }
3434101Seric /*
344*5196Seric **  BUILDFNAME -- build full name from gecos style entry.
3454375Seric **
346*5196Seric **	This routine interprets the strange entry that would appear
347*5196Seric **	in the GECOS field of the password file.
348*5196Seric **
3494375Seric **	Parameters:
350*5196Seric **		p -- name to build.
351*5196Seric **		login -- the login name of this user (for &).
352*5196Seric **		buf -- place to put the result.
3534375Seric **
3544375Seric **	Returns:
3554375Seric **		none.
3564375Seric **
3574375Seric **	Side Effects:
3584375Seric **		none.
3594375Seric */
3604375Seric 
361*5196Seric buildfname(p, login, buf)
362*5196Seric 	register char *p;
363*5196Seric 	char *login;
3644375Seric 	char *buf;
3654375Seric {
3664375Seric 	register char *bp = buf;
3674375Seric 
3684438Seric 	if (*p == '*')
3694438Seric 		p++;
3704375Seric 	while (*p != '\0' && *p != ',' && *p != ';')
3714375Seric 	{
3724375Seric 		if (*p == '&')
3734375Seric 		{
374*5196Seric 			(void) strcpy(bp, login);
3754375Seric 			*bp = toupper(*bp);
3764375Seric 			while (*bp != '\0')
3774375Seric 				bp++;
3784375Seric 			p++;
3794375Seric 		}
3804375Seric 		else
3814375Seric 			*bp++ = *p++;
3824375Seric 	}
3834375Seric 	*bp = '\0';
3844375Seric }
3854375Seric /*
3864538Seric **  SAFEFILE -- return true if a file exists and is safe for a user.
3874538Seric **
3884538Seric **	Parameters:
3894538Seric **		fn -- filename to check.
3904538Seric **		uid -- uid to compare against.
3914538Seric **		mode -- mode bits that must match.
3924538Seric **
3934538Seric **	Returns:
3944538Seric **		TRUE if fn exists, is owned by uid, and matches mode.
3954538Seric **		FALSE otherwise.
3964538Seric **
3974538Seric **	Side Effects:
3984538Seric **		none.
3994538Seric */
4004538Seric 
4014538Seric bool
4024538Seric safefile(fn, uid, mode)
4034538Seric 	char *fn;
4044538Seric 	int uid;
4054538Seric 	int mode;
4064538Seric {
4074538Seric 	struct stat stbuf;
4084538Seric 
4094538Seric 	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
4104538Seric 	    (stbuf.st_mode & mode) == mode)
4114538Seric 		return (TRUE);
4124538Seric 	return (FALSE);
4134538Seric }
4144538Seric /*
4154557Seric **  FIXCRLF -- fix <CR><LF> in line.
4164557Seric **
4174557Seric **	Looks for the <CR><LF> combination and turns it into the
4184557Seric **	UNIX canonical <NL> character.  It only takes one line,
4194557Seric **	i.e., it is assumed that the first <NL> found is the end
4204557Seric **	of the line.
4214557Seric **
4224557Seric **	Parameters:
4234557Seric **		line -- the line to fix.
4244557Seric **		stripnl -- if true, strip the newline also.
4254557Seric **
4264557Seric **	Returns:
4274557Seric **		none.
4284557Seric **
4294557Seric **	Side Effects:
4304557Seric **		line is changed in place.
4314557Seric */
4324557Seric 
4334557Seric fixcrlf(line, stripnl)
4344557Seric 	char *line;
4354557Seric 	bool stripnl;
4364557Seric {
4374557Seric 	register char *p;
4384557Seric 
4394557Seric 	p = index(line, '\n');
4404557Seric 	if (p == NULL)
4414557Seric 		return;
4424794Seric 	if (p[-1] == '\r')
4434557Seric 		p--;
4444557Seric 	if (!stripnl)
4454557Seric 		*p++ = '\n';
4464557Seric 	*p = '\0';
4474557Seric }
4484557Seric /*
4494086Seric **  SYSLOG -- fake entry to fool lint
4504086Seric */
4514086Seric 
4524086Seric # ifdef LOG
4534086Seric # ifdef lint
4544086Seric 
4554086Seric /*VARARGS2*/
4564086Seric syslog(pri, fmt, args)
4574086Seric 	int pri;
4584086Seric 	char *fmt;
4594086Seric {
4604086Seric 	pri = *fmt;
4614086Seric 	args = pri;
4624086Seric 	pri = args;
4634086Seric }
4644086Seric 
4654086Seric # endif lint
4664086Seric # endif LOG
467