Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/sysklogd
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- Location:
- branches/stable/mindi-busybox/sysklogd
- Files:
-
- 2 deleted
- 5 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/sysklogd/Config.in
r821 r1770 6 6 menu "System Logging Utilities" 7 7 8 config CONFIG_SYSLOGD8 config SYSLOGD 9 9 bool "syslogd" 10 10 default n … … 21 21 you wait long enough.... 22 22 23 config CONFIG_FEATURE_ROTATE_LOGFILE23 config FEATURE_ROTATE_LOGFILE 24 24 bool "Rotate message files" 25 25 default n 26 depends on CONFIG_SYSLOGD26 depends on SYSLOGD 27 27 help 28 28 This enables syslogd to rotate the message files 29 29 on his own. No need to use an external rotatescript. 30 30 31 config CONFIG_FEATURE_REMOTE_LOG31 config FEATURE_REMOTE_LOG 32 32 bool "Remote Log support" 33 33 default n 34 depends on CONFIG_SYSLOGD34 depends on SYSLOGD 35 35 help 36 36 When you enable this feature, the syslogd utility can … … 43 43 by an intruder. 44 44 45 config CONFIG_FEATURE_IPC_SYSLOG45 config FEATURE_IPC_SYSLOG 46 46 bool "Circular Buffer support" 47 47 default n 48 depends on CONFIG_SYSLOGD48 depends on SYSLOGD 49 49 help 50 50 When you enable this feature, the syslogd utility will … … 57 57 break badly. 58 58 59 config CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE59 config FEATURE_IPC_SYSLOG_BUFFER_SIZE 60 60 int " Circular buffer size in Kbytes (minimum 4KB)" 61 61 default 16 62 depends on CONFIG_FEATURE_IPC_SYSLOG 62 range 4 2147483647 63 depends on FEATURE_IPC_SYSLOG 63 64 help 64 65 This option sets the size of the circular buffer 65 66 used to record system log messages. 66 67 67 config CONFIG_LOGREAD68 config LOGREAD 68 69 bool "logread" 69 70 default y 70 depends on CONFIG_FEATURE_IPC_SYSLOG71 depends on FEATURE_IPC_SYSLOG 71 72 help 72 73 If you enabled Circular Buffer support, you almost … … 75 76 stored in the syslogd circular buffer. 76 77 77 config CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING78 config FEATURE_LOGREAD_REDUCED_LOCKING 78 79 bool "logread double buffering" 79 80 default n 80 depends on CONFIG_LOGREAD81 depends on LOGREAD 81 82 help 82 83 'logread' ouput to slow serial terminals can have … … 86 87 contention at some minor memory expense. 87 88 88 config CONFIG_KLOGD89 config KLOGD 89 90 bool "klogd" 90 91 default n 91 depends on CONFIG_SYSLOGD92 92 help 93 93 klogd is a utility which intercepts and logs all … … 97 97 you should enable this option. 98 98 99 config CONFIG_LOGGER99 config LOGGER 100 100 bool "logger" 101 101 default n 102 select FEATURE_SYSLOG 102 103 help 103 104 The logger utility allows you to send arbitrary text -
branches/stable/mindi-busybox/sysklogd/klogd.c
r821 r1770 18 18 */ 19 19 20 #include "busybox.h" 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <signal.h> /* for our signal() handlers */ 24 #include <string.h> /* strncpy() */ 25 #include <errno.h> /* errno and friends */ 26 #include <unistd.h> 27 #include <ctype.h> 20 #include "libbb.h" 28 21 #include <sys/syslog.h> 29 22 #include <sys/klog.h> … … 33 26 klogctl(7, NULL, 0); 34 27 klogctl(0, 0, 0); 35 /* logMessage(0, "Kernel log daemon exiting."); */ 36 syslog(LOG_NOTICE, "Kernel log daemon exiting."); 28 syslog(LOG_NOTICE, "Kernel log daemon exiting"); 37 29 exit(EXIT_SUCCESS); 38 30 } … … 41 33 #define OPT_FOREGROUND 2 42 34 43 #define KLOGD_LOGBUF_SIZE 4096 35 #define KLOGD_LOGBUF_SIZE BUFSIZ 36 #define log_buffer bb_common_bufsiz1 44 37 38 int klogd_main(int argc, char **argv); 45 39 int klogd_main(int argc, char **argv) 46 40 { 47 RESERVE_CONFIG_BUFFER(log_buffer, KLOGD_LOGBUF_SIZE); 48 int console_log_level = -1; 49 int priority = LOG_INFO; 50 int i, n, lastc; 41 int i = i; /* silence gcc */ 51 42 char *start; 52 43 44 /* do normal option parsing */ 45 getopt32(argv, "c:n", &start); 53 46 54 { 55 unsigned long opt; 47 if (option_mask32 & OPT_LEVEL) { 48 /* Valid levels are between 1 and 8 */ 49 i = xatoul_range(start, 1, 8); 50 } 56 51 57 /* do normal option parsing */ 58 opt = bb_getopt_ulflags(argc, argv, "c:n", &start); 59 60 if (opt & OPT_LEVEL) { 61 /* Valid levels are between 1 and 8 */ 62 console_log_level = bb_xgetlarg(start, 10, 1, 8); 63 } 64 65 if (!(opt & OPT_FOREGROUND)) { 66 #ifdef BB_NOMMU 67 vfork_daemon_rexec(0, 1, argc, argv, "-n"); 68 #else 69 bb_xdaemon(0, 1); 70 #endif 71 } 52 if (!(option_mask32 & OPT_FOREGROUND)) { 53 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 72 54 } 73 55 … … 83 65 klogctl(1, NULL, 0); 84 66 85 /* Set level of kernel console messaging. .*/86 if ( console_log_level != -1)87 klogctl(8, NULL, console_log_level);67 /* Set level of kernel console messaging. */ 68 if (option_mask32 & OPT_LEVEL) 69 klogctl(8, NULL, i); 88 70 89 syslog(LOG_NOTICE, "klogd started: %s", BB_BANNER);71 syslog(LOG_NOTICE, "klogd started: %s", bb_banner); 90 72 73 /* Note: this code does not detect incomplete messages 74 * (messages not ending with '\n' or just when kernel 75 * generates too many messages for us to keep up) 76 * and will split them in two separate lines */ 91 77 while (1) { 92 /* Use kernel syscalls */ 93 memset(log_buffer, '\0', KLOGD_LOGBUF_SIZE); 94 n = klogctl(2, log_buffer, KLOGD_LOGBUF_SIZE); 78 int n; 79 int priority; 80 81 n = klogctl(2, log_buffer, KLOGD_LOGBUF_SIZE - 1); 95 82 if (n < 0) { 96 83 if (errno == EINTR) 97 84 continue; 98 syslog(LOG_ERR, "klogd: Error from sys_sycall: %d - %m.\n",99 100 exit(EXIT_FAILURE);85 syslog(LOG_ERR, "klogd: error from klogctl(2): %d - %m", 86 errno); 87 break; 101 88 } 102 103 /* klogctl buffer parsing modelled after code in dmesg.c */ 104 start = &log_buffer[0]; 105 lastc = '\0'; 106 for (i = 0; i < n; i++) { 107 if (lastc == '\0' && log_buffer[i] == '<') { 108 priority = 0; 89 log_buffer[n] = '\n'; 90 i = 0; 91 while (i < n) { 92 priority = LOG_INFO; 93 start = &log_buffer[i]; 94 if (log_buffer[i] == '<') { 109 95 i++; 110 while (log_buffer[i] >= '0' && log_buffer[i] <= '9') { 111 priority = priority * 10 + (log_buffer[i] - '0'); 96 // kernel never ganerates multi-digit prios 97 //priority = 0; 98 //while (log_buffer[i] >= '0' && log_buffer[i] <= '9') { 99 // priority = priority * 10 + (log_buffer[i] - '0'); 100 // i++; 101 //} 102 if (isdigit(log_buffer[i])) { 103 priority = (log_buffer[i] - '0'); 112 104 i++; 113 105 } … … 116 108 start = &log_buffer[i]; 117 109 } 118 if (log_buffer[i] == '\n') { 119 log_buffer[i] = '\0'; /* zero terminate this message */ 120 syslog(priority, "%s", start); 121 start = &log_buffer[i + 1]; 122 priority = LOG_INFO; 123 } 124 lastc = log_buffer[i]; 110 while (log_buffer[i] != '\n') 111 i++; 112 log_buffer[i] = '\0'; 113 syslog(priority, "%s", start); 114 i++; 125 115 } 126 116 } 127 if (ENABLE_FEATURE_CLEAN_UP)128 RELEASE_CONFIG_BUFFER(log_buffer);129 117 130 return EXIT_ SUCCESS;118 return EXIT_FAILURE; 131 119 } -
branches/stable/mindi-busybox/sysklogd/logger.c
r821 r1770 8 8 */ 9 9 10 #include "busybox.h" 11 #include <stdio.h> 12 #include <unistd.h> 13 #include <sys/types.h> 14 #include <fcntl.h> 15 #include <ctype.h> 16 #include <string.h> 17 #include <stdlib.h> 10 #include "libbb.h" 18 11 19 12 #if !defined CONFIG_SYSLOGD … … 49 42 50 43 if (isdigit(*name)) 51 return (atoi(name));44 return atoi(name); 52 45 for (c = codetab; c->c_name; c++) { 53 46 if (!strcasecmp(name, c->c_name)) { 54 return (c->c_val);47 return c->c_val; 55 48 } 56 49 } 57 50 58 return (-1);51 return -1; 59 52 } 60 53 … … 71 64 int lev, fac = LOG_USER; 72 65 73 for (save = s; *s && *s != '.'; ++s); 66 for (save = s; *s && *s != '.'; ++s) 67 ; 74 68 if (*s) { 75 69 *s = '\0'; 76 70 fac = decode(save, facilitynames); 77 71 if (fac < 0) 78 bb_error_msg_and_die("unknown facility name: %s", save);72 bb_error_msg_and_die("unknown %s name: %s", "facility", save); 79 73 *s++ = '.'; 80 74 } else { … … 83 77 lev = decode(s, prioritynames); 84 78 if (lev < 0) 85 bb_error_msg_and_die("unknown priority name: %s", save);79 bb_error_msg_and_die("unknown %s name: %s", "priority", save); 86 80 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); 87 81 } 88 82 89 83 84 int logger_main(int argc, char **argv); 90 85 int logger_main(int argc, char **argv) 91 86 { 92 int pri = LOG_USER | LOG_NOTICE; 93 int option = 0; 94 int c, i, opt; 95 char buf[1024], name[128]; 87 char *str_p, *str_t; 88 int i = 0; 89 char name[80]; 96 90 97 91 /* Fill out the name string early (may be overwritten later) */ 98 bb_getpwuid(name, geteuid(), sizeof(name)); 92 bb_getpwuid(name, sizeof(name), geteuid()); 93 str_t = name; 99 94 100 95 /* Parse any options */ 101 while ((opt = getopt(argc, argv, "p:st:")) > 0) { 102 switch (opt) { 103 case 's': 104 option |= LOG_PERROR; 105 break; 106 case 'p': 107 pri = pencode(optarg); 108 break; 109 case 't': 110 safe_strncpy(name, optarg, sizeof(name)); 111 break; 112 default: 113 bb_show_usage(); 96 getopt32(argv, "p:st:", &str_p, &str_t); 97 98 if (option_mask32 & 0x2) /* -s */ 99 i |= LOG_PERROR; 100 //if (option_mask32 & 0x4) /* -t */ 101 openlog(str_t, i, 0); 102 i = LOG_USER | LOG_NOTICE; 103 if (option_mask32 & 0x1) /* -p */ 104 i = pencode(str_p); 105 106 argc -= optind; 107 argv += optind; 108 if (!argc) { 109 #define strbuf bb_common_bufsiz1 110 while (fgets(strbuf, BUFSIZ, stdin)) { 111 if (strbuf[0] 112 && NOT_LONE_CHAR(strbuf, '\n') 113 ) { 114 /* Neither "" nor "\n" */ 115 syslog(i, "%s", strbuf); 116 } 114 117 } 115 }116 117 openlog(name, option, 0);118 if (optind == argc) {119 do {120 /* read from stdin */121 i = 0;122 while ((c = getc(stdin)) != EOF && c != '\n' &&123 i < (sizeof(buf)-1)) {124 buf[i++] = c;125 }126 if (i > 0) {127 buf[i++] = '\0';128 syslog(pri, "%s", buf);129 }130 } while (c != EOF);131 118 } else { 132 119 char *message = NULL; 133 int len = argc - optind; /* for the space between the args 134 and '\0' */ 135 opt = len; 136 argv += optind; 137 for (i = 0; i < opt; i++) { 138 len += strlen(*argv); 120 int len = 1; /* for NUL */ 121 int pos = 0; 122 do { 123 len += strlen(*argv) + 1; 139 124 message = xrealloc(message, len); 140 if(!i) 141 message[0] = 0; 142 else 143 strcat(message, " "); 144 strcat(message, *argv); 145 argv++; 146 } 147 syslog(pri, "%s", message); 125 sprintf(message + pos, " %s", *argv), 126 pos = len; 127 } while (*++argv); 128 syslog(i, "%s", message + 1); /* skip leading " " */ 148 129 } 149 130 … … 187 168 * SUCH DAMAGE. 188 169 */ 189 190 191 -
branches/stable/mindi-busybox/sysklogd/logread.c
r821 r1770 10 10 */ 11 11 12 13 #include "busybox.h" 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 12 #include "libbb.h" 17 13 #include <sys/ipc.h> 18 #include <sys/types.h>19 14 #include <sys/sem.h> 20 15 #include <sys/shm.h> 21 #include <signal.h>22 #include <setjmp.h>23 #include <unistd.h>24 16 25 static const long KEY_ID = 0x414e4547; /*"GENA"*/ 17 #define DEBUG 0 18 19 enum { KEY_ID = 0x414e4547 }; /* "GENA" */ 26 20 27 21 static struct shbuf_ds { 28 int size; // size of data written 29 int head; // start of message list 30 int tail; // end of message list 31 char data[1]; // data/messages 32 } *buf = NULL; // shared memory pointer 33 22 int32_t size; // size of data - 1 23 int32_t tail; // end of message list 24 char data[1]; // messages 25 } *shbuf; 34 26 35 27 // Semaphore operation structures … … 37 29 static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn 38 30 39 static int log_shmid = -1; // ipc shared memory id40 static int log_semid = -1; // ipc semaphore id41 static jmp_buf jmp_env;42 31 43 static void error_exit(const char *str); 44 static void interrupted(int sig); 32 static void error_exit(const char *str) ATTRIBUTE_NORETURN; 33 static void error_exit(const char *str) 34 { 35 //release all acquired resources 36 shmdt(shbuf); 37 bb_perror_msg_and_die(str); 38 } 45 39 46 40 /* 47 41 * sem_up - up()'s a semaphore. 48 42 */ 49 static inlinevoid sem_up(int semid)43 static void sem_up(int semid) 50 44 { 51 if ( semop(semid, SMrup, 1) == -1)45 if (semop(semid, SMrup, 1) == -1) 52 46 error_exit("semop[SMrup]"); 53 47 } 54 48 55 /* 56 * sem_down - down()'s a semaphore 57 */ 58 static inline void sem_down(int semid) 49 static void interrupted(int sig ATTRIBUTE_UNUSED) 59 50 { 60 if ( semop(semid, SMrdn, 2) == -1 ) 61 error_exit("semop[SMrdn]"); 51 signal(SIGINT, SIG_IGN); 52 shmdt(shbuf); 53 exit(0); 62 54 } 63 55 56 int logread_main(int argc, char **argv); 64 57 int logread_main(int argc, char **argv) 65 58 { 66 int i; 67 int follow=0; 59 int cur; 60 int log_semid; /* ipc semaphore id */ 61 int log_shmid; /* ipc shared memory id */ 62 smallint follow = getopt32(argv, "f"); 68 63 69 if (argc == 2 && argv[1][0]=='-' && argv[1][1]=='f') { 70 follow = 1; 71 } else { 72 /* no options, no getopt */ 73 if (argc > 1) 74 bb_show_usage(); 75 } 64 log_shmid = shmget(KEY_ID, 0, 0); 65 if (log_shmid == -1) 66 bb_perror_msg_and_die("can't find syslogd buffer"); 76 67 77 // handle interrupt signal 78 if (setjmp(jmp_env)) goto output_end; 68 /* Attach shared memory to our char* */ 69 shbuf = shmat(log_shmid, NULL, SHM_RDONLY); 70 if (shbuf == NULL) 71 bb_perror_msg_and_die("can't access syslogd buffer"); 79 72 80 // attempt to redefine ^C signal 73 log_semid = semget(KEY_ID, 0, 0); 74 if (log_semid == -1) 75 error_exit("can't get access to semaphores for syslogd buffer"); 76 81 77 signal(SIGINT, interrupted); 82 78 83 if ( (log_shmid = shmget(KEY_ID, 0, 0)) == -1) 84 error_exit("Can't find circular buffer"); 79 /* Suppose atomic memory read */ 80 /* Max possible value for tail is shbuf->size - 1 */ 81 cur = shbuf->tail; 85 82 86 // Attach shared memory to our char* 87 if ( (buf = shmat(log_shmid, NULL, SHM_RDONLY)) == NULL) 88 error_exit("Can't get access to circular buffer from syslogd"); 83 /* Loop for logread -f, one pass if there was no -f */ 84 do { 85 unsigned shbuf_size; 86 unsigned shbuf_tail; 87 const char *shbuf_data; 88 #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 89 int i; 90 int len_first_part; 91 int len_total = len_total; /* for gcc */ 92 char *copy = copy; /* for gcc */ 93 #endif 94 if (semop(log_semid, SMrdn, 2) == -1) 95 error_exit("semop[SMrdn]"); 89 96 90 if ( (log_semid = semget(KEY_ID, 0, 0)) == -1) 91 error_exit("Can't get access to semaphone(s) for circular buffer from syslogd"); 97 /* Copy the info, helps gcc to realize that it doesn't change */ 98 shbuf_size = shbuf->size; 99 shbuf_tail = shbuf->tail; 100 shbuf_data = shbuf->data; /* pointer! */ 92 101 93 // Suppose atomic memory move 94 i = follow ? buf->tail : buf->head; 102 if (DEBUG) 103 printf("cur:%d tail:%i size:%i\n", 104 cur, shbuf_tail, shbuf_size); 95 105 96 do { 97 #ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING 98 char *buf_data; 99 int log_len,j; 100 #endif 101 102 sem_down(log_semid); 103 104 //printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size); 105 if (buf->head == buf->tail || i==buf->tail) { 106 if (follow) { 106 if (!follow) { 107 /* advance to oldest complete message */ 108 /* find NUL */ 109 cur += strlen(shbuf_data + cur); 110 if (cur >= shbuf_size) { /* last byte in buffer? */ 111 cur = strnlen(shbuf_data, shbuf_tail); 112 if (cur == shbuf_tail) 113 goto unlock; /* no complete messages */ 114 } 115 /* advance to first byte of the message */ 116 cur++; 117 if (cur >= shbuf_size) /* last byte in buffer? */ 118 cur = 0; 119 } else { /* logread -f */ 120 if (cur == shbuf_tail) { 107 121 sem_up(log_semid); 108 sleep(1); /* TODO: replace me with a sleep_on */ 122 fflush(stdout); 123 sleep(1); /* TODO: replace me with a sleep_on */ 109 124 continue; 110 } else {111 printf("<empty syslog>\n");112 125 } 113 126 } 114 127 115 // Read Memory 116 #ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING 117 log_len = buf->tail - i; 118 if (log_len < 0) 119 log_len += buf->size; 120 buf_data = (char *)xmalloc(log_len); 121 122 if (buf->tail < i) { 123 memcpy(buf_data, buf->data+i, buf->size-i); 124 memcpy(buf_data+buf->size-i, buf->data, buf->tail); 125 } else { 126 memcpy(buf_data, buf->data+i, buf->tail-i); 128 /* Read from cur to tail */ 129 #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 130 len_first_part = len_total = shbuf_tail - cur; 131 if (len_total < 0) { 132 /* message wraps: */ 133 /* [SECOND PART.........FIRST PART] */ 134 /* ^data ^tail ^cur ^size */ 135 len_total += shbuf_size; 127 136 } 128 i = buf->tail; 129 137 copy = xmalloc(len_total + 1); 138 if (len_first_part < 0) { 139 /* message wraps (see above) */ 140 len_first_part = shbuf_size - cur; 141 memcpy(copy + len_first_part, shbuf_data, shbuf_tail); 142 } 143 memcpy(copy, shbuf_data + cur, len_first_part); 144 copy[len_total] = '\0'; 145 cur = shbuf_tail; 130 146 #else 131 while ( i != buf->tail) {132 printf("%s", buf->data+i);133 i+= strlen(buf->data+i) + 1;134 if ( i >= buf->size)135 i=0;147 while (cur != shbuf_tail) { 148 fputs(shbuf_data + cur, stdout); 149 cur += strlen(shbuf_data + cur) + 1; 150 if (cur >= shbuf_size) 151 cur = 0; 136 152 } 137 153 #endif 138 // release the lock on the log chain 154 unlock: 155 /* release the lock on the log chain */ 139 156 sem_up(log_semid); 140 157 141 #ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING 142 for (j=0; j < log_len; j+=strlen(buf_data+j)+1) { 143 printf("%s", buf_data+j); 144 if (follow) 145 fflush(stdout); 158 #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 159 for (i = 0; i < len_total; i += strlen(copy + i) + 1) { 160 fputs(copy + i, stdout); 146 161 } 147 free( buf_data);162 free(copy); 148 163 #endif 149 fflush(stdout);150 164 } while (follow); 151 165 152 output_end: 153 if (log_shmid != -1) 154 shmdt(buf); 166 shmdt(shbuf); 155 167 156 return EXIT_SUCCESS;168 fflush_stdout_and_exit(EXIT_SUCCESS); 157 169 } 158 159 static void interrupted(int sig){160 signal(SIGINT, SIG_IGN);161 longjmp(jmp_env, 1);162 }163 164 static void error_exit(const char *str){165 bb_perror_msg(str);166 //release all acquired resources167 if (log_shmid != -1)168 shmdt(buf);169 170 exit(1);171 } -
branches/stable/mindi-busybox/sysklogd/syslogd.c
r821 r1770 14 14 */ 15 15 16 #include "busybox.h" 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <ctype.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <getopt.h> 23 #include <netdb.h> 16 #include "libbb.h" 24 17 #include <paths.h> 25 #include <signal.h>26 #include <stdarg.h>27 #include <stdbool.h>28 #include <time.h>29 #include <string.h>30 #include <unistd.h>31 #include <sys/socket.h>32 #include <sys/types.h>33 18 #include <sys/un.h> 34 #include <sys/param.h> 35 36 /* SYSLOG_NAMES defined to pull some extra junk from syslog.h*/19 20 /* SYSLOG_NAMES defined to pull prioritynames[] and facilitynames[] 21 * from syslog.h. Grrrr - glibc puts those in _rwdata_! :( */ 37 22 #define SYSLOG_NAMES 23 #define SYSLOG_NAMES_CONST /* uclibc is saner :) */ 38 24 #include <sys/syslog.h> 39 25 #include <sys/uio.h> 40 26 41 /* Path for the file where all log messages are written */ 42 #define __LOG_FILE "/var/log/messages" 43 44 /* Path to the unix socket */ 45 static char lfile[MAXPATHLEN]; 46 47 static const char *logFilePath = __LOG_FILE; 48 49 #ifdef CONFIG_FEATURE_ROTATE_LOGFILE 50 /* max size of message file before being rotated */ 51 static int logFileSize = 200 * 1024; 52 53 /* number of rotated message files */ 54 static int logFileRotate = 1; 55 #endif 56 57 /* interval between marks in seconds */ 58 static int MarkInterval = 20 * 60; 59 60 /* localhost's name */ 61 static char LocalHostName[64]; 62 63 #ifdef CONFIG_FEATURE_REMOTE_LOG 27 #if ENABLE_FEATURE_REMOTE_LOG 64 28 #include <netinet/in.h> 65 /* udp socket for logging to remote host */ 66 static int remotefd = -1; 67 static struct sockaddr_in remoteaddr; 68 69 /* where do we log? */ 70 static char *RemoteHost; 71 72 /* what port to log to? */ 73 static int RemotePort = 514; 74 75 /* To remote log or not to remote log, that is the question. */ 76 static int doRemoteLog = FALSE; 77 static int local_logging = FALSE; 78 #endif 79 80 /* Make loging output smaller. */ 81 static bool small = false; 82 83 84 #define MAXLINE 1024 /* maximum line length */ 29 #endif 30 31 #if ENABLE_FEATURE_IPC_SYSLOG 32 #include <sys/ipc.h> 33 #include <sys/sem.h> 34 #include <sys/shm.h> 35 #endif 36 37 38 #define DEBUG 0 39 40 /* MARK code is not very useful, is bloat, and broken: 41 * can deadlock if alarmed to make MARK while writing to IPC buffer 42 * (semaphores are down but do_mark routine tries to down them again) */ 43 #undef SYSLOGD_MARK 44 45 enum { MAX_READ = 256 }; 46 47 /* Semaphore operation structures */ 48 struct shbuf_ds { 49 int32_t size; /* size of data - 1 */ 50 int32_t tail; /* end of message list */ 51 char data[1]; /* data/messages */ 52 }; 53 54 /* Allows us to have smaller initializer. Ugly. */ 55 #define GLOBALS \ 56 const char *logFilePath; \ 57 int logFD; \ 58 /* interval between marks in seconds */ \ 59 /*int markInterval;*/ \ 60 /* level of messages to be logged */ \ 61 int logLevel; \ 62 USE_FEATURE_ROTATE_LOGFILE( \ 63 /* max size of file before rotation */ \ 64 unsigned logFileSize; \ 65 /* number of rotated message files */ \ 66 unsigned logFileRotate; \ 67 unsigned curFileSize; \ 68 smallint isRegular; \ 69 ) \ 70 USE_FEATURE_REMOTE_LOG( \ 71 /* udp socket for remote logging */ \ 72 int remoteFD; \ 73 len_and_sockaddr* remoteAddr; \ 74 ) \ 75 USE_FEATURE_IPC_SYSLOG( \ 76 int shmid; /* ipc shared memory id */ \ 77 int s_semid; /* ipc semaphore id */ \ 78 int shm_size; \ 79 struct sembuf SMwup[1]; \ 80 struct sembuf SMwdn[3]; \ 81 ) 82 83 struct init_globals { 84 GLOBALS 85 }; 86 87 struct globals { 88 GLOBALS 89 #if ENABLE_FEATURE_IPC_SYSLOG 90 struct shbuf_ds *shbuf; 91 #endif 92 time_t last_log_time; 93 /* localhost's name */ 94 char localHostName[64]; 95 96 /* We recv into recvbuf... */ 97 char recvbuf[MAX_READ]; 98 /* ...then copy to parsebuf, escaping control chars */ 99 /* (can grow x2 max) */ 100 char parsebuf[MAX_READ*2]; 101 /* ...then sprintf into printbuf, adding timestamp (15 chars), 102 * host (64), fac.prio (20) to the message */ 103 /* (growth by: 15 + 64 + 20 + delims = ~110) */ 104 char printbuf[MAX_READ*2 + 128]; 105 }; 106 107 static const struct init_globals init_data = { 108 .logFilePath = "/var/log/messages", 109 .logFD = -1, 110 #ifdef SYSLOGD_MARK 111 .markInterval = 20 * 60, 112 #endif 113 .logLevel = 8, 114 #if ENABLE_FEATURE_ROTATE_LOGFILE 115 .logFileSize = 200 * 1024, 116 .logFileRotate = 1, 117 #endif 118 #if ENABLE_FEATURE_REMOTE_LOG 119 .remoteFD = -1, 120 #endif 121 #if ENABLE_FEATURE_IPC_SYSLOG 122 .shmid = -1, 123 .s_semid = -1, 124 .shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024), // default shm size 125 .SMwup = { {1, -1, IPC_NOWAIT} }, 126 .SMwdn = { {0, 0}, {1, 0}, {1, +1} }, 127 #endif 128 }; 129 130 #define G (*ptr_to_globals) 131 132 133 /* Options */ 134 enum { 135 OPTBIT_mark = 0, // -m 136 OPTBIT_nofork, // -n 137 OPTBIT_outfile, // -O 138 OPTBIT_loglevel, // -l 139 OPTBIT_small, // -S 140 USE_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize ,) // -s 141 USE_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt ,) // -b 142 USE_FEATURE_REMOTE_LOG( OPTBIT_remote ,) // -R 143 USE_FEATURE_REMOTE_LOG( OPTBIT_localtoo ,) // -L 144 USE_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C 145 146 OPT_mark = 1 << OPTBIT_mark , 147 OPT_nofork = 1 << OPTBIT_nofork , 148 OPT_outfile = 1 << OPTBIT_outfile , 149 OPT_loglevel = 1 << OPTBIT_loglevel, 150 OPT_small = 1 << OPTBIT_small , 151 OPT_filesize = USE_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize )) + 0, 152 OPT_rotatecnt = USE_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt )) + 0, 153 OPT_remotelog = USE_FEATURE_REMOTE_LOG( (1 << OPTBIT_remote )) + 0, 154 OPT_locallog = USE_FEATURE_REMOTE_LOG( (1 << OPTBIT_localtoo )) + 0, 155 OPT_circularlog = USE_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, 156 }; 157 #define OPTION_STR "m:nO:l:S" \ 158 USE_FEATURE_ROTATE_LOGFILE("s:" ) \ 159 USE_FEATURE_ROTATE_LOGFILE("b:" ) \ 160 USE_FEATURE_REMOTE_LOG( "R:" ) \ 161 USE_FEATURE_REMOTE_LOG( "L" ) \ 162 USE_FEATURE_IPC_SYSLOG( "C::") 163 #define OPTION_DECL *opt_m, *opt_l \ 164 USE_FEATURE_ROTATE_LOGFILE(,*opt_s) \ 165 USE_FEATURE_ROTATE_LOGFILE(,*opt_b) \ 166 USE_FEATURE_REMOTE_LOG( ,*opt_R) \ 167 USE_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) 168 #define OPTION_PARAM &opt_m, &G.logFilePath, &opt_l \ 169 USE_FEATURE_ROTATE_LOGFILE(,&opt_s) \ 170 USE_FEATURE_ROTATE_LOGFILE(,&opt_b) \ 171 USE_FEATURE_REMOTE_LOG( ,&opt_R) \ 172 USE_FEATURE_IPC_SYSLOG( ,&opt_C) 85 173 86 174 87 175 /* circular buffer variables/structures */ 88 #if def CONFIG_FEATURE_IPC_SYSLOG176 #if ENABLE_FEATURE_IPC_SYSLOG 89 177 90 178 #if CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE < 4 … … 93 181 #endif 94 182 95 #include <sys/ipc.h>96 #include <sys/sem.h>97 #include <sys/shm.h>98 99 183 /* our shared key */ 100 static const long KEY_ID = 0x414e4547; /*"GENA" */ 101 102 // Semaphore operation structures 103 static struct shbuf_ds { 104 int size; // size of data written 105 int head; // start of message list 106 int tail; // end of message list 107 char data[1]; // data/messages 108 } *buf = NULL; // shared memory pointer 109 110 static struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; // set SMwup 111 static struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; // set SMwdn 112 113 static int shmid = -1; // ipc shared memory id 114 static int s_semid = -1; // ipc semaphore id 115 static int shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024); // default shm size 116 static int circular_logging = FALSE; 117 118 /* 119 * sem_up - up()'s a semaphore. 120 */ 121 static inline void sem_up(int semid) 122 { 123 if (semop(semid, SMwup, 1) == -1) { 124 bb_perror_msg_and_die("semop[SMwup]"); 125 } 126 } 127 128 /* 129 * sem_down - down()'s a semaphore 130 */ 131 static inline void sem_down(int semid) 132 { 133 if (semop(semid, SMwdn, 3) == -1) { 134 bb_perror_msg_and_die("semop[SMwdn]"); 135 } 136 } 137 184 #define KEY_ID ((long)0x414e4547) /* "GENA" */ 138 185 139 186 static void ipcsyslog_cleanup(void) 140 187 { 141 printf("Exiting Syslogd!\n"); 142 if (shmid != -1) { 143 shmdt(buf); 144 } 145 146 if (shmid != -1) { 147 shmctl(shmid, IPC_RMID, NULL); 148 } 149 if (s_semid != -1) { 150 semctl(s_semid, 0, IPC_RMID, 0); 188 if (G.shmid != -1) { 189 shmdt(G.shbuf); 190 } 191 if (G.shmid != -1) { 192 shmctl(G.shmid, IPC_RMID, NULL); 193 } 194 if (G.s_semid != -1) { 195 semctl(G.s_semid, 0, IPC_RMID, 0); 151 196 } 152 197 } … … 154 199 static void ipcsyslog_init(void) 155 200 { 156 if (buf == NULL) { 157 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1) { 158 bb_perror_msg_and_die("shmget"); 159 } 160 161 if ((buf = shmat(shmid, NULL, 0)) == NULL) { 162 bb_perror_msg_and_die("shmat"); 163 } 164 165 buf->size = shm_size - sizeof(*buf); 166 buf->head = buf->tail = 0; 167 168 // we'll trust the OS to set initial semval to 0 (let's hope) 169 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1) { 170 if (errno == EEXIST) { 171 if ((s_semid = semget(KEY_ID, 2, 0)) == -1) { 172 bb_perror_msg_and_die("semget"); 173 } 174 } else { 175 bb_perror_msg_and_die("semget"); 176 } 177 } 201 if (DEBUG) 202 printf("shmget(%lx, %d,...)\n", KEY_ID, G.shm_size); 203 204 G.shmid = shmget(KEY_ID, G.shm_size, IPC_CREAT | 0644); 205 if (G.shmid == -1) { 206 bb_perror_msg_and_die("shmget"); 207 } 208 209 G.shbuf = shmat(G.shmid, NULL, 0); 210 if (!G.shbuf) { 211 bb_perror_msg_and_die("shmat"); 212 } 213 214 memset(G.shbuf, 0, G.shm_size); 215 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1; 216 /*G.shbuf->tail = 0;*/ 217 218 // we'll trust the OS to set initial semval to 0 (let's hope) 219 G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); 220 if (G.s_semid == -1) { 221 if (errno == EEXIST) { 222 G.s_semid = semget(KEY_ID, 2, 0); 223 if (G.s_semid != -1) 224 return; 225 } 226 bb_perror_msg_and_die("semget"); 227 } 228 } 229 230 /* Write message to shared mem buffer */ 231 static void log_to_shmem(const char *msg, int len) 232 { 233 int old_tail, new_tail; 234 235 if (semop(G.s_semid, G.SMwdn, 3) == -1) { 236 bb_perror_msg_and_die("SMwdn"); 237 } 238 239 /* Circular Buffer Algorithm: 240 * -------------------------- 241 * tail == position where to store next syslog message. 242 * tail's max value is (shbuf->size - 1) 243 * Last byte of buffer is never used and remains NUL. 244 */ 245 len++; /* length with NUL included */ 246 again: 247 old_tail = G.shbuf->tail; 248 new_tail = old_tail + len; 249 if (new_tail < G.shbuf->size) { 250 /* store message, set new tail */ 251 memcpy(G.shbuf->data + old_tail, msg, len); 252 G.shbuf->tail = new_tail; 178 253 } else { 179 printf("Buffer already allocated just grab the semaphore?"); 180 } 181 } 182 183 /* write message to buffer */ 184 static void circ_message(const char *msg) 185 { 186 int l = strlen(msg) + 1; /* count the whole message w/ '\0' included */ 187 188 sem_down(s_semid); 189 190 /* 191 * Circular Buffer Algorithm: 192 * -------------------------- 193 * 194 * Start-off w/ empty buffer of specific size SHM_SIZ 195 * Start filling it up w/ messages. I use '\0' as separator to break up messages. 196 * This is also very handy since we can do printf on message. 197 * 198 * Once the buffer is full we need to get rid of the first message in buffer and 199 * insert the new message. (Note: if the message being added is >1 message then 200 * we will need to "remove" >1 old message from the buffer). The way this is done 201 * is the following: 202 * When we reach the end of the buffer we set a mark and start from the beginning. 203 * Now what about the beginning and end of the buffer? Well we have the "head" 204 * index/pointer which is the starting point for the messages and we have "tail" 205 * index/pointer which is the ending point for the messages. When we "display" the 206 * messages we start from the beginning and continue until we reach "tail". If we 207 * reach end of buffer, then we just start from the beginning (offset 0). "head" and 208 * "tail" are actually offsets from the beginning of the buffer. 209 * 210 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide 211 * a threadsafe way of handling shared memory operations. 212 */ 213 if ((buf->tail + l) < buf->size) { 214 /* before we append the message we need to check the HEAD so that we won't 215 overwrite any of the message that we still need and adjust HEAD to point 216 to the next message! */ 217 if (buf->tail < buf->head) { 218 if ((buf->tail + l) >= buf->head) { 219 /* we need to move the HEAD to point to the next message 220 * Theoretically we have enough room to add the whole message to the 221 * buffer, because of the first outer IF statement, so we don't have 222 * to worry about overflows here! 223 */ 224 int k = buf->tail + l - buf->head; /* we need to know how many bytes 225 we are overwriting to make 226 enough room */ 227 char *c = 228 memchr(buf->data + buf->head + k, '\0', 229 buf->size - (buf->head + k)); 230 if (c != NULL) { /* do a sanity check just in case! */ 231 buf->head = c - buf->data + 1; /* we need to convert pointer to 232 offset + skip the '\0' since 233 we need to point to the beginning 234 of the next message */ 235 /* Note: HEAD is only used to "retrieve" messages, it's not used 236 when writing messages into our buffer */ 237 } else { /* show an error message to know we messed up? */ 238 printf("Weird! Can't find the terminator token?\n"); 239 buf->head = 0; 240 } 241 } 242 } 243 244 /* in other cases no overflows have been done yet, so we don't care! */ 245 /* we should be ok to append the message now */ 246 strncpy(buf->data + buf->tail, msg, l); /* append our message */ 247 buf->tail += l; /* count full message w/ '\0' terminating char */ 254 /* k == available buffer space ahead of old tail */ 255 int k = G.shbuf->size - old_tail; 256 /* copy what fits to the end of buffer, and repeat */ 257 memcpy(G.shbuf->data + old_tail, msg, k); 258 msg += k; 259 len -= k; 260 G.shbuf->tail = 0; 261 goto again; 262 } 263 if (semop(G.s_semid, G.SMwup, 1) == -1) { 264 bb_perror_msg_and_die("SMwup"); 265 } 266 if (DEBUG) 267 printf("tail:%d\n", G.shbuf->tail); 268 } 269 #else 270 void ipcsyslog_cleanup(void); 271 void ipcsyslog_init(void); 272 void log_to_shmem(const char *msg); 273 #endif /* FEATURE_IPC_SYSLOG */ 274 275 276 /* Print a message to the log file. */ 277 static void log_locally(char *msg) 278 { 279 struct flock fl; 280 int len = strlen(msg); 281 282 #if ENABLE_FEATURE_IPC_SYSLOG 283 if ((option_mask32 & OPT_circularlog) && G.shbuf) { 284 log_to_shmem(msg, len); 285 return; 286 } 287 #endif 288 if (G.logFD >= 0) { 289 time_t cur; 290 time(&cur); 291 if (G.last_log_time != cur) { 292 G.last_log_time = cur; /* reopen log file every second */ 293 close(G.logFD); 294 goto reopen; 295 } 248 296 } else { 249 /* we need to break up the message and "circle" it around */ 250 char *c; 251 int k = buf->tail + l - buf->size; /* count # of bytes we don't fit */ 252 253 /* We need to move HEAD! This is always the case since we are going 254 * to "circle" the message. 255 */ 256 c = memchr(buf->data + k, '\0', buf->size - k); 257 258 if (c != NULL) { /* if we don't have '\0'??? weird!!! */ 259 /* move head pointer */ 260 buf->head = c - buf->data + 1; 261 262 /* now write the first part of the message */ 263 strncpy(buf->data + buf->tail, msg, l - k - 1); 264 265 /* ALWAYS terminate end of buffer w/ '\0' */ 266 buf->data[buf->size - 1] = '\0'; 267 268 /* now write out the rest of the string to the beginning of the buffer */ 269 strcpy(buf->data, &msg[l - k - 1]); 270 271 /* we need to place the TAIL at the end of the message */ 272 buf->tail = k + 1; 273 } else { 274 printf 275 ("Weird! Can't find the terminator token from the beginning?\n"); 276 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */ 277 } 278 279 } 280 sem_up(s_semid); 281 } 282 #endif /* CONFIG_FEATURE_IPC_SYSLOG */ 283 284 /* Note: There is also a function called "message()" in init.c */ 285 /* Print a message to the log file. */ 286 static void message(char *fmt, ...) __attribute__ ((format(printf, 1, 2))); 287 static void message(char *fmt, ...) 288 { 289 int fd; 290 struct flock fl; 291 va_list arguments; 297 reopen: 298 G.logFD = device_open(G.logFilePath, O_WRONLY | O_CREAT 299 | O_NOCTTY | O_APPEND | O_NONBLOCK); 300 if (G.logFD < 0) { 301 /* cannot open logfile? - print to /dev/console then */ 302 int fd = device_open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK); 303 if (fd < 0) 304 fd = 2; /* then stderr, dammit */ 305 full_write(fd, msg, len); 306 if (fd != 2) 307 close(fd); 308 return; 309 } 310 #if ENABLE_FEATURE_ROTATE_LOGFILE 311 { 312 struct stat statf; 313 G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode)); 314 /* bug (mostly harmless): can wrap around if file > 4gb */ 315 G.curFileSize = statf.st_size; 316 } 317 #endif 318 } 292 319 293 320 fl.l_whence = SEEK_SET; 294 321 fl.l_start = 0; 295 322 fl.l_len = 1; 296 297 #ifdef CONFIG_FEATURE_IPC_SYSLOG 298 if ((circular_logging == TRUE) && (buf != NULL)) { 299 char b[1024]; 300 301 va_start(arguments, fmt); 302 vsnprintf(b, sizeof(b) - 1, fmt, arguments); 303 va_end(arguments); 304 circ_message(b); 305 306 } else 307 #endif 308 if ((fd = device_open(logFilePath, 309 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | 310 O_NONBLOCK)) >= 0) { 311 fl.l_type = F_WRLCK; 312 fcntl(fd, F_SETLKW, &fl); 313 #ifdef CONFIG_FEATURE_ROTATE_LOGFILE 314 if ( logFileSize > 0 ) { 315 struct stat statf; 316 int r = fstat(fd, &statf); 317 if( !r && (statf.st_mode & S_IFREG) 318 && (lseek(fd,0,SEEK_END) > logFileSize) ) { 319 if(logFileRotate > 0) { 320 int i; 321 char oldFile[(strlen(logFilePath)+4)], newFile[(strlen(logFilePath)+4)]; 322 for(i=logFileRotate-1;i>0;i--) { 323 sprintf(oldFile, "%s.%d", logFilePath, i-1); 324 sprintf(newFile, "%s.%d", logFilePath, i); 325 rename(oldFile, newFile); 326 } 327 sprintf(newFile, "%s.%d", logFilePath, 0); 328 fl.l_type = F_UNLCK; 329 fcntl (fd, F_SETLKW, &fl); 330 close(fd); 331 rename(logFilePath, newFile); 332 fd = device_open (logFilePath, 333 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | 334 O_NONBLOCK); 335 fl.l_type = F_WRLCK; 336 fcntl (fd, F_SETLKW, &fl); 337 } else { 338 ftruncate( fd, 0 ); 323 fl.l_type = F_WRLCK; 324 fcntl(G.logFD, F_SETLKW, &fl); 325 326 #if ENABLE_FEATURE_ROTATE_LOGFILE 327 if (G.logFileSize && G.isRegular && G.curFileSize > G.logFileSize) { 328 if (G.logFileRotate) { /* always 0..99 */ 329 int i = strlen(G.logFilePath) + 3 + 1; 330 char oldFile[i]; 331 char newFile[i]; 332 i = G.logFileRotate - 1; 333 /* rename: f.8 -> f.9; f.7 -> f.8; ... */ 334 while (1) { 335 sprintf(newFile, "%s.%d", G.logFilePath, i); 336 if (i == 0) break; 337 sprintf(oldFile, "%s.%d", G.logFilePath, --i); 338 rename(oldFile, newFile); 339 } 340 /* newFile == "f.0" now */ 341 rename(G.logFilePath, newFile); 342 fl.l_type = F_UNLCK; 343 fcntl(G.logFD, F_SETLKW, &fl); 344 close(G.logFD); 345 goto reopen; 346 } 347 ftruncate(G.logFD, 0); 348 } 349 G.curFileSize += 350 #endif 351 full_write(G.logFD, msg, len); 352 fl.l_type = F_UNLCK; 353 fcntl(G.logFD, F_SETLKW, &fl); 354 } 355 356 static void parse_fac_prio_20(int pri, char *res20) 357 { 358 const CODE *c_pri, *c_fac; 359 360 if (pri != 0) { 361 c_fac = facilitynames; 362 while (c_fac->c_name) { 363 if (c_fac->c_val != (LOG_FAC(pri) << 3)) { 364 c_fac++; continue; 365 } 366 /* facility is found, look for prio */ 367 c_pri = prioritynames; 368 while (c_pri->c_name) { 369 if (c_pri->c_val != LOG_PRI(pri)) { 370 c_pri++; continue; 339 371 } 340 } 341 } 342 #endif 343 va_start(arguments, fmt); 344 vdprintf(fd, fmt, arguments); 345 va_end(arguments); 346 fl.l_type = F_UNLCK; 347 fcntl(fd, F_SETLKW, &fl); 348 close(fd); 349 } else { 350 /* Always send console messages to /dev/console so people will see them. */ 351 if ((fd = device_open(_PATH_CONSOLE, 352 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) { 353 va_start(arguments, fmt); 354 vdprintf(fd, fmt, arguments); 355 va_end(arguments); 356 close(fd); 357 } else { 358 fprintf(stderr, "Bummer, can't print: "); 359 va_start(arguments, fmt); 360 vfprintf(stderr, fmt, arguments); 361 fflush(stderr); 362 va_end(arguments); 363 } 364 } 365 } 366 367 #ifdef CONFIG_FEATURE_REMOTE_LOG 368 static void init_RemoteLog(void) 369 { 370 memset(&remoteaddr, 0, sizeof(remoteaddr)); 371 remotefd = bb_xsocket(AF_INET, SOCK_DGRAM, 0); 372 remoteaddr.sin_family = AF_INET; 373 remoteaddr.sin_addr = *(struct in_addr *) *(xgethostbyname(RemoteHost))->h_addr_list; 374 remoteaddr.sin_port = htons(RemotePort); 375 } 376 #endif 377 378 static void logMessage(int pri, char *msg) 379 { 380 time_t now; 372 snprintf(res20, 20, "%s.%s", 373 c_fac->c_name, c_pri->c_name); 374 return; 375 } 376 /* prio not found, bail out */ 377 break; 378 } 379 snprintf(res20, 20, "<%d>", pri); 380 } 381 } 382 383 /* len parameter is used only for "is there a timestamp?" check. 384 * NB: some callers cheat and supply 0 when they know 385 * that there is no timestamp, short-cutting the test. */ 386 static void timestamp_and_log(int pri, char *msg, int len) 387 { 381 388 char *timestamp; 382 static char res[20]; 383 #ifdef CONFIG_FEATURE_REMOTE_LOG 384 static char line[MAXLINE + 1]; 385 #endif 386 CODE *c_pri, *c_fac; 387 388 if (pri != 0) { 389 for (c_fac = facilitynames; 390 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++); 391 for (c_pri = prioritynames; 392 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++); 393 if (c_fac->c_name == NULL || c_pri->c_name == NULL) { 394 snprintf(res, sizeof(res), "<%d>", pri); 395 } else { 396 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name); 397 } 398 } 399 400 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' || 401 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') { 389 390 if (len < 16 || msg[3] != ' ' || msg[6] != ' ' 391 || msg[9] != ':' || msg[12] != ':' || msg[15] != ' ' 392 ) { 393 time_t now; 402 394 time(&now); 403 395 timestamp = ctime(&now) + 4; 404 timestamp[15] = '\0';405 396 } else { 406 397 timestamp = msg; 407 timestamp[15] = '\0';408 398 msg += 16; 409 399 } 410 411 /* todo: supress duplicates */ 412 413 #ifdef CONFIG_FEATURE_REMOTE_LOG 414 if (doRemoteLog == TRUE) { 415 /* trying connect the socket */ 416 if (-1 == remotefd) { 417 init_RemoteLog(); 418 } 419 420 /* if we have a valid socket, send the message */ 421 if (-1 != remotefd) { 422 now = 1; 423 snprintf(line, sizeof(line), "<%d>%s", pri, msg); 424 425 retry: 426 /* send message to remote logger */ 427 if(( -1 == sendto(remotefd, line, strlen(line), 0, 428 (struct sockaddr *) &remoteaddr, 429 sizeof(remoteaddr))) && (errno == EINTR)) { 430 /* sleep now seconds and retry (with now * 2) */ 431 sleep(now); 432 now *= 2; 433 goto retry; 434 } 435 } 436 } 437 438 if (local_logging == TRUE) 439 #endif 440 { 441 /* now spew out the message to wherever it is supposed to go */ 442 if (small) 443 message("%s %s\n", timestamp, msg); 444 else 445 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg); 400 timestamp[15] = '\0'; 401 402 /* Log message locally (to file or shared mem) */ 403 if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) { 404 if (LOG_PRI(pri) < G.logLevel) { 405 if (option_mask32 & OPT_small) 406 sprintf(G.printbuf, "%s %s\n", timestamp, msg); 407 else { 408 char res[20]; 409 parse_fac_prio_20(pri, res); 410 sprintf(G.printbuf, "%s %s %s %s\n", timestamp, G.localHostName, res, msg); 411 } 412 log_locally(G.printbuf); 413 } 414 } 415 } 416 417 static void split_escape_and_log(char *tmpbuf, int len) 418 { 419 char *p = tmpbuf; 420 421 tmpbuf += len; 422 while (p < tmpbuf) { 423 char c; 424 char *q = G.parsebuf; 425 int pri = (LOG_USER | LOG_NOTICE); 426 427 if (*p == '<') { 428 /* Parse the magic priority number */ 429 pri = bb_strtou(p + 1, &p, 10); 430 if (*p == '>') p++; 431 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { 432 pri = (LOG_USER | LOG_NOTICE); 433 } 434 } 435 436 while ((c = *p++)) { 437 if (c == '\n') 438 c = ' '; 439 if (!(c & ~0x1f) && c != '\t') { 440 *q++ = '^'; 441 c += '@'; /* ^@, ^A, ^B... */ 442 } 443 *q++ = c; 444 } 445 *q = '\0'; 446 /* Now log it */ 447 timestamp_and_log(pri, G.parsebuf, q - G.parsebuf); 446 448 } 447 449 } … … 449 451 static void quit_signal(int sig) 450 452 { 451 logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting."); 452 unlink(lfile); 453 #ifdef CONFIG_FEATURE_IPC_SYSLOG 454 ipcsyslog_cleanup(); 455 #endif 456 457 exit(TRUE); 458 } 459 460 static void domark(int sig) 461 { 462 if (MarkInterval > 0) { 463 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --"); 464 alarm(MarkInterval); 465 } 466 } 467 468 /* This must be a #define, since when CONFIG_DEBUG and BUFFERS_GO_IN_BSS are 469 * enabled, we otherwise get a "storage size isn't constant error. */ 470 static int serveConnection(char *tmpbuf, int n_read) 471 { 472 char *p = tmpbuf; 473 474 while (p < tmpbuf + n_read) { 475 476 int pri = (LOG_USER | LOG_NOTICE); 477 int num_lt = 0; 478 char line[MAXLINE + 1]; 479 unsigned char c; 480 char *q = line; 481 482 while ((c = *p) && q < &line[sizeof(line) - 1]) { 483 if (c == '<' && num_lt == 0) { 484 /* Parse the magic priority number. */ 485 num_lt++; 486 pri = 0; 487 while (isdigit(*(++p))) { 488 pri = 10 * pri + (*p - '0'); 489 } 490 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { 491 pri = (LOG_USER | LOG_NOTICE); 492 } 493 } else if (c == '\n') { 494 *q++ = ' '; 495 } else if (iscntrl(c) && (c < 0177)) { 496 *q++ = '^'; 497 *q++ = c ^ 0100; 498 } else { 499 *q++ = c; 500 } 501 p++; 502 } 503 *q = '\0'; 504 p++; 505 /* Now log it */ 506 logMessage(pri, line); 507 } 508 return n_read; 509 } 510 511 static void doSyslogd(void) ATTRIBUTE_NORETURN; 512 static void doSyslogd(void) 453 timestamp_and_log(LOG_SYSLOG | LOG_INFO, (char*)"syslogd exiting", 0); 454 puts("syslogd exiting"); 455 if (ENABLE_FEATURE_IPC_SYSLOG) 456 ipcsyslog_cleanup(); 457 exit(1); 458 } 459 460 #ifdef SYSLOGD_MARK 461 static void do_mark(int sig) 462 { 463 if (G.markInterval) { 464 timestamp_and_log(LOG_SYSLOG | LOG_INFO, (char*)"-- MARK --", 0); 465 alarm(G.markInterval); 466 } 467 } 468 #endif 469 470 static void do_syslogd(void) ATTRIBUTE_NORETURN; 471 static void do_syslogd(void) 513 472 { 514 473 struct sockaddr_un sunx; 515 socklen_t addrLength;516 517 474 int sock_fd; 518 475 fd_set fds; 519 520 /* Set up signal handlers. */ 476 char *dev_log_name; 477 478 /* Set up signal handlers */ 521 479 signal(SIGINT, quit_signal); 522 480 signal(SIGTERM, quit_signal); … … 527 485 signal(SIGCLD, SIG_IGN); 528 486 #endif 529 signal(SIGALRM, domark); 530 alarm(MarkInterval); 531 532 /* Create the syslog file so realpath() can work. */ 533 if (realpath(_PATH_LOG, lfile) != NULL) { 534 unlink(lfile); 535 } 487 #ifdef SYSLOGD_MARK 488 signal(SIGALRM, do_mark); 489 alarm(G.markInterval); 490 #endif 491 remove_pidfile("/var/run/syslogd.pid"); 536 492 537 493 memset(&sunx, 0, sizeof(sunx)); 538 494 sunx.sun_family = AF_UNIX; 539 strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path)); 540 sock_fd = bb_xsocket(AF_UNIX, SOCK_DGRAM, 0); 541 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path); 542 if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) { 543 bb_perror_msg_and_die("Could not connect to socket " _PATH_LOG); 544 } 545 546 if (chmod(lfile, 0666) < 0) { 547 bb_perror_msg_and_die("Could not set permission on " _PATH_LOG); 548 } 549 #ifdef CONFIG_FEATURE_IPC_SYSLOG 550 if (circular_logging == TRUE) { 495 strcpy(sunx.sun_path, "/dev/log"); 496 497 /* Unlink old /dev/log or object it points to. */ 498 /* (if it exists, bind will fail) */ 499 logmode = LOGMODE_NONE; 500 dev_log_name = xmalloc_readlink_or_warn("/dev/log"); 501 logmode = LOGMODE_STDIO; 502 if (dev_log_name) { 503 int fd = xopen(".", O_NONBLOCK); 504 xchdir("/dev"); 505 /* we do not check whether this is a link also */ 506 unlink(dev_log_name); 507 fchdir(fd); 508 close(fd); 509 safe_strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path)); 510 free(dev_log_name); 511 } else { 512 unlink("/dev/log"); 513 } 514 515 sock_fd = xsocket(AF_UNIX, SOCK_DGRAM, 0); 516 xbind(sock_fd, (struct sockaddr *) &sunx, sizeof(sunx)); 517 518 if (chmod("/dev/log", 0666) < 0) { 519 bb_perror_msg_and_die("cannot set permission on /dev/log"); 520 } 521 if (ENABLE_FEATURE_IPC_SYSLOG && (option_mask32 & OPT_circularlog)) { 551 522 ipcsyslog_init(); 552 523 } 553 #endif 554 555 #ifdef CONFIG_FEATURE_REMOTE_LOG 556 if (doRemoteLog == TRUE) { 557 init_RemoteLog(); 558 } 559 #endif 560 561 logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " "BusyBox v" BB_VER ); 524 525 timestamp_and_log(LOG_SYSLOG | LOG_INFO, 526 (char*)"syslogd started: BusyBox v" BB_VER, 0); 562 527 563 528 for (;;) { 564 565 529 FD_ZERO(&fds); 566 530 FD_SET(sock_fd, &fds); … … 568 532 if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) { 569 533 if (errno == EINTR) { 570 /* alarm may have happened .*/534 /* alarm may have happened */ 571 535 continue; 572 536 } 573 bb_perror_msg_and_die("select error");537 bb_perror_msg_and_die("select"); 574 538 } 575 539 576 540 if (FD_ISSET(sock_fd, &fds)) { 577 541 int i; 578 #if MAXLINE > BUFSIZ 579 # define TMP_BUF_SZ BUFSIZ 580 #else 581 # define TMP_BUF_SZ MAXLINE 582 #endif 583 #define tmpbuf bb_common_bufsiz1 584 585 if ((i = recv(sock_fd, tmpbuf, TMP_BUF_SZ, 0)) > 0) { 586 tmpbuf[i] = '\0'; 587 serveConnection(tmpbuf, i); 588 } else { 542 i = recv(sock_fd, G.recvbuf, MAX_READ - 1, 0); 543 if (i <= 0) 589 544 bb_perror_msg_and_die("UNIX socket error"); 590 } 591 } /* FD_ISSET() */ 592 } /* for main loop */ 593 } 594 545 /* TODO: maybe suppress duplicates? */ 546 #if ENABLE_FEATURE_REMOTE_LOG 547 /* We are not modifying log messages in any way before send */ 548 /* Remote site cannot trust _us_ anyway and need to do validation again */ 549 if (G.remoteAddr) { 550 if (-1 == G.remoteFD) { 551 G.remoteFD = socket(G.remoteAddr->sa.sa_family, SOCK_DGRAM, 0); 552 } 553 if (-1 != G.remoteFD) { 554 /* send message to remote logger, ignore possible error */ 555 sendto(G.remoteFD, G.recvbuf, i, MSG_DONTWAIT, 556 &G.remoteAddr->sa, G.remoteAddr->len); 557 } 558 } 559 #endif 560 G.recvbuf[i] = '\0'; 561 split_escape_and_log(G.recvbuf, i); 562 } /* FD_ISSET() */ 563 } /* for */ 564 } 565 566 int syslogd_main(int argc, char **argv); 595 567 int syslogd_main(int argc, char **argv) 596 568 { 597 int opt; 598 599 int doFork = TRUE; 600 569 char OPTION_DECL; 601 570 char *p; 602 571 572 PTR_TO_GLOBALS = memcpy(xzalloc(sizeof(G)), &init_data, sizeof(init_data)); 573 603 574 /* do normal option parsing */ 604 while ((opt = getopt(argc, argv, "m:nO:s:Sb:R:LC::")) > 0) { 605 switch (opt) { 606 case 'm': 607 MarkInterval = atoi(optarg) * 60; 608 break; 609 case 'n': 610 doFork = FALSE; 611 break; 612 case 'O': 613 logFilePath = optarg; 614 break; 615 #ifdef CONFIG_FEATURE_ROTATE_LOGFILE 616 case 's': 617 logFileSize = atoi(optarg) * 1024; 618 break; 619 case 'b': 620 logFileRotate = atoi(optarg); 621 if( logFileRotate > 99 ) logFileRotate = 99; 622 break; 623 #endif 624 #ifdef CONFIG_FEATURE_REMOTE_LOG 625 case 'R': 626 RemoteHost = bb_xstrdup(optarg); 627 if ((p = strchr(RemoteHost, ':'))) { 628 RemotePort = atoi(p + 1); 629 *p = '\0'; 630 } 631 doRemoteLog = TRUE; 632 break; 633 case 'L': 634 local_logging = TRUE; 635 break; 636 #endif 637 #ifdef CONFIG_FEATURE_IPC_SYSLOG 638 case 'C': 639 if (optarg) { 640 int buf_size = atoi(optarg); 641 if (buf_size >= 4) { 642 shm_size = buf_size * 1024; 643 } 644 } 645 circular_logging = TRUE; 646 break; 647 #endif 648 case 'S': 649 small = true; 650 break; 651 default: 652 bb_show_usage(); 653 } 654 } 655 656 #ifdef CONFIG_FEATURE_REMOTE_LOG 575 opt_complementary = "=0"; /* no non-option params */ 576 getopt32(argv, OPTION_STR, OPTION_PARAM); 577 #ifdef SYSLOGD_MARK 578 if (option_mask32 & OPT_mark) // -m 579 G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60; 580 #endif 581 //if (option_mask32 & OPT_nofork) // -n 582 //if (option_mask32 & OPT_outfile) // -O 583 if (option_mask32 & OPT_loglevel) // -l 584 G.logLevel = xatou_range(opt_l, 1, 8); 585 //if (option_mask32 & OPT_small) // -S 586 #if ENABLE_FEATURE_ROTATE_LOGFILE 587 if (option_mask32 & OPT_filesize) // -s 588 G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; 589 if (option_mask32 & OPT_rotatecnt) // -b 590 G.logFileRotate = xatou_range(opt_b, 0, 99); 591 #endif 592 #if ENABLE_FEATURE_REMOTE_LOG 593 if (option_mask32 & OPT_remotelog) { // -R 594 G.remoteAddr = xhost2sockaddr(opt_R, 514); 595 } 596 //if (option_mask32 & OPT_locallog) // -L 597 #endif 598 #if ENABLE_FEATURE_IPC_SYSLOG 599 if (opt_C) // -Cn 600 G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; 601 #endif 602 657 603 /* If they have not specified remote logging, then log locally */ 658 if (doRemoteLog == FALSE) 659 local_logging = TRUE; 660 #endif 661 604 if (ENABLE_FEATURE_REMOTE_LOG && !(option_mask32 & OPT_remotelog)) 605 option_mask32 |= OPT_locallog; 662 606 663 607 /* Store away localhost's name before the fork */ 664 gethostname(LocalHostName, sizeof(LocalHostName)); 665 if ((p = strchr(LocalHostName, '.'))) { 608 gethostname(G.localHostName, sizeof(G.localHostName)); 609 p = strchr(G.localHostName, '.'); 610 if (p) { 666 611 *p = '\0'; 667 612 } 668 613 614 if (!(option_mask32 & OPT_nofork)) { 615 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); 616 } 669 617 umask(0); 670 671 if (doFork == TRUE) { 672 #ifdef BB_NOMMU 673 vfork_daemon_rexec(0, 1, argc, argv, "-n"); 674 #else 675 bb_xdaemon(0, 1); 676 #endif 677 } 678 doSyslogd(); 679 680 return EXIT_SUCCESS; 681 } 618 write_pidfile("/var/run/syslogd.pid"); 619 do_syslogd(); 620 /* return EXIT_SUCCESS; */ 621 }
Note:
See TracChangeset
for help on using the changeset viewer.