logread.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. *
  9. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  10. */
  11. #include "busybox.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/ipc.h>
  16. #include <sys/types.h>
  17. #include <sys/sem.h>
  18. #include <sys/shm.h>
  19. #include <signal.h>
  20. #include <setjmp.h>
  21. #include <unistd.h>
  22. static const long KEY_ID = 0x414e4547; /*"GENA"*/
  23. static struct shbuf_ds {
  24. int size; // size of data written
  25. int head; // start of message list
  26. int tail; // end of message list
  27. char data[1]; // data/messages
  28. } *buf = NULL; // shared memory pointer
  29. // Semaphore operation structures
  30. static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
  31. static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn
  32. static int log_shmid = -1; // ipc shared memory id
  33. static int log_semid = -1; // ipc semaphore id
  34. static jmp_buf jmp_env;
  35. static void error_exit(const char *str);
  36. static void interrupted(int sig);
  37. /*
  38. * sem_up - up()'s a semaphore.
  39. */
  40. static void sem_up(int semid)
  41. {
  42. if ( semop(semid, SMrup, 1) == -1 )
  43. error_exit("semop[SMrup]");
  44. }
  45. /*
  46. * sem_down - down()'s a semaphore
  47. */
  48. static void sem_down(int semid)
  49. {
  50. if ( semop(semid, SMrdn, 2) == -1 )
  51. error_exit("semop[SMrdn]");
  52. }
  53. int logread_main(int argc, char **argv)
  54. {
  55. int i;
  56. int follow=0;
  57. if (argc == 2 && argv[1][0]=='-' && argv[1][1]=='f') {
  58. follow = 1;
  59. } else {
  60. /* no options, no getopt */
  61. if (argc > 1)
  62. bb_show_usage();
  63. }
  64. // handle interrupt signal
  65. if (setjmp(jmp_env)) goto output_end;
  66. // attempt to redefine ^C signal
  67. signal(SIGINT, interrupted);
  68. if ( (log_shmid = shmget(KEY_ID, 0, 0)) == -1)
  69. error_exit("Can't find circular buffer");
  70. // Attach shared memory to our char*
  71. if ( (buf = shmat(log_shmid, NULL, SHM_RDONLY)) == NULL)
  72. error_exit("Can't get access to circular buffer from syslogd");
  73. if ( (log_semid = semget(KEY_ID, 0, 0)) == -1)
  74. error_exit("Can't get access to semaphore(s) for circular buffer from syslogd");
  75. // Suppose atomic memory move
  76. i = follow ? buf->tail : buf->head;
  77. do {
  78. #ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
  79. char *buf_data;
  80. int log_len,j;
  81. #endif
  82. sem_down(log_semid);
  83. //printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size);
  84. if (buf->head == buf->tail || i==buf->tail) {
  85. if (follow) {
  86. sem_up(log_semid);
  87. sleep(1); /* TODO: replace me with a sleep_on */
  88. continue;
  89. } else {
  90. printf("<empty syslog>\n");
  91. }
  92. }
  93. // Read Memory
  94. #ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
  95. log_len = buf->tail - i;
  96. if (log_len < 0)
  97. log_len += buf->size;
  98. buf_data = (char *)xmalloc(log_len);
  99. if (buf->tail < i) {
  100. memcpy(buf_data, buf->data+i, buf->size-i);
  101. memcpy(buf_data+buf->size-i, buf->data, buf->tail);
  102. } else {
  103. memcpy(buf_data, buf->data+i, buf->tail-i);
  104. }
  105. i = buf->tail;
  106. #else
  107. while ( i != buf->tail) {
  108. printf("%s", buf->data+i);
  109. i+= strlen(buf->data+i) + 1;
  110. if (i >= buf->size )
  111. i=0;
  112. }
  113. #endif
  114. // release the lock on the log chain
  115. sem_up(log_semid);
  116. #ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
  117. for (j=0; j < log_len; j+=strlen(buf_data+j)+1) {
  118. printf("%s", buf_data+j);
  119. if (follow)
  120. fflush(stdout);
  121. }
  122. free(buf_data);
  123. #endif
  124. fflush(stdout);
  125. } while (follow);
  126. output_end:
  127. if (log_shmid != -1)
  128. shmdt(buf);
  129. return EXIT_SUCCESS;
  130. }
  131. static void interrupted(int sig){
  132. signal(SIGINT, SIG_IGN);
  133. longjmp(jmp_env, 1);
  134. }
  135. static void error_exit(const char *str){
  136. bb_perror_msg(str);
  137. //release all acquired resources
  138. if (log_shmid != -1)
  139. shmdt(buf);
  140. exit(1);
  141. }