]> mj.ucw.cz Git - libucw.git/blob - lib/log-file.c
Replaced the long-lived "close(0) if logging to file" hack by closing
[libucw.git] / lib / log-file.c
1 /*
2  *      UCW Library -- Keeping of Log Files
3  *
4  *      (c) 1997--2005 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <time.h>
17
18 static char *log_name_patt;
19 static int log_params;
20 static int log_filename_size;
21 volatile int log_switch_nest;
22
23 static int
24 do_log_switch(struct tm *tm)
25 {
26   int fd, l;
27   char name[log_filename_size];
28   int switched = 0;
29
30   if (!log_name_patt ||
31       log_filename[0] && !log_params)
32     return 0;
33   log_switch_nest++;
34   l = strftime(name, log_filename_size, log_name_patt, tm);
35   if (l < 0 || l >= log_filename_size)
36     die("Error formatting log file name: %m");
37   if (strcmp(name, log_filename))
38     {
39       strcpy(log_filename, name);
40       fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666);
41       if (fd < 0)
42         die("Unable to open log file %s: %m", name);
43       close(2);
44       dup(fd);
45       close(fd);
46       close(1);
47       dup(2);
48       switched = 1;
49     }
50   log_switch_nest--;
51   return switched;
52 }
53
54 int
55 log_switch(void)
56 {
57   time_t tim = time(NULL);
58   return do_log_switch(localtime(&tim));
59 }
60
61 static void
62 internal_log_switch(struct tm *tm)
63 {
64   if (!log_switch_nest)
65     do_log_switch(tm);
66 }
67
68 void
69 log_file(byte *name)
70 {
71   if (name)
72     {
73       if (log_name_patt)
74         xfree(log_name_patt);
75       if (log_filename)
76         {
77           xfree(log_filename);
78           log_filename = NULL;
79         }
80       log_name_patt = xstrdup(name);
81       log_params = !!strchr(name, '%');
82       log_filename_size = strlen(name) + 64;    /* 63 is an upper bound on expansion of % escapes */
83       log_filename = xmalloc(log_filename_size);
84       log_filename[0] = 0;
85       log_switch();
86       log_switch_hook = internal_log_switch;
87     }
88 }
89
90 void
91 log_fork(void)
92 {
93   log_pid = getpid();
94 }
95
96 #ifdef TEST
97
98 int main(int argc, char **argv)
99 {
100   log_init(argv[0]);
101   log_file("/proc/self/fd/1");
102   for (int i=1; i<argc; i++)
103     log(L_INFO, argv[i]);
104   return 0;
105 }
106
107 #endif