Related: rhbz#636570 --- loader/init.c | 139 +++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 101 insertions(+), 38 deletions(-) diff --git a/loader/init.c b/loader/init.c index 175f1d7..44da5ec 100644 --- a/loader/init.c +++ b/loader/init.c @@ -52,6 +52,7 @@ #include <sys/reboot.h> #include <linux/vt.h> #include <termios.h> +#include <time.h> #include <libgen.h> #include "init.h" @@ -138,35 +139,103 @@ static void fatal_error(int usePerror) { #endif } -static int logChunk(int len, char *inbuf, char *outbuf) { - int inctr, outctr; +struct log_chunk_context { + int starts_message; + int log1_fd; /* always nonzero */ + int log2_fd; +}; + +static char* get_time_string() +{ + struct timeval current_time; + struct tm *t; + int msecs; + char *ret_string; + int rc; + + gettimeofday(¤t_time, NULL); + t = gmtime(¤t_time.tv_sec); + msecs = current_time.tv_usec / 1000; + rc = asprintf(&ret_string, "%02d:%02d:%02d,%03d ", + t->tm_hour, t->tm_min, t->tm_sec, msecs); + if (rc < 0) + return NULL; + return ret_string; +} + +static void log_chunk_context_init(struct log_chunk_context *context, + int log1, int log2) +{ + context->starts_message = 1; + context->log1_fd = log1; + context->log2_fd = log2; +} - for (inctr = 0, outctr = 0; inctr < len; inctr++) { - /* If the character is a NULL that's immediately followed by a open - * bracket, we've found the beginning of a new kernel message. Put in - * a line separator. +static void log_chunk_flush(struct log_chunk_context *context, + char *buf, int length) +{ + int rc; + rc = write(context->log1_fd, buf, length); + if (context->log2_fd > 0) { + rc = write(context->log2_fd, buf, length); + } +} + +static void log_chunk(struct log_chunk_context *context, + int len, char *inbuf) +{ + int inctr, outctr = 0; + const unsigned BSIZE = 4; + char outbuf[512]; + char *time_str = NULL; + + + /* We finished the previous chunk on message boundary. Put in the time + * stamp. + */ + if (context->starts_message) { + time_str = get_time_string(0); + log_chunk_flush(context, time_str, strlen(time_str)); + context->starts_message = 0; + free(time_str); + } + + + for (inctr = 0; inctr < len; ++inctr) { + /* If the character is a NULL or a newline, immediately followed by an + * open bracket, we've found the beginning of a new kernel message. Put + * in a line separator and the time stamp. */ - if (inbuf[inctr] == '\0' && inctr+1 < len && inbuf[inctr+1] == '<') { - outbuf[outctr] = '\n'; - outctr++; + if ((inbuf[inctr] == '\0' || inbuf[inctr] == '\n') && + inctr+1 < len && inbuf[inctr+1] == '<') { + outbuf[outctr++] = '\n'; + log_chunk_flush(context, outbuf, outctr); + outctr = 0; + time_str = get_time_string(0); + log_chunk_flush(context, time_str, strlen(time_str)); + free(time_str); } - - /* Or, if we see a NULL right before the end of the chunk, that's also - * a good place to add a separator. + /* Or, if we see a NULL or a newline right before the end of the chunk, + add a separator and remember timestamp should be added the next time. */ - else if (inbuf[inctr] == '\0' && inctr+1 == len) { - outbuf[outctr] = '\n'; - outctr++; + else if ((inbuf[inctr] == '\0' || inbuf[inctr] == '\n') && + inctr+1 == len) { + outbuf[outctr++] = '\n'; + context->starts_message = 1; + } + else { + outbuf[outctr++] = inbuf[inctr]; } - /* Otherwise, simply output the character as long as it's not NULL. */ - else if (inbuf[inctr] != '\0') { - outbuf[outctr] = inbuf[inctr]; - outctr++; + /* flush everything if we've filled up the buffer */ + if (outctr == BSIZE) { + log_chunk_flush(context, outbuf, outctr); + outctr = 0; } } - return outctr; + /* flush everything */ + log_chunk_flush(context, outbuf, outctr); } static void doklog(char * fn) { @@ -176,7 +245,7 @@ static void doklog(char * fn) { socklen_t s; int sock = -1; struct sockaddr_un sockaddr; - char inbuf[1024], outbuf[1024]; + char inbuf[1024]; int readfd; int ret; @@ -188,7 +257,7 @@ static void doklog(char * fn) { } out = open(fn, O_WRONLY, 0); - if (out < 0) + if (out < 0) printf("couldn't open %s for syslog -- still using /tmp/syslog\n", fn); log = open("/tmp/syslog", O_WRONLY | O_CREAT, 0644); @@ -196,7 +265,7 @@ static void doklog(char * fn) { /* FIXME: was perror */ printstr("error opening /tmp/syslog"); sleep(5); - + close(in); return; } @@ -210,7 +279,7 @@ static void doklog(char * fn) { close(log); return; } - close(0); + close(0); close(1); close(2); @@ -226,7 +295,7 @@ static void doklog(char * fn) { sleep(5); } printstr("got socket\n"); - if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + + if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + strlen(sockaddr.sun_path))) { printf("bind error: %d\n", errno); sleep(5); @@ -241,6 +310,9 @@ static void doklog(char * fn) { syslog(8, NULL, 1); + struct log_chunk_context context; + log_chunk_context_init(&context, log, out); + FD_ZERO(&unixs); while (1) { memcpy(&readset, &unixs, sizeof(unixs)); @@ -256,24 +328,15 @@ static void doklog(char * fn) { if (FD_ISSET(in, &readset)) { i = read(in, inbuf, sizeof(inbuf)); if (i > 0) { - int loggedLen = logChunk(i, inbuf, outbuf); - - if (out >= 0) - ret = write(out, outbuf, loggedLen); - ret = write(log, outbuf, loggedLen); + log_chunk(&context, i, inbuf); } - } + } for (readfd = 0; readfd < 20; ++readfd) { if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs)) { i = read(readfd, inbuf, sizeof(inbuf)); if (i > 0) { - int loggedLen = logChunk(i, inbuf, outbuf); - - if (out >= 0) - ret = write(out, outbuf, loggedLen); - - ret = write(log, outbuf, loggedLen); + log_chunk(&context, i, inbuf); } else if (i == 0) { /* socket closed */ close(readfd); @@ -295,7 +358,7 @@ static void doklog(char * fn) { FD_SET(readfd, &unixs); } } - } + } } static int setupTerminal(int fd) { -- 1.7.3.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list