--- embedtools/src/Attic/syslogd.c 2010/09/28 17:19:58 1.1.2.1 +++ embedtools/src/Attic/syslogd.c 2011/04/28 08:08:20 1.1.2.4 @@ -106,11 +106,21 @@ __FBSDID("$FreeBSD: src/usr.sbin/syslogd/syslogd.c,v 1 #include #include #include +#if defined(__FreeBSD__) && (__FreeBSD__ > 8) #include +#else +#include +#endif #include "pathnames.h" -#include "ttymsg.h" +// CPP: +#include "defs.h" +#include "clog.h" +#include +#include +// CPP:: + #define SYSLOG_NAMES #include @@ -182,6 +192,13 @@ struct filed { char f_pname[MAXPATHLEN]; pid_t f_pid; } f_pipe; + // CPP: + struct { + char f_rname[MAXPATHLEN]; + struct clogFooter *f_footer; + size_t f_size; + } f_ring; + // CPP:: } f_un; char f_prevline[MAXSVLINE]; /* last message logged */ char f_lasttime[16]; /* time of last occurrence */ @@ -260,11 +277,15 @@ int repeatinterval[] = { 30, 120, 600 }; /* # of secs #define F_USERS 5 /* list of users */ #define F_WALL 6 /* everyone logged on */ #define F_PIPE 7 /* pipe to program */ +#define F_RING 8 /* ring buffer (circular log) */ -const char *TypeNames[8] = { +// CPP: +const char *TypeNames[] = { "UNUSED", "FILE", "TTY", "CONSOLE", - "FORW", "USERS", "WALL", "PIPE" + "FORW", "USERS", "WALL", "PIPE", + "RING" }; +// CPP:: static struct filed *Files; /* Log files that we write to */ static struct filed consfile; /* Console */ @@ -337,6 +358,163 @@ static int waitdaemon(int, int, int); static void timedout(int); static void double_rbuf(int); +// CPP: +static const char * +ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout) +{ + struct iovec localiov[7]; + ssize_t left, wret; + int cnt, fd; + static char device[MAXNAMLEN] = _PATH_DEV; + static char errbuf[1024]; + char *p; + int forked; + + forked = 0; + if (iovcnt > (int)(sizeof(localiov) / sizeof(localiov[0]))) + return ("too many iov's (change code in wall/ttymsg.c)"); + + p = device + sizeof(_PATH_DEV) - 1; + strlcpy(p, line, sizeof(device)); + if (strncmp(p, "pts/", 4) == 0) + p += 4; + if (strchr(p, '/') != NULL) { + /* A slash is an attempt to break security... */ + (void) snprintf(errbuf, sizeof(errbuf), + "Too many '/' in \"%s\"", device); + return (errbuf); + } + + /* + * open will fail on slip lines or exclusive-use lines + * if not running as root; not an error. + */ + if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { + if (errno == EBUSY || errno == EACCES) + return (NULL); + (void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device, + strerror(errno)); + return (errbuf); + } + + for (cnt = 0, left = 0; cnt < iovcnt; ++cnt) + left += iov[cnt].iov_len; + + for (;;) { + wret = writev(fd, iov, iovcnt); + if (wret >= left) + break; + if (wret >= 0) { + left -= wret; + if (iov != localiov) { + bcopy(iov, localiov, + iovcnt * sizeof(struct iovec)); + iov = localiov; + } + for (cnt = 0; (size_t)wret >= iov->iov_len; ++cnt) { + wret -= iov->iov_len; + ++iov; + --iovcnt; + } + if (wret) { + iov->iov_base = (char *)iov->iov_base + wret; + iov->iov_len -= wret; + } + continue; + } + if (errno == EWOULDBLOCK) { + int cpid; + + if (forked) { + (void) close(fd); + _exit(1); + } + cpid = fork(); + if (cpid < 0) { + (void) snprintf(errbuf, sizeof(errbuf), + "fork: %s", strerror(errno)); + (void) close(fd); + return (errbuf); + } + if (cpid) { /* parent */ + (void) close(fd); + return (NULL); + } + forked++; + /* wait at most tmout seconds */ + (void) signal(SIGALRM, SIG_DFL); + (void) signal(SIGTERM, SIG_DFL); /* XXX */ + (void) sigsetmask(0); + (void) alarm((u_int)tmout); + (void) fcntl(fd, F_SETFL, 0); /* clear O_NONBLOCK */ + continue; + } + /* + * 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) + break; + (void) close(fd); + if (forked) + _exit(1); + (void) snprintf(errbuf, sizeof(errbuf), + "%s: %s", device, strerror(errno)); + return (errbuf); + } + + (void) close(fd); + if (forked) + _exit(0); + return (NULL); +} + +static ssize_t +rbwrite(struct filed *f, char *buf, size_t nbytes) +{ + ssize_t err, out = 0; + size_t maxwrite = f->f_un.f_ring.f_footer->cf_max - f->f_un.f_ring.f_footer->cf_next; + + f->f_un.f_ring.f_footer->cf_lock = 1; + while (nbytes > 0) { + maxwrite = f->f_un.f_ring.f_footer->cf_max - f->f_un.f_ring.f_footer->cf_next; + if (maxwrite > nbytes) + maxwrite = nbytes; + err = pwrite(f->f_file, buf, maxwrite, f->f_un.f_ring.f_footer->cf_next); + if (err == -1) { + f->f_un.f_ring.f_footer->cf_lock = 0; + return -1; + } + nbytes -= err; + out += err; + buf += err; + f->f_un.f_ring.f_footer->cf_next += err; + if (f->f_un.f_ring.f_footer->cf_next == f->f_un.f_ring.f_footer->cf_max) { + f->f_un.f_ring.f_footer->cf_next = 0; + f->f_un.f_ring.f_footer->cf_wrap = 1; + } + } + + f->f_un.f_ring.f_footer->cf_lock = 0; + return out; +} +static ssize_t +rbwritev(struct filed *f, struct iovec *iov, int iovcnt) +{ + register int i; + ssize_t err, out = 0; + + for(i = 0; i < iovcnt; i++) { + err = rbwrite(f, iov[i].iov_base, iov[i].iov_len); + if (err == -1) + return -1; + out += err; + } + + return out; +} +// CPP:: + int main(int argc, char *argv[]) { @@ -1278,6 +1456,23 @@ fprintlog(struct filed *f, int flags, const char *msg) } break; + // CPP: + case F_RING: + dprintf(" %s\n", f->f_un.f_ring.f_rname); + v->iov_base = "\n"; + v->iov_len = 1; + if (rbwritev(f, iov, 7) == -1) { + int e = errno; + + munmap(f->f_un.f_ring.f_footer, sizeof(struct clogFooter)); + close(f->f_file); + f->f_type = F_UNUSED; + errno = e; + logerror(f->f_un.f_fname); + } + break; + // CPP:: + case F_PIPE: dprintf(" %s\n", f->f_un.f_pipe.f_pname); v->iov_base = lf; @@ -1343,17 +1538,37 @@ static void wallmsg(struct filed *f, struct iovec *iov, const int iovlen) { static int reenter; /* avoid calling ourselves */ - struct utmpx *ut; int i; const char *p; if (reenter++) return; +#if defined(__FreeBSD__) && (__FreeBSD__ > 8) + struct utmpx *ut; + setutxent(); /* NOSTRICT */ while ((ut = getutxent()) != NULL) { if (ut->ut_type != USER_PROCESS) continue; +#else + struct utmp ut_, *ut = &ut_; + FILE *uf; + char line[sizeof(ut_.ut_line) + 1]; + + if ((uf = fopen(_PATH_UTMP, "r")) == NULL) { + logerror(_PATH_UTMP); + reenter = 0; + return; + } + /* NOSTRICT */ + while (fread((char *)ut, sizeof(ut_), 1, uf) == 1) { + if (ut->ut_name[0] == '\0') + continue; + /* We must use strncpy since ut_* may not be NUL terminated. */ + strncpy(line, ut->ut_line, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; +#endif if (f->f_type == F_WALL) { if ((p = ttymsg(iov, iovlen, ut->ut_line, TTYMSGTIME)) != NULL) { @@ -1366,7 +1581,11 @@ wallmsg(struct filed *f, struct iovec *iov, const int for (i = 0; i < MAXUNAMES; i++) { if (!f->f_un.f_uname[i][0]) break; +#if defined(__FreeBSD__) && (__FreeBSD__ > 8) if (!strcmp(f->f_un.f_uname[i], ut->ut_user)) { +#else + if (!strncmp(f->f_un.f_uname[i], ut->ut_name, UT_NAMESIZE)) { +#endif if ((p = ttymsg(iov, iovlen, ut->ut_line, TTYMSGTIME)) != NULL) { errno = 0; /* already in msg */ @@ -1376,7 +1595,11 @@ wallmsg(struct filed *f, struct iovec *iov, const int } } } +#if defined(__FreeBSD__) && (__FreeBSD__ > 8) endutxent(); +#else + fclose(uf); +#endif reenter = 0; } @@ -1580,6 +1803,12 @@ init(int signo) } f->f_un.f_pipe.f_pid = 0; break; + // CPP: + case F_RING: + munmap(f->f_un.f_ring.f_footer, sizeof(struct clogFooter)); + close(f->f_file); + break; + // CPP:: } next = f->f_next; if (f->f_program) free(f->f_program); @@ -1721,6 +1950,12 @@ init(int signo) } break; + // CPP: + case F_RING: + printf("%s", f->f_un.f_ring.f_rname); + break; + // CPP:: + case F_PIPE: printf("%s", f->f_un.f_pipe.f_pname); break; @@ -1771,6 +2006,7 @@ cfline(const char *line, struct filed *f, const char * const char *p, *q; char *bp; char buf[MAXLINE], ebuf[100]; + struct stat sb; dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host); @@ -1977,6 +2213,41 @@ cfline(const char *line, struct filed *f, const char * f->f_type = F_FILE; } break; + + // CPP: + case '%': + if ((f->f_file = open(p + 1, O_RDWR, 0)) < 0) { + f->f_type = F_UNUSED; + logerror(p + 1); + break; + } + if (fstat(f->f_file, &sb) < 0) { + close(f->f_file); + f->f_type = F_UNUSED; + logerror(p + 1); + break; + } + f->f_un.f_ring.f_footer = mmap(NULL, sizeof(struct clogFooter), PROT_READ | PROT_WRITE, MAP_SHARED, + f->f_file, sb.st_size - sizeof(struct clogFooter)); + if (!f->f_un.f_ring.f_footer) { + close(f->f_file); + f->f_type = F_UNUSED; + logerror(p + 1); + break; + } + if (memcmp(&(f->f_un.f_ring.f_footer->cf_magic), MAGIC, 4)) { + munmap(f->f_un.f_ring.f_footer, sizeof(struct clogFooter)); + close(f->f_file); + f->f_type = F_UNUSED; + errno = ENODEV; + logerror(p + 1); + break; + } + f->f_un.f_ring.f_size = sb.st_size; + strcpy(f->f_un.f_ring.f_rname, p + 1); + f->f_type = F_RING; + break; + // CPP:: case '|': f->f_un.f_pipe.f_pid = 0;