b06d12eb23edc62f2dc34c2599f7c4007f7a9bcb
[nfs-utils.git] / support / nfs / xlog.c
1 /*
2  * support/nfs/xlog.c
3  *
4  * This module handles the logging of requests.
5  *
6  * TODO:        Merge the two "XXX_log() calls.
7  *
8  * Authors:     Donald J. Becker, <becker@super.org>
9  *              Rick Sladkey, <jrs@world.std.com>
10  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
11  *              Olaf Kirch, <okir@monad.swb.de>
12  *
13  *              This software maybe be used for any purpose provided
14  *              the above copyright notice is retained.  It is supplied
15  *              as is, with no warranty expressed or implied.
16  */
17
18 #include "config.h"
19
20 #include <unistd.h>
21 #include <signal.h>
22 #include <time.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <syslog.h>
28 #include "nfslib.h"
29
30 #undef  VERBOSE_PRINTF
31
32 static int  foreground = 1;             /* not a daemon initially       */
33 static int  logging = 0;                /* enable/disable DEBUG logs    */
34 static int  logmask = 0;                /* What will be logged          */
35 static char log_name[256];              /* name of this program         */
36 static int  log_pid = -1;               /* PID of this program          */
37 static FILE *log_fp = (FILE *)NULL;     /* fp for the log file          */
38
39 static void     xlog_toggle(int sig);
40 static struct xlog_debugfac     debugnames[] = {
41         { "general",    D_GENERAL, },
42         { "call",       D_CALL, },
43         { "auth",       D_AUTH, },
44         { "parse",      D_PARSE, },
45         { "all",        D_ALL, },
46         { NULL,         0, },
47 };
48
49 void
50 xlog_open(char *progname)
51 {
52         openlog(progname, LOG_PID, LOG_DAEMON);
53         if (foreground) {
54                 log_fp = stderr;
55                 if (log_fp != NULL)
56                         setbuf(log_fp, NULL);
57         }
58
59         strncpy(log_name, progname, sizeof (log_name) - 1);
60         log_name [sizeof (log_name) - 1] = '\0';
61         log_pid = getpid();
62
63         signal(SIGUSR1, xlog_toggle);
64         signal(SIGUSR2, xlog_toggle);
65 }
66
67 void
68 xlog_background(void)
69 {
70         foreground = 0;
71 }
72
73 static void
74 xlog_toggle(int sig)
75 {
76         unsigned int    tmp, i;
77
78         if (sig == SIGUSR1) {
79                 if ((logmask & D_ALL) && !logging) {
80                         xlog(D_GENERAL, "turned on logging");
81                         logging = 1;
82                         return;
83                 }
84                 tmp = ~logmask;
85                 logmask |= ((logmask & D_ALL) << 1) | D_GENERAL;
86                 for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++)
87                         if (tmp & 1)
88                                 xlog(D_GENERAL,
89                                         "turned on logging level %d", i);
90         } else {
91                 xlog(D_GENERAL, "turned off logging");
92                 logging = 0;
93         }
94         signal(sig, xlog_toggle);
95 }
96
97 void
98 xlog_config(int fac, int on)
99 {
100         if (on)
101                 logmask |= fac;
102         else
103                 logmask &= ~fac;
104         if (on)
105                 logging = 1;
106 }
107
108 void
109 xlog_sconfig(char *kind, int on)
110 {
111         struct xlog_debugfac    *tbl = debugnames;
112
113         while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) 
114                 tbl++;
115         if (!tbl->df_name) {
116                 xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
117                 return;
118         }
119         xlog_config(tbl->df_fac, on);
120 }
121
122 int
123 xlog_enabled(int fac)
124 {
125         return (logging && (fac & logmask));
126 }
127
128
129 /* Write something to the system logfile. */
130 void
131 xlog(int kind, const char *fmt, ...)
132 {
133         char            buff[1024];
134         va_list         args;
135         int             logged = 1, n;
136 #ifdef VERBOSE_PRINTF
137         time_t          now;
138         struct tm       *tm;
139 #endif
140
141         if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
142                 return;
143
144         va_start(args, fmt);
145         vsnprintf(buff, sizeof (buff), fmt, args);
146         va_end(args);
147
148         if ((n = strlen(buff)) > 0 && buff[n-1] == '\n')
149                 buff[--n] = '\0';
150
151         switch (kind) {
152         case L_FATAL:
153                 syslog(LOG_ERR, "%s", buff);
154                 break;
155         case L_ERROR:
156                 syslog(LOG_ERR, "%s", buff);
157                 break;
158         case L_WARNING:
159                 syslog(LOG_WARNING, "%s", buff);
160                 break;
161         case L_NOTICE:
162                 syslog(LOG_NOTICE, "%s", buff);
163                 break;
164         default:
165                 logged = 0;
166                 break;
167         }
168         if (!logged || foreground) {
169                 if (!logged && log_fp == NULL) {
170                         syslog(LOG_DEBUG, "%s", buff);
171                 } else if (log_fp != NULL) {
172 #ifdef VERBOSE_PRINTF
173                         time(&now);
174                         tm = localtime(&now);
175                         fprintf(log_fp, "%s[%d] %02d/%02d/%02d %02d:%02d %s\n",
176                                         log_name, log_pid,
177                                         tm->tm_mon + 1, tm->tm_mday,
178                                         tm->tm_year, tm->tm_hour, tm->tm_min,
179                                         buff);
180 #else
181                         fprintf(log_fp, "%s: %s\n", log_name, buff);
182 #endif
183                 }
184         }
185         if (kind == L_FATAL)
186                 exit(1);
187 }