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