📄 util.c
字号:
if (!isascii(c))
{
if (c == MATCHREPL)
{
printf("%s$", TermEscape.te_rv_on);
shiftout = TRUE;
if (*s == '\0')
continue;
c = *s++ & 0377;
goto printchar;
}
if (c == MACROEXPAND || c == MACRODEXPAND)
{
printf("%s$", TermEscape.te_rv_on);
if (c == MACRODEXPAND)
(void) putchar('&');
shiftout = TRUE;
if (*s == '\0')
continue;
if (strchr("=~&?", *s) != NULL)
(void) putchar(*s++);
if (bitset(0200, *s))
printf("{%s}", macname(*s++ & 0377));
else
printf("%c", *s++);
continue;
}
for (mp = MetaMacros; mp->metaname != '\0'; mp++)
{
if ((mp->metaval & 0377) == c)
{
printf("%s$%c",
TermEscape.te_rv_on,
mp->metaname);
shiftout = TRUE;
break;
}
}
if (c == MATCHCLASS || c == MATCHNCLASS)
{
if (bitset(0200, *s))
printf("{%s}", macname(*s++ & 0377));
else if (*s != '\0')
printf("%c", *s++);
}
if (mp->metaname != '\0')
continue;
/* unrecognized meta character */
printf("%sM-", TermEscape.te_rv_on);
shiftout = TRUE;
c &= 0177;
}
printchar:
if (isprint(c))
{
(void) putchar(c);
continue;
}
/* wasn't a meta-macro -- find another way to print it */
switch (c)
{
case '\n':
c = 'n';
break;
case '\r':
c = 'r';
break;
case '\t':
c = 't';
break;
}
if (!shiftout)
{
printf("%s", TermEscape.te_rv_on);
shiftout = TRUE;
}
if (isprint(c))
{
(void) putchar('\\');
(void) putchar(c);
}
else
{
(void) putchar('^');
(void) putchar(c ^ 0100);
}
}
if (shiftout)
printf("%s", TermEscape.te_rv_off);
(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.
*/
void
makelower(p)
register char *p;
{
register char c;
if (p == NULL)
return;
for (; (c = *p) != '\0'; p++)
if (isascii(c) && isupper(c))
*p = tolower(c);
}
/*
** 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.
** user -- the login name of this user (for &).
** buf -- place to put the result.
** buflen -- length of buf.
**
** Returns:
** none.
**
** Side Effects:
** none.
*/
void
buildfname(gecos, user, buf, buflen)
register char *gecos;
char *user;
char *buf;
int buflen;
{
register char *p;
register char *bp = buf;
if (*gecos == '*')
gecos++;
/* copy gecos, interpolating & to be full name */
for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
{
if (bp >= &buf[buflen - 1])
{
/* buffer overflow -- just use login name */
snprintf(buf, buflen, "%s", user);
return;
}
if (*p == '&')
{
/* interpolate full name */
snprintf(bp, buflen - (bp - buf), "%s", user);
*bp = toupper(*bp);
bp += strlen(bp);
}
else
*bp++ = *p;
}
*bp = '\0';
}
/*
** 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.
*/
void
fixcrlf(line, stripnl)
char *line;
bool stripnl;
{
register char *p;
p = strchr(line, '\n');
if (p == NULL)
return;
if (p > line && p[-1] == '\r')
p--;
if (!stripnl)
*p++ = '\n';
*p = '\0';
}
/*
** 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.
** mci -- the mailer connection information.
**
** Returns:
** none
**
** Side Effects:
** output of l to fp.
*/
void
putline(l, mci)
register char *l;
register MCI *mci;
{
putxline(l, strlen(l), mci, PXLF_MAPFROM);
}
/*
** PUTXLINE -- putline with flags bits.
**
** This routine always guarantees outputing a newline (or CRLF,
** as appropriate) at the end of the string.
**
** Parameters:
** l -- line to put.
** len -- the length of the line.
** mci -- the mailer connection information.
** pxflags -- flag bits:
** PXLF_MAPFROM -- map From_ to >From_.
** PXLF_STRIP8BIT -- strip 8th bit.
** PXLF_HEADER -- map bare newline in header to newline space.
**
** Returns:
** none
**
** Side Effects:
** output of l to fp.
*/
void
putxline(l, len, mci, pxflags)
register char *l;
size_t len;
register MCI *mci;
int pxflags;
{
bool dead = FALSE;
register char *p, *end;
int slop = 0;
/* strip out 0200 bits -- these can look like TELNET protocol */
if (bitset(MCIF_7BIT, mci->mci_flags) ||
bitset(PXLF_STRIP8BIT, pxflags))
{
register char svchar;
for (p = l; (svchar = *p) != '\0'; ++p)
if (bitset(0200, svchar))
*p = svchar &~ 0200;
}
end = l + len;
do
{
/* find the end of the line */
p = memchr(l, '\n', end - l);
if (p == NULL)
p = end;
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d >>> ", (int) getpid());
/* check for line overflow */
while (mci->mci_mailer->m_linelimit > 0 &&
(p - l + slop) > mci->mci_mailer->m_linelimit)
{
char *l_base = l;
register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1];
if (l[0] == '.' && slop == 0 &&
bitnset(M_XDOT, mci->mci_mailer->m_flags))
{
if (putc('.', mci->mci_out) == EOF)
dead = TRUE;
if (TrafficLogFile != NULL)
(void) putc('.', TrafficLogFile);
}
else if (l[0] == 'F' && slop == 0 &&
bitset(PXLF_MAPFROM, pxflags) &&
strncmp(l, "From ", 5) == 0 &&
bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
{
if (putc('>', mci->mci_out) == EOF)
dead = TRUE;
if (TrafficLogFile != NULL)
(void) putc('>', TrafficLogFile);
}
if (dead)
break;
while (l < q)
{
if (putc((unsigned char) *l++, mci->mci_out) ==
EOF)
{
dead = TRUE;
break;
}
/* record progress for DATA timeout */
DataProgress = TRUE;
}
if (dead)
break;
if (putc('!', mci->mci_out) == EOF ||
fputs(mci->mci_mailer->m_eol,
mci->mci_out) == EOF ||
putc(' ', mci->mci_out) == EOF)
{
dead = TRUE;
break;
}
/* record progress for DATA timeout */
DataProgress = TRUE;
if (TrafficLogFile != NULL)
{
for (l = l_base; l < q; l++)
(void) putc((unsigned char)*l,
TrafficLogFile);
fprintf(TrafficLogFile, "!\n%05d >>> ",
(int) getpid());
}
slop = 1;
}
if (dead)
break;
/* output last part */
if (l[0] == '.' && slop == 0 &&
bitnset(M_XDOT, mci->mci_mailer->m_flags))
{
if (putc('.', mci->mci_out) == EOF)
break;
if (TrafficLogFile != NULL)
(void) putc('.', TrafficLogFile);
}
else if (l[0] == 'F' && slop == 0 &&
bitset(PXLF_MAPFROM, pxflags) &&
strncmp(l, "From ", 5) == 0 &&
bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
{
if (putc('>', mci->mci_out) == EOF)
break;
if (TrafficLogFile != NULL)
(void) putc('>', TrafficLogFile);
}
for ( ; l < p; ++l)
{
if (TrafficLogFile != NULL)
(void) putc((unsigned char)*l, TrafficLogFile);
if (putc((unsigned char) *l, mci->mci_out) == EOF)
{
dead = TRUE;
break;
}
/* record progress for DATA timeout */
DataProgress = TRUE;
}
if (dead)
break;
if (TrafficLogFile != NULL)
(void) putc('\n', TrafficLogFile);
if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF)
break;
if (l < end && *l == '\n')
{
if (*++l != ' ' && *l != '\t' && *l != '\0' &&
bitset(PXLF_HEADER, pxflags))
{
if (putc(' ', mci->mci_out) == EOF)
break;
if (TrafficLogFile != NULL)
(void) putc(' ', TrafficLogFile);
}
}
/* record progress for DATA timeout */
DataProgress = TRUE;
} while (l < end);
}
/*
** XUNLINK -- unlink a file, doing logging as appropriate.
**
** Parameters:
** f -- name of file to unlink.
**
** Returns:
** none.
**
** Side Effects:
** f is unlinked.
*/
void
xunlink(f)
char *f;
{
register int i;
if (LogLevel > 98)
sm_syslog(LOG_DEBUG, CurEnv->e_id,
"unlink %s",
f);
i = unlink(f);
if (i < 0 && LogLevel > 97)
sm_syslog(LOG_DEBUG, CurEnv->e_id,
"%s: unlink-fail %d",
f, errno);
}
/*
** 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.
** timeout -- the timeout before error occurs.
** during -- what we are trying to read (for error messages).
**
** Returns:
** NULL on error (including timeout). This will also leave
** buf containing a null string.
** buf otherwise.
**
** Side Effects:
** none.
*/
static jmp_buf CtxReadTimeout;
char *
sfgets(buf, siz, fp, timeout, during)
char *buf;
int siz;
FILE *fp;
time_t timeout;
char *during;
{
register EVENT *ev = NULL;
register char *p;
int save_errno;
if (fp == NULL)
{
buf[0] = '\0';
return NULL;
}
/* set the timeout */
if (timeout != 0)
{
if (setjmp(CtxReadTimeout) != 0)
{
if (LogLevel > 1)
sm_syslog(LOG_NOTICE, CurEnv->e_id,
"timeout waiting for input from %.100s during %s",
CurHostName ? CurHostName : "local",
during);
buf[0] = '\0';
#if XDEBUG
checkfd012(during);
#endif /* XDEBUG */
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n",
(int) getpid());
errno = 0;
return NULL;
}
ev = setevent(timeout, readtimeout, 0);
}
/* try to read */
p = NULL;
errno = 0;
while (!feof(fp) && !ferror(fp))
{
errno = 0;
p = fgets(buf, siz, fp);
if (p != NULL || errno != EINTR)
break;
clearerr(fp);
}
save_errno = errno;
/* clear the event if it has not sprung */
clrevent(ev);
/* clean up the books and exit */
LineNumber++;
if (p == NULL)
{
buf[0] = '\0';
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d <<< [EOF]\n", (int) getpid());
errno = save_errno;
return NULL;
}
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d <<< %s", (int) getpid(), buf);
if (SevenBitInput)
{
for (p = buf; *p != '\0'; p++)
*p &= ~0200;
}
else if (!HasEightBits)
{
for (p = buf; *p != '\0'; p++)
{
if (bitset(0200, *p))
{
HasEightBits = TRUE;
break;
}
}
}
return buf;
}
/* ARGSUSED */
static void
readtimeout(timeout)
time_t timeout;
{
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:
** input line(s) on success, NULL on error or EOF.
** This will normally be buf -- unless the line is too
** long, when it will be xalloc()ed.
**
** 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;
char *bp = 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)
{
/* allocate new space */
char *nbp;
int nn;
nn = (p - bp);
if (nn < MEMCHUNKSIZE)
nn *= 2;
else
nn += MEMCHUNKSIZE;
nbp = xalloc(nn);
memmove(nbp, bp, p - bp);
p = &nbp[p - bp];
if (bp != buf)
free(bp);
bp = nbp;
n = nn - (p - bp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -