aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/syslogd.c770
1 files changed, 770 insertions, 0 deletions
diff --git a/toys/pending/syslogd.c b/toys/pending/syslogd.c
new file mode 100644
index 00000000..5ac96c6f
--- /dev/null
+++ b/toys/pending/syslogd.c
@@ -0,0 +1,770 @@
+/* syslogd.c - a system logging utility.
+ *
+ * Copyright 2013 Madhur Verma <mad.flexi@gmail.com>
+ *
+ * No Standard
+
+USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1s#<0=200m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT))
+
+config SYSLOGD
+ bool "syslogd"
+ default n
+ help
+ Usage: syslogd [-a socket] [-p socket] [-O logfile] [-f config file] [-m interval]
+ [-p socket] [-s SIZE] [-b N] [-R HOST] [-l N] [-nSLKD]
+
+ System logging utility
+
+ -a Extra unix socket for listen
+ -O FILE Default log file <DEFAULT: /var/log/messages>
+ -f FILE Config file <DEFAULT: /etc/syslog.conf>
+ -p Alternative unix domain socket <DEFAULT : /dev/log>
+ -n Avoid auto-backgrounding.
+ -S Smaller output
+ -m MARK interval <DEFAULT: 20 minutes> (RANGE: 0 to 71582787)
+ -R HOST Log to IP or hostname on PORT (default PORT=514/UDP)"
+ -L Log locally and via network (default is network only if -R)"
+ -s SIZE Max size (KB) before rotation (default:200KB, 0=off)
+ -b N rotated logs to keep (default:1, max=99, 0=purge)
+ -K Log to kernel printk buffer (use dmesg to read it)
+ -l N Log only messages more urgent than prio(default:8 max:8 min:1)
+ -D Drop duplicates
+*/
+
+#define FOR_syslogd
+#include "toys.h"
+#include "toynet.h"
+
+GLOBALS(
+ char *socket;
+ char *config_file;
+ char *unix_socket;
+ char *logfile;
+ long interval;
+ long rot_size;
+ long rot_count;
+ char *remote_log;
+ long log_prio;
+
+ struct arg_list *lsocks; // list of listen sockets
+ struct arg_list *lfiles; // list of write logfiles
+ fd_set rfds; // fds for reading
+ int sd; // socket for logging remote messeges.
+)
+
+#define flag_get(f,v,d) ((toys.optflags & f) ? v : d)
+#define flag_chk(f) ((toys.optflags & f) ? 1 : 0)
+
+#ifndef SYSLOG_NAMES
+#define INTERNAL_NOPRI 0x10
+#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0)
+
+typedef struct _code {
+ char *c_name;
+ int c_val;
+} CODE;
+
+static CODE prioritynames[] =
+{
+ { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT },
+ { "debug", LOG_DEBUG },
+ { "emerg", LOG_EMERG },
+ { "err", LOG_ERR },
+ { "error", LOG_ERR }, /* DEPRECATED */
+ { "info", LOG_INFO },
+ { "none", INTERNAL_NOPRI }, /* INTERNAL */
+ { "notice", LOG_NOTICE },
+ { "panic", LOG_EMERG }, /* DEPRECATED */
+ { "warn", LOG_WARNING }, /* DEPRECATED */
+ { "warning", LOG_WARNING },
+ { NULL, -1 }
+};
+
+static CODE facilitynames[] =
+{
+ { "auth", LOG_AUTH },
+ { "authpriv", LOG_AUTHPRIV },
+ { "cron", LOG_CRON },
+ { "daemon", LOG_DAEMON },
+ { "ftp", LOG_FTP },
+ { "kern", LOG_KERN },
+ { "lpr", LOG_LPR },
+ { "mail", LOG_MAIL },
+ { "mark", INTERNAL_MARK }, /* INTERNAL */
+ { "news", LOG_NEWS },
+ { "security", LOG_AUTH }, /* DEPRECATED */
+ { "syslog", LOG_SYSLOG },
+ { "user", LOG_USER },
+ { "uucp", LOG_UUCP },
+ { "local0", LOG_LOCAL0 },
+ { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 },
+ { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 },
+ { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 },
+ { "local7", LOG_LOCAL7 },
+ { NULL, -1 }
+};
+#endif
+
+
+// Signal handling
+struct fd_pair { int rd; int wr; };
+static struct fd_pair sigfd;
+
+// UNIX Sockets for listening
+typedef struct unsocks_s {
+ char *path;
+ struct sockaddr_un sdu;
+ int sd;
+} unsocks_t;
+
+// Log file entry to log into.
+typedef struct logfile_s {
+ char *filename;
+ char *config;
+ uint8_t isNetwork;
+ uint32_t facility[8];
+ uint8_t level[LOG_NFACILITIES];
+ int logfd;
+ struct sockaddr_in saddr;
+} logfile_t;
+
+// Adds opened socks to rfds for select()
+static int addrfds(void)
+{
+ unsocks_t *sock;
+ int ret = 0;
+ struct arg_list *node = TT.lsocks;
+ FD_ZERO(&TT.rfds);
+
+ while (node) {
+ sock = (unsocks_t*) node->arg;
+ if (sock->sd > 2) {
+ FD_SET(sock->sd, &TT.rfds);
+ ret = sock->sd;
+ }
+ node = node->next;
+ }
+ FD_SET(sigfd.rd, &TT.rfds);
+ return (sigfd.rd > ret)?sigfd.rd:ret;
+}
+
+/*
+ * initializes unsock_t structure
+ * and opens socket for reading
+ * and adds to global lsock list.
+ */
+static int open_unix_socks(void)
+{
+ struct arg_list *node;
+ unsocks_t *sock;
+ int ret = 0;
+
+ for(node = TT.lsocks; node; node = node->next) {
+ sock = (unsocks_t*) node->arg;
+ sock->sdu.sun_family = AF_UNIX;
+ strcpy(sock->sdu.sun_path, sock->path);
+ sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (sock->sd < 0) {
+ perror_msg("OPEN SOCKS : failed");
+ continue;
+ }
+ unlink(sock->sdu.sun_path);
+ if (bind(sock->sd, (struct sockaddr *) &sock->sdu, sizeof(sock->sdu))) {
+ perror_msg("BIND SOCKS : failed sock : %s", sock->sdu.sun_path);
+ close(sock->sd);
+ continue;
+ }
+ chmod(sock->path, 0777);
+ ret++;
+ }
+ return ret;
+}
+
+/*
+ * creates a socket of family INET and protocol UDP
+ * if successful then returns SOCK othrwise error
+ */
+static int open_udp_socks(char *host, int port, struct sockaddr_in *sadd)
+{
+ struct addrinfo *info, rp;
+
+ memset(&rp, 0, sizeof(rp));
+ rp.ai_family = AF_INET;
+ rp.ai_socktype = SOCK_DGRAM;
+ rp.ai_protocol = IPPROTO_UDP;
+
+ if (getaddrinfo(host, NULL, &rp, &info) || !info)
+ perror_exit("BAD ADDRESS: can't find : %s ", host);
+ ((struct sockaddr_in*)info->ai_addr)->sin_port = htons(port);
+ memcpy(sadd, info->ai_addr, info->ai_addrlen);
+ freeaddrinfo(info);
+
+ return xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+}
+
+// Returns node having filename
+static struct arg_list *get_file_node(char *filename, struct arg_list *list)
+{
+ while (list) {
+ if (!strcmp(((logfile_t*) list->arg)->filename, filename)) return list;
+ list = list->next;
+ }
+ return list;
+}
+
+/*
+ * recurses the logfile list and resolves config
+ * for evry file and updates facilty and log level bits.
+ */
+static int resolve_config(logfile_t *file)
+{
+ char *tk, *fac, *lvl, *tmp, *nfac;
+ int count = 0;
+ unsigned facval = 0;
+ uint8_t set, levval, neg;
+ CODE *val = NULL;
+
+ tmp = xstrdup(file->config);
+ for (tk = strtok(tmp, "; \0"); tk; tk = strtok(NULL, "; \0")) {
+ fac = tk;
+ tk = strchr(fac, '.');
+ if (!tk) return -1;
+ *tk = '\0';
+ lvl = tk + 1;
+
+ while(1) {
+ count = 0;
+ if (*fac == '*') {
+ facval = 0xFFFFFFFF;
+ fac++;
+ }
+ nfac = strchr(fac, ',');
+ if (nfac) *nfac = '\0';
+ while (*fac && ((CODE*) &facilitynames[count])->c_name) {
+ val = (CODE*) &facilitynames[count];
+ if (!strcmp(fac, val->c_name)) {
+ facval |= (1<<LOG_FAC(val->c_val));
+ break;
+ }
+ count++;
+ }
+ if (((CODE*) &facilitynames[count])->c_val == -1)
+ return -1;
+
+ if (nfac) fac = nfac+1;
+ else break;
+ }
+
+ count = 0;
+ set = 0;
+ levval = 0;
+ neg = 0;
+ if (*lvl == '!') {
+ neg = 1;
+ lvl++;
+ }
+ if (*lvl == '=') {
+ set = 1;
+ lvl++;
+ }
+ if (*lvl == '*') {
+ levval = 0xFF;
+ lvl++;
+ }
+ while (*lvl && ((CODE*) &prioritynames[count])->c_name) {
+ val = (CODE*) &prioritynames[count];
+ if (!strcmp(lvl, val->c_name)) {
+ levval |= set ? LOG_MASK(val->c_val):LOG_UPTO(val->c_val);
+ if (neg) levval = ~levval;
+ break;
+ }
+ count++;
+ }
+ if (((CODE*) &prioritynames[count])->c_val == -1) return -1;
+
+ count = 0;
+ set = levval;
+ while(set) {
+ if (set & 0x1) file->facility[count] |= facval;
+ set >>= 1;
+ count++;
+ }
+ for (count = 0; count < LOG_NFACILITIES; count++) {
+ if (facval & 0x1) file->level[count] |= levval;
+ facval >>= 1;
+ }
+ }
+ free(tmp);
+
+ return 0;
+}
+
+// Parse config file and update the log file list.
+static int parse_config_file(void)
+{
+ logfile_t *file;
+ FILE *fp = NULL;
+ char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL};
+ int len, linelen, tcount, lineno = 0;
+ struct arg_list *node;
+ /*
+ * if -K then open only /dev/kmsg
+ * all other log files are neglected
+ * thus no need to open config either.
+ */
+ if (flag_chk(FLAG_K)) {
+ node = xzalloc(sizeof(struct arg_list));
+ file = xzalloc(sizeof(logfile_t));
+ file->filename = "/dev/kmsg";
+ file->config = "*.*";
+ memset(file->level, 0xFF, sizeof(file->level));
+ memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
+ node->arg = (char*) file;
+ TT.lfiles = node;
+ return 0;
+ }
+ /*
+ * if -R then add remote host to log list
+ * if -L is not provided all other log
+ * files are neglected thus no need to
+ * open config either so just return.
+ */
+ if (flag_chk(FLAG_R)) {
+ node = xzalloc(sizeof(struct arg_list));
+ file = xzalloc(sizeof(logfile_t));
+ file->filename = xmsprintf("@%s",TT.remote_log);
+ file->isNetwork = 1;
+ file->config = "*.*";
+ memset(file->level, 0xFF, sizeof(file->level));
+ memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
+ node->arg = (char*) file;
+ TT.lfiles = node;
+ if (!flag_chk(FLAG_L))return 0;
+ }
+ /*
+ * Read config file and add logfiles to the list
+ * with their configuration.
+ */
+ fp = fopen(TT.config_file, "r");
+ if (!fp && flag_chk(FLAG_f))
+ perror_exit("can't open '%s'", TT.config_file);
+
+ for (len = 0, linelen = 0; fp;) {
+ len = getline(&confline, (size_t*) &linelen, fp);
+ if (len <= 0) break;
+ lineno++;
+ for (; *confline == ' '; confline++, len--) ;
+ if ((confline[0] == '#') || (confline[0] == '\n')) continue;
+ for (tcount = 0, tk = strtok(confline, " \t"); tk && (tcount < 2); tk =
+ strtok(NULL, " \t"), tcount++) {
+ if (tcount == 2) {
+ error_msg("error in '%s' at line %d", TT.config_file, lineno);
+ return -1;
+ }
+ tokens[tcount] = xstrdup(tk);
+ }
+ if (tcount <= 1 || tcount > 2) {
+ if (tokens[0]) free(tokens[0]);
+ error_msg("bad line %d: 1 tokens found, 2 needed", lineno);
+ return -1;
+ }
+ tk = (tokens[1] + (strlen(tokens[1]) - 1));
+ if (*tk == '\n') *tk = '\0';
+ if (*tokens[1] == '\0') {
+ error_msg("bad line %d: 1 tokens found, 2 needed", lineno);
+ return -1;
+ }
+ if (*tokens[1] == '*') goto loop_again;
+
+ node = get_file_node(tokens[1], TT.lfiles);
+ if (!node) {
+ node = xzalloc(sizeof(struct arg_list));
+ file = xzalloc(sizeof(logfile_t));
+ file->config = xstrdup(tokens[0]);
+ if (resolve_config(file)==-1) {
+ error_msg("error in '%s' at line %d", TT.config_file, lineno);
+ return -1;
+ }
+ file->filename = xstrdup(tokens[1]);
+ if (*file->filename == '@') file->isNetwork = 1;
+ node->arg = (char*) file;
+ node->next = TT.lfiles;
+ TT.lfiles = node;
+ } else {
+ file = (logfile_t*) node->arg;
+ int rel = strlen(file->config) + strlen(tokens[0]) + 2;
+ file->config = xrealloc(file->config, rel);
+ sprintf(file->config, "%s;%s", file->config, tokens[0]);
+ }
+loop_again:
+ if (tokens[0]) free(tokens[0]);
+ if (tokens[1]) free(tokens[1]);
+ free(confline);
+ confline = NULL;
+ }
+ /*
+ * Can't open config file or support is not enabled
+ * adding default logfile to the head of list.
+ */
+ if (!fp){
+ node = xzalloc(sizeof(struct arg_list));
+ file = xzalloc(sizeof(logfile_t));
+ file->filename = flag_get(FLAG_O, TT.logfile, "/var/log/messages"); //DEFLOGFILE
+ file->isNetwork = 0;
+ file->config = "*.*";
+ memset(file->level, 0xFF, sizeof(file->level));
+ memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
+ node->arg = (char*) file;
+ node->next = TT.lfiles;
+ TT.lfiles = node;
+ }
+ if (fp) {
+ fclose(fp);
+ fp = NULL;
+ }
+ return 0;
+}
+
+static int getport(char *str, char *filename)
+{
+ char *endptr = NULL;
+ int base = 10;
+ errno = 0;
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
+ base = 16;
+ str += 2;
+ }
+ long port = strtol(str, &endptr, base);
+ if (errno || *endptr!='\0'|| endptr == str
+ || port < 0 || port > 65535) error_exit("wrong port no in %s", filename);
+ return (int)port;
+}
+
+// open every log file in list.
+static void open_logfiles(void)
+{
+ logfile_t *tfd;
+ char *p, *tmpfile;
+ int port = -1;
+ struct arg_list *node = TT.lfiles;
+
+ while (node) {
+ tfd = (logfile_t*) node->arg;
+ if (tfd->isNetwork) {
+ tmpfile = xstrdup(tfd->filename +1);
+ if ((p = strchr(tmpfile, ':'))) {
+ *p = '\0';
+ port = getport(p + 1, tfd->filename);
+ }
+ tfd->logfd = open_udp_socks(tmpfile, (port>=0)?port:514, &tfd->saddr);
+ free(tmpfile);
+ } else tfd->logfd = open(tfd->filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
+ if (tfd->logfd < 0) {
+ tfd->filename = "/dev/console";
+ tfd->logfd = open(tfd->filename, O_APPEND);
+ }
+ node = node->next;
+ }
+}
+
+//write to file with rotation
+static int write_rotate( logfile_t *tf, int len)
+{
+ int size, isreg;
+ struct stat statf;
+ isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode));
+ size = statf.st_size;
+
+ if (flag_chk(FLAG_s) || flag_chk(FLAG_b)) {
+ if (TT.rot_size && isreg && (size + len) > (TT.rot_size*1024)) {
+ if (TT.rot_count) { /* always 0..99 */
+ int i = strlen(tf->filename) + 3 + 1;
+ char old_file[i];
+ char new_file[i];
+ i = TT.rot_count - 1;
+ while (1) {
+ sprintf(new_file, "%s.%d", tf->filename, i);
+ if (!i) break;
+ sprintf(old_file, "%s.%d", tf->filename, --i);
+ rename(old_file, new_file);
+ }
+ rename(tf->filename, new_file);
+ unlink(tf->filename);
+ close(tf->logfd);
+ tf->logfd = open(tf->filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
+ }
+ ftruncate(tf->logfd, 0);
+ }
+ }
+ return write(tf->logfd, toybuf, len);
+}
+
+//search the given name and return its value
+static char *dec(int val, CODE *clist)
+{
+ const CODE *c;
+
+ for (c = clist; c->c_name; c++)
+ if (val == c->c_val) return c->c_name;
+ return itoa(val);
+}
+
+// Compute priority from "facility.level" pair
+static void priority_to_string(int pri, char **facstr, char **lvlstr)
+{
+ int fac,lev;
+
+ fac = LOG_FAC(pri);
+ lev = LOG_PRI(pri);
+ *facstr = dec(fac<<3, facilitynames);
+ *lvlstr = dec(lev, prioritynames);
+}
+
+//Parse messege and write to file.
+static void logmsg(char *msg, int len)
+{
+ time_t now;
+ char *p, *ts, *lvlstr, *facstr;
+ struct utsname uts;
+ int pri = 0;
+ struct arg_list *lnode = TT.lfiles;
+
+ char *omsg = msg;
+ int olen = len, fac, lvl;
+
+ if (*msg == '<') { // Extract the priority no.
+ pri = (int) strtoul(msg + 1, &p, 10);
+ if (*p == '>') msg = p + 1;
+ }
+ /* Jan 18 00:11:22 msg...
+ * 01234567890123456
+ */
+ if (len < 16 || msg[3] != ' ' || msg[6] != ' ' || msg[9] != ':'
+ || msg[12] != ':' || msg[15] != ' ') {
+ time(&now);
+ ts = ctime(&now) + 4; /* skip day of week */
+ } else {
+ now = 0;
+ ts = msg;
+ msg += 16;
+ }
+ ts[15] = '\0';
+ fac = LOG_FAC(pri);
+ lvl = LOG_PRI(pri);
+
+ if (flag_chk(FLAG_K)) {
+ len = sprintf(toybuf, "<%d> %s\n", pri, msg);
+ goto do_log;
+ }
+ priority_to_string(pri, &facstr, &lvlstr);
+
+ p = "local";
+ if (!uname(&uts)) p = uts.nodename;
+ if (flag_chk(FLAG_S)) len = sprintf(toybuf, "%s %s\n", ts, msg);
+ else len = sprintf(toybuf, "%s %s %s.%s %s\n", ts, p, facstr, lvlstr, msg);
+
+do_log:
+ if (lvl >= TT.log_prio) return;
+
+ while (lnode) {
+ logfile_t *tf = (logfile_t*) lnode->arg;
+ if (tf->logfd > 0) {
+ if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) {
+ int wlen;
+ if (tf->isNetwork)
+ wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr));
+ else wlen = write_rotate(tf, len);
+ if (wlen < 0) perror_msg("write failed file : %s ", (tf->isNetwork)?(tf->filename+1):tf->filename);
+ }
+ }
+ lnode = lnode->next;
+ }
+}
+
+/*
+ * closes all read and write fds
+ * and frees all nodes and lists
+ */
+static void cleanup(void)
+{
+ struct arg_list *fnode;
+ while (TT.lsocks) {
+ fnode = TT.lsocks;
+ if (((unsocks_t*) fnode->arg)->sd >= 0)
+ close(((unsocks_t*) fnode->arg)->sd);
+ free(fnode->arg);
+ TT.lsocks = fnode->next;
+ free(fnode);
+ }
+ unlink("/dev/log");
+
+ while (TT.lfiles) {
+ fnode = TT.lfiles;
+ if (((logfile_t*) fnode->arg)->logfd >= 0)
+ close(((logfile_t*) fnode->arg)->logfd);
+ free(fnode->arg);
+ TT.lfiles = fnode->next;
+ free(fnode);
+ }
+}
+
+static void signal_handler(int sig)
+{
+ unsigned char ch = sig;
+ if (write(sigfd.wr, &ch, 1) != 1) error_msg("can't send signal");
+}
+
+static void setup_signal()
+{
+ if (pipe((int *)&sigfd) < 0) error_exit("pipe failed\n");
+
+ fcntl(sigfd.wr , F_SETFD, FD_CLOEXEC);
+ fcntl(sigfd.rd , F_SETFD, FD_CLOEXEC);
+ int flags = fcntl(sigfd.wr, F_GETFL);
+ fcntl(sigfd.wr, F_SETFL, flags | O_NONBLOCK);
+ signal(SIGHUP, signal_handler);
+ signal(SIGTERM, signal_handler);
+ signal(SIGINT, signal_handler);
+ signal(SIGQUIT, signal_handler);
+}
+
+static void syslog_daemon(void)
+{
+ int fd = open("/dev/null", O_RDWR);
+ if (fd < 0) fd = xcreate("/", O_RDONLY, 0666);
+
+ pid_t pid = fork();
+ if (pid < 0) perror_exit("DAEMON: failed to fork");
+ if (pid) exit(EXIT_SUCCESS);
+
+ setsid();
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ if (fd > 2) close(fd);
+
+ //don't daemonize again if SIGHUP received.
+ toys.optflags |= FLAG_n;
+}
+
+void syslogd_main(void)
+{
+ unsocks_t *tsd;
+ int maxfd, retval, last_len=0;
+ struct timeval tv;
+ struct arg_list *node;
+ char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each
+
+ if (flag_chk(FLAG_p) && strlen(TT.unix_socket) > 108)
+ error_exit("Socket path should not be more than 108");
+
+ TT.config_file = flag_get(FLAG_f, TT.config_file, "/etc/syslog.conf"); //DEFCONFFILE
+init_jumpin:
+ TT.lsocks = xzalloc(sizeof(struct arg_list));
+ tsd = xzalloc(sizeof(unsocks_t));
+
+ tsd->path = flag_get(FLAG_p, TT.unix_socket , "/dev/log"); // DEFLOGSOCK
+ TT.lsocks->arg = (char*) tsd;
+
+ if (flag_chk(FLAG_a)) {
+ for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) {
+ struct arg_list *ltemp = xzalloc(sizeof(struct arg_list));
+ if (strlen(temp) > 107) temp[108] = '\0';
+ tsd = xzalloc(sizeof(unsocks_t));
+ tsd->path = temp;
+ ltemp->arg = (char*) tsd;
+ ltemp->next = TT.lsocks;
+ TT.lsocks = ltemp;
+ }
+ }
+ if (!open_unix_socks()) {
+ error_msg("Can't open single socket for listenning.");
+ goto clean_and_exit;
+ }
+ setup_signal();
+ if (parse_config_file() == -1) goto clean_and_exit;
+ open_logfiles();
+ if (!flag_chk(FLAG_n)) syslog_daemon();
+ {
+ int pid_fd = open("/var/run/syslogd.pid", O_CREAT | O_WRONLY | O_TRUNC, 0666);
+ if (pid_fd > 0) {
+ unsigned pid = getpid();
+ int len = sprintf(toybuf, "%u\n", pid);
+ write(pid_fd, toybuf, len);
+ close(pid_fd);
+ }
+ }
+
+ logmsg("<46>Toybox: syslogd started", 27); //27 : the length of message
+ for (;;) {
+ maxfd = addrfds();
+ tv.tv_usec = 0;
+ tv.tv_sec = TT.interval*60;
+
+ retval = select(maxfd + 1, &TT.rfds, NULL, NULL, (TT.interval)?&tv:NULL);
+ if (retval < 0) { /* Some error. */
+ if (errno == EINTR) continue;
+ perror_msg("Error in select ");
+ continue;
+ }
+ if (!retval) { /* Timed out */
+ logmsg("<46>-- MARK --", 14);
+ continue;
+ }
+ if (FD_ISSET(sigfd.rd, &TT.rfds)) { /* May be a signal */
+ unsigned char sig;
+
+ if (read(sigfd.rd, &sig, 1) != 1) {
+ error_msg("signal read failed.\n");
+ continue;
+ }
+ switch(sig) {
+ case SIGTERM: /* FALLTHROUGH */
+ case SIGINT: /* FALLTHROUGH */
+ case SIGQUIT:
+ logmsg("<46>syslogd exiting", 19);
+ if (CFG_TOYBOX_FREE ) cleanup();
+ signal(sig, SIG_DFL);
+ sigset_t ss;
+ sigemptyset(&ss);
+ sigaddset(&ss, sig);
+ sigprocmask(SIG_UNBLOCK, &ss, NULL);
+ raise(sig);
+ _exit(1); /* Should not reach it */
+ break;
+ case SIGHUP:
+ logmsg("<46>syslogd exiting", 19);
+ cleanup(); //cleanup is done, as we restart syslog.
+ goto init_jumpin;
+ default: break;
+ }
+ }
+ if (retval > 0) { /* Some activity on listen sockets. */
+ node = TT.lsocks;
+ while (node) {
+ int sd = ((unsocks_t*) node->arg)->sd;
+ if (FD_ISSET(sd, &TT.rfds)) {
+ int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL
+ if (len > 0) {
+ buffer[len] = '\0';
+ if(flag_chk(FLAG_D) && (len == last_len))
+ if (!memcmp(last_buf, buffer, len)) break;
+
+ memcpy(last_buf, buffer, len);
+ last_len = len;
+ logmsg(buffer, len);
+ }
+ break;
+ }
+ node = node->next;
+ }
+ }
+ }
+clean_and_exit:
+ logmsg("<46>syslogd exiting", 19);
+ if (CFG_TOYBOX_FREE ) cleanup();
+}