util.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 891 行

C
891
字号
#ifndef lintstatic	char	*sccsid = "@(#)util.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1987 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/# include <stdio.h># include <sys/types.h># include <sys/stat.h># include <sysexits.h># include <errno.h># include <ctype.h># include "sendmail.h"/***  STRIPQUOTES -- Strip quotes & quote bits from a string.****	Runs through a string and strips off unquoted quote**	characters and quote bits.  This is done in place.****	Parameters:**		s -- the string to strip.**		qf -- if set, remove actual `` " '' characters**			as well as the quote bits.****	Returns:**		none.****	Side Effects:**		none.****	Called By:**		deliver*/stripquotes(s, qf)	char *s;	bool qf;{	register char *p;	register char *q;	register char c;	if (s == NULL)		return;	for (p = q = s; (c = *p++) != '\0'; )	{		if (c != '"' || !qf)			*q++ = c & 0177;	}	*q = '\0';}/***  QSTRLEN -- give me the string length assuming 0200 bits add a char****	Parameters:**		s -- the string to measure.****	Reurns:**		The length of s, including space for backslash escapes.****	Side Effects:**		none.*/qstrlen(s)	register char *s;{	register int l = 0;	register char c;	while ((c = *s++) != '\0')	{		if (bitset(0200, c))			l++;		l++;	}	return (l);}/***  CAPITALIZE -- return a copy of a string, properly capitalized.****	Parameters:**		s -- the string to capitalize.****	Returns:**		a pointer to a properly capitalized string.****	Side Effects:**		none.*/char *capitalize(s)	register char *s;{	static char buf[50];	register char *p;	p = buf;	for (;;)	{		while (!isalpha(*s) && *s != '\0')			*p++ = *s++;		if (*s == '\0')			break;		*p++ = toupper(*s++);		while (isalpha(*s))			*p++ = *s++;	}	*p = '\0';	return (buf);}/***  XALLOC -- Allocate memory and bitch wildly on failure.****	THIS IS A CLUDGE.  This should be made to give a proper**	error -- but after all, what can we do?****	Parameters:**		sz -- size of area to allocate.****	Returns:**		pointer to data region.****	Side Effects:**		Memory is allocated.*/char *xalloc(sz)	register int sz;{	register char *p;	extern char *malloc();	p = malloc((unsigned) sz);	if (p == NULL)	{		syserr("Out of memory!!");		abort();		/* exit(EX_UNAVAILABLE); */	}	return (p);}/***  COPYPLIST -- copy list of pointers.****	This routine is the equivalent of newstr for lists of**	pointers.****	Parameters:**		list -- list of pointers to copy.**			Must be NULL terminated.**		copycont -- if TRUE, copy the contents of the vector**			(which must be a string) also.****	Returns:**		a copy of 'list'.****	Side Effects:**		none.*/char **copyplist(list, copycont)	char **list;	bool copycont;{	register char **vp;	register char **newvp;	for (vp = list; *vp != NULL; vp++)		continue;	vp++;	newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);	bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp);	if (copycont)	{		for (vp = newvp; *vp != NULL; vp++)			*vp = newstr(*vp);	}	return (newvp);}/***  PRINTAV -- print argument vector.****	Parameters:**		av -- argument vector.****	Returns:**		none.****	Side Effects:**		prints av.*/printav(av)	register char **av;{	while (*av != NULL)	{		if (tTd(0, 44))			printf("\n\t%08x=", *av);		else			(void) putchar(' ');		xputs(*av++);	}	(void) putchar('\n');}/***  LOWER -- turn letter into lower case.****	Parameters:**		c -- character to turn into lower case.****	Returns:**		c, in lower case.****	Side Effects:**		none.*/charlower(c)	register char c;{	if (isascii(c) && isupper(c))		c = c - 'A' + 'a';	return (c);}/***  XPUTS -- put string doing control escapes.****	Parameters:**		s -- string to put.****	Returns:**		none.****	Side Effects:**		output to stdout*/xputs(s)	register char *s;{	register char c;	if (s == NULL)	{		printf("<null>");		return;	}	(void) putchar('"');	while ((c = *s++) != '\0')	{		if (!isascii(c))		{			(void) putchar('\\');			c &= 0177;		}		if (c < 040 || c >= 0177)		{			(void) putchar('^');			c ^= 0100;		}		(void) putchar(c);	}	(void) putchar('"');	(void) fflush(stdout);}/***  MAKELOWER -- Translate a line into lower case****	Parameters:**		p -- the string to translate.  If NULL, return is**			immediate.****	Returns:**		none.****	Side Effects:**		String pointed to by p is translated to lower case.****	Called By:**		parse*/makelower(p)	register char *p;{	register char c;	if (p == NULL)		return;	for (; (c = *p) != '\0'; p++)		if (isascii(c) && isupper(c))			*p = c - 'A' + 'a';}/***  SAMEWORD -- return TRUE if the words are the same****	Ignores case.****	Parameters:**		a, b -- the words to compare.****	Returns:**		TRUE if a & b match exactly (modulo case)**		FALSE otherwise.****	Side Effects:**		none.*/boolsameword(a, b)	register char *a, *b;{	char ca, cb;	do	{		ca = *a++;		cb = *b++;		if (isascii(ca) && isupper(ca))			ca = ca - 'A' + 'a';		if (isascii(cb) && isupper(cb))			cb = cb - 'A' + 'a';	} while (ca != '\0' && ca == cb);	return (ca == cb);}/***  BUILDFNAME -- build full name from gecos style entry.****	This routine interprets the strange entry that would appear**	in the GECOS field of the password file.****	Parameters:**		p -- name to build.**		login -- the login name of this user (for &).**		buf -- place to put the result.****	Returns:**		none.****	Side Effects:**		none.*/buildfname(p, login, buf)	register char *p;	char *login;	char *buf;{	register char *bp = buf;	if (*p == '*')		p++;	while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')	{		if (*p == '&')		{			(void) strcpy(bp, login);			*bp = toupper(*bp);			while (*bp != '\0')				bp++;			p++;		}		else			*bp++ = *p++;	}	*bp = '\0';}/***  SAFEFILE -- return true if a file exists and is safe for a user.****	Parameters:**		fn -- filename to check.**		uid -- uid to compare against.**		mode -- mode bits that must match.****	Returns:**		TRUE if fn exists, is owned by uid, and matches mode.**		FALSE otherwise.****	Side Effects:**		none.*/boolsafefile(fn, uid, mode)	char *fn;	int uid;	int mode;{	struct stat stbuf;	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&	    (stbuf.st_mode & mode) == mode)		return (TRUE);	errno = 0;	return (FALSE);}/***  FIXCRLF -- fix <CR><LF> in line.****	Looks for the <CR><LF> combination and turns it into the**	UNIX canonical <NL> character.  It only takes one line,**	i.e., it is assumed that the first <NL> found is the end**	of the line.****	Parameters:**		line -- the line to fix.**		stripnl -- if true, strip the newline also.****	Returns:**		none.****	Side Effects:**		line is changed in place.*/fixcrlf(line, stripnl)	char *line;	bool stripnl;{	register char *p;	p = index(line, '\n');	if (p == NULL)		return;/* * Fix handling of blank lines .. p[-1] in this case might be trash. * *	if (p[-1] == '\r') */	if (p != line && p[-1] == '\r')		p--;	if (!stripnl)		*p++ = '\n';	*p = '\0';}/***  DFOPEN -- determined file open****	This routine has the semantics of fopen, except that it will**	keep trying a few times to make this happen.  The idea is that**	on very loaded systems, we may run out of resources (inodes,**	whatever), so this tries to get around it.*/FILE *dfopen(filename, mode)	char *filename;	char *mode;{	register int tries;	register FILE *fp;	for (tries = 0; tries < 10; tries++)	{		sleep((unsigned) (10 * tries));		errno = 0;		fp = fopen(filename, mode);		if (fp != NULL)			break;		if (errno != ENFILE && errno != EINTR)			break;	}	errno = 0;	return (fp);}/***  PUTLINE -- put a line like fputs obeying SMTP conventions****	This routine always guarantees outputing a newline (or CRLF,**	as appropriate) at the end of the string.****	Parameters:**		l -- line to put.**		fp -- file to put it onto.**		m -- the mailer used to control output.****	Returns:**		none****	Side Effects:**		output of l to fp.*/# define SMTPLINELIM	990	/* maximum line length */putline(l, fp, m)	register char *l;	FILE *fp;	MAILER *m;{	register char *p;	char svchar;	/* strip out 0200 bits -- these can look like TELNET protocol */	if (bitnset(M_LIMITS, m->m_flags))	{		p = l;		while ((*p++ &= ~0200) != 0)			continue;	}	do	{		/* find the end of the line */		p = index(l, '\n');		if (p == NULL)			p = &l[strlen(l)];		/* check for line overflow */		while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags))		{			register char *q = &l[SMTPLINELIM - 1];			svchar = *q;			*q = '\0';			if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))				(void) putc('.', fp);			fputs(l, fp);			(void) putc('!', fp);			fputs(m->m_eol, fp);			*q = svchar;			l = q;		}		/* output last part */		svchar = *p;		*p = '\0';		if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))			(void) putc('.', fp);		fputs(l, fp);		fputs(m->m_eol, fp);		*p = svchar;		l = p;		if (*l == '\n')			l++;	} while (l[0] != '\0');}/***  XUNLINK -- unlink a file, doing logging as appropriate.****	Parameters:**		f -- name of file to unlink.****	Returns:**		none.****	Side Effects:**		f is unlinked.*/xunlink(f)	char *f;{	register int i;# ifdef LOG	if (LogLevel > 20)		syslog(LOG_INFO, "%s: unlink %s\n", CurEnv->e_id, f);# endif LOG	i = unlink(f);# ifdef LOG	if (i < 0 && LogLevel > 21)		syslog(LOG_INFO, "%s: unlink-fail %d", f, errno);# endif LOG}/***  SFGETS -- "safe" fgets -- times out and ignores random interrupts.****	Parameters:**		buf -- place to put the input line.**		siz -- size of buf.**		fp -- file to read from.****	Returns:**		NULL on error (including timeout).  This will also leave**			buf containing a null string.**		buf otherwise.****	Side Effects:**		none.*/static jmp_buf	CtxReadTimeout;#ifndef ETIMEDOUT#define ETIMEDOUT	EINTR#endifchar *sfgets(buf, siz, fp)	char *buf;	int siz;	FILE *fp;{	register EVENT *ev = NULL;	register char *p;	extern readtimeout();	/* set the timeout */	if (ReadTimeout != 0)	{		if (setjmp(CtxReadTimeout) != 0)		{			errno = ETIMEDOUT;			syserr("net timeout");			buf[0] = '\0';			return (NULL);		}		ev = setevent((time_t) ReadTimeout, readtimeout, 0);	}	/* try to read */	p = NULL;	while (p == NULL && !feof(fp) && !ferror(fp))	{		errno = 0;		p = fgets(buf, siz, fp);		if (errno == EINTR)			clearerr(fp);	}	/* clear the event if it has not sprung */	clrevent(ev);	/* clean up the books and exit */	LineNumber++;	if (p == NULL)	{		buf[0] = '\0';		return (NULL);	}	for (p = buf; *p != '\0'; p++)		*p &= ~0200;	return (buf);}staticreadtimeout(){	longjmp(CtxReadTimeout, 1);}/***  FGETFOLDED -- like fgets, but know about folded lines.****	Parameters:**		buf -- place to put result.**		n -- bytes available.**		f -- file to read from.****	Returns:**		buf on success, NULL on error or EOF.****	Side Effects:**		buf gets lines from f, with continuation lines (lines**		with leading white space) appended.  CRLF's are mapped**		into single newlines.  Any trailing NL is stripped.*/char *fgetfolded(buf, n, f)	char *buf;	register int n;	FILE *f;{	register char *p = buf;	register int i;	n--;	while ((i = getc(f)) != EOF)	{		if (i == '\r')		{			i = getc(f);			if (i != '\n')			{				if (i != EOF)					(void) ungetc(i, f);				i = '\r';			}		}		if (--n > 0)			*p++ = i;		if (i == '\n')		{			LineNumber++;			i = getc(f);			if (i != EOF)				(void) ungetc(i, f);			if (i != ' ' && i != '\t')			{				*--p = '\0';				return (buf);			}		}	}	return (NULL);}/***  CURTIME -- return current time.****	Parameters:**		none.****	Returns:**		the current time.****	Side Effects:**		none.*/time_tcurtime(){	auto time_t t;	(void) time(&t);	return (t);}/***  ATOBOOL -- convert a string representation to boolean.****	Defaults to "TRUE"****	Parameters:**		s -- string to convert.  Takes "tTyY" as true,**			others as false.****	Returns:**		A boolean representation of the string.****	Side Effects:**		none.*/boolatobool(s)	register char *s;{	if (*s == '\0' || index("tTyY", *s) != NULL)		return (TRUE);	return (FALSE);}/***  ATOOCT -- convert a string representation to octal.****	Parameters:**		s -- string to convert.****	Returns:**		An integer representing the string interpreted as an**		octal number.****	Side Effects:**		none.*/atooct(s)	register char *s;{	register int i = 0;	while (*s >= '0' && *s <= '7')		i = (i << 3) | (*s++ - '0');	return (i);}/***  WAITFOR -- wait for a particular process id.****	Parameters:**		pid -- process id to wait for.****	Returns:**		status of pid.**		-1 if pid never shows up.****	Side Effects:**		none.*/waitfor(pid)	int pid;{	auto int st;	int i;	do	{		errno = 0;		i = wait(&st);	} while ((i >= 0 || errno == EINTR) && i != pid);	if (i < 0)		st = -1;	return (st);}/***  BITINTERSECT -- tell if two bitmaps intersect****	Parameters:**		a, b -- the bitmaps in question****	Returns:**		TRUE if they have a non-null intersection**		FALSE otherwise****	Side Effects:**		none.*/boolbitintersect(a, b)	BITMAP a;	BITMAP b;{	int i;	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )		if ((a[i] & b[i]) != 0)			return (TRUE);	return (FALSE);}/***  BITZEROP -- tell if a bitmap is all zero****	Parameters:**		map -- the bit map to check****	Returns:**		TRUE if map is all zero.**		FALSE if there are any bits set in map.****	Side Effects:**		none.*/boolbitzerop(map)	BITMAP map;{	int i;	for (i = BITMAPBYTES / sizeof (int); --i >= 0; )		if (map[i] != 0)			return (FALSE);	return (TRUE);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?