** This file has been modified to get it to compile more easily
** on pre-4.4BSD (e.g., SysVr4 :-) systems. Rich $alz, June 1991.
/* change these three if you must keep running an old syslog. */
#define _PATH_LOGFILE "/dev/log"
#define _PATH_LOGCONF "/etc/syslog.conf"
#define _PATH_LOGPID "/etc/syslog.pid"
/* #define this to enable verbose debugging of all messages. */
/* #define this to line to listen on the INET port. */
/* #undef this to not read kernel syslog messages. */
#define _PATH_KLOG "/dev/klog"
/* set this depending on what your sighandler is. */
/* =()<#define SIGHANDLER @<SIGHANDLER>@>()= */
/* if you need various BSD functions, set this. */
/* Use "union wait" instead of int? */
/* =()<#define @<USE_UNION_WAIT>@_USE_UNION_WAIT>()= */
#define DONT_USE_UNION_WAIT
#if defined(DO_USE_UNION_WAIT)
#define WAITVALUE union wait
#endif /* defined(DO_USE_UNION_WAIT) */
* Copyright (c) 1983, 1988 Regents of the University of California.
* 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.
"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
static char sccsid
[] = "@(#)syslogd.c 5.42 (Berkeley) 6/29/90";
* syslogd -- log system messages
* This program implements a system log. It takes a series of lines.
* Each line may have a priority, signified as "<n>" as
* the first characters of the line. If this is
* not present, a default priority is used.
* To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
* cause it to reread its configuration file.
* MAXLINE -- the maximimum line length that can be handled.
* DEFUPRI -- the default priority for user messages
* DEFSPRI -- the default priority for kernel messages
* extensive changes by Ralph Campbell
* more extensive changes by Eric Allman (again)
#define MAXLINE 1024 /* maximum line length */
#define MAXSVLINE 120 /* maximum saved line length */
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_CRIT)
#define TIMERINTVL 30 /* interval for checking flush, mark */
#include <sys/resource.h>
#define _PATH_UTMP "/etc/utmp"
#define _PATH_DEV "/dev/"
#define _PATH_CONSOLE "/dev/console"
#define sigmask(m) (1 << ((m)-1))
char *LogName
= _PATH_LOGFILE
;
char *ConfFile
= _PATH_LOGCONF
;
char *PidFile
= _PATH_LOGPID
;
char ctty
[] = _PATH_CONSOLE
;
#define FDMASK(fd) (1 << (fd))
#define dprintf if (Debug) printf
#define MAXUNAMES 20 /* maximum number of user names */
return waitpid(-1, status
, WNOHANG
);
/* Not a general mask handler -- it know what we call, below. */
SIGHANDLER (*oldhup
)(), (*oldalrm
)();
if (omask
& sigmask(SIGHUP
))
(void) signal(SIGHUP
, oldhup
);
if (omask
& sigmask(SIGALRM
))
(void) signal(SIGALRM
, oldalrm
);
if (mask
& sigmask(SIGHUP
))
oldhup
= signal(SIGHUP
, SIG_IGN
);
if (mask
& sigmask(SIGALRM
))
oldhup
= signal(SIGALRM
, SIG_IGN
);
#define IGN_CONS 0x001 /* don't print on console */
#define SYNC_FILE 0x002 /* do fsync on file after printing */
#define ADDDATE 0x004 /* add a date to the message */
#define MARK 0x008 /* this message is a mark */
* This structure represents the files that will have log
struct filed
*f_nextone
; /* next in linked list */
short f_type
; /* entry type, see below */
short f_file
; /* file descriptor */
time_t f_time
; /* time this was last written */
u_char f_pmask
[LOG_NFACILITIES
+1]; /* priority mask */
char f_uname
[MAXUNAMES
][UT_NAMESIZE
+1];
char f_hname
[MAXHOSTNAMELEN
+1];
struct sockaddr_in f_addr
;
} f_forw
; /* forwarding address */
char f_fname
[MAXPATHLEN
];
char f_prevline
[MAXSVLINE
]; /* last message logged */
char f_lasttime
[16]; /* time of last occurrence */
char f_prevhost
[MAXHOSTNAMELEN
+1]; /* host from which recd. */
int f_prevpri
; /* pri of f_prevline */
int f_prevlen
; /* length of f_prevline */
int f_prevcount
; /* repetition cnt of prevline */
int f_repeatcount
; /* number of "repeated" msgs */
* Intervals at which we flush out "message repeated" messages,
* in seconds after previous message is logged. After each flush,
* we move to the next interval until we reach the largest.
int repeatinterval
[] = { 30, 120, 600 }; /* # of secs before flush */
#define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
(f)->f_repeatcount = MAXREPEAT; \
#define F_UNUSED 0 /* unused entry */
#define F_FILE 1 /* regular file */
#define F_TTY 2 /* terminal */
#define F_CONSOLE 3 /* console terminal */
#define F_FORW 4 /* remote machine */
#define F_USERS 5 /* list of users */
#define F_WALL 6 /* everyone logged on */
"UNUSED", "FILE", "TTY", "CONSOLE",
int Debug
; /* debug flag */
char LocalHostName
[MAXHOSTNAMELEN
+1]; /* our hostname */
char *LocalDomain
; /* our local domain name */
int InetInuse
= 0; /* non-zero if INET sockets are being used */
int finet
; /* Internet datagram socket */
int LogPort
; /* port number for INET connections */
int Initialized
= 0; /* set when we have initialized ourselves */
int MarkInterval
= 20 * 60; /* interval between marks in seconds */
int MarkSeq
= 0; /* mark sequence number */
extern char *ctime(), *strchr(), *malloc();
SIGHANDLER
die(), domark(), init(), reapchild();
int funix
, inetm
, fklog
, klogm
, len
;
struct sockaddr_un sunx
, fromunix
;
struct sockaddr_in sin
, frominet
;
char line
[MSG_BSIZE
+ 1];
while ((ch
= getopt(argc
, argv
, "df:m:p:")) != EOF
)
case 'f': /* configuration file */
case 'm': /* mark interval */
MarkInterval
= atoi(optarg
) * 60;
consfile
.f_type
= F_CONSOLE
;
(void) strcpy(consfile
.f_un
.f_fname
, ctty
);
(void) gethostname(LocalHostName
, sizeof LocalHostName
);
if (p
= strchr(LocalHostName
, '.')) {
(void) signal(SIGTERM
, die
);
(void) signal(SIGINT
, die
);
(void) signal(SIGQUIT
, die
);
(void) signal(SIGINT
, SIG_IGN
);
(void) signal(SIGQUIT
, SIG_IGN
);
(void) signal(SIGCHLD
, reapchild
);
(void) signal(SIGALRM
, domark
);
(void) alarm(TIMERINTVL
);
bzero((char *)&sunx
, sizeof(sunx
));
sunx
.sun_family
= AF_UNIX
;
(void) strncpy(sunx
.sun_path
, LogName
, sizeof sunx
.sun_path
);
funix
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
if (funix
< 0 || bind(funix
, (struct sockaddr
*) &sunx
,
chmod(LogName
, 0666) < 0) {
(void) sprintf(line
, "cannot create %s", LogName
);
dprintf("cannot create %s (%d)\n", LogName
, errno
);
finet
= socket(AF_INET
, SOCK_DGRAM
, 0);
sp
= getservbyname("syslog", "udp");
logerror("syslog/udp: unknown service");
bzero((char *)&sin
, sizeof(sin
)); /* added uunet!rbj */
sin
.sin_family
= AF_INET
;
sin
.sin_addr
.s_addr
= INADDR_ANY
;
sin
.sin_port
= LogPort
= htons(sp
->s_port
);
if (bind(finet
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
#endif /* DO_INET_SOCKET */
if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) >= 0)
dprintf("can't open %s (%d)\n", _PATH_KLOG
, errno
);
/* tuck my process id away */
fp
= fopen(PidFile
, "w");
fprintf(fp
, "%d\n", getpid());
dprintf("off & running....\n");
(void) signal(SIGHUP
, init
);
int nfds
, readfds
= FDMASK(funix
) | inetm
| klogm
;
dprintf("readfds = %#x\n", readfds
);
nfds
= select(20, (fd_set
*) &readfds
, (fd_set
*) NULL
,
(fd_set
*) NULL
, (struct timeval
*) NULL
);
dprintf("got a message (%d, %#x)\n", nfds
, readfds
);
i
= read(fklog
, line
, sizeof(line
) - 1);
} else if (i
< 0 && errno
!= EINTR
) {
if (readfds
& FDMASK(funix
)) {
i
= recvfrom(funix
, line
, MAXLINE
, 0,
(struct sockaddr
*) &fromunix
, &len
);
printline(LocalHostName
, line
);
} else if (i
< 0 && errno
!= EINTR
)
logerror("recvfrom unix");
i
= recvfrom(finet
, line
, MAXLINE
, 0,
(struct sockaddr
*) &frominet
, &len
);
printline(cvthname(&frominet
), line
);
} else if (i
< 0 && errno
!= EINTR
)
logerror("recvfrom inet");
"usage: syslogd [-d] [-f conffile] [-m markinterval] [-p path]\n");
* Take a raw input line, decode the message, and print the message
* on the appropriate log files.
/* test for special codes */
pri
= 10 * pri
+ (*p
- '0');
if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
/* don't allow users to log kernel messages */
if (LOG_FAC(pri
) == LOG_KERN
)
pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
while ((c
= *p
++ & 0177) != '\0' &&
q
< &line
[sizeof(line
) - 1])
logmsg(pri
, line
, hname
, 0);
* Take a raw input line from /dev/klog, split and format similar to syslog().
(void) strcpy(line
, "vmunix: ");
lp
= line
+ strlen(line
);
for (p
= msg
; *p
!= '\0'; ) {
flags
= SYNC_FILE
| ADDDATE
; /* fsync file after write */
pri
= 10 * pri
+ (*p
- '0');
/* kernel printf's come out on console */
if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
while (*p
!= '\0' && (c
= *p
++) != '\n' &&
logmsg(pri
, line
, LocalHostName
, flags
);
* Decode a numeric value to a symbolic name
for (c
= codetab
; c
->c_val
!= -1; c
++)
* Log a message to the appropriate log files, users, etc. based on
logmsg(pri
, msg
, from
, flags
)
register struct filed
*f
;
int pfac
= (flags
& MARK
) ? INTERNAL_MARK
: (pri
& LOG_FACMASK
);
printf("logmsg: {%s.%s} pri %o, flags %x, from %s, msg %s\n",
edoced(pfac
, facilitynames
),
edoced(LOG_PRI(pri
), prioritynames
),
dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
* Check to see if msg looks non-standard.
if (msglen
< 16 || msg
[3] != ' ' || msg
[6] != ' ' ||
msg
[9] != ':' || msg
[12] != ':' || msg
[15] != ' ')
timestamp
= ctime(&now
) + 4;
/* extract facility and priority level */
/* log the message to the particular outputs */
f
->f_file
= open(ctty
, O_WRONLY
, 0);
fprintlog(f
, flags
, msg
);
(void) sigsetmask(omask
);
for (f
= Files
; f
; f
= f
->f_nextone
) {
/* skip messages that are incorrect priority */
if ((int)f
->f_pmask
[fac
] < prilev
||
f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
if (f
->f_type
== F_CONSOLE
&& (flags
& IGN_CONS
))
/* don't output marks to recently written files */
if ((flags
& MARK
) && (now
- f
->f_time
) < MarkInterval
/ 2)
* suppress duplicate lines to this file
if ((flags
& MARK
) == 0 && msglen
== f
->f_prevlen
&&
!strcmp(msg
, f
->f_prevline
) &&
!strcmp(from
, f
->f_prevhost
)) {
(void) strncpy(f
->f_lasttime
, timestamp
, 15);
dprintf("msg repeated %d times, %ld sec of %d\n",
f
->f_prevcount
, now
- f
->f_time
,
repeatinterval
[f
->f_repeatcount
]);
* If domark would have logged this by now,
* flush it now (so we don't hold isolated messages),
* but back off so we'll flush less often
if (now
> REPEATTIME(f
)) {
fprintlog(f
, flags
, (char *)NULL
);
fprintlog(f
, 0, (char *)NULL
);
(void) strncpy(f
->f_lasttime
, timestamp
, 15);
(void) strncpy(f
->f_prevhost
, from
,
if (msglen
< MAXSVLINE
) {
(void) strcpy(f
->f_prevline
, msg
);
fprintlog(f
, flags
, (char *)NULL
);
fprintlog(f
, flags
, msg
);
(void) sigsetmask(omask
);
register struct filed
*f
;
register struct iovec
*v
;
char line
[MAXLINE
+ 1], repbuf
[80], greetings
[200];
if (f
->f_type
== F_WALL
) {
"\r\n\7Message from syslogd@%s at %.24s ...\r\n",
f
->f_prevhost
, ctime(&now
));
v
->iov_len
= strlen(greetings
);
v
->iov_base
= f
->f_lasttime
;
v
->iov_base
= f
->f_prevhost
;
v
->iov_len
= strlen(v
->iov_base
);
v
->iov_len
= strlen(msg
);
} else if (f
->f_prevcount
> 1) {
sprintf(repbuf
, "last message repeated %d times",
v
->iov_len
= strlen(repbuf
);
v
->iov_base
= f
->f_prevline
;
v
->iov_len
= f
->f_prevlen
;
dprintf("Logging to %s", TypeNames
[f
->f_type
]);
dprintf(" %s\n", f
->f_un
.f_forw
.f_hname
);
sprintf(line
, "<%d>%.15s %s", f
->f_prevpri
,
iov
[0].iov_base
, iov
[4].iov_base
);
if (sendto(finet
, line
, l
, 0, &f
->f_un
.f_forw
.f_addr
,
sizeof f
->f_un
.f_forw
.f_addr
) != l
) {
dprintf(" %s\n", f
->f_un
.f_fname
);
if (f
->f_type
!= F_FILE
) {
if (writev(f
->f_file
, iov
, 6) < 0) {
* Check for errors on TTY's due to loss of tty
if ((e
== EIO
|| e
== EBADF
) && f
->f_type
!= F_FILE
) {
f
->f_file
= open(f
->f_un
.f_fname
,
logerror(f
->f_un
.f_fname
);
logerror(f
->f_un
.f_fname
);
} else if (flags
& SYNC_FILE
)
* WALLMSG -- Write a message to the world at large
* Write the specified message to either the entire
* world, or a list of approved users.
register struct filed
*f
;
static int reenter
; /* avoid calling ourselves */
if ((uf
= fopen(_PATH_UTMP
, "r")) == NULL
) {
while (fread((char *) &ut
, sizeof ut
, 1, uf
) == 1) {
if (ut
.ut_name
[0] == '\0')
if (f
->f_type
== F_WALL
) {
if (p
= ttymsg(iov
, 6, ut
.ut_line
, 1)) {
errno
= 0; /* already in msg */
/* should we send the message to this user? */
for (i
= 0; i
< MAXUNAMES
; i
++) {
if (!f
->f_un
.f_uname
[i
][0])
if (!strncmp(f
->f_un
.f_uname
[i
], ut
.ut_name
,
if (p
= ttymsg(iov
, 6, ut
.ut_line
, 1)) {
errno
= 0; /* already in msg */
while (wait3(&status
, WNOHANG
, (struct rusage
*) NULL
) > 0)
* Return a printable representation of a host address.
extern char *inet_ntoa();
dprintf("cvthname(%s)\n", inet_ntoa(f
->sin_addr
));
if (f
->sin_family
!= AF_INET
) {
dprintf("Malformed from address\n");
hp
= gethostbyaddr(&f
->sin_addr
, sizeof(struct in_addr
), f
->sin_family
);
dprintf("Host name for your address (%s) unknown\n",
return (inet_ntoa(f
->sin_addr
));
if ((p
= strchr(hp
->h_name
, '.')) && strcmp(p
+ 1, LocalDomain
) == 0)
register struct filed
*f
;
now
= time((time_t *)NULL
);
if (MarkSeq
>= MarkInterval
) {
logmsg(LOG_INFO
, "-- MARK --", LocalHostName
, ADDDATE
|MARK
);
for (f
= Files
; f
; f
= f
->f_nextone
) {
if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
dprintf("flush %s: repeated %d times, %d sec.\n",
TypeNames
[f
->f_type
], f
->f_prevcount
,
repeatinterval
[f
->f_repeatcount
]);
fprintlog(f
, 0, (char *)NULL
);
(void) alarm(TIMERINTVL
);
extern char *sys_errlist
[];
if (errno
>= 0 && errno
< sys_nerr
)
return sys_errlist
[errno
];
(void)sprintf(buff
, "Error code %d\n", errno
);
* Print syslogd errors some place.
(void) sprintf(buf
, "syslogd: %s: %s", type
, xstrerror(errno
));
(void) sprintf(buf
, "syslogd: %s", type
);
logmsg(LOG_SYSLOG
|LOG_ERR
, buf
, LocalHostName
, ADDDATE
);
register struct filed
*f
;
for (f
= Files
; f
!= NULL
; f
= f
->f_nextone
) {
/* flush any pending output */
fprintlog(f
, 0, (char *)NULL
);
dprintf("syslogd: exiting on signal %d\n", sig
);
(void) sprintf(buf
, "exiting on signal %d", sig
);
* INIT -- Initialize syslogd from configuration table
register struct filed
*f
, *next
, **nextp
;
* Close all open log files.
for (f
= Files
; f
!= NULL
; f
= next
) {
/* flush any pending output */
fprintlog(f
, 0, (char *)NULL
);
/* open the configuration file */
if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
dprintf("cannot open %s\n", ConfFile
);
*nextp
= (struct filed
*)malloc(sizeof(*f
));
cfline("*.ERR\t/dev/console", *nextp
);
(*nextp
)->f_nextone
= (struct filed
*)malloc(sizeof(*f
));
cfline("*.PANIC\t*", (*nextp
)->f_nextone
);
* Foreach line in the conf table, open that file.
while (fgets(cline
, sizeof cline
, cf
) != NULL
) {
* check for end-of-section, comments, strip off trailing
* spaces and newline character.
for (p
= cline
; isspace(*p
); ++p
);
if (*p
== NULL
|| *p
== '#')
for (p
= strchr(cline
, '\0'); isspace(*--p
););
f
= (struct filed
*)malloc(sizeof(*f
));
/* close the configuration file */
for (f
= Files
; f
; f
= f
->f_nextone
) {
for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
printf("%d ", f
->f_pmask
[i
]);
printf("%s: ", TypeNames
[f
->f_type
]);
printf("%s", f
->f_un
.f_fname
);
printf("%s", f
->f_un
.f_forw
.f_hname
);
for (i
= 0; i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
printf("%s, ", f
->f_un
.f_uname
[i
]);
logmsg(LOG_SYSLOG
|LOG_INFO
, "syslogd: restart", LocalHostName
, ADDDATE
);
dprintf("syslogd: restarted\n");
* Crack a configuration file line
register struct filed
*f
;
dprintf("cfline(%s)\n", line
);
errno
= 0; /* keep strerror() stuff out of logerror messages */
/* clear out file entry */
bzero((char *) f
, sizeof *f
);
for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
f
->f_pmask
[i
] = INTERNAL_NOPRI
;
/* scan through the list of selectors */
for (p
= line
; *p
&& *p
!= '\t';) {
/* find the end of this facility name list */
for (q
= p
; *q
&& *q
!= '\t' && *q
++ != '.'; )
/* collect priority name */
for (bp
= buf
; *q
&& !strchr("\t,;", *q
); )
while (strchr(", ;", *q
))
/* decode priority name */
pri
= decode(buf
, prioritynames
);
(void) sprintf(xbuf
, "unknown priority name \"%s\"",
while (*p
&& !strchr("\t.;", *p
)) {
for (bp
= buf
; *p
&& !strchr("\t,;.", *p
); )
for (i
= 0; i
< LOG_NFACILITIES
; i
++)
i
= decode(buf
, facilitynames
);
"unknown facility name \"%s\"",
f
->f_pmask
[i
>> 3] = pri
;
while (*p
== ',' || *p
== ' ')
/* skip to action part */
(void) strcpy(f
->f_un
.f_forw
.f_hname
, ++p
);
logerror("hostname lookup error");
bzero((char *) &f
->f_un
.f_forw
.f_addr
,
sizeof f
->f_un
.f_forw
.f_addr
);
f
->f_un
.f_forw
.f_addr
.sin_family
= AF_INET
;
f
->f_un
.f_forw
.f_addr
.sin_port
= LogPort
;
bcopy(hp
->h_addr
, (char *) &f
->f_un
.f_forw
.f_addr
.sin_addr
, hp
->h_length
);
(void) strcpy(f
->f_un
.f_fname
, p
);
if ((f
->f_file
= open(p
, O_WRONLY
|O_APPEND
, 0)) < 0) {
if (strcmp(p
, ctty
) == 0)
for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
for (q
= p
; *q
&& *q
!= ','; )
(void) strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
if ((q
- p
) > UT_NAMESIZE
)
f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
f
->f_un
.f_uname
[i
][q
- p
] = '\0';
while (*q
== ',' || *q
== ' ')
* Decode a symbolic name to a numeric value
(void) strcpy(buf
, name
);
for (c
= codetab
; c
->c_name
; c
++)
if (!strcmp(buf
, c
->c_name
))
if ((cpid
= fork()) == -1)
int devnull
= open("/dev/null", O_RDWR
, 0);
* Display the contents of a uio structure on a terminal. Used by wall(1)
* and syslogd(8). Forks and finishes in child if write would block, waiting
* at most five minutes. Returns pointer to error string on unexpected error;
* string is not newline-terminated. Various "normal" errors are ignored
* (exclusive-use, lack of permission, etc.).
ttymsg(iov
, iovcnt
, line
)
static char device
[64] = _PATH_DEV
;
static char errbuf
[1024];
register int cnt
, fd
, left
, wret
;
struct iovec localiov
[6];
return ("too many iov's");
* open will fail on slip lines or exclusive-use lines
* if not running as root; not an error.
(void) strcpy(device
+ sizeof(_PATH_DEV
) - 1, line
);
if ((fd
= open(device
, O_WRONLY
|O_NONBLOCK
, 0)) < 0) {
if (errno
== EBUSY
|| errno
== EACCES
)
(void) sprintf(errbuf
, "%s: error %d", device
, errno
);
for (cnt
= left
= 0; cnt
< iovcnt
; ++cnt
)
left
+= iov
[cnt
].iov_len
;
wret
= writev(fd
, iov
, iovcnt
);
iovcnt
* sizeof(struct iovec
));
for (cnt
= 0; wret
>= iov
->iov_len
; ++cnt
) {
if (errno
== EWOULDBLOCK
) {
"fork: error %d", errno
);
/* wait at most 5 minutes */
(void) signal(SIGALRM
, SIG_DFL
);
(void) signal(SIGTERM
, SIG_DFL
); /* XXX */
(void) alarm((u_int
)(60 * 5));
(void) fcntl(fd
, FNDELAY
, &off
);
* We get ENODEV on a slip line if we're running as root,
* and EIO if the line just went away.
if (errno
== ENODEV
|| errno
== EIO
)
(void) sprintf(errbuf
, "%s: error %d", errno
);