Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/syslogd/syslogd.c
Show First 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | #define sl_family sl_ai.ai_family | ||||
int sl_socket; | int sl_socket; | ||||
struct peer *sl_peer; | struct peer *sl_peer; | ||||
int (*sl_recv)(struct socklist *); | int (*sl_recv)(struct socklist *); | ||||
STAILQ_ENTRY(socklist) next; | STAILQ_ENTRY(socklist) next; | ||||
}; | }; | ||||
static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INITIALIZER(shead); | static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INITIALIZER(shead); | ||||
/* | /* | ||||
* If a file has a size limit specified, and that limit is exceeded, we treat | |||||
* the last few kbytes of the file as a circular buffer and repeatedly overwrite | |||||
* it. When that happens we write a msg to the file saying that we're doing so. | |||||
* This effectively turns the end of the file into a small circular buffer but | |||||
* preserves the bulk of the file (and thus hopefully preserves some clue as to | |||||
* what began spewing to the log to create this condition). | |||||
* | |||||
*/ | |||||
#define LIMIT_CIRCBUF_SIZE (32 * 1024) | |||||
#define LIMIT_CIRCBUF_MESSAGE \ | |||||
"\n" \ | |||||
"\n*******************************************************************************" \ | |||||
"\nsyslogd: Configured file size limit has been exceeded; data has been lost." \ | |||||
"\nsyslogd: From here down the file is being recycled in circular-buffer mode." \ | |||||
"\n*******************************************************************************" \ | |||||
"\n" | |||||
/* | |||||
* Flags to logmsg(). | * Flags to logmsg(). | ||||
*/ | */ | ||||
#define IGN_CONS 0x001 /* don't print on console */ | #define IGN_CONS 0x001 /* don't print on console */ | ||||
#define SYNC_FILE 0x002 /* do fsync on file after printing */ | #define SYNC_FILE 0x002 /* do fsync on file after printing */ | ||||
#define MARK 0x008 /* this message is a mark */ | #define MARK 0x008 /* this message is a mark */ | ||||
/* Timestamps of log entries. */ | /* Timestamps of log entries. */ | ||||
Show All 27 Lines | #define PRI_GT 0x4 | ||||
char *f_program; /* program this applies to */ | char *f_program; /* program this applies to */ | ||||
union { | union { | ||||
char f_uname[MAXUNAMES][MAXLOGNAME]; | char f_uname[MAXUNAMES][MAXLOGNAME]; | ||||
struct { | struct { | ||||
char f_hname[MAXHOSTNAMELEN]; | char f_hname[MAXHOSTNAMELEN]; | ||||
struct addrinfo *f_addr; | struct addrinfo *f_addr; | ||||
} f_forw; /* forwarding address */ | } f_forw; /* forwarding address */ | ||||
struct { | |||||
char f_fname[MAXPATHLEN]; | char f_fname[MAXPATHLEN]; | ||||
off_t f_fsizelimit; | |||||
} f_logfile; | |||||
struct { | struct { | ||||
char f_pname[MAXPATHLEN]; | char f_pname[MAXPATHLEN]; | ||||
pid_t f_pid; | pid_t f_pid; | ||||
} f_pipe; | } f_pipe; | ||||
} f_un; | } f_un; | ||||
#define fu_uname f_un.f_uname | #define fu_uname f_un.f_uname | ||||
#define fu_forw_hname f_un.f_forw.f_hname | #define fu_forw_hname f_un.f_forw.f_hname | ||||
#define fu_forw_addr f_un.f_forw.f_addr | #define fu_forw_addr f_un.f_forw.f_addr | ||||
#define fu_fname f_un.f_fname | #define fu_fname f_un.f_logfile.f_fname | ||||
#define fu_fsizelimit f_un.f_logfile.f_fsizelimit | |||||
#define fu_pipe_pname f_un.f_pipe.f_pname | #define fu_pipe_pname f_un.f_pipe.f_pname | ||||
#define fu_pipe_pid f_un.f_pipe.f_pid | #define fu_pipe_pid f_un.f_pipe.f_pid | ||||
char f_prevline[MAXSVLINE]; /* last message logged */ | char f_prevline[MAXSVLINE]; /* last message logged */ | ||||
struct logtime f_lasttime; /* time of last occurrence */ | struct logtime f_lasttime; /* time of last occurrence */ | ||||
int f_prevpri; /* pri of f_prevline */ | int f_prevpri; /* pri of f_prevline */ | ||||
size_t f_prevlen; /* length of f_prevline */ | size_t f_prevlen; /* length of f_prevline */ | ||||
int f_prevcount; /* repetition cnt of prevline */ | int f_prevcount; /* repetition cnt of prevline */ | ||||
u_int f_repeatcount; /* number of "repeated" msgs */ | u_int f_repeatcount; /* number of "repeated" msgs */ | ||||
▲ Show 20 Lines • Show All 1,459 Lines • ▼ Show 20 Lines | if (lsent != (ssize_t)il->totalsize) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case F_FILE: | case F_FILE: | ||||
dprintf(" %s\n", f->fu_fname); | dprintf(" %s\n", f->fu_fname); | ||||
iovlist_append(il, "\n"); | iovlist_append(il, "\n"); | ||||
/* | |||||
* If this file has a size limit, and we're about to write to a | |||||
* location beyond that limit, seek to limit-CIRCBUF_SIZE before | |||||
* writing and drop a message into the file to say we lost data. | |||||
*/ | |||||
if (f->fu_fsizelimit != 0 && f->fu_fsizelimit < | |||||
lseek(f->f_file, 0, SEEK_CUR)) { | |||||
lseek(f->f_file, f->fu_fsizelimit - LIMIT_CIRCBUF_SIZE, | |||||
SEEK_SET); | |||||
write(f->f_file, LIMIT_CIRCBUF_MESSAGE, | |||||
sizeof(LIMIT_CIRCBUF_MESSAGE) - 1); | |||||
} | |||||
if (writev(f->f_file, il->iov, il->iovcnt) < 0) { | if (writev(f->f_file, il->iov, il->iovcnt) < 0) { | ||||
/* | /* | ||||
* If writev(2) fails for potentially transient errors | * If writev(2) fails for potentially transient errors | ||||
* like the filesystem being full, ignore it. | * like the filesystem being full, ignore it. | ||||
* Otherwise remove this logfile from the list. | * Otherwise remove this logfile from the list. | ||||
*/ | */ | ||||
if (errno != ENOSPC) { | if (errno != ENOSPC) { | ||||
int e = errno; | int e = errno; | ||||
▲ Show 20 Lines • Show All 786 Lines • ▼ Show 20 Lines | (void)snprintf(bootfileMsg, sizeof(bootfileMsg), | ||||
"kernel boot file is %s", bootfile); | "kernel boot file is %s", bootfile); | ||||
logmsg(LOG_KERN | LOG_INFO, NULL, LocalHostName, "syslogd", | logmsg(LOG_KERN | LOG_INFO, NULL, LocalHostName, "syslogd", | ||||
NULL, NULL, NULL, bootfileMsg, 0); | NULL, NULL, NULL, bootfileMsg, 0); | ||||
dprintf("%s\n", bootfileMsg); | dprintf("%s\n", bootfileMsg); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Parse a filename config line to extract the filename and any options that may | |||||
* follow it on the line, storing the values into f->f_un.logfile. | |||||
*/ | |||||
static void | |||||
parse_fline(const char *p, struct filed *f) | |||||
{ | |||||
char *q, *r, *s; | |||||
uint64_t sizelimit; | |||||
(void)strlcpy(f->fu_fname, p, sizeof(f->fu_fname)); | |||||
/* If there are no spaces on the line, no options follow the name. */ | |||||
if ((q = strpbrk(f->fu_fname, "\t ")) == NULL) | |||||
return; | |||||
/* The only option we support right now is 'R' for recycle. */ | |||||
r = q + strspn(q, "\t "); | |||||
if (*r++ != 'R') | |||||
return; | |||||
/* The thing following the R must be numeric. */ | |||||
s = r + strspn(r, "\t "); | |||||
if (expand_number(s, &sizelimit) == -1) | |||||
return; | |||||
/* | |||||
* Looks like a valid R <size> option is present. Terminate fu_name at | |||||
* the first space and store the limit associated with the file. | |||||
*/ | |||||
*q = 0; | |||||
f->fu_fsizelimit = sizelimit; | |||||
if (f->fu_fsizelimit < LIMIT_CIRCBUF_SIZE) | |||||
f->fu_fsizelimit = LIMIT_CIRCBUF_SIZE; | |||||
} | |||||
/* | |||||
* Crack a configuration file line | * Crack a configuration file line | ||||
*/ | */ | ||||
static struct filed * | static struct filed * | ||||
cfline(const char *line, const char *prog, const char *host) | cfline(const char *line, const char *prog, const char *host) | ||||
{ | { | ||||
struct filed *f; | struct filed *f; | ||||
struct addrinfo hints, *res; | struct addrinfo hints, *res; | ||||
int error, i, pri, syncfile; | int error, i, pri, syncfile; | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | if (error) { | ||||
logerror(gai_strerror(error)); | logerror(gai_strerror(error)); | ||||
break; | break; | ||||
} | } | ||||
f->fu_forw_addr = res; | f->fu_forw_addr = res; | ||||
f->f_type = F_FORW; | f->f_type = F_FORW; | ||||
break; | break; | ||||
case '/': | case '/': | ||||
if ((f->f_file = open(p, logflags, 0600)) < 0) { | /* Parse the filename and any options into f->f_un.f_logfile. */ | ||||
parse_fline(p, f); | |||||
if (f->fu_fsizelimit != 0) { | |||||
logflags &= ~O_APPEND; | |||||
} | |||||
if ((f->f_file = open(f->fu_fname, logflags, 0600)) < 0) { | |||||
f->f_type = F_UNUSED; | f->f_type = F_UNUSED; | ||||
logerror(p); | logerror(f->fu_fname); | ||||
break; | break; | ||||
} | } | ||||
if (syncfile) | if (syncfile) | ||||
f->f_flags |= FFLAG_SYNC; | f->f_flags |= FFLAG_SYNC; | ||||
if (isatty(f->f_file)) { | if (isatty(f->f_file)) { | ||||
if (strcmp(p, ctty) == 0) | if (strcmp(p, ctty) == 0) | ||||
f->f_type = F_CONSOLE; | f->f_type = F_CONSOLE; | ||||
else | else | ||||
f->f_type = F_TTY; | f->f_type = F_TTY; | ||||
(void)strlcpy(f->fu_fname, p + sizeof(_PATH_DEV) - 1, | (void)strlcpy(f->fu_fname, p + sizeof(_PATH_DEV) - 1, | ||||
sizeof(f->fu_fname)); | sizeof(f->fu_fname)); | ||||
} else { | } else { | ||||
(void)strlcpy(f->fu_fname, p, sizeof(f->fu_fname)); | /* | ||||
* O_APPEND isn't used when limiting file size; limiting | |||||
* requires seeking. Start by seeking to end of file. | |||||
*/ | |||||
if (f->fu_fsizelimit != 0) | |||||
lseek(f->f_file, 0, SEEK_END); | |||||
f->f_type = F_FILE; | f->f_type = F_FILE; | ||||
} | } | ||||
break; | break; | ||||
case '|': | case '|': | ||||
f->fu_pipe_pid = 0; | f->fu_pipe_pid = 0; | ||||
(void)strlcpy(f->fu_pipe_pname, p + 1, | (void)strlcpy(f->fu_pipe_pname, p + 1, | ||||
sizeof(f->fu_pipe_pname)); | sizeof(f->fu_pipe_pname)); | ||||
▲ Show 20 Lines • Show All 799 Lines • Show Last 20 Lines |