]> git.decadent.org.uk Git - nfs-utils.git/blob - support/nfs/xlog.c
"rpc.nfsd XX" should not fail if ports are already open.
[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 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include <unistd.h>
23 #include <signal.h>
24 #include <time.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <syslog.h>
30 #include "nfslib.h"
31
32 #undef  VERBOSE_PRINTF
33
34 static int  log_stderr = 1;
35 static int  log_syslog = 1;
36 static int  logging = 0;                /* enable/disable DEBUG logs    */
37 static int  logmask = 0;                /* What will be logged          */
38 static char log_name[256];              /* name of this program         */
39 static int  log_pid = -1;               /* PID of this program          */
40
41 static void     xlog_toggle(int sig);
42 static struct xlog_debugfac     debugnames[] = {
43         { "general",    D_GENERAL, },
44         { "call",       D_CALL, },
45         { "auth",       D_AUTH, },
46         { "parse",      D_PARSE, },
47         { "all",        D_ALL, },
48         { NULL,         0, },
49 };
50
51 void
52 xlog_open(char *progname)
53 {
54         openlog(progname, LOG_PID, LOG_DAEMON);
55
56         strncpy(log_name, progname, sizeof (log_name) - 1);
57         log_name [sizeof (log_name) - 1] = '\0';
58         log_pid = getpid();
59
60         signal(SIGUSR1, xlog_toggle);
61         signal(SIGUSR2, xlog_toggle);
62 }
63
64 void
65 xlog_stderr(int on)
66 {
67         log_stderr = on;
68 }
69
70 void
71 xlog_syslog(int on)
72 {
73         log_syslog = on;
74 }
75
76 static void
77 xlog_toggle(int sig)
78 {
79         unsigned int    tmp, i;
80
81         if (sig == SIGUSR1) {
82                 if ((logmask & D_ALL) && !logging) {
83                         xlog(D_GENERAL, "turned on logging");
84                         logging = 1;
85                         return;
86                 }
87                 tmp = ~logmask;
88                 logmask |= ((logmask & D_ALL) << 1) | D_GENERAL;
89                 for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++)
90                         if (tmp & 1)
91                                 xlog(D_GENERAL,
92                                         "turned on logging level %d", i);
93         } else {
94                 xlog(D_GENERAL, "turned off logging");
95                 logging = 0;
96         }
97         signal(sig, xlog_toggle);
98 }
99
100 void
101 xlog_config(int fac, int on)
102 {
103         if (on)
104                 logmask |= fac;
105         else
106                 logmask &= ~fac;
107         if (on)
108                 logging = 1;
109 }
110
111 void
112 xlog_sconfig(char *kind, int on)
113 {
114         struct xlog_debugfac    *tbl = debugnames;
115
116         while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) 
117                 tbl++;
118         if (!tbl->df_name) {
119                 xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
120                 return;
121         }
122         xlog_config(tbl->df_fac, on);
123 }
124
125 int
126 xlog_enabled(int fac)
127 {
128         return (logging && (fac & logmask));
129 }
130
131
132 /* Write something to the system logfile and/or stderr */
133 void
134 xlog(int kind, const char *fmt, ...)
135 {
136         char            buff[1024];
137         va_list         args;
138         int             n;
139
140         if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
141                 return;
142
143         va_start(args, fmt);
144         vsnprintf(buff, sizeof (buff), fmt, args);
145         va_end(args);
146
147         if ((n = strlen(buff)) > 0 && buff[n-1] == '\n')
148                 buff[--n] = '\0';
149
150         if (log_syslog) {
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                         if (!log_stderr)
166                                 syslog(LOG_INFO, "%s", buff);
167                         break;
168                 }
169         }
170
171         if (log_stderr) {
172 #ifdef VERBOSE_PRINTF
173                 time_t          now;
174                 struct tm       *tm;
175
176                 time(&now);
177                 tm = localtime(&now);
178                 fprintf(stderr, "%s[%d] %04d-%02d-%02d %02d:%02d:%02d %s\n",
179                                 log_name, log_pid,
180                                 tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday,
181                                 tm->tm_hour, tm->tm_min, tm->tm_sec,
182                                 buff);
183 #else
184                 fprintf(stderr, "%s: %s\n", log_name, buff);
185 #endif
186         }
187
188         if (kind == L_FATAL)
189                 exit(1);
190 }