libc syslog, syslogd, logger, uds fixes

changes necessary for libc syslog() using a unix domain socket.

	. libc syslog: don't use send() connect() for unix
	  datagram sockets, minix wants write() and ioctl()
	. syslogd: listen on _PATH_LOG unix domain socket
	. logger: warnings fixes
	. pfs: make uds dgram socket type nonblocking so
	  syslog() doesn't block
	. vfs: add sanity check for empty fd in unpause()

Change-Id: Ied136c6fe0cc288f5a53478f1eebccc1ab1f39fb
This commit is contained in:
Ben Gras 2013-06-10 23:47:42 +00:00
parent 1d71e39b73
commit 9178749e13
5 changed files with 102 additions and 33 deletions

View file

@ -160,11 +160,11 @@ int main(int argc, char **argv)
len = strlen(*argv); len = strlen(*argv);
if (p + len < endp && p > buf) { if (p + len < endp && p > buf) {
*--p = '\0'; *--p = '\0';
syslog(pri, buf); syslog(pri, "%s", buf);
p = buf; p = buf;
} }
if (len > sizeof(buf) - 1) { if (len > sizeof(buf) - 1) {
syslog(pri, *argv++); syslog(pri, "%s", *argv++);
if (!--argc) break; if (!--argc) break;
} else { } else {
memcpy(p, *argv++, len); memcpy(p, *argv++, len);
@ -176,10 +176,10 @@ int main(int argc, char **argv)
} }
if (p != buf) { if (p != buf) {
*p = '\0'; *p = '\0';
syslog(pri, buf); syslog(pri, "%s", buf);
} }
} else /* Main loop */ } else /* Main loop */
while (fgets(buf, sizeof(buf), stdin) != NULL) syslog(pri, buf); while (fgets(buf, sizeof(buf), stdin) != NULL) syslog(pri, "%s", buf);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -94,6 +94,8 @@
#include <time.h> #include <time.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <net/netlib.h> #include <net/netlib.h>
#include <net/hton.h> #include <net/hton.h>
@ -330,7 +332,7 @@ void logmsg(int pri, char *msg, char *from, int flags)
!strcmp(from, f->f_prevhost)) { !strcmp(from, f->f_prevhost)) {
strncpy(f->f_lasttime, timestamp, 15); strncpy(f->f_lasttime, timestamp, 15);
f->f_prevcount += 1; f->f_prevcount += 1;
DEBUG(dprintf("msg repeated %d times, %ld sec of %d\n", DEBUG(dprintf("msg repeated %d times, %d sec of %d\n",
f->f_prevcount, now - f->f_time, f->f_prevcount, now - f->f_time,
repeatinterval[f->f_repeatcount]);) repeatinterval[f->f_repeatcount]);)
/* If domark would have logged this by now, /* If domark would have logged this by now,
@ -694,6 +696,7 @@ void init(int sig)
DEBUG ( DEBUG (
if (DbgOpt) { if (DbgOpt) {
for (fLog = Files; fLog; fLog = fLog->f_next) { for (fLog = Files; fLog; fLog = fLog->f_next) {
int i;
for (i = 0; i <= LOG_NFACILITIES; i += 1) for (i = 0; i <= LOG_NFACILITIES; i += 1)
if (fLog->f_pmask[i] == INTERNAL_NOPRI) if (fLog->f_pmask[i] == INTERNAL_NOPRI)
printf("X "); printf("X ");
@ -774,6 +777,34 @@ void daemonize(char *line)
return; return;
} }
int sockread(int *fd, char *buf, int maxlen)
{
int len;
/* Read a message from application programs */
len = read(*fd, buf, maxlen);
if (len > 0) { /* Got a message */
buf[len] = '\0';
dprintf("got a message (%d, %#x)\n", *fd, len);
printline(LocalHostName, buf);
} else if (len < 0) { /* Got an error or signal while reading */
if (errno != EINTR) /* */
{
logerror("Receive error from UDP channel");
close(*fd);
*fd= -1;
}
} else { /* (len == 0) Channel has been closed */
logerror("network channel has closed");
close(*fd);
die(-1);
}
return len;
}
/* /*
** Name: int main(int argc, char **argv); ** Name: int main(int argc, char **argv);
** Function: Syslog daemon entry point ** Function: Syslog daemon entry point
@ -782,6 +813,7 @@ int main(int argc, char **argv)
{ {
char *p, *udpdev, *eol; char *p, *udpdev, *eol;
int nfd, kfd, len, fdmax; int nfd, kfd, len, fdmax;
int ufd;
int ch, port = 0; int ch, port = 0;
fd_set fdset; fd_set fdset;
struct nwio_udpopt udpopt; struct nwio_udpopt udpopt;
@ -863,7 +895,27 @@ int main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
fdmax = max(nfd, kfd) + 1; /* Open unix domain socket */
if((ufd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("unix socket");
} else {
struct sockaddr_un uaddr;
memset(&uaddr, 0, sizeof(uaddr));
strncpy(uaddr.sun_path, _PATH_LOG, sizeof(uaddr.sun_path) - 1);
uaddr.sun_family = AF_UNIX;
if(bind(ufd, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
perror("unix socket bind");
close(ufd);
ufd = -1;
}
}
if(ufd < 0) exit(1);
DEBUG(dprintf("unix domain socket = %d, at %s....\n", ufd, _PATH_LOG);)
fdmax = max(max(nfd, kfd), ufd) + 1;
DEBUG(dprintf("off & running....\n");) DEBUG(dprintf("off & running....\n");)
@ -874,35 +926,26 @@ int main(int argc, char **argv)
FD_ZERO(&fdset); /* Setup descriptors for select */ FD_ZERO(&fdset); /* Setup descriptors for select */
if(nfd >= 0) FD_SET(nfd, &fdset); if(nfd >= 0) FD_SET(nfd, &fdset);
if(kfd >= 0) FD_SET(kfd, &fdset); if(kfd >= 0) FD_SET(kfd, &fdset);
if(ufd >= 0) FD_SET(ufd, &fdset);
dprintf("select: nfd = %d, ufd = %d, fdmax = %d\n", nfd, ufd, fdmax);
if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) { if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) {
sleep(1); sleep(1);
continue; continue;
} }
if (nfd >= 0 && FD_ISSET(nfd, &fdset)) { if (nfd >= 0 && FD_ISSET(nfd, &fdset)) {
dprintf("got nfd message (%d)\n", nfd);
/* Read a message from application programs */ len = sockread(&nfd, line, MAXLINE);
len = read(nfd, line, MAXLINE);
if (len > 0) { /* Got a message */
line[len] = '\0';
dprintf("got a message (%d, %#x)\n", nfd, len);
printline(LocalHostName, line);
} else if (len < 0) { /* Got an error or signal while reading */
if (errno != EINTR) /* */
{
logerror("Receive error from UDP channel");
close(nfd);
nfd= -1;
}
} else { /* (len == 0) Channel has been closed */
logerror("UDP channel has closed");
close(nfd);
die(-1);
}
} }
if (ufd >= 0 && FD_ISSET(ufd, &fdset)) {
dprintf("got ufd message (%d)\n", ufd);
len = sockread(&ufd, line, MAXLINE);
}
if (kfd >= 0 && FD_ISSET(kfd, &fdset)) { if (kfd >= 0 && FD_ISSET(kfd, &fdset)) {
static char linebuf[5*1024]; static char linebuf[5*1024];

View file

@ -59,6 +59,10 @@ __RCSID("$NetBSD: syslog.c,v 1.53 2012/10/11 17:09:55 christos Exp $");
#include "reentrant.h" #include "reentrant.h"
#include "extern.h" #include "extern.h"
#ifdef __minix
#include <sys/ioctl.h>
#endif
#ifdef __weak_alias #ifdef __weak_alias
__weak_alias(closelog,_closelog) __weak_alias(closelog,_closelog)
__weak_alias(openlog,_openlog) __weak_alias(openlog,_openlog)
@ -448,7 +452,11 @@ vsyslogp_r(int pri, struct syslog_data *data, const char *msgid,
* to give syslogd a chance to empty its socket buffer. * to give syslogd a chance to empty its socket buffer.
*/ */
for (tries = 0; tries < MAXTRIES; tries++) { for (tries = 0; tries < MAXTRIES; tries++) {
#ifdef __minix
if (write(data->log_file, tbuf, cnt) != -1)
#else
if (send(data->log_file, tbuf, cnt, 0) != -1) if (send(data->log_file, tbuf, cnt, 0) != -1)
#endif
break; break;
if (errno != ENOBUFS) { if (errno != ENOBUFS) {
disconnectlog_r(data); disconnectlog_r(data);
@ -517,9 +525,15 @@ connectlog_r(struct syslog_data *data)
data->log_connected = 0; data->log_connected = 0;
} }
if (!data->log_connected) { if (!data->log_connected) {
#ifdef __minix
if(ioctl(data->log_file, NWIOSUDSTADDR, (void *) &sun) < 0)
#else
if (connect(data->log_file, if (connect(data->log_file,
(const struct sockaddr *)(const void *)&sun, (const struct sockaddr *)(const void *)&sun,
(socklen_t)sizeof(sun)) == -1) { (socklen_t)sizeof(sun)) == -1)
#endif
{
(void)close(data->log_file); (void)close(data->log_file);
data->log_file = -1; data->log_file = -1;
} else } else

View file

@ -579,14 +579,21 @@ static int uds_perform_write(int minor, endpoint_t m_source,
return EPIPE; return EPIPE;
} }
/* we have to preserve the boundary for DGRAM. if there's
* already a packet waiting, discard it silently and pretend
* it was written.
*/
if(uds_fd_table[minor].type == SOCK_DGRAM &&
uds_fd_table[peer].size > 0) {
return size;
}
/* check if write would overrun buffer. check if message /* check if write would overrun buffer. check if message
* boundry preserving types (SEQPACKET and DGRAM) wouldn't write * SEQPACKET wouldn't write to an empty buffer. check if
* to an empty buffer. check if connectionless sockets have a * connectionless sockets have a target to write to.
* target to write to.
*/ */
if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) || if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) ||
((uds_fd_table[minor].type == SOCK_SEQPACKET || ((uds_fd_table[minor].type == SOCK_SEQPACKET) &&
uds_fd_table[minor].type == SOCK_DGRAM) &&
uds_fd_table[peer].size > 0)) { uds_fd_table[peer].size > 0)) {
if (pretend) { if (pretend) {

View file

@ -604,6 +604,11 @@ void unpause(endpoint_t proc_e)
if (fild < 0 || fild >= OPEN_MAX) if (fild < 0 || fild >= OPEN_MAX)
panic("file descriptor out-of-range"); panic("file descriptor out-of-range");
f = rfp->fp_filp[fild]; f = rfp->fp_filp[fild];
if(!f) {
sys_sysctl_stacktrace(rfp->fp_endpoint);
panic("process %d blocked on empty fd %d",
rfp->fp_endpoint, fild);
}
dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */ dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */
major_dev = major(dev); major_dev = major(dev);
minor_dev = minor(dev); minor_dev = minor(dev);