blob: 54e53a600cf5a1fddaeeb25d7e2cc434f4df7b6b [file] [log] [blame]
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +00001/* vi: set sw=4 ts=4: */
2/*
3 * circular buffer syslog implementation for busybox
4 *
Glenn L McGrath6ed77592002-12-12 10:54:48 +00005 * Copyright (C) 2000 by Gennady Feldman <gfeldman@gena01.com>
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +00006 *
Glenn L McGrath6ed77592002-12-12 10:54:48 +00007 * Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +00008 *
Bernhard Reutner-Fischerd04e9b82006-06-01 14:36:14 +00009 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000010 */
11
12
Bernhard Reutner-Fischerd04e9b82006-06-01 14:36:14 +000013#include "busybox.h"
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000014#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <sys/ipc.h>
18#include <sys/types.h>
19#include <sys/sem.h>
20#include <sys/shm.h>
21#include <signal.h>
22#include <setjmp.h>
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +000023#include <unistd.h>
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000024
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000025static const long KEY_ID = 0x414e4547; /*"GENA"*/
26
27static 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
34
35// Semaphore operation structures
36static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
37static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn
38
Eric Andersen8ffaf8d2001-03-23 17:04:47 +000039static int log_shmid = -1; // ipc shared memory id
40static int log_semid = -1; // ipc semaphore id
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000041static jmp_buf jmp_env;
42
43static void error_exit(const char *str);
44static void interrupted(int sig);
45
46/*
47 * sem_up - up()'s a semaphore.
48 */
49static inline void sem_up(int semid)
50{
Eric Andersenc7bda1c2004-03-15 08:29:22 +000051 if ( semop(semid, SMrup, 1) == -1 )
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000052 error_exit("semop[SMrup]");
53}
54
55/*
56 * sem_down - down()'s a semaphore
Eric Andersenc7bda1c2004-03-15 08:29:22 +000057 */
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000058static inline void sem_down(int semid)
59{
60 if ( semop(semid, SMrdn, 2) == -1 )
61 error_exit("semop[SMrdn]");
62}
63
Rob Landleydfba7412006-03-06 20:47:33 +000064int logread_main(int argc, char **argv)
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000065{
66 int i;
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +000067 int follow=0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000068
Bernhard Reutner-Fischerd04e9b82006-06-01 14:36:14 +000069 if (argc == 2 && argv[1][0]=='-' && argv[1][1]=='f') {
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +000070 follow = 1;
71 } else {
72 /* no options, no getopt */
73 if (argc > 1)
74 bb_show_usage();
75 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +000076
Bernhard Reutner-Fischerd04e9b82006-06-01 14:36:14 +000077 // handle interrupt signal
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000078 if (setjmp(jmp_env)) goto output_end;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000079
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000080 // attempt to redefine ^C signal
81 signal(SIGINT, interrupted);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000082
Eric Andersen8ffaf8d2001-03-23 17:04:47 +000083 if ( (log_shmid = shmget(KEY_ID, 0, 0)) == -1)
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000084 error_exit("Can't find circular buffer");
Eric Andersenc7bda1c2004-03-15 08:29:22 +000085
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000086 // Attach shared memory to our char*
Eric Andersen8ffaf8d2001-03-23 17:04:47 +000087 if ( (buf = shmat(log_shmid, NULL, SHM_RDONLY)) == NULL)
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000088 error_exit("Can't get access to circular buffer from syslogd");
89
Eric Andersen8ffaf8d2001-03-23 17:04:47 +000090 if ( (log_semid = semget(KEY_ID, 0, 0)) == -1)
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000091 error_exit("Can't get access to semaphone(s) for circular buffer from syslogd");
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000092
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +000093 // Suppose atomic memory move
94 i = follow ? buf->tail : buf->head;
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +000095
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +000096 do {
Eric Andersend4a5e252003-12-19 11:32:14 +000097#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +000098 char *buf_data;
99 int log_len,j;
100#endif
101
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000102 sem_down(log_semid);
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +0000103
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) {
107 sem_up(log_semid);
108 sleep(1); /* TODO: replace me with a sleep_on */
109 continue;
110 } else {
111 printf("<empty syslog>\n");
112 }
113 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000114
115 // Read Memory
Eric Andersend4a5e252003-12-19 11:32:14 +0000116#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +0000117 log_len = buf->tail - i;
118 if (log_len < 0)
119 log_len += buf->size;
Bernhard Reutner-Fischerd04e9b82006-06-01 14:36:14 +0000120 buf_data = (char *)xmalloc(log_len);
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +0000121
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);
127 }
128 i = buf->tail;
129
130#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;
136 }
137#endif
138 // release the lock on the log chain
139 sem_up(log_semid);
140
Eric Andersend4a5e252003-12-19 11:32:14 +0000141#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +0000142 for (j=0; j < log_len; j+=strlen(buf_data+j)+1) {
143 printf("%s", buf_data+j);
144 if (follow)
145 fflush(stdout);
146 }
147 free(buf_data);
148#endif
Rob Landley10fb2b72005-12-12 07:04:59 +0000149 fflush(stdout);
Glenn L McGrathf7dd10f2003-09-26 01:03:16 +0000150 } while (follow);
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +0000151
152output_end:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000153 if (log_shmid != -1)
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +0000154 shmdt(buf);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000155
156 return EXIT_SUCCESS;
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +0000157}
158
159static void interrupted(int sig){
160 signal(SIGINT, SIG_IGN);
161 longjmp(jmp_env, 1);
162}
163
164static void error_exit(const char *str){
Bernhard Reutner-Fischerd04e9b82006-06-01 14:36:14 +0000165 bb_perror_msg(str);
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +0000166 //release all acquired resources
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000167 if (log_shmid != -1)
Mark Whitleyb0c2b7d2001-03-15 19:05:59 +0000168 shmdt(buf);
169
170 exit(1);
171}