Correct incorrect type-punning fixes
[openafs.git] / src / util / serverLog.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*  serverLog.c     - Server logging                                      */
11 /*                                                                        */
12 /*  Information Technology Center                                         */
13 /*  Date: 05/21/97                                                        */
14 /*                                                                        */
15 /*  Function    - These routiens implement logging from the servers       */
16 /*                                                                        */
17 /* ********************************************************************** */
18
19 #include <afsconfig.h>
20 #include <afs/param.h>
21
22
23 #include <stdio.h>
24 #ifdef AFS_NT40_ENV
25 #include <io.h>
26 #include <time.h>
27 #else
28 #ifdef AFS_AIX_ENV
29 #include <time.h>
30 #endif
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <syslog.h>
34 #endif
35 #include <afs/procmgmt.h>       /* signal(), kill(), wait(), etc. */
36 #include <fcntl.h>
37 #include <afs/stds.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include "afsutil.h"
41 #include "fileutil.h"
42 #include <lwp.h>
43 #ifdef HAVE_STDINT_H
44 # include <stdint.h>
45 #endif
46 #if defined(AFS_PTHREAD_ENV)
47 #include <assert.h>
48 #include <pthread.h>
49 static pthread_mutex_t serverLogMutex;
50 #define LOCK_SERVERLOG() assert(pthread_mutex_lock(&serverLogMutex)==0)
51 #define UNLOCK_SERVERLOG() assert(pthread_mutex_unlock(&serverLogMutex)==0)
52
53 #ifdef AFS_NT40_ENV
54 #define NULLDEV "NUL"
55 #else
56 #define NULLDEV "/dev/null"
57 #endif
58
59 #else /* AFS_PTHREAD_ENV */
60 #define LOCK_SERVERLOG()
61 #define UNLOCK_SERVERLOG()
62 #endif /* AFS_PTHREAD_ENV */
63
64 #ifdef AFS_NT40_ENV
65 #define F_OK 0
66 #define O_NONBLOCK 0
67 #endif
68
69 static int
70 dummyThreadNum(void)
71 {
72     return -1;
73 }
74 static int (*threadNumProgram) (void) = dummyThreadNum;
75
76 static int serverLogFD = -1;
77
78 #ifndef AFS_NT40_ENV
79 int serverLogSyslog = 0;
80 int serverLogSyslogFacility = LOG_DAEMON;
81 char *serverLogSyslogTag = 0;
82 #endif
83
84 #include <stdarg.h>
85 int LogLevel;
86 int mrafsStyleLogs = 0;
87 static int threadIdLogs = 0;
88 int printLocks = 0;
89 static char ourName[MAXPATHLEN];
90
91 void
92 SetLogThreadNumProgram(int (*func) (void) )
93 {
94     threadNumProgram = func;
95 }
96
97 void
98 WriteLogBuffer(char *buf, afs_uint32 len)
99 {
100     LOCK_SERVERLOG();
101     if (serverLogFD > 0)
102         (void)write(serverLogFD, buf, len);
103     UNLOCK_SERVERLOG();
104 }
105
106 int
107 LogThreadNum(void) 
108 {
109   return (*threadNumProgram) ();
110 }
111
112 void
113 vFSLog(const char *format, va_list args)
114 {
115     time_t currenttime;
116     char *timeStamp;
117     char tbuffer[1024];
118     char *info;
119     size_t len;
120     int num;
121
122     currenttime = time(0);
123     timeStamp = afs_ctime(&currenttime, tbuffer, sizeof(tbuffer));
124     timeStamp[24] = ' ';        /* ts[24] is the newline, 25 is the null */
125     info = &timeStamp[25];
126
127     if (mrafsStyleLogs || threadIdLogs) {
128         num = (*threadNumProgram) ();
129         if (num > -1) {
130         (void)afs_snprintf(info, (sizeof tbuffer) - strlen(tbuffer), "[%d] ",
131                            num);
132         info += strlen(info);
133     }
134     }
135
136     (void)afs_vsnprintf(info, (sizeof tbuffer) - strlen(tbuffer), format,
137                         args);
138
139     len = strlen(tbuffer);
140     LOCK_SERVERLOG();
141 #ifndef AFS_NT40_ENV
142     if (serverLogSyslog) {
143         syslog(LOG_INFO, "%s", info);
144     } else
145 #endif
146     if (serverLogFD > 0)
147         (void)write(serverLogFD, tbuffer, len);
148     UNLOCK_SERVERLOG();
149
150 #if !defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
151     if (!serverLogSyslog) {
152         fflush(stdout);
153         fflush(stderr);         /* in case they're sharing the same FD */
154     }
155 #endif
156 }                               /*vFSLog */
157
158 /* VARARGS1 */
159 /*@printflike@*/
160 void
161 FSLog(const char *format, ...)
162 {
163     va_list args;
164
165     va_start(args, format);
166     vFSLog(format, args);
167     va_end(args);
168 }                               /*FSLog */
169
170 static void*
171 DebugOn(void *param)
172 {
173     int loglevel = (intptr_t)param;
174     if (loglevel == 0) {
175         ViceLog(0, ("Reset Debug levels to 0\n"));
176     } else {
177         ViceLog(0, ("Set Debug On level = %d\n", loglevel));
178     }
179     return 0;
180 }                               /*DebugOn */
181
182
183
184 void
185 SetDebug_Signal(int signo)
186 {
187     if (LogLevel > 0) {
188         LogLevel *= 5;
189
190 #if defined(AFS_PTHREAD_ENV)
191         if (LogLevel > 1 && threadNumProgram != NULL && 
192             threadIdLogs == 0) {
193             threadIdLogs = 1;
194         }
195 #endif
196     } else {
197         LogLevel = 1;
198
199 #if defined(AFS_PTHREAD_ENV)
200         if (threadIdLogs == 1)
201             threadIdLogs = 0;
202 #endif
203     }
204     printLocks = 2;
205 #if defined(AFS_PTHREAD_ENV)
206     DebugOn((void *)(intptr_t)LogLevel);
207 #else /* AFS_PTHREAD_ENV */
208     IOMGR_SoftSig(DebugOn, (void *)(intptr_t)LogLevel);
209 #endif /* AFS_PTHREAD_ENV */
210
211     (void)signal(signo, SetDebug_Signal);       /* on some platforms, this
212                                                  * signal handler needs to
213                                                  * be set again */
214 }                               /*SetDebug_Signal */
215
216 void
217 ResetDebug_Signal(int signo)
218 {
219     LogLevel = 0;
220
221     if (printLocks > 0)
222         --printLocks;
223 #if defined(AFS_PTHREAD_ENV)
224     DebugOn((void *)(intptr_t)LogLevel);
225 #else /* AFS_PTHREAD_ENV */
226     IOMGR_SoftSig(DebugOn, (void *)(intptr_t)LogLevel);
227 #endif /* AFS_PTHREAD_ENV */
228
229     (void)signal(signo, ResetDebug_Signal);     /* on some platforms,
230                                                  * this signal handler
231                                                  * needs to be set
232                                                  * again */
233 #if defined(AFS_PTHREAD_ENV)
234     if (threadIdLogs == 1)
235         threadIdLogs = 0;
236 #endif
237     if (mrafsStyleLogs)
238         OpenLog((char *)&ourName);
239 }                               /*ResetDebug_Signal */
240
241
242 void
243 SetupLogSignals(void)
244 {
245     (void)signal(SIGHUP, ResetDebug_Signal);
246     /* Note that we cannot use SIGUSR1 -- Linux stole it for pthreads! */
247     (void)signal(SIGTSTP, SetDebug_Signal);
248 #ifndef AFS_NT40_ENV
249     (void)signal(SIGPIPE, SIG_IGN);
250 #endif
251 }
252
253 int
254 OpenLog(const char *fileName)
255 {
256     /*
257      * This function should allow various libraries that inconsistently
258      * use stdout/stderr to all go to the same place
259      */
260     int tempfd, isfifo = 0;
261     char oldName[MAXPATHLEN];
262     struct timeval Start;
263     struct tm *TimeFields;
264     char FileName[MAXPATHLEN];
265
266 #ifndef AFS_NT40_ENV
267     struct stat statbuf;
268
269     if (serverLogSyslog) {
270         openlog(serverLogSyslogTag, LOG_PID, serverLogSyslogFacility);
271         return (0);
272     }
273
274     /* Support named pipes as logs by not rotating them */
275     if ((lstat(fileName, &statbuf) == 0)  && (S_ISFIFO(statbuf.st_mode))) {
276         isfifo = 1;
277     }
278 #endif
279
280     if (mrafsStyleLogs) {
281         time_t t;
282         FT_GetTimeOfDay(&Start, 0);
283         t = Start.tv_sec;       
284         TimeFields = localtime(&t);
285         if (fileName) {
286             if (strncmp(fileName, (char *)&ourName, strlen(fileName)))
287                 strcpy((char *)&ourName, (char *)fileName);
288         }
289         afs_snprintf(FileName, MAXPATHLEN, "%s.%d%02d%02d%02d%02d%02d",
290                      ourName, TimeFields->tm_year + 1900,
291                      TimeFields->tm_mon + 1, TimeFields->tm_mday,
292                      TimeFields->tm_hour, TimeFields->tm_min,
293                      TimeFields->tm_sec);
294         if (!isfifo)
295             renamefile(fileName, FileName);     /* don't check error code */
296         tempfd = open(fileName, O_WRONLY | O_TRUNC | O_CREAT | (isfifo?O_NONBLOCK:0), 0666);
297     } else {
298         strcpy(oldName, fileName);
299         strcat(oldName, ".old");
300
301         /* don't check error */
302         if (!isfifo)
303             renamefile(fileName, oldName);
304         tempfd = open(fileName, O_WRONLY | O_TRUNC | O_CREAT | (isfifo?O_NONBLOCK:0), 0666);
305     }
306
307     if (tempfd < 0) {
308         printf("Unable to open log file %s\n", fileName);
309         return -1;
310     }
311     /* redirect stdout and stderr so random printf's don't write to data */
312     (void)freopen(fileName, "a", stdout);
313     (void)freopen(fileName, "a", stderr);
314 #ifdef HAVE_SETVBUF
315     setvbuf(stderr, NULL, _IONBF, 0);
316 #else
317     setbuf(stderr, NULL);
318 #endif
319
320 #if defined(AFS_PTHREAD_ENV)
321     assert(pthread_mutex_init(&serverLogMutex, NULL) == 0);
322 #endif /* AFS_PTHREAD_ENV */
323
324     serverLogFD = tempfd;
325
326     return 0;
327 }                               /*OpenLog */
328
329 int
330 ReOpenLog(const char *fileName)
331 {
332     int isfifo = 0;
333 #if !defined(AFS_NT40_ENV)
334     struct stat statbuf;
335 #endif
336
337     if (access(fileName, F_OK) == 0)
338         return 0;               /* exists, no need to reopen. */
339
340 #if !defined(AFS_NT40_ENV)
341     if (serverLogSyslog) {
342         return 0;
343     }
344
345     /* Support named pipes as logs by not rotating them */
346     if ((lstat(fileName, &statbuf) == 0)  && (S_ISFIFO(statbuf.st_mode))) {
347         isfifo = 1;
348     }
349 #endif
350
351     LOCK_SERVERLOG();
352     if (serverLogFD > 0)
353         close(serverLogFD);
354     serverLogFD = open(fileName, O_WRONLY | O_APPEND | O_CREAT | (isfifo?O_NONBLOCK:0), 0666);
355     if (serverLogFD > 0) {
356         (void)freopen(fileName, "a", stdout);
357         (void)freopen(fileName, "a", stderr);
358 #ifdef HAVE_SETVBUF
359 #ifdef SETVBUF_REVERSED
360         setvbuf(stderr, _IONBF, NULL, 0);
361 #else
362         setvbuf(stderr, NULL, _IONBF, 0);
363 #endif
364 #else
365         setbuf(stderr, NULL);
366 #endif
367
368     }
369     UNLOCK_SERVERLOG();
370     return serverLogFD < 0 ? -1 : 0;
371 }