c5840d797d4cca22deae3c3fc059732b8d8a1bee
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)util.c 8.75 (Berkeley) %G%";
** 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.
** s -- the string to strip.
** 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?
** sz -- size of area to allocate.
** pointer to data region.
/* some systems can't handle size zero mallocs */
p
= malloc((unsigned) sz
);
syserr("!Out of memory!!");
/* exit(EX_UNAVAILABLE); */
** COPYPLIST -- copy list of pointers.
** This routine is the equivalent of newstr for lists of
** 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.
copyplist(list
, copycont
)
for (vp
= list
; *vp
!= NULL
; vp
++)
newvp
= (char **) xalloc((int) (vp
- list
) * sizeof *vp
);
bcopy((char *) list
, (char *) newvp
, (int) (vp
- list
) * sizeof *vp
);
for (vp
= newvp
; *vp
!= NULL
; vp
++)
** COPYQUEUE -- copy address queue.
** This routine is the equivalent of newstr for address queues
** addresses marked with QDONTSEND aren't copied
** addr -- list of address structures to copy.
register ADDRESS
*newaddr
;
register ADDRESS
**tail
= &ret
;
if (!bitset(QDONTSEND
, addr
->q_flags
))
newaddr
= (ADDRESS
*) xalloc(sizeof(ADDRESS
));
STRUCTCOPY(*addr
, *newaddr
);
** PRINTAV -- print argument vector.
** av -- argument vector.
printf("\n\t%08x=", *av
);
** LOWER -- turn letter into lower case.
** c -- character to turn into lower case.
return((isascii(c
) && isupper(c
)) ? tolower(c
) : c
);
** XPUTS -- put string doing control escapes.
register struct metamac
*mp
;
extern struct metamac MetaMacros
[];
while ((c
= (*s
++ & 0377)) != '\0')
printf("{%s}", macname(*s
++ & 0377));
for (mp
= MetaMacros
; mp
->metaname
!= '\0'; mp
++)
if ((mp
->metaval
& 0377) == c
)
printf("$%c", mp
->metaname
);
if (mp
->metaname
!= '\0')
/* wasn't a meta-macro -- find another way to print it */
(void) putchar(c
^ 0100);
** MAKELOWER -- Translate a line into lower case
** p -- the string to translate. If NULL, return is
** String pointed to by p is translated to lower case.
for (; (c
= *p
) != '\0'; p
++)
if (isascii(c
) && isupper(c
))
** FULLNAME -- extract full name from a passwd file entry.
** pw -- password entry to start from.
** buf -- buffer to store result in.
** TRUE -- if the resulting message should be a MIME format.
** FALSE -- if MIME is not necessary.
/* values for should_quote */
register unsigned char *gecos
;
const unsigned char *login
;
register unsigned char *bp
= buf
;
int should_quote
= NO_QUOTE
;
register char *p
= pw
->pw_gecos
;
/* make sure specials, SPACE and CTLs are quoted within " " */
for (p
= gecos
; *p
&& *p
!= ',' && *p
!= ';' && *p
!= '%'; p
++)
should_quote
= SHOULD_MIME
;
should_quote
= SHOULD_QUOTE
;
if (should_quote
== SHOULD_MIME
)
strcpy (bp
, "=?iso-8859-1?Q?");
for (p
= gecos
; *p
&& *p
!= ',' && *p
!= ';' && *p
!= '%'; p
++)
(void) strcpy(bp
, login
);
else if (*p
< 040 || *p
>= 200 ||
strchr("_?()<>@:\\\".[]", *p
) != NULL
)
*bp
++ = "0123456789ABCDEF"[(*p
>> 4) & 0xf];
*bp
++ = "0123456789ABCDEF"[*p
& 0xf];
for (p
= gecos
; *p
&& *p
!= ',' && *p
!= ';' && *p
!= '%'; p
++)
(void) strcpy(bp
, login
);
return should_quote
== SHOULD_MIME
;
** SAFEFILE -- return true if a file exists and is safe for a user.
** fn -- filename to check.
** uid -- user id to compare against.
** gid -- group id to compare against.
** uname -- user name to compare against (used for group
** SFF_MUSTOWN -- "uid" must own this file.
** SFF_NOSLINK -- file cannot be a symbolic link.
** mode -- mode bits that must match.
** st -- if set, points to a stat structure that will
** get the stat info for the file.
** 0 if fn exists, is owned by uid, and matches mode.
** An errno otherwise. The actual errno is cleared.
# define S_IXOTH (S_IEXEC >> 6)
# define S_IXGRP (S_IEXEC >> 3)
# define S_IXUSR (S_IEXEC)
#define ST_MODE_NOFILE 0171147 /* unlikely to occur */
safefile(fn
, uid
, gid
, uname
, flags
, mode
, st
)
register struct group
*gr
= NULL
;
printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
fn
, uid
, gid
, flags
, mode
);
if (!bitset(SFF_NOPATHCHECK
, flags
) ||
(uid
== 0 && !bitset(SFF_ROOTOK
, flags
)))
/* check the path to the file for acceptability */
for (p
= fn
; (p
= strchr(++p
, '/')) != NULL
; *p
= '/')
if (stat(fn
, &stbuf
) < 0)
if (uid
== 0 && bitset(S_IWGRP
|S_IWOTH
, stbuf
.st_mode
))
message("051 WARNING: writable directory %s",
if (uid
== 0 && !bitset(SFF_ROOTOK
, flags
))
if (bitset(S_IXOTH
, stbuf
.st_mode
))
if (stbuf
.st_uid
== uid
&&
bitset(S_IXUSR
, stbuf
.st_mode
))
if (stbuf
.st_gid
== gid
&&
bitset(S_IXGRP
, stbuf
.st_mode
))
((gr
!= NULL
&& gr
->gr_gid
== stbuf
.st_gid
) ||
(gr
= getgrgid(stbuf
.st_gid
)) != NULL
))
for (gp
= gr
->gr_mem
; gp
!= NULL
&& *gp
!= NULL
; gp
++)
if (strcmp(*gp
, uname
) == 0)
if (gp
!= NULL
&& *gp
!= NULL
&&
bitset(S_IXGRP
, stbuf
.st_mode
))
if (!bitset(S_IXOTH
, stbuf
.st_mode
))
printf("\t[dir %s] %s\n", fn
, errstring(ret
));
if ((bitset(SFF_NOSLINK
, flags
) ? lstat(fn
, st
)
printf("\t%s\n", errstring(ret
));
if (!bitset(SFF_CREAT
, flags
))
/* check to see if legal to create the file */
if (stat(fn
, &stbuf
) >= 0)
int md
= S_IWRITE
|S_IEXEC
;
if ((stbuf
.st_mode
& md
) != md
)
printf("\t[final dir %s uid %d mode %o] %s\n",
fn
, stbuf
.st_uid
, stbuf
.st_mode
,
st
->st_mode
= ST_MODE_NOFILE
;
if (bitset(SFF_NOSLINK
, flags
) && S_ISLNK(st
->st_mode
))
printf("\t[slink mode %o]\tEPERM\n", st
->st_mode
);
if (bitset(SFF_REGONLY
, flags
) && !S_ISREG(st
->st_mode
))
printf("\t[non-reg mode %o]\tEPERM\n", st
->st_mode
);
if (bitset(S_IWUSR
|S_IWGRP
|S_IWOTH
, mode
) && bitset(0111, st
->st_mode
))
printf("failed (mode %o: x bits)\n", st
->st_mode
);
if (bitset(SFF_SETUIDOK
, flags
))
if (bitset(S_ISUID
, st
->st_mode
) &&
(st
->st_uid
!= 0 || bitset(SFF_ROOTOK
, flags
)))
if (bitset(S_ISGID
, st
->st_mode
) &&
(st
->st_gid
!= 0 || bitset(SFF_ROOTOK
, flags
)))
if (uid
== 0 && !bitset(SFF_ROOTOK
, flags
))
else if (st
->st_uid
!= uid
)
else if (uname
!= NULL
&&
((gr
!= NULL
&& gr
->gr_gid
== st
->st_gid
) ||
(gr
= getgrgid(st
->st_gid
)) != NULL
))
for (gp
= gr
->gr_mem
; *gp
!= NULL
; gp
++)
if (strcmp(*gp
, uname
) == 0)
printf("\t[uid %d, stat %o, mode %o] ",
st
->st_uid
, st
->st_mode
, mode
);
if ((st
->st_uid
== uid
|| st
->st_uid
== 0 ||
!bitset(SFF_MUSTOWN
, flags
)) &&
(st
->st_mode
& mode
) == mode
)
** SAFEFOPEN -- do a file open with extra checking
** fn -- the file name to open.
** omode -- the open-style mode flags.
** cmode -- the create-style mode flags.
** sff -- safefile flags.
# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
safefopen(fn
, omode
, cmode
, sff
)
if (bitset(O_CREAT
, omode
))
switch (omode
& O_ACCMODE
)
smode
= S_IREAD
|S_IWRITE
;
if (bitset(SFF_OPENASROOT
, sff
))
rval
= safefile(fn
, 0, 0, NULL
, sff
, smode
, &stb
);
rval
= safefile(fn
, RealUid
, RealGid
, RealUserName
,
if (stb
.st_mode
== ST_MODE_NOFILE
)
fp
= dfopen(fn
, omode
, cmode
);
if (bitset(O_EXCL
, omode
))
if (fstat(fileno(fp
), &sta
) < 0 ||
sta
.st_nlink
!= stb
.st_nlink
||
sta
.st_dev
!= stb
.st_dev
||
sta
.st_ino
!= stb
.st_ino
||
sta
.st_uid
!= stb
.st_uid
||
sta
.st_gid
!= stb
.st_gid
)
syserr("554 cannot open: file %s changed after open", fn
);
** 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
** line -- the line to fix.
** stripnl -- if true, strip the newline also.
** line is changed in place.
if (p
> line
&& p
[-1] == '\r')
** 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.
O_ACCMODE
, O_RDONLY
, "r",
O_ACCMODE
|O_APPEND
, O_WRONLY
, "w",
O_ACCMODE
|O_APPEND
, O_WRONLY
|O_APPEND
, "a",
O_APPEND
, O_APPEND
, "a+",
dfopen(filename
, omode
, cmode
)
register struct omodes
*om
;
for (om
= OpenModes
; om
->mask
!= 0; om
++)
if ((omode
& om
->mask
) == om
->mode
)
for (tries
= 0; tries
< 10; tries
++)
sleep((unsigned) (10 * tries
));
fd
= open(filename
, omode
, cmode
);
case ENFILE
: /* system file table full */
case EINTR
: /* interrupted syscall */
case ETXTBSY
: /* Apollo: net file locked */
if (fd
>= 0 && fstat(fd
, &st
) >= 0 && S_ISREG(st
.st_mode
))
/* lock the file to avoid accidental conflicts */
if ((omode
& O_ACCMODE
) != O_RDONLY
)
(void) lockfile(fd
, filename
, NULL
, locktype
);
return fdopen(fd
, om
->farg
);
** 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.
** mci -- the mailer connection information.
putxline(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.
** mci -- the mailer connection information.
** PXLF_MAPFROM -- map From_ to >From_.
** PXLF_STRIP8BIT -- strip 8th bit.
putxline(l
, mci
, pxflags
)
/* strip out 0200 bits -- these can look like TELNET protocol */
if (bitset(MCIF_7BIT
, mci
->mci_flags
) ||
bitset(PXLF_STRIP8BIT
, pxflags
))
for (p
= l
; (svchar
= *p
) != '\0'; ++p
)
if (bitset(0200, svchar
))
/* find the end of the line */
if (TrafficLogFile
!= NULL
)
fprintf(TrafficLogFile
, "%05d >>> ", getpid());
/* check for line overflow */
while (mci
->mci_mailer
->m_linelimit
> 0 &&
(p
- l
+ slop
) > mci
->mci_mailer
->m_linelimit
)
register char *q
= &l
[mci
->mci_mailer
->m_linelimit
- slop
- 1];
if (l
[0] == '.' && slop
== 0 &&
bitnset(M_XDOT
, mci
->mci_mailer
->m_flags
))
(void) putc('.', mci
->mci_out
);
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
))
(void) putc('>', mci
->mci_out
);
if (TrafficLogFile
!= NULL
)
(void) putc('>', TrafficLogFile
);
(void) putc('!', mci
->mci_out
);
fputs(mci
->mci_mailer
->m_eol
, mci
->mci_out
);
(void) putc(' ', mci
->mci_out
);
if (TrafficLogFile
!= NULL
)
fprintf(TrafficLogFile
, "%s!\n%05d >>> ",
if (l
[0] == '.' && slop
== 0 &&
bitnset(M_XDOT
, mci
->mci_mailer
->m_flags
))
(void) putc('.', mci
->mci_out
);
if (TrafficLogFile
!= NULL
)
(void) putc('.', TrafficLogFile
);
if (TrafficLogFile
!= NULL
)
fprintf(TrafficLogFile
, "%.*s\n", p
- l
, l
);
(void) putc(*l
, mci
->mci_out
);
fputs(mci
->mci_mailer
->m_eol
, mci
->mci_out
);
** XUNLINK -- unlink a file, doing logging as appropriate.
** f -- name of file to unlink.
syslog(LOG_DEBUG
, "%s: unlink %s", CurEnv
->e_id
, f
);
if (i
< 0 && LogLevel
> 97)
syslog(LOG_DEBUG
, "%s: unlink-fail %d", f
, errno
);
** XFCLOSE -- close a file, doing logging as appropriate.
** fp -- file pointer for the file to close
** a, b -- miscellaneous crud to print for debugging
printf("xfclose(%x) %s %s\n", fp
, a
, b
);
syserr("xfclose(%s %s): fd = 1", a
, b
);
if (fclose(fp
) < 0 && tTd(53, 99))
printf("xfclose FAILURE: %s\n", errstring(errno
));
** SFGETS -- "safe" fgets -- times out and ignores random interrupts.
** buf -- place to put the input line.
** fp -- file to read from.
** timeout -- the timeout before error occurs.
** during -- what we are trying to read (for error messages).
** NULL on error (including timeout). This will also leave
** buf containing a null string.
static jmp_buf CtxReadTimeout
;
static void readtimeout();
sfgets(buf
, siz
, fp
, timeout
, during
)
register EVENT
*ev
= NULL
;
if (setjmp(CtxReadTimeout
) != 0)
"timeout waiting for input from %s during %s\n",
CurHostName
? CurHostName
: "local", during
);
usrerr("451 timeout waiting for input during %s",
ev
= setevent(timeout
, readtimeout
, 0);
while (!feof(fp
) && !ferror(fp
))
if (p
!= NULL
|| errno
!= EINTR
)
/* clear the event if it has not sprung */
/* clean up the books and exit */
if (TrafficLogFile
!= NULL
)
fprintf(TrafficLogFile
, "%05d <<< [EOF]\n", getpid());
if (TrafficLogFile
!= NULL
)
fprintf(TrafficLogFile
, "%05d <<< %s", getpid(), buf
);
for (p
= buf
; *p
!= '\0'; p
++)
for (p
= buf
; *p
!= '\0'; p
++)
longjmp(CtxReadTimeout
, 1);
** FGETFOLDED -- like fgets, but know about folded lines.
** buf -- place to put result.
** f -- file to read from.
** 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.
** 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.
while ((i
= getc(f
)) != EOF
)
if (i
!= ' ' && i
!= '\t')
** CURTIME -- return current time.
** ATOBOOL -- convert a string representation to boolean.
** s -- string to convert. Takes "tTyY" as true,
** A boolean representation of the string.
if (s
== NULL
|| *s
== '\0' || strchr("tTyY", *s
) != NULL
)
** ATOOCT -- convert a string representation to octal.
** s -- string to convert.
** An integer representing the string interpreted as an
while (*s
>= '0' && *s
<= '7')
i
= (i
<< 3) | (*s
++ - '0');
** WAITFOR -- wait for a particular process id.
** pid -- process id to wait for.
** -1 if pid never shows up.
} while ((i
>= 0 || errno
== EINTR
) && i
!= pid
);
** BITINTERSECT -- tell if two bitmaps intersect
** a, b -- the bitmaps in question
** TRUE if they have a non-null intersection
for (i
= BITMAPBYTES
/ sizeof (int); --i
>= 0; )
** BITZEROP -- tell if a bitmap is all zero
** map -- the bit map to check
** TRUE if map is all zero.
** FALSE if there are any bits set in map.
for (i
= BITMAPBYTES
/ sizeof (int); --i
>= 0; )
** STRCONTAINEDIN -- tell if one string is contained in another
** a -- possible substring.
** b -- possible superstring.
** TRUE if a is contained in b.
if (isascii(c
) && isupper(c
))
if (*b
!= c
&& isascii(*b
) && isupper(*b
) && tolower(*b
) != c
)
if (strncasecmp(a
, b
, la
) == 0)
** 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.
** where -- a tag printed if the assertion failed
if (fstat(i
, &stbuf
) < 0 && errno
!= EOPNOTSUPP
)
syserr("%s: fd %d not open", where
, i
);
fd
= open("/dev/null", i
== 0 ? O_RDONLY
: O_WRONLY
, 0666);
** PRINTOPENFDS -- print the open file descriptors (for debugging)
** logit -- if set, send output to syslog; otherwise
for (fd
= 0; fd
< DtableSize
; fd
++)
dumpfd(fd
, FALSE
, logit
);
** DUMPFD -- dump a file descriptor
** 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.
dumpfd(fd
, printclosed
, logit
)
extern char *hostnamebyanyaddr();
if (printclosed
|| errno
!= EBADF
)
sprintf(p
, "CANNOT STAT (%s)", errstring(errno
));
slen
= fcntl(fd
, F_GETFL
, NULL
);
sprintf(p
, "fl=0x%x, ", slen
);
sprintf(p
, "mode=%o: ", st
.st_mode
);
switch (st
.st_mode
& S_IFMT
)
if (getsockname(fd
, &sa
.sa
, &slen
) < 0)
sprintf(p
, "(%s)", errstring(errno
));
hp
= hostnamebyanyaddr(&sa
);
if (sa
.sa
.sa_family
== AF_INET
)
sprintf(p
, "%s/%d", hp
, ntohs(sa
.sin
.sin_port
));
if (getpeername(fd
, &sa
.sa
, &slen
) < 0)
sprintf(p
, "(%s)", errstring(errno
));
hp
= hostnamebyanyaddr(&sa
);
if (sa
.sa
.sa_family
== AF_INET
)
sprintf(p
, "%s/%d", hp
, ntohs(sa
.sin
.sin_port
));
#if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK)
if (sizeof st
.st_size
> sizeof (long))
fmtstr
= "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%qd";
fmtstr
= "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%ld";
major(st
.st_dev
), minor(st
.st_dev
), st
.st_ino
,
st
.st_nlink
, st
.st_uid
, st
.st_gid
, st
.st_size
);
syslog(LOG_DEBUG
, "%s", buf
);
** SHORTENSTRING -- return short version of a string
** If the string is already short, just return it. If it is too
** long, return the head and tail of the string.
** s -- the string to shorten.
** m -- the max length of the string.
** Either s or a short version of s.
static char buf
[MAXSHORTSTR
+ 1];
strcpy(buf
+ m
- 3, "...");
strcpy(buf
+ m
+ 3, s
+ l
- m
);
** SHORTEN_HOSTNAME -- strip local domain information off of hostname.
** host -- the host to shorten (stripped in place).
/* strip off final dot */
p
= &host
[strlen(host
) - 1];
/* see if there is any domain at all -- if not, we are done */
/* yes, we have a domain -- see if it looks like us */
mydom
= macvalue('m', CurEnv
);
if ((canon
? strcasecmp(p
, mydom
) : strncasecmp(p
, mydom
, i
)) == 0 &&
(mydom
[i
] == '.' || mydom
[i
] == '\0'))
** PROG_OPEN -- open a program for reading
** argv -- the argument list.
** pfd -- pointer to a place to store the file descriptor.
** e -- the current envelope.
** pid of the process -- -1 if it failed.
syserr("%s: cannot create pipe for stdout", argv
[0]);
syserr("%s: cannot fork", argv
[0]);
/* child -- close stdin */
/* stdout goes back to parent */
syserr("%s: cannot dup2 for stdout", argv
[0]);
/* stderr goes to transcript if available */
if (dup2(fileno(e
->e_xfp
), 2) < 0)
syserr("%s: cannot dup2 for stderr", argv
[0]);
/* this process has no right to the queue file */
close(fileno(e
->e_lockfp
));
/* run as default user */
/* run in some directory */
p
= ProgMailer
->m_execdir
;
expand(p
, buf
, sizeof buf
, e
);
if (buf
[0] != '\0' && chdir(buf
) >= 0)
/* arrange for all the files to be closed */
for (i
= 3; i
< DtableSize
; i
++)
if ((j
= fcntl(i
, F_GETFD
, 0)) != -1)
(void) fcntl(i
, F_SETFD
, j
| 1);
/* now exec the process */
execve(argv
[0], (ARGV_T
) argv
, (ARGV_T
) UserEnviron
);
syserr("%s: cannot exec", argv
[0]);
if (transienterror(saveerrno
))
** GET_COLUMN -- look up a Column in a line buffer
** line -- the raw text line to search.
** col -- the column number to fetch.
** delim -- the delimiter between columns. If null,
** buf -- the output buffer.
get_column(line
, col
, delim
, buf
)
strcpy(delimbuf
, "\n\t ");
return NULL
; /* line empty */
if (*p
== delim
&& col
== 0)
return NULL
; /* first column empty */
if (col
== 0 && delim
== '\0')
while (*begin
&& isspace(*begin
))
for (i
= 0; i
< col
; i
++)
if ((begin
= strpbrk(begin
, delimbuf
)) == NULL
)
return NULL
; /* no such column */
while (*begin
&& isspace(*begin
))
end
= strpbrk(begin
, delimbuf
);
strncpy(buf
, begin
, end
- begin
);
** CLEANSTRCPY -- copy string keeping out bogus characters
** l -- length of space available in "to" string.
/* check for newlines and log if necessary */
(void) denlstring(f
, TRUE
, TRUE
);
while (l
> 0 && *f
!= '\0')
(isalnum(*f
) || strchr("!#$%&'*+-./^_`{|}~", *f
) != NULL
))
** DENLSTRING -- convert newlines in a string to spaces
** strict -- if set, don't permit continuation lines.
** logattacks -- if set, log attempted attacks.
** A pointer to a version of the string with newlines
** mapped to spaces. This should be copied.
denlstring(s
, strict
, logattacks
)
while ((p
= strchr(p
, '\n')) != NULL
)
if (strict
|| (*++p
!= ' ' && *p
!= '\t'))
/* allocate more space */
for (p
= bp
; (p
= strchr(p
, '\n')) != NULL
; )
syslog(LOG_NOTICE, "POSSIBLE ATTACK from %s: newline in string \"%s\"",
RealHostName == NULL ? "[UNKNOWN]" : RealHostName,