source: MondoRescue/branches/3.3/mindi-busybox/sysklogd/logread.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.1 KB
RevLine 
[821]1/* vi: set sw=4 ts=4: */
2/*
3 * circular buffer syslog implementation for busybox
4 *
5 * Copyright (C) 2000 by Gennady Feldman <gfeldman@gena01.com>
6 *
7 * Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
8 *
[2725]9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
[821]10 */
[3621]11//config:config LOGREAD
12//config: bool "logread"
13//config: default y
14//config: depends on FEATURE_IPC_SYSLOG
15//config: help
16//config: If you enabled Circular Buffer support, you almost
17//config: certainly want to enable this feature as well. This
18//config: utility will allow you to read the messages that are
19//config: stored in the syslogd circular buffer.
20//config:
21//config:config FEATURE_LOGREAD_REDUCED_LOCKING
22//config: bool "Double buffering"
23//config: default y
24//config: depends on LOGREAD
25//config: help
26//config: 'logread' ouput to slow serial terminals can have
27//config: side effects on syslog because of the semaphore.
28//config: This option make logread to double buffer copy
29//config: from circular buffer, minimizing semaphore
30//config: contention at some minor memory expense.
31//config:
[821]32
[3621]33//applet:IF_LOGREAD(APPLET(logread, BB_DIR_SBIN, BB_SUID_DROP))
34
35//kbuild:lib-$(CONFIG_LOGREAD) += logread.o
36
[3232]37//usage:#define logread_trivial_usage
[3621]38//usage: "[-fF]"
[3232]39//usage:#define logread_full_usage "\n\n"
40//usage: "Show messages in syslogd's circular buffer\n"
41//usage: "\n -f Output data as log grows"
[3621]42//usage: "\n -F Same as -f, but dump buffer first"
[3232]43
[1765]44#include "libbb.h"
[3621]45#include "common_bufsiz.h"
[821]46#include <sys/ipc.h>
47#include <sys/sem.h>
48#include <sys/shm.h>
49
[1765]50#define DEBUG 0
[821]51
[2725]52/* our shared key (syslogd.c and logread.c must be in sync) */
[1765]53enum { KEY_ID = 0x414e4547 }; /* "GENA" */
54
[2725]55struct shbuf_ds {
[1765]56 int32_t size; // size of data - 1
57 int32_t tail; // end of message list
58 char data[1]; // messages
[2725]59};
[821]60
[2725]61static const struct sembuf init_sem[3] = {
62 {0, -1, IPC_NOWAIT | SEM_UNDO},
63 {1, 0}, {0, +1, SEM_UNDO}
64};
[821]65
[2725]66struct globals {
67 struct sembuf SMrup[1]; // {0, -1, IPC_NOWAIT | SEM_UNDO},
68 struct sembuf SMrdn[2]; // {1, 0}, {0, +1, SEM_UNDO}
69 struct shbuf_ds *shbuf;
70} FIX_ALIASING;
[3621]71#define G (*(struct globals*)bb_common_bufsiz1)
[2725]72#define SMrup (G.SMrup)
73#define SMrdn (G.SMrdn)
74#define shbuf (G.shbuf)
75#define INIT_G() do { \
[3621]76 setup_common_bufsiz(); \
[2725]77 memcpy(SMrup, init_sem, sizeof(init_sem)); \
78} while (0)
[821]79
[3621]80#if 0
[2725]81static void error_exit(const char *str) NORETURN;
[1765]82static void error_exit(const char *str)
83{
[3621]84 /* Release all acquired resources */
[1765]85 shmdt(shbuf);
86 bb_perror_msg_and_die(str);
87}
[3621]88#else
89/* On Linux, shmdt is not mandatory on exit */
90# define error_exit(str) bb_perror_msg_and_die(str)
91#endif
[821]92
93/*
94 * sem_up - up()'s a semaphore.
95 */
[1765]96static void sem_up(int semid)
[821]97{
[1765]98 if (semop(semid, SMrup, 1) == -1)
[821]99 error_exit("semop[SMrup]");
100}
101
[3621]102static void interrupted(int sig)
[821]103{
[3621]104 /* shmdt(shbuf); - on Linux, shmdt is not mandatory on exit */
105 kill_myself_with_sig(sig);
[821]106}
107
[2725]108int logread_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
109int logread_main(int argc UNUSED_PARAM, char **argv)
[821]110{
[2725]111 unsigned cur;
[1765]112 int log_semid; /* ipc semaphore id */
113 int log_shmid; /* ipc shared memory id */
[3621]114 int follow = getopt32(argv, "fF");
[821]115
[2725]116 INIT_G();
117
[1765]118 log_shmid = shmget(KEY_ID, 0, 0);
119 if (log_shmid == -1)
[3621]120 bb_perror_msg_and_die("can't %s syslogd buffer", "find");
[821]121
[1765]122 /* Attach shared memory to our char* */
123 shbuf = shmat(log_shmid, NULL, SHM_RDONLY);
124 if (shbuf == NULL)
[3621]125 bb_perror_msg_and_die("can't %s syslogd buffer", "access");
[821]126
[1765]127 log_semid = semget(KEY_ID, 0, 0);
128 if (log_semid == -1)
129 error_exit("can't get access to semaphores for syslogd buffer");
130
[3621]131 bb_signals(BB_FATAL_SIGS, interrupted);
[821]132
[1765]133 /* Suppose atomic memory read */
134 /* Max possible value for tail is shbuf->size - 1 */
135 cur = shbuf->tail;
[821]136
[3621]137 /* Loop for -f or -F, one pass otherwise */
[821]138 do {
[1765]139 unsigned shbuf_size;
140 unsigned shbuf_tail;
141 const char *shbuf_data;
142#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
143 int i;
144 int len_first_part;
145 int len_total = len_total; /* for gcc */
146 char *copy = copy; /* for gcc */
[821]147#endif
[1765]148 if (semop(log_semid, SMrdn, 2) == -1)
149 error_exit("semop[SMrdn]");
[821]150
[1765]151 /* Copy the info, helps gcc to realize that it doesn't change */
152 shbuf_size = shbuf->size;
153 shbuf_tail = shbuf->tail;
154 shbuf_data = shbuf->data; /* pointer! */
[821]155
[1765]156 if (DEBUG)
[3621]157 printf("cur:%u tail:%u size:%u\n",
[1765]158 cur, shbuf_tail, shbuf_size);
159
[3621]160 if (!(follow & 1)) { /* not -f */
161 /* if -F, "convert" it to -f, so that we dont
162 * dump the entire buffer on each iteration
163 */
164 follow >>= 1;
165
[1765]166 /* advance to oldest complete message */
167 /* find NUL */
168 cur += strlen(shbuf_data + cur);
169 if (cur >= shbuf_size) { /* last byte in buffer? */
170 cur = strnlen(shbuf_data, shbuf_tail);
171 if (cur == shbuf_tail)
172 goto unlock; /* no complete messages */
173 }
174 /* advance to first byte of the message */
175 cur++;
176 if (cur >= shbuf_size) /* last byte in buffer? */
177 cur = 0;
[3621]178 } else { /* -f */
[1765]179 if (cur == shbuf_tail) {
[821]180 sem_up(log_semid);
[2725]181 fflush_all();
[1765]182 sleep(1); /* TODO: replace me with a sleep_on */
[821]183 continue;
184 }
185 }
186
[1765]187 /* Read from cur to tail */
188#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
189 len_first_part = len_total = shbuf_tail - cur;
190 if (len_total < 0) {
191 /* message wraps: */
192 /* [SECOND PART.........FIRST PART] */
193 /* ^data ^tail ^cur ^size */
194 len_total += shbuf_size;
[821]195 }
[1765]196 copy = xmalloc(len_total + 1);
197 if (len_first_part < 0) {
198 /* message wraps (see above) */
199 len_first_part = shbuf_size - cur;
200 memcpy(copy + len_first_part, shbuf_data, shbuf_tail);
201 }
202 memcpy(copy, shbuf_data + cur, len_first_part);
203 copy[len_total] = '\0';
204 cur = shbuf_tail;
[821]205#else
[1765]206 while (cur != shbuf_tail) {
207 fputs(shbuf_data + cur, stdout);
208 cur += strlen(shbuf_data + cur) + 1;
209 if (cur >= shbuf_size)
210 cur = 0;
[821]211 }
212#endif
[1765]213 unlock:
214 /* release the lock on the log chain */
[821]215 sem_up(log_semid);
216
[1765]217#if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING
218 for (i = 0; i < len_total; i += strlen(copy + i) + 1) {
219 fputs(copy + i, stdout);
[821]220 }
[1765]221 free(copy);
[821]222#endif
[3621]223 fflush_all();
[821]224 } while (follow);
225
[3621]226 /* shmdt(shbuf); - on Linux, shmdt is not mandatory on exit */
[821]227
[1765]228 fflush_stdout_and_exit(EXIT_SUCCESS);
[821]229}
Note: See TracBrowser for help on using the repository browser.