Reset timezone information on reconfigure
[multipath-tools/.git] / libmultipath / log.c
1 /*
2  * Copyright (c) 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Jun'ichi Nomura, NEC
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include <syslog.h>
11
12 #include "memory.h"
13 #include "log.h"
14
15 #define ALIGN(len, s) (((len)+(s)-1)/(s)*(s))
16
17 #if LOGDBG
18 static void dump_logarea (void)
19 {
20         struct logmsg * msg;
21
22         logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n",
23                 la->start, la->end);
24         logdbg(stderr, "|addr     |next     |prio|msg\n");
25
26         for (msg = (struct logmsg *)la->head; (void *)msg != la->tail;
27              msg = msg->next)
28                 logdbg(stderr, "|%p |%p |%i   |%s\n", (void *)msg, msg->next,
29                                 msg->prio, (char *)&msg->str);
30
31         logdbg(stderr, "|%p |%p |%i   |%s\n", (void *)msg, msg->next,
32                         msg->prio, (char *)&msg->str);
33
34         logdbg(stderr, "\n\n");
35 }
36 #endif
37
38 static int logarea_init (int size)
39 {
40         logdbg(stderr,"enter logarea_init\n");
41         la = (struct logarea *)MALLOC(sizeof(struct logarea));
42
43         if (!la)
44                 return 1;
45
46         if (size < MAX_MSG_SIZE)
47                 size = DEFAULT_AREA_SIZE;
48
49         la->start = MALLOC(size);
50         if (!la->start) {
51                 FREE(la);
52                 return 1;
53         }
54         memset(la->start, 0, size);
55
56         la->empty = 1;
57         la->end = la->start + size;
58         la->head = la->start;
59         la->tail = la->start;
60
61         la->buff = MALLOC(MAX_MSG_SIZE + sizeof(struct logmsg));
62
63         if (!la->buff) {
64                 FREE(la->start);
65                 FREE(la);
66                 return 1;
67         }
68         return 0;
69
70 }
71
72 int log_init(char *program_name, int size)
73 {
74         logdbg(stderr,"enter log_init\n");
75         openlog(program_name, 0, LOG_DAEMON);
76
77         if (logarea_init(size))
78                 return 1;
79
80         return 0;
81 }
82
83 void free_logarea (void)
84 {
85         FREE(la->start);
86         FREE(la->buff);
87         FREE(la);
88         return;
89 }
90
91 void log_close (void)
92 {
93         free_logarea();
94         closelog();
95
96         return;
97 }
98
99 void log_reset (char *program_name)
100 {
101         closelog();
102         tzset();
103         openlog(program_name, 0, LOG_DAEMON);
104 }
105
106 int log_enqueue (int prio, const char * fmt, va_list ap)
107 {
108         int len, fwd;
109         char buff[MAX_MSG_SIZE];
110         struct logmsg * msg;
111         struct logmsg * lastmsg;
112
113         lastmsg = (struct logmsg *)la->tail;
114
115         if (!la->empty) {
116                 fwd = sizeof(struct logmsg) +
117                       strlen((char *)&lastmsg->str) * sizeof(char) + 1;
118                 la->tail += ALIGN(fwd, sizeof(void *));
119         }
120         vsnprintf(buff, MAX_MSG_SIZE, fmt, ap);
121         len = ALIGN(sizeof(struct logmsg) + strlen(buff) * sizeof(char) + 1,
122                     sizeof(void *));
123
124         /* not enough space on tail : rewind */
125         if (la->head <= la->tail && len > (la->end - la->tail)) {
126                 logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail);
127                 if (la->head == la->start ) {
128                         logdbg(stderr, "enqueue: can not rewind tail, drop msg\n");
129                         la->tail = lastmsg;
130                         return 1;  /* can't reuse */
131                 }
132                 la->tail = la->start;
133
134                 if (la->empty)
135                         la->head = la->start;
136         }
137
138         /* not enough space on head : drop msg */
139         if (la->head > la->tail && len >= (la->head - la->tail)) {
140                 logdbg(stderr, "enqueue: log area overrun, drop msg\n");
141
142                 if (!la->empty)
143                         la->tail = lastmsg;
144
145                 return 1;
146         }
147
148         /* ok, we can stage the msg in the area */
149         la->empty = 0;
150         msg = (struct logmsg *)la->tail;
151         msg->prio = prio;
152         memcpy((void *)&msg->str, buff, strlen(buff) + 1);
153         lastmsg->next = la->tail;
154         msg->next = la->head;
155
156         logdbg(stderr, "enqueue: %p, %p, %i, %s\n", (void *)msg, msg->next,
157                 msg->prio, (char *)&msg->str);
158
159 #if LOGDBG
160         dump_logarea();
161 #endif
162         return 0;
163 }
164
165 int log_dequeue (void * buff)
166 {
167         struct logmsg * src = (struct logmsg *)la->head;
168         struct logmsg * dst = (struct logmsg *)buff;
169         struct logmsg * lst = (struct logmsg *)la->tail;
170
171         if (la->empty)
172                 return 1;
173
174         int len = strlen((char *)&src->str) * sizeof(char) +
175                   sizeof(struct logmsg) + 1;
176
177         dst->prio = src->prio;
178         memcpy(dst, src,  len);
179
180         if (la->tail == la->head)
181                 la->empty = 1; /* we purge the last logmsg */
182         else {
183                 la->head = src->next;
184                 lst->next = la->head;
185         }
186         logdbg(stderr, "dequeue: %p, %p, %i, %s\n",
187                 (void *)src, src->next, src->prio, (char *)&src->str);
188
189         memset((void *)src, 0,  len);
190
191         return 0;
192 }
193
194 /*
195  * this one can block under memory pressure
196  */
197 void log_syslog (void * buff)
198 {
199         struct logmsg * msg = (struct logmsg *)buff;
200
201         syslog(msg->prio, "%s", (char *)&msg->str);
202 }