📄 util.c
字号:
*p++ = i;
if (i == '\n')
{
LineNumber++;
i = getc(f);
if (i != EOF)
(void) ungetc(i, f);
if (i != ' ' && i != '\t')
break;
}
}
if (p == bp)
return NULL;
if (p[-1] == '\n')
p--;
*p = '\0';
return bp;
}
/*
** CURTIME -- return current time.
**
** Parameters:
** none.
**
** Returns:
** the current time.
**
** Side Effects:
** none.
*/
time_t
curtime()
{
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.
*/
bool
atobool(s)
register char *s;
{
if (s == NULL || *s == '\0' || strchr("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.
*/
int
atooct(s)
register char *s;
{
register int i = 0;
while (*s >= '0' && *s <= '7')
i = (i << 3) | (*s++ - '0');
return i;
}
/*
** 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.
*/
bool
bitintersect(a, b)
BITMAP256 a;
BITMAP256 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.
*/
bool
bitzerop(map)
BITMAP256 map;
{
int i;
for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
if (map[i] != 0)
return FALSE;
return TRUE;
}
/*
** STRCONTAINEDIN -- tell if one string is contained in another
**
** Parameters:
** a -- possible substring.
** b -- possible superstring.
**
** Returns:
** TRUE if a is contained in b.
** FALSE otherwise.
*/
bool
strcontainedin(a, b)
register char *a;
register char *b;
{
int la;
int lb;
int c;
la = strlen(a);
lb = strlen(b);
c = *a;
if (isascii(c) && isupper(c))
c = tolower(c);
for (; lb-- >= la; b++)
{
if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c)
continue;
if (strncasecmp(a, b, la) == 0)
return TRUE;
}
return FALSE;
}
/*
** CHECKFD012 -- check low numbered file descriptors
**
** File descriptors 0, 1, and 2 should be open at all times.
** This routine verifies that, and fixes it if not true.
**
** Parameters:
** where -- a tag printed if the assertion failed
**
** Returns:
** none
*/
void
checkfd012(where)
char *where;
{
#if XDEBUG
register int i;
for (i = 0; i < 3; i++)
fill_fd(i, where);
#endif /* XDEBUG */
}
/*
** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging
**
** Parameters:
** fd -- file descriptor to check.
** where -- tag to print on failure.
**
** Returns:
** none.
*/
void
checkfdopen(fd, where)
int fd;
char *where;
{
#if XDEBUG
struct stat st;
if (fstat(fd, &st) < 0 && errno == EBADF)
{
syserr("checkfdopen(%d): %s not open as expected!", fd, where);
printopenfds(TRUE);
}
#endif /* XDEBUG */
}
/*
** CHECKFDS -- check for new or missing file descriptors
**
** Parameters:
** where -- tag for printing. If null, take a base line.
**
** Returns:
** none
**
** Side Effects:
** If where is set, shows changes since the last call.
*/
void
checkfds(where)
char *where;
{
int maxfd;
register int fd;
bool printhdr = TRUE;
int save_errno = errno;
static BITMAP256 baseline;
extern int DtableSize;
if (DtableSize > 256)
maxfd = 256;
else
maxfd = DtableSize;
if (where == NULL)
clrbitmap(baseline);
for (fd = 0; fd < maxfd; fd++)
{
struct stat stbuf;
if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP)
{
if (!bitnset(fd, baseline))
continue;
clrbitn(fd, baseline);
}
else if (!bitnset(fd, baseline))
setbitn(fd, baseline);
else
continue;
/* file state has changed */
if (where == NULL)
continue;
if (printhdr)
{
sm_syslog(LOG_DEBUG, CurEnv->e_id,
"%s: changed fds:",
where);
printhdr = FALSE;
}
dumpfd(fd, TRUE, TRUE);
}
errno = save_errno;
}
/*
** PRINTOPENFDS -- print the open file descriptors (for debugging)
**
** Parameters:
** logit -- if set, send output to syslog; otherwise
** print for debugging.
**
** Returns:
** none.
*/
#if NETINET || NETINET6
# include <arpa/inet.h>
#endif /* NETINET || NETINET6 */
void
printopenfds(logit)
bool logit;
{
register int fd;
extern int DtableSize;
for (fd = 0; fd < DtableSize; fd++)
dumpfd(fd, FALSE, logit);
}
/*
** DUMPFD -- dump a file descriptor
**
** Parameters:
** fd -- the file descriptor to dump.
** printclosed -- if set, print a notification even if
** it is closed; otherwise print nothing.
** logit -- if set, send output to syslog instead of stdout.
*/
void
dumpfd(fd, printclosed, logit)
int fd;
bool printclosed;
bool logit;
{
register char *p;
char *hp;
#ifdef S_IFSOCK
SOCKADDR sa;
#endif /* S_IFSOCK */
auto SOCKADDR_LEN_T slen;
int i;
#if STAT64 > 0
struct stat64 st;
#else /* STAT64 > 0 */
struct stat st;
#endif /* STAT64 > 0 */
char buf[200];
p = buf;
snprintf(p, SPACELEFT(buf, p), "%3d: ", fd);
p += strlen(p);
if (
#if STAT64 > 0
fstat64(fd, &st)
#else /* STAT64 > 0 */
fstat(fd, &st)
#endif /* STAT64 > 0 */
< 0)
{
if (errno != EBADF)
{
snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)",
errstring(errno));
goto printit;
}
else if (printclosed)
{
snprintf(p, SPACELEFT(buf, p), "CLOSED");
goto printit;
}
return;
}
i = fcntl(fd, F_GETFL, NULL);
if (i != -1)
{
snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i);
p += strlen(p);
}
snprintf(p, SPACELEFT(buf, p), "mode=%o: ", (int) st.st_mode);
p += strlen(p);
switch (st.st_mode & S_IFMT)
{
#ifdef S_IFSOCK
case S_IFSOCK:
snprintf(p, SPACELEFT(buf, p), "SOCK ");
p += strlen(p);
memset(&sa, '\0', sizeof sa);
slen = sizeof sa;
if (getsockname(fd, &sa.sa, &slen) < 0)
snprintf(p, SPACELEFT(buf, p), "(%s)",
errstring(errno));
else
{
hp = hostnamebyanyaddr(&sa);
if (hp == NULL)
{
/* EMPTY */
/* do nothing */
}
# if NETINET
else if (sa.sa.sa_family == AF_INET)
snprintf(p, SPACELEFT(buf, p), "%s/%d",
hp, ntohs(sa.sin.sin_port));
# endif /* NETINET */
# if NETINET6
else if (sa.sa.sa_family == AF_INET6)
snprintf(p, SPACELEFT(buf, p), "%s/%d",
hp, ntohs(sa.sin6.sin6_port));
# endif /* NETINET6 */
else
snprintf(p, SPACELEFT(buf, p), "%s", hp);
}
p += strlen(p);
snprintf(p, SPACELEFT(buf, p), "->");
p += strlen(p);
slen = sizeof sa;
if (getpeername(fd, &sa.sa, &slen) < 0)
snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno));
else
{
hp = hostnamebyanyaddr(&sa);
if (hp == NULL)
{
/* EMPTY */
/* do nothing */
}
# if NETINET
else if (sa.sa.sa_family == AF_INET)
snprintf(p, SPACELEFT(buf, p), "%s/%d",
hp, ntohs(sa.sin.sin_port));
# endif /* NETINET */
# if NETINET6
else if (sa.sa.sa_family == AF_INET6)
snprintf(p, SPACELEFT(buf, p), "%s/%d",
hp, ntohs(sa.sin6.sin6_port));
# endif /* NETINET6 */
else
snprintf(p, SPACELEFT(buf, p), "%s", hp);
}
break;
#endif /* S_IFSOCK */
case S_IFCHR:
snprintf(p, SPACELEFT(buf, p), "CHR: ");
p += strlen(p);
goto defprint;
case S_IFBLK:
snprintf(p, SPACELEFT(buf, p), "BLK: ");
p += strlen(p);
goto defprint;
#if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK)
case S_IFIFO:
snprintf(p, SPACELEFT(buf, p), "FIFO: ");
p += strlen(p);
goto defprint;
#endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */
#ifdef S_IFDIR
case S_IFDIR:
snprintf(p, SPACELEFT(buf, p), "DIR: ");
p += strlen(p);
goto defprint;
#endif /* S_IFDIR */
#ifdef S_IFLNK
case S_IFLNK:
snprintf(p, SPACELEFT(buf, p), "LNK: ");
p += strlen(p);
goto defprint;
#endif /* S_IFLNK */
default:
defprint:
/*CONSTCOND*/
if (sizeof st.st_ino > sizeof (long))
snprintf(p, SPACELEFT(buf, p),
"dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ",
major(st.st_dev), minor(st.st_dev),
quad_to_string(st.st_ino),
(int) st.st_nlink, (int) st.st_uid,
(int) st.st_gid);
else
snprintf(p, SPACELEFT(buf, p),
"dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ",
major(st.st_dev), minor(st.st_dev),
(unsigned long) st.st_ino,
(int) st.st_nlink, (int) st.st_uid,
(int) st.st_gid);
/*CONSTCOND*/
if (sizeof st.st_size > sizeof (long))
snprintf(p, SPACELEFT(buf, p), "size=%s",
quad_to_string(st.st_size));
else
snprintf(p, SPACELEFT(buf, p), "size=%lu",
(unsigned long) st.st_size);
break;
}
printit:
if (logit)
sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL,
"%.800s", buf);
else
printf("%s\n", buf);
}
/*
** SHORTEN_HOSTNAME -- strip local domain information off of hostname.
**
** Parameters:
** host -- the host to shorten (stripped in place).
**
** Returns:
** none.
*/
void
shorten_hostname(host)
char host[];
{
register char *p;
char *mydom;
int i;
bool canon = FALSE;
/* strip off final dot */
p = &host[strlen(host) - 1];
if (*p == '.')
{
*p = '\0';
canon = TRUE;
}
/* see if there is any domain at all -- if not, we are done */
p = strchr(host, '.');
if (p == NULL)
return;
/* yes, we have a domain -- see if it looks like us */
mydom = macvalue('m', CurEnv);
if (mydom == NULL)
mydom = "";
i = strlen(++p);
if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 &&
(mydom[i] == '.' || mydom[i] == '\0'))
*--p = '\0';
}
/*
** PROG_OPEN -- open a program for reading
**
** Parameters:
** argv -- the argument list.
** pfd -- pointer to a place to store the file descriptor.
** e -- the current envelope.
**
** Returns:
** pid of the process -- -1 if it failed.
*/
int
prog_open(argv, pfd, e)
char **argv;
int *pfd;
ENVELOPE *e;
{
int pid;
int i;
int save_errno;
int fdv[2];
char *p, *q;
char buf[MAXLINE + 1];
extern int DtableSize;
if (pipe(fdv) < 0)
{
syserr("%s: cannot create pipe for stdout", argv[0]);
return -1;
}
pid = fork();
if (pid < 0)
{
syserr("%s: cannot fork", argv[0]);
(void) close(fdv[0]);
(void) close(fdv[1]);
return -1;
}
if (pid > 0)
{
/* parent */
(void) close(fdv[1]);
*pfd = fdv[0];
return pid;
}
/* child -- close stdin */
(void) close(0);
/* stdout goes back to parent */
(void) close(fdv[0]);
if (dup2(fdv[1], 1) < 0)
{
syserr("%s: cannot dup2 for stdout", argv[0]);
_exit(EX_OSERR);
}
(void) close(fdv[1]);
/* stderr goes to transcript if available */
if (e->e_xfp != NULL)
{
int xfd;
xfd = fileno(e->e_xfp);
if (xfd >= 0 && dup2(xfd, 2) < 0)
{
syserr("%s: cannot dup2 for stderr", argv[0]);
_exit(EX_OSERR);
}
}
/* this process has no right to the queue file */
if (e->e_lockfp != NULL)
(void) close(fileno(e->e_lockfp));
/* chroot to the program mailer directory, if defined */
if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -