1 /*
2 Anacron - run commands periodically
3 Copyright (C) 1998 Itai Tzur <itzur@actcom.co.il>
4 Copyright (C) 1999 Sean 'Shaleh' Perry <shaleh@debian.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 The GNU General Public License can also be found in the file
21 `COPYING' that comes with the Anacron source distribution.
22 */
23
24
25 /* Error logging
26 *
27 * We have two levels of logging (plus debugging if DEBUG is defined):
28 * "explain" level for informational messages, and "complain" level for errors.
29 *
30 * We log everything to syslog, see the top of global.h for relevant
31 * definitions.
32 *
33 * Stderr gets "complain" messages when we're in the foreground,
34 * and "explain" messages when we're in the foreground, and not "quiet".
35 */
36
37 #include <unistd.h>
38 #include <syslog.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <stdarg.h>
42 #include <errno.h>
43 #include <signal.h>
44 #include <sys/types.h>
45 #include <string.h>
46 #include "global.h"
47
48 static char truncated[] = " (truncated)";
49 static char msg[MAX_MSG + 1];
50 static int log_open = 0;
51
52 static void
xopenlog()53 xopenlog()
54 {
55 if (!log_open)
56 {
57 openlog(program_name, LOG_PID, SYSLOG_FACILITY);
58 log_open = 1;
59 }
60 }
61
62 void
xcloselog()63 xcloselog()
64 {
65 if (log_open) closelog();
66 log_open = 0;
67 }
68
69 static void
make_msg(const char * fmt,va_list args)70 make_msg(const char *fmt, va_list args)
71 /* Construct the message string from its parts */
72 {
73 int len;
74
75 /* There's some confusion in the documentation about what vsnprintf
76 * returns when the buffer overflows. Hmmm... */
77 len = vsnprintf(msg, sizeof(msg), fmt, args);
78 if (len >= sizeof(msg) - 1)
79 strcpy(msg + sizeof(msg) - sizeof(truncated), truncated);
80 }
81
82 static void
log(int priority,const char * fmt,va_list args)83 log(int priority, const char *fmt, va_list args)
84 /* Log a message, described by "fmt" and "args", with the specified
85 * "priority". */
86 {
87 make_msg(fmt, args);
88 xopenlog();
89 syslog(priority, "%s", msg);
90 if (!in_background)
91 {
92 if (priority == EXPLAIN_LEVEL && !quiet)
93 fprintf(stderr, "%s\n", msg);
94 else if (priority == COMPLAIN_LEVEL)
95 fprintf(stderr, "%s: %s\n", program_name, msg);
96 }
97 }
98
99 static void
log_e(int priority,const char * fmt,va_list args)100 log_e(int priority, const char *fmt, va_list args)
101 /* Same as log(), but also appends an error description corresponding
102 * to "errno". */
103 {
104 int saved_errno;
105
106 saved_errno = errno;
107 make_msg(fmt, args);
108 xopenlog();
109 syslog(priority, "%s: %s", msg, strerror(saved_errno));
110 if (!in_background)
111 {
112 if (priority == EXPLAIN_LEVEL && !quiet)
113 fprintf(stderr, "%s: %s\n", msg, strerror(saved_errno));
114 else if (priority == COMPLAIN_LEVEL)
115 fprintf(stderr, "%s: %s: %s\n",
116 program_name, msg, strerror(saved_errno));
117 }
118 }
119
120 void
explain(const char * fmt,...)121 explain(const char *fmt, ...)
122 /* Log an "explain" level message */
123 {
124 va_list args;
125
126 va_start(args, fmt);
127 log(EXPLAIN_LEVEL, fmt, args);
128 va_end(args);
129 }
130
131 void
explain_e(const char * fmt,...)132 explain_e(const char *fmt, ...)
133 /* Log an "explain" level message, with an error description */
134 {
135 va_list args;
136
137 va_start(args, fmt);
138 log_e(EXPLAIN_LEVEL, fmt, args);
139 va_end(args);
140 }
141
142 void
complain(const char * fmt,...)143 complain(const char *fmt, ...)
144 /* Log a "complain" level message */
145 {
146 va_list args;
147
148 va_start(args, fmt);
149 log(COMPLAIN_LEVEL, fmt, args);
150 va_end(args);
151 }
152
153 void
complain_e(const char * fmt,...)154 complain_e(const char *fmt, ...)
155 /* Log a "complain" level message, with an error description */
156 {
157 va_list args;
158
159 va_start(args, fmt);
160 log_e(COMPLAIN_LEVEL, fmt, args);
161 va_end(args);
162 }
163
164 void
die(const char * fmt,...)165 die(const char *fmt, ...)
166 /* Log a "complain" level message, and exit */
167 {
168 va_list args;
169
170 va_start(args, fmt);
171 log(COMPLAIN_LEVEL, fmt, args);
172 va_end(args);
173 if (getpid() == primary_pid) complain("Aborted");
174
175 exit(FAILURE_EXIT);
176 }
177
178 void
die_e(const char * fmt,...)179 die_e(const char *fmt, ...)
180 /* Log a "complain" level message, with an error description, and exit */
181 {
182 va_list args;
183
184 va_start(args, fmt);
185 log_e(COMPLAIN_LEVEL, fmt, args);
186 va_end(args);
187 if (getpid() == primary_pid) complain("Aborted");
188
189 exit(FAILURE_EXIT);
190 }
191
192 #ifdef DEBUG
193
194 /* These are called through the Debug() and Debug_e() macros, defined
195 * in global.h */
196
197 void
xdebug(const char * fmt,...)198 xdebug(const char *fmt, ...)
199 {
200 va_list args;
201
202 va_start(args, fmt);
203 log(DEBUG_LEVEL, fmt, args);
204 va_end(args);
205 }
206
207 void
xdebug_e(const char * fmt,...)208 xdebug_e(const char *fmt, ...)
209 {
210 va_list args;
211
212 va_start(args, fmt);
213 log_e(DEBUG_LEVEL, fmt, args);
214 va_end(args);
215 }
216
217 #endif /* DEBUG */
218