/* VI: Set Sw = 4 ts = 4 :*/
/*
* Circular buffer syslog implementation for busybox
*
* Copyright (c) 2000 by Gennady Feldman <gfeldman@gena01.com>
*
* Maintainer: Gennady Feldman <gfeldman@gena01.com> As of MAR 12,200 1
*
* Licensed under gplv2 or later, see file license in this source tree.
*/
// # Include "../include/libbb. H"
# Include <sys/IPC. h>
# Include <sys/SEM. h>
# Include <sys/SHM. h>
# Include <sys/SHM. h>
# Include <ctype. h>
# Include <dirent. h>
# Include <errno. h>
# Include <fcntl. h>
# Include <inttypes. h>
# Include <netdb. h>
# Include <setjmp. h>
# Include <signal. h>
# Include <stdint. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <stdarg. h>
# Include <stddef. h>
# Include <string. h>
# Include <sys/poll. h>
# Include <sys/IOCTL. h>
# Include <sys/Mman. h>
# Include <sys/socket. h>
# Include <sys/STAT. h>
# Include <sys/time. h>
# Include <sys/types. h>
# Include <sys/Wait. H>
# Include <termios. h>
# Include <time. h>
# Include <unistd. h>
# Include <sys/Param. h>
# Define debug 0
Char bb_common_bufsiz1 [2, 2048];
/* Our shared key (syslogd. C and logread. C must be in sync )*/
Enum {key_id = 0x414e4547};/* "Gena "*/
Struct shbuf_ds {
Int32_t size; // size of data-1
Int32_t tail; // End of message list
Char data [1]; // messages
};
Static const struct sembuf init_sem [3] = {
{0,-1, ipc_nowait | sem_undo },
{1, 0}, {0, + 1, sem_undo}
};
Struct globals {
Struct sembuf smrup [1]; // {0,-1, ipc_nowait | sem_undo },
Struct sembuf smrdn [2]; // {1, 0}, {0, + 1, sem_undo}
Struct shbuf_ds * shbuf;
} Fix_aliasing;
# Define g (* (struct globals *) & bb_common_bufsiz1)
# Define smrup (G. smrup)
# Define smrdn (G. smrdn)
# Define shbuf (G. shbuf)
# Define init_g () do {\
Memcpy (smrup, init_sem, sizeof (init_sem ));\
} While (0)
Static void error_exit (const char * Str)
{
// Release all acquired resources
Shmdt (shbuf );
// Bb_perror_msg_and_die (STR );
}
/*
* Sem_up-up ()'s a semaphore.
*/
Static void sem_up (INT Semid)
{
If (semop (Semid, smrup, 1) =-1)
Error_exit ("semop [smrup]");
}
Static void interrupted (INT sig)
{
Signal (SIGINT, sig_ign );
Shmdt (shbuf );
Exit (exit_success );
}
Int main (INT argc, char ** argv)
{
Unsigned cur;
Int log_semid;/* IPC semaphore ID */
Int log_shmid;/* IPC shared memory ID */
Char follow = 1; // getopt32 (argv, "F ");
Init_g ();
Log_shmid = shmget (key_id, 0, 0 );
If (log_shmid =-1)
{;}// Bb_perror_msg_and_die ("can't find syslogd buffer ");
/* Attach shared memory to our char **/
Shbuf = shmat (log_shmid, null, shm_rdonly );
If (shbuf = NULL)
{;}// Bb_perror_msg_and_die ("can't access syslogd buffer ");
Log_semid = semget (key_id, 0, 0 );
If (log_semid =-1)
Error_exit ("can't get access to semaphores for syslogd buffer ");
Signal (SIGINT, interrupted );
/* Suppose atomic memory read */
/* Max possible value for tail is shbuf-> size-1 */
Cur = shbuf-> tail;
/* Loop for logread-F, one pass if there was no-f */
Do {
Unsigned shbuf_size;
Unsigned shbuf_tail;
Const char * shbuf_data;
# If enable_feature_logread_reduced_locking
Int I;
Int len_first_part;
Int len_total = len_total;/* for GCC */
Char * Copy = copy;/* for GCC */
# Endif
If (semop (log_semid, smrdn, 2) =-1)
Error_exit ("semop [smrdn]");
/* Copy the info, helps GCC to realize that it doesn't change */
Shbuf_size = shbuf-> size;
Shbuf_tail = shbuf-> tail;
Shbuf_data = shbuf-> data;/* pointer! */
If (Debug)
Printf ("cur: % d Tail: % I size: % I \ n ",
Cur, shbuf_tail, shbuf_size );
If (! Follow ){
/* Advance to oldest complete message */
/* Find NUL */
Cur + = strlen (shbuf_data + cur );
If (cur> = shbuf_size) {/* last byte in buffer? */
Cur = strnlen (shbuf_data, shbuf_tail );
If (cur = shbuf_tail)
Goto unlock;/* No complete messages */
}
/* Advance to first byte of the Message */
Cur ++;
If (cur> = shbuf_size)/* last byte in buffer? */
Cur = 0;
} Else {/* logread-f */
If (cur = shbuf_tail ){
Sem_up (log_semid );
Fflush (null );
Sleep (1);/* todo: replace me with a sleep_on */
Continue;
}
}
/* Read from cur to tail */
# If enable_feature_logread_reduced_locking
Len_first_part = len_total = shbuf_tail-cur;
If (len_total <0 ){
/* Message wraps :*/
/* [Second part... first part] */
/* ^ Data ^ tail ^ cur ^ size */
Len_total + = shbuf_size;
}
Copy = xmalloc (len_total + 1 );
If (len_first_part <0 ){
/* Message wraps (see above )*/
Len_first_part = shbuf_size-cur;
Memcpy (Copy + len_first_part, shbuf_data, shbuf_tail );
}
Memcpy (copy, shbuf_data + cur, len_first_part );
Copy [len_total] = '\ 0 ';
Cur = shbuf_tail;
# Else
While (cur! = Shbuf_tail ){
Fputs (shbuf_data + cur, stdout );
Cur + = strlen (shbuf_data + cur) + 1;
If (cur> = shbuf_size)
Cur = 0;
}
# Endif
Unlock:
/* Release the lock on the log chain */
Sem_up (log_semid );
# If enable_feature_logread_reduced_locking
For (I = 0; I <len_total; I + = strlen (Copy + I) + 1 ){
Fputs (Copy + I, stdout );
}
Free (copy );
# Endif
} While (follow );
Shmdt (shbuf );
// Fflush_stdout_and_exit (exit_success );
}