aboutsummaryrefslogtreecommitdiff
path: root/sysklogd
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-12 21:33:06 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-12 21:33:06 +0000
commit5f1b149d541ebba7cab841cb647f113248f9fb8f (patch)
treee7f962fba89b6e201b4c857e32d85c9671b3db0d /sysklogd
parent1b9064d5355b5c26676e8447a1900116066e42e4 (diff)
downloadbusybox-w32-5f1b149d541ebba7cab841cb647f113248f9fb8f.tar.gz
busybox-w32-5f1b149d541ebba7cab841cb647f113248f9fb8f.tar.bz2
busybox-w32-5f1b149d541ebba7cab841cb647f113248f9fb8f.zip
syslogd,logread: get rid of head pointer, fix logread bug in the process
function old new delta logread_main 450 462 +12 syslogd_main 1246 1252 +6 shbuf - 4 +4 buf 34 30 -4 packed_usage 22729 22724 -5 log_locally 957 767 -190 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/3 up/down: 22/-199) Total: -177 bytes text data bss dec hex filename 773886 1116 11316 786318 bff8e busybox_old 773714 1116 11316 786146 bfee2 busybox_unstripped
Diffstat (limited to 'sysklogd')
-rw-r--r--sysklogd/logread.c113
-rw-r--r--sysklogd/syslogd.c55
2 files changed, 81 insertions, 87 deletions
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
index ac354b5c3..597e285a5 100644
--- a/sysklogd/logread.c
+++ b/sysklogd/logread.c
@@ -19,11 +19,10 @@
19enum { KEY_ID = 0x414e4547 }; /* "GENA" */ 19enum { KEY_ID = 0x414e4547 }; /* "GENA" */
20 20
21static struct shbuf_ds { 21static struct shbuf_ds {
22 int32_t size; // size of data written 22 int32_t size; // size of data - 1
23 int32_t head; // start of message list
24 int32_t tail; // end of message list 23 int32_t tail; // end of message list
25 char data[1]; // data/messages 24 char data[1]; // messages
26} *buf; // shared memory pointer 25} *shbuf;
27 26
28// Semaphore operation structures 27// Semaphore operation structures
29static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup 28static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
@@ -34,7 +33,7 @@ static void error_exit(const char *str) ATTRIBUTE_NORETURN;
34static void error_exit(const char *str) 33static void error_exit(const char *str)
35{ 34{
36 //release all acquired resources 35 //release all acquired resources
37 shmdt(buf); 36 shmdt(shbuf);
38 bb_perror_msg_and_die(str); 37 bb_perror_msg_and_die(str);
39} 38}
40 39
@@ -50,7 +49,7 @@ static void sem_up(int semid)
50static void interrupted(int sig ATTRIBUTE_UNUSED) 49static void interrupted(int sig ATTRIBUTE_UNUSED)
51{ 50{
52 signal(SIGINT, SIG_IGN); 51 signal(SIGINT, SIG_IGN);
53 shmdt(buf); 52 shmdt(shbuf);
54 exit(0); 53 exit(0);
55} 54}
56 55
@@ -66,79 +65,105 @@ int logread_main(int argc, char **argv)
66 if (log_shmid == -1) 65 if (log_shmid == -1)
67 bb_perror_msg_and_die("can't find syslogd buffer"); 66 bb_perror_msg_and_die("can't find syslogd buffer");
68 67
69 // Attach shared memory to our char* 68 /* Attach shared memory to our char* */
70 buf = shmat(log_shmid, NULL, SHM_RDONLY); 69 shbuf = shmat(log_shmid, NULL, SHM_RDONLY);
71 if (buf == NULL) 70 if (shbuf == NULL)
72 bb_perror_msg_and_die("can't access syslogd buffer"); 71 bb_perror_msg_and_die("can't access syslogd buffer");
73 72
74 log_semid = semget(KEY_ID, 0, 0); 73 log_semid = semget(KEY_ID, 0, 0);
75 if (log_semid == -1) 74 if (log_semid == -1)
76 error_exit("can't get access to semaphores for syslogd buffer"); 75 error_exit("can't get access to semaphores for syslogd buffer");
77 76
78 // attempt to redefine ^C signal
79 signal(SIGINT, interrupted); 77 signal(SIGINT, interrupted);
80 78
81 // Suppose atomic memory move 79 /* Suppose atomic memory read */
82 cur = follow ? buf->tail : buf->head; 80 /* Max possible value for tail is shbuf->size - 1 */
81 cur = shbuf->tail;
83 82
83 /* Loop for logread -f, one pass if there was no -f */
84 do { 84 do {
85 unsigned shbuf_size;
86 unsigned shbuf_tail;
87 const char *shbuf_data;
85#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 88#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
86 char *buf_data; 89 int i;
87 int log_len, j; 90 int len_first_part;
91 int len_total = len_total; /* for gcc */
92 char *copy = copy; /* for gcc */
88#endif 93#endif
89 if (semop(log_semid, SMrdn, 2) == -1) 94 if (semop(log_semid, SMrdn, 2) == -1)
90 error_exit("semop[SMrdn]"); 95 error_exit("semop[SMrdn]");
91 96
92 if (DEBUG) 97 /* Copy the info, helps gcc to realize that it doesn't change */
93 printf("head:%i cur:%d tail:%i size:%i\n", 98 shbuf_size = shbuf->size;
94 buf->head, cur, buf->tail, buf->size); 99 shbuf_tail = shbuf->tail;
100 shbuf_data = shbuf->data; /* pointer! */
95 101
96 if (buf->head == buf->tail || cur == buf->tail) { 102 if (DEBUG)
97 if (follow) { 103 printf("cur:%d tail:%i size:%i\n",
104 cur, shbuf_tail, shbuf_size);
105
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) {
98 sem_up(log_semid); 121 sem_up(log_semid);
99 fflush(stdout); 122 fflush(stdout);
100 sleep(1); /* TODO: replace me with a sleep_on */ 123 sleep(1); /* TODO: replace me with a sleep_on */
101 continue; 124 continue;
102 } 125 }
103 puts("<empty syslog>");
104 } 126 }
105 127
106 // Read Memory 128 /* Read from cur to tail */
107#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 129#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
108 log_len = buf->tail - cur; 130 len_first_part = len_total = shbuf_tail - cur;
109 if (log_len < 0) 131 if (len_total < 0) {
110 log_len += buf->size; 132 /* message wraps: */
111 buf_data = xmalloc(log_len); 133 /* [SECOND PART.........FIRST PART] */
112 134 /* ^data ^tail ^cur ^size */
113 if (buf->tail >= cur) 135 len_total += shbuf_size;
114 j = log_len; 136 }
115 else 137 copy = xmalloc(len_total + 1);
116 j = buf->size - cur; 138 if (len_first_part < 0) {
117 memcpy(buf_data, buf->data + cur, j); 139 /* message wraps (see above) */
118 140 len_first_part = shbuf_size - cur;
119 if (buf->tail < cur) 141 memcpy(copy + len_first_part, shbuf_data, shbuf_tail);
120 memcpy(buf_data + buf->size - cur, buf->data, buf->tail); 142 }
121 cur = buf->tail; 143 memcpy(copy, shbuf_data + cur, len_first_part);
144 copy[len_total] = '\0';
145 cur = shbuf_tail;
122#else 146#else
123 while (cur != buf->tail) { 147 while (cur != shbuf_tail) {
124 fputs(buf->data + cur, stdout); 148 fputs(shbuf_data + cur, stdout);
125 cur += strlen(buf->data + cur) + 1; 149 cur += strlen(shbuf_data + cur) + 1;
126 if (cur >= buf->size) 150 if (cur >= shbuf_size)
127 cur = 0; 151 cur = 0;
128 } 152 }
129#endif 153#endif
130 // release the lock on the log chain 154 unlock:
155 /* release the lock on the log chain */
131 sem_up(log_semid); 156 sem_up(log_semid);
132 157
133#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 158#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
134 for (j = 0; j < log_len; j += strlen(buf_data+j) + 1) { 159 for (i = 0; i < len_total; i += strlen(copy + i) + 1) {
135 fputs(buf_data + j, stdout); 160 fputs(copy + i, stdout);
136 } 161 }
137 free(buf_data); 162 free(copy);
138#endif 163#endif
139 } while (follow); 164 } while (follow);
140 165
141 shmdt(buf); 166 shmdt(shbuf);
142 167
143 fflush_stdout_and_exit(EXIT_SUCCESS); 168 fflush_stdout_and_exit(EXIT_SUCCESS);
144} 169}
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 0ed16bc9e..6ecbd16f0 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -46,8 +46,7 @@ enum { MAX_READ = 256 };
46 46
47/* Semaphore operation structures */ 47/* Semaphore operation structures */
48struct shbuf_ds { 48struct shbuf_ds {
49 int32_t size; /* size of data written */ 49 int32_t size; /* size of data - 1 */
50 int32_t head; /* start of message list */
51 int32_t tail; /* end of message list */ 50 int32_t tail; /* end of message list */
52 char data[1]; /* data/messages */ 51 char data[1]; /* data/messages */
53}; 52};
@@ -212,8 +211,9 @@ static void ipcsyslog_init(void)
212 bb_perror_msg_and_die("shmat"); 211 bb_perror_msg_and_die("shmat");
213 } 212 }
214 213
215 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data); 214 memset(G.shbuf, 0, G.shm_size);
216 G.shbuf->head = G.shbuf->tail = 0; 215 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1;
216 /*G.shbuf->tail = 0;*/
217 217
218 // we'll trust the OS to set initial semval to 0 (let's hope) 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); 219 G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023);
@@ -231,7 +231,6 @@ static void ipcsyslog_init(void)
231static void log_to_shmem(const char *msg, int len) 231static void log_to_shmem(const char *msg, int len)
232{ 232{
233 int old_tail, new_tail; 233 int old_tail, new_tail;
234 char *c;
235 234
236 if (semop(G.s_semid, G.SMwdn, 3) == -1) { 235 if (semop(G.s_semid, G.SMwdn, 3) == -1) {
237 bb_perror_msg_and_die("SMwdn"); 236 bb_perror_msg_and_die("SMwdn");
@@ -240,49 +239,20 @@ static void log_to_shmem(const char *msg, int len)
240 /* Circular Buffer Algorithm: 239 /* Circular Buffer Algorithm:
241 * -------------------------- 240 * --------------------------
242 * tail == position where to store next syslog message. 241 * tail == position where to store next syslog message.
243 * head == position of next message to retrieve ("print"). 242 * tail's max value is (shbuf->size - 1)
244 * if head == tail, there is no "unprinted" messages left. 243 * Last byte of buffer is never used and remains NUL.
245 * head is typically advanced by separate "reader" program,
246 * but if there isn't one, we have to do it ourself.
247 * messages are NUL-separated.
248 */ 244 */
249 len++; /* length with NUL included */ 245 len++; /* length with NUL included */
250 again: 246 again:
251 old_tail = G.shbuf->tail; 247 old_tail = G.shbuf->tail;
252 new_tail = old_tail + len; 248 new_tail = old_tail + len;
253 if (new_tail < G.shbuf->size) { 249 if (new_tail < G.shbuf->size) {
254 /* No need to move head if shbuf->head <= old_tail,
255 * else... */
256 if (old_tail < G.shbuf->head && G.shbuf->head <= new_tail) {
257 /* ...need to move head forward */
258 c = memchr(G.shbuf->data + new_tail, '\0',
259 G.shbuf->size - new_tail);
260 if (!c) /* no NUL ahead of us, wrap around */
261 c = memchr(G.shbuf->data, '\0', old_tail);
262 if (!c) { /* still nothing? point to this msg... */
263 G.shbuf->head = old_tail;
264 } else {
265 /* convert pointer to offset + skip NUL */
266 G.shbuf->head = c - G.shbuf->data + 1;
267 }
268 }
269 /* store message, set new tail */ 250 /* store message, set new tail */
270 memcpy(G.shbuf->data + old_tail, msg, len); 251 memcpy(G.shbuf->data + old_tail, msg, len);
271 G.shbuf->tail = new_tail; 252 G.shbuf->tail = new_tail;
272 } else { 253 } else {
273 /* we need to break up the message and wrap it around */
274 /* k == available buffer space ahead of old tail */ 254 /* k == available buffer space ahead of old tail */
275 int k = G.shbuf->size - old_tail - 1; 255 int k = G.shbuf->size - old_tail;
276 if (G.shbuf->head > old_tail) {
277 /* we are going to overwrite head, need to
278 * move it out of the way */
279 c = memchr(G.shbuf->data, '\0', old_tail);
280 if (!c) { /* nothing? point to this msg... */
281 G.shbuf->head = old_tail;
282 } else { /* convert pointer to offset + skip NUL */
283 G.shbuf->head = c - G.shbuf->data + 1;
284 }
285 }
286 /* copy what fits to the end of buffer, and repeat */ 256 /* copy what fits to the end of buffer, and repeat */
287 memcpy(G.shbuf->data + old_tail, msg, k); 257 memcpy(G.shbuf->data + old_tail, msg, k);
288 msg += k; 258 msg += k;
@@ -294,7 +264,7 @@ static void log_to_shmem(const char *msg, int len)
294 bb_perror_msg_and_die("SMwup"); 264 bb_perror_msg_and_die("SMwup");
295 } 265 }
296 if (DEBUG) 266 if (DEBUG)
297 printf("head:%d tail:%d\n", G.shbuf->head, G.shbuf->tail); 267 printf("tail:%d\n", G.shbuf->tail);
298} 268}
299#else 269#else
300void ipcsyslog_cleanup(void); 270void ipcsyslog_cleanup(void);
@@ -339,11 +309,10 @@ static void log_locally(char *msg)
339 } 309 }
340#if ENABLE_FEATURE_ROTATE_LOGFILE 310#if ENABLE_FEATURE_ROTATE_LOGFILE
341 { 311 {
342 struct stat statf; 312 struct stat statf;
343 313 G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode));
344 G.isRegular = (fstat(G.logFD, &statf) == 0 && (statf.st_mode & S_IFREG)); 314 /* bug (mostly harmless): can wrap around if file > 4gb */
345 /* bug (mostly harmless): can wrap around if file > 4gb */ 315 G.curFileSize = statf.st_size;
346 G.curFileSize = statf.st_size;
347 } 316 }
348#endif 317#endif
349 } 318 }