|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T u
Length: 20822 (0x5156)
Types: TextFile
Names: »util.c,v«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z«
└─⟦f9e35cd84⟧
└─⟦this⟧ »sendmail/src/RCS/util.c,v«
head 5.18;
branch 5.18.0;
access;
symbols
UICSO:5.18.0
VANILLA:5.18;
locks; strict;
comment @ * @;
5.18
date 90.06.20.08.37.21; author paul; state Exp;
branches
5.18.0.1;
next ;
5.18.0.1
date 90.06.20.09.44.16; author paul; state Exp;
branches;
next 5.18.0.2;
5.18.0.2
date 90.10.13.19.23.30; author paul; state Exp;
branches;
next 5.18.0.3;
5.18.0.3
date 90.11.24.17.11.49; author paul; state Exp;
branches;
next 5.18.0.4;
5.18.0.4
date 90.11.29.21.17.22; author paul; state Exp;
branches;
next 5.18.0.5;
5.18.0.5
date 91.01.19.19.26.02; author paul; state Exp;
branches;
next 5.18.0.6;
5.18.0.6
date 91.03.04.21.48.23; author paul; state Exp;
branches;
next 5.18.0.7;
5.18.0.7
date 91.03.06.15.14.22; author paul; state Exp;
branches;
next 5.18.0.8;
5.18.0.8
date 91.03.06.17.32.56; author paul; state Exp;
branches;
next ;
desc
@@
5.18
log
@5.64 Berkeley release
@
text
@/*
* Copyright (c) 1983 Eric P. Allman
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char sccsid[] = "@@(#)util.c 5.18 (Berkeley) 6/1/90";
#endif /* not lint */
# include <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <sysexits.h>
# include <errno.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';
}
\f
/*
** 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);
}
\f
/*
** 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);
s++;
while (isalpha(*s))
*p++ = *s++;
}
*p = '\0';
return (buf);
}
\f
/*
** 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);
}
\f
/*
** 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);
}
\f
/*
** 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');
}
\f
/*
** LOWER -- turn letter into lower case.
**
** Parameters:
** c -- character to turn into lower case.
**
** Returns:
** c, in lower case.
**
** Side Effects:
** none.
*/
char
lower(c)
register char c;
{
return(isascii(c) && isupper(c) ? tolower(c) : c);
}
\f
/*
** 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);
}
\f
/*
** 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 = tolower(c);
}
\f
/*
** 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';
}
\f
/*
** 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.
*/
bool
safefile(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);
}
\f
/*
** 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;
if (p > line && p[-1] == '\r')
p--;
if (!stripnl)
*p++ = '\n';
*p = '\0';
}
\f
/*
** 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);
}
\f
/*
** 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');
}
\f
/*
** 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_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
# endif LOG
i = unlink(f);
# ifdef LOG
if (i < 0 && LogLevel > 21)
syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
# endif LOG
}
\f
/*
** 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;
char *
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)
{
# ifdef LOG
syslog(LOG_NOTICE,
"timeout waiting for input from %s\n",
RealHostName? RealHostName: "local");
# endif
errno = 0;
usrerr("451 timeout waiting for input");
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);
}
static
readtimeout()
{
longjmp(CtxReadTimeout, 1);
}
\f
/*
** 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);
}
\f
/*
** 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);
}
\f
/*
** 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 == '\0' || index("tTyY", *s) != NULL)
return (TRUE);
return (FALSE);
}
\f
/*
** 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);
}
\f
/*
** 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);
}
\f
/*
** 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)
BITMAP a;
BITMAP b;
{
int i;
for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
if ((a[i] & b[i]) != 0)
return (TRUE);
return (FALSE);
}
\f
/*
** 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)
BITMAP map;
{
int i;
for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
if (map[i] != 0)
return (FALSE);
return (TRUE);
}
@
5.18.0.1
log
@IDA patches
@
text
@a31 2
bool catPrint = FALSE; /* xputs: print strings for catenation */
a271 1
register struct metamac *m;
a272 5
if (s == MACNULL)
{
printf("<macnull>");
return;
}
d278 1
a278 16
if (s[0] == MATCHREPL && isdigit(s[1]) && s[2] == '\0')
{
printf("$%c", s[1]);
return;
}
else
for (m = MetaMacros; m->metaname != '\0'; m++)
if (m->metaval == *s)
{
printf("$%c%s", m->metaname, &s[1]);
return;
}
if (!catPrint)
(void) putchar('"');
d293 1
a293 2
if (!catPrint)
(void) putchar('"');
a316 1
register bool quoted_string = FALSE;
d321 1
a321 3
if (c == '"')
quoted_string = !quoted_string;
else if (!quoted_string && isascii(c) && isupper(c))
d553 1
a553 1
# endif /* LOG */
d559 1
a559 1
# endif /* LOG */
a589 7
/* check for reasonable siz arg */
if (siz < 1)
{
buf[0] = '\0';
return (NULL);
}
d599 1
a599 1
# endif /* LOG */
a841 44
/*
** PRINTCAV -- Print concatenated argument vector
**
** Parameters:
** av -- argument vector.
**
** Returns:
** none.
**
** Side Effects:
** prints av.
*/
printcav(av)
register char **av;
{
bool oldCatPrint = catPrint;
catPrint = TRUE;
printav(av);
catPrint = oldCatPrint;
}
#ifdef OUTPUT_PID
write_pid_to_file ()
{
extern char *PidFile;
FILE *f;
(void) unlink (PidFile); /* try to be safe :-) */
f = dfopen (PidFile, "w");
if (errno == 0)
{
fprintf (f, "%d\n", getpid());
(void) chmod (PidFile, 0444);
(void) fclose (f);
}
#ifdef LOG
else
syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s\n",
getpid(), PidFile);
#endif
}
#endif /* OUTPUT_PID */
@
5.18.0.2
log
@Bruce Lilly (bruce%balilly@@sonyd1.broadcast.sony.com) contributed putline()
changes: efficiency (don't re-compute XDOT inside loops), and readability
(let fprintf do the hard work). Also strip extraneous newlines from
syslog() statements.
@
text
@a513 1
int limitsflag, xdotflag;
a514 1
limitsflag = bitnset(M_LIMITS, m->m_flags);
d516 6
a521 4
if (limitsflag)
for (p=l; (*p & ~0200)!=0; p++)
if (*p & 0200)
*p &= ~0200;
a522 1
xdotflag = bitnset(M_XDOT, m->m_flags);
d531 1
a531 1
while (((p - l) > SMTPLINELIM) && limitsflag)
d535 3
a537 1
if ((*l == '.') && xdotflag)
d539 4
a542 1
fprintf(fp, "%.*s!%s", SMTPLINELIM-1, l, m->m_eol);
d547 3
a549 1
if ((*l == '.') && xdotflag)
d551 3
a553 1
fprintf(fp, "%.*s%s", p-l, l, m->m_eol);
d557 1
a557 1
} while (*l != '\0');
d579 1
a579 1
syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f);
d615 1
a615 1
static readtimeout();
d631 1
a631 1
"timeout waiting for input from %s",
d915 1
a915 1
syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s",
@
5.18.0.3
log
@Fixed forward declaration of readtimeout().
@
text
@a597 1
void readtimeout();
d607 1
d659 1
a659 1
static void
@
5.18.0.4
log
@Deleted #ifdef/#define OUTPUT_PID in favor of testing whether _PATH_SENDMAILPID
is set. sendmail.h now #include's pathnames.h instead of the other
modules.
@
text
@d25 6
a30 6
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <errno.h>
#include "sendmail.h"
d505 1
a505 1
#define SMTPLINELIM 990 /* maximum line length */
d569 1
a569 1
#ifdef LOG
d572 1
a572 1
#endif /* LOG */
d575 1
a575 1
#ifdef LOG
d578 1
a578 1
#endif /* LOG */
d621 1
a621 1
#ifdef LOG
d625 1
a625 1
#endif /* LOG */
d892 2
a893 15
/*
** WRITEPID -- Write process id to file
**
** Parameters:
** none
**
** Returns:
** none.
**
** Side Effects:
** writes pid file, creating if necessary
*/
#ifdef _PATH_SENDMAILPID
WritePid()
d897 2
a898 3
(void) unlink(PidFile); /* try to be safe :-) */
f = dfopen(PidFile, "w");
d901 3
a903 3
fprintf(f, "%d\n", getpid());
(void) chmod(PidFile, 0444);
(void) fclose(f);
d905 1
a905 1
# ifdef LOG
d907 1
a907 1
syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s: %m",
d909 1
a909 1
# endif /* LOG */
d911 1
a911 1
#endif /* _PATH_SENDMAILPID */
@
5.18.0.5
log
@Deleted #include <sys/types.h> as it's already included via sendmail.h from
useful.h. #include "sendmail.h" relocated to top of #include list.
@
text
@a24 1
#include "sendmail.h"
d26 1
d30 1
@
5.18.0.6
log
@ANSIfied.
@
text
@a30 2
static void readtimeout();
a53 1
void
d78 1
a78 1
** Returns:
d86 1
a86 1
register const char *s;
d114 1
a114 1
register const char *s;
a223 1
void
a268 1
void
d270 1
a270 1
register const char *s;
a335 1
void
a367 1
void
d369 2
a370 2
register const char *p;
const char *login;
a440 1
void
d467 2
a468 2
const char *filename;
const char *mode;
d475 1
a475 1
Xsleep((unsigned) (10 * tries));
a505 1
void
d544 1
a544 10
/*
* Some broken compilers evaluate %.0s%s as %s%s. This
* doubles blank lines. I have to remember that portability
* is one of my goals (*sigh*). -pbp
*/
if ((p-l) == 0)
fprintf(fp, "%s", m->m_eol);
else
fprintf(fp, "%.*s%s", p-l, l, m->m_eol);
a562 1
void
d564 1
a564 1
const char *f;
d597 1
d758 1
a758 1
register const char *s;
d779 1
a779 1
register const char *s;
a810 2
if (i > 0 && tTd(4, 2))
printf("waitfor: wait (pid = %d)\n", i);
a880 1
void
d882 1
a882 1
register char **av;
d884 1
a884 1
bool oldCatPrint = catPrint;
d886 3
a888 3
catPrint = TRUE;
printav(av);
catPrint = oldCatPrint;
a904 1
void
@
5.18.0.7
log
@Deleted extern declaration of malloc() (moved to def.h), deleted
inappropriate const qualifier.
@
text
@d160 1
d583 1
a583 1
char *f;
@
5.18.0.8
log
@WritePid() was checking errno and not return value from dfopen().
@
text
@d932 2
a933 1
if ((f = dfopen(PidFile, "w")) != NULL)
@