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