home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / syslog.sysv / syslog.c < prev   
Encoding:
C/C++ Source or Header  |  1987-09-15  |  7.5 KB  |  379 lines

  1. #ifdef LIB_SYSLOG
  2. static char SCCS_ID[] = "@(#)@ syslog    1.8 system logger";
  3. #else
  4. static char SCCS_ID[] = "@(#)@ syslog    1.8 syslog.o";
  5. #endif
  6. static char CPYRGHT[] = "@(#)@ (c) Multihouse Group Support";
  7. /*
  8.  * usage: /etc/syslog [ logfilename ]
  9.  *
  10.  *    default logfilename: /tmp/syslog.log
  11.  *
  12.  * use    "kill -1  pid"    to release and re-open the logfile
  13.  *    "kill -15 pid"    to exit the program and remove the message queue
  14.  *
  15.  * Reasons to terminate:
  16.  *
  17.  *  0:    normal (catched a SIGTERM)
  18.  *  1:    could not reopen logfile after SIGHUP
  19.  *  2:    error during message recveive
  20.  *  3:    catched another signal
  21.  *
  22.  * define LIB_SYSLOG to obtain a library of access routines
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <sys/ipc.h>
  28. #include <sys/msg.h>
  29. #include <unistd.h>
  30. #include <signal.h>
  31. #include <errno.h>
  32.  
  33. #define TRUE    1
  34. #define FALSE    0
  35. #define EOS    '\0'
  36. #define SIG_ERR    ((int (*)())-1)
  37.  
  38. static int msgkey = -1;
  39. static int msgid = -1;
  40. static char *msgnam = "/etc/syslog";    /* used for ftok! */
  41.  
  42. #define SYSLOG_MAGIC    0xfeff
  43. #define MSG_SIZE    512
  44.  
  45. static struct {
  46.     long type;            /* must be SYSLOG_MAGIC */
  47.     long tm;            /* timestamp */
  48.     unsigned char class;    /* message class */
  49.     unsigned char length;    /* length of msg.text */
  50.     short pid;            /* pid of sending process */
  51.     short uid;            /* uid of sending process */
  52.     char text[MSG_SIZE];    /* text of the message */
  53.   } msg;
  54.  
  55. #ifndef LIB_SYSLOG
  56.  
  57. static struct {
  58.     long type;            /* must be not SYSLOG_MAGIC */
  59.     char text[MSG_SIZE];
  60.   } oldmsg;
  61.  
  62. static char *lognam = "/tmp/syslog.log";
  63. static FILE *logfile = NULL;
  64.  
  65. #define MAXERRCNT    10    /* max number of conseq. recv errors */
  66.  
  67. static char *msgclass[] = {
  68.     "ALERT",
  69.     "SALERT",
  70.     "EMERG",
  71.     "ERROR",
  72.     "CRIT",
  73.     "WARNING",
  74.     "NOTICE",
  75.     "INFO",
  76.     "DEBUG"
  77. };
  78.  
  79. /* signal catchers */
  80.  
  81. static int hup = FALSE;
  82. static int term = FALSE;
  83. static int timedout = FALSE;
  84. static int delay = 24 * 60 * 60;
  85.  
  86. int timeout ()
  87. {
  88.     timedout = TRUE;
  89.     (void) signal (SIGALRM, timeout);
  90. }
  91.  
  92. int sighup ()
  93. {
  94.     hup = TRUE;
  95.     (void) signal (SIGHUP, sighup);
  96. }
  97.  
  98. int sigterm ()
  99. {
  100.     term = TRUE;
  101.     (void) signal (SIGTERM, sigterm);
  102. }
  103.  
  104. int sigcatch ()
  105. {
  106.     terminate (3);
  107. }
  108.  
  109. terminate (why)
  110. int why;
  111. {
  112.     (void) msgctl (msgid, IPC_RMID, ((struct msqid_ds *) NULL));
  113.     if (logfile != NULL) {
  114.     if (why == 0 && term)
  115.         sprintf (msg.text, "normal termination (caught SIGTERM)");
  116.     else
  117.         sprintf (msg.text, "terminated reason=%d", why);
  118.     putlog (TRUE);
  119.     }
  120.     fclose (logfile);
  121.     exit (why);
  122. }
  123.  
  124. catchit (sig)
  125. int sig;
  126. {
  127.     int (*sg)();
  128.     sg = signal (sig, sigcatch);
  129.     if (sg != SIG_DFL && sg != SIG_ERR)
  130.     signal (sig, sg);
  131. }
  132.  
  133. main (argc, argv)
  134. int argc;
  135. char *argv[];
  136. {
  137.     char *cp;
  138.     int errcnt = 0;
  139.  
  140.     msgkey = ftok (msgnam, 0);
  141.     if (msgkey < 0) {
  142.     perror ("ftok");
  143.     exit (2);
  144.     }
  145.  
  146.     msgid = msgget (msgkey, IPC_CREAT | IPC_EXCL | 0722);
  147.     while (msgid < 0) {
  148.     if (errno = EEXIST) {
  149.         fprintf (stderr, "syslog: warning - queue already exists\n");
  150.         msgid = msgget (msgkey, IPC_CREAT | 0722);
  151.     }
  152.     else {
  153.         perror ("msgget");
  154.         exit (2);
  155.     }
  156.     }
  157.  
  158.     if (argc > 1)
  159.     lognam = *++argv;
  160.  
  161.     /* open logfile with correct protection */
  162.     umask (022);
  163.     logfile = fopen (lognam, "a");
  164.     if (logfile == NULL) {
  165.     perror ("open logfile");
  166.     exit (2);
  167.     }
  168.  
  169.     /* make sure no other logger is active */
  170.     if (lockf (fileno (logfile), F_TEST, 0l) < 0) {
  171.     perror ("syslog: cannot lock logfile");
  172.     exit (2);
  173.     }
  174.  
  175. #ifndef DEBUG
  176.     /* detach */
  177.     if (fork ())
  178.     exit (0);
  179.  
  180.     setpgrp ();            /* forget where we came from */
  181.  
  182.     /* re-claim the logfile (we lost the lock because we are a fork) */
  183.     if (lockf (fileno (logfile), F_TLOCK, 0l) < 0) {
  184.     perror ("syslog: logfile lock failed");
  185.     exit (2);
  186.     }
  187. #endif
  188.  
  189.     /* catch SIGHUP and SIGTERM */
  190.     (void) signal (SIGTERM, sigterm);
  191.     (void) signal (SIGHUP, sighup);
  192.  
  193.     /* ignore SIGINT and SIGQUIT */
  194.     (void) signal (SIGINT, SIG_IGN);
  195.     (void) signal (SIGQUIT, SIG_IGN);
  196.  
  197.     /* set alarm */
  198.     (void) signal (SIGALRM, timeout);
  199.  
  200.     strcpy (msg.text, "started");
  201.     putlog (TRUE);
  202.  
  203.     for (;;) {
  204.     int res = msgrcv (msgid, &msg, MSG_SIZE, 0, 0 & MSG_NOERROR);
  205.     if (res >= 0) {
  206.         if (msg.type != SYSLOG_MAGIC) {
  207.         memcpy (&oldmsg, &msg, sizeof (oldmsg));
  208.         (void) time (&msg.tm);
  209.         msg.class = oldmsg.type;
  210.         msg.length = strlen (oldmsg.text);
  211.         msg.type = SYSLOG_MAGIC;
  212.         msg.pid = msg.uid = -1;
  213.         strcpy (msg.text, oldmsg.text);
  214.         }
  215.         putlog (FALSE);
  216.         errcnt = 0;
  217.     }
  218.     else {
  219.         /* message receive error */
  220.         if (errno == EINTR) {
  221.         /* receive was interrupted */
  222.         if (hup) {
  223.             /* catched SIGHUP => release logfile */
  224.             strcpy (msg.text, "logfile released (caught SIGHUP)");
  225.             putlog (TRUE);
  226.             fclose (logfile);
  227.             logfile = fopen (lognam, "a");
  228.             if (logfile == NULL) {
  229.             perror ("reopen logfile");
  230.             terminate (1);
  231.             }
  232.             strcpy (msg.text, "logfile reopened after SIGHUP");
  233.             putlog (TRUE);
  234.             hup = FALSE;
  235.         }
  236.         if (term) {
  237.             /* catched SIGTERM => exit receive loop */
  238.             break;
  239.         }
  240.         if (timedout) {
  241.             strcpy (msg.text, "timestamp");
  242.             putlog (TRUE);
  243.             timedout = FALSE;
  244.         }
  245.         /* otherwise, retry */
  246.         errcnt = 0;
  247.         continue;
  248.         }
  249.         else {
  250.         /* other message receive error */
  251.         sprintf (msg.text, "msgrcv error %d", errno);
  252.         putlog (TRUE);
  253.         if (errcnt++ > MAXERRCNT)
  254.             terminate (2);
  255.         }
  256.     }
  257.     }
  258.  
  259.     /* come here to exit the program */
  260.     terminate (0);
  261. }
  262.  
  263. putlog (internal)
  264. int internal;
  265. {
  266.     long time();
  267.     char *ctime();
  268.     long now = (internal) ? time (&now) : msg.tm;
  269.     register char *date = ctime (&now);
  270.  
  271.     if (internal) {
  272.     msg.pid = getpid ();
  273.     msg.uid = getuid ();
  274.     msg.length = strlen (msg.text);
  275.     }
  276.  
  277.     fprintf (logfile, "%.2s-%.3s-%.2s %.8s", date+8, date+4, date+22, date+11);
  278.  
  279.     if (msg.pid >= 0)
  280.     fprintf (logfile, "%6d ", msg.pid);
  281.     else
  282.     fprintf (logfile, "       ");
  283.  
  284.     if (msg.uid >= 0)
  285.     fprintf (logfile, "%6d ", msg.uid);
  286.     else
  287.     fprintf (logfile, "       ");
  288.  
  289.     if (internal)
  290.     fprintf (logfile, "SYSLOG  ");
  291.     else
  292.     if (msg.class > 0 && msg.class < 10)
  293.     fprintf (logfile, "%-7s ", msgclass[msg.class-1]);
  294.     else
  295.     fprintf (logfile, "?%-7d", msg.class);
  296.  
  297.     fprintf (logfile, "%.*s", msg.length, msg.text);
  298.  
  299.     /* append newline if needed */
  300.     if (msg.text[msg.length-1] != '\n')
  301.         fprintf (logfile, "\n");
  302.  
  303.     fflush (logfile);
  304.  
  305.     /* set new time out */
  306.     alarm (delay);
  307. }
  308.  
  309. #endif !LIB_SYSLOG
  310.  
  311. #ifdef LIB_SYSLOG
  312.  
  313. #define MAX_LOGNAME    32
  314. #define MAX_BUF    256
  315. static char logname[MAX_LOGNAME] = "";
  316.  
  317. /* chkque - checks message queue existence */
  318.  
  319. static int
  320. chkque ()
  321. {
  322.     if (msgid == -1)
  323.     msgid = msgget (ftok (msgnam, 0), 0, 0);
  324.     return (msgid != -1);
  325. }
  326.  
  327. /* openlog - sets up logname; checks message queue existence */
  328.  
  329. int
  330. openlog (tag)
  331. char *tag;
  332. {
  333.     strncpy (logname, tag, MAX_LOGNAME);
  334.     logname[MAX_LOGNAME-1] = EOS;
  335.     return (chkque () ? 0 : -1);
  336. }
  337.  
  338. /* syslog - writes message to system logger */
  339.  
  340. int
  341. syslog (class, fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9)
  342. int class;
  343. char *fmt;
  344. {
  345.     if (logname[0])
  346.     sprintf (msg.text, "%s: ", logname);
  347.     sprintf (msg.text+strlen(msg.text),
  348.         fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9);
  349.     if (!chkque ())
  350.     return (-1);
  351.     msg.type = SYSLOG_MAGIC;
  352.     (void) time (&msg.tm);
  353.     msg.class = class;
  354.     msg.pid = getpid ();
  355.     msg.uid = getuid ();
  356.     msg.length = strlen (msg.text);
  357.     return (msgsnd (msgid, &msg, sizeof (msg) - MSG_SIZE + msg.length + 1, 0));
  358. }
  359.  
  360. /* closelog - close message queue, resets logname */
  361.  
  362. void
  363. closelog ()
  364. {
  365.     msgid = -1;
  366.     logname[0] = EOS;
  367. }
  368.  
  369. #ifdef TEST
  370.  
  371. main () {
  372.     openlog ("test");
  373.     syslog (55, "test message %d", 4);
  374. }
  375.  
  376. #endif TEST
  377.  
  378. #endif LIB_SYSLOG
  379.