Remove includes of darkstat.h, add cdefs.h where needed.
[darkstat.git] / err.c
1 /* darkstat 3
2  * copyright (c) 2001-2009 Emil Mikulic.
3  *
4  * err.c: BSD-like err() and warn() functions
5  *
6  * Permission to use, copy, modify, and distribute this file for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include "cdefs.h"
20 #include "conv.h"
21 #include "err.h"
22 #include "opt.h"
23 #include "pidfile.h"
24
25 #include <errno.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <syslog.h>
31 #include <unistd.h>
32 #include <unistd.h>
33
34 static void to_syslog(const char *type, const int want_err,
35           const char *format, va_list va) _printflike_(3, 0);
36
37 static void
38 to_syslog(const char *type, const int want_err,
39           const char *format, va_list va)
40 {
41    char buf[512];
42    size_t pos = 0;
43    int saved_errno = errno;
44
45    if (type != NULL) {
46       strlcpy(buf, type, sizeof(buf));
47       pos = strlen(buf);
48    }
49    vsnprintf(buf+pos, sizeof(buf)-pos, format, va);
50    if (want_err) {
51       strlcat(buf, ": ", sizeof(buf));
52       strlcat(buf, strerror(saved_errno), sizeof(buf));
53    }
54    syslog(LOG_DEBUG, "%s", buf);
55 }
56
57 void
58 err(const int code, const char *format, ...)
59 {
60    va_list va;
61
62    va_start(va, format);
63    if (opt_want_syslog)
64       to_syslog("ERROR: ", 1, format, va);
65    else {
66       fprintf(stderr, "%5d: error: ", (int)getpid());
67       vfprintf(stderr, format, va);
68       fprintf(stderr, ": %s\n", strerror(errno));
69    }
70    va_end(va);
71    pidfile_unlink();
72    exit(code);
73 }
74
75 void
76 errx(const int code, const char *format, ...)
77 {
78    va_list va;
79
80    va_start(va, format);
81    if (opt_want_syslog)
82       to_syslog("ERROR: ", 0, format, va);
83    else {
84       fprintf(stderr, "%5d: error: ", (int)getpid());
85       vfprintf(stderr, format, va);
86       fprintf(stderr, "\n");
87    }
88    va_end(va);
89    pidfile_unlink();
90    exit(code);
91 }
92
93 void
94 warn(const char *format, ...)
95 {
96    va_list va;
97
98    va_start(va, format);
99    if (opt_want_syslog)
100       to_syslog("WARNING: ", 1, format, va);
101    else {
102       fprintf(stderr, "%5d: warning: ", (int)getpid());
103       vfprintf(stderr, format, va);
104       fprintf(stderr, ": %s\n", strerror(errno));
105    }
106    va_end(va);
107 }
108
109 void
110 warnx(const char *format, ...)
111 {
112    va_list va;
113
114    va_start(va, format);
115    if (opt_want_syslog)
116       to_syslog("WARNING: ", 0, format, va);
117    else {
118       fprintf(stderr, "%5d: warning: ", (int)getpid());
119       vfprintf(stderr, format, va);
120       fprintf(stderr, "\n");
121    }
122    va_end(va);
123 }
124
125 /* We interlock verbosef() between processes by using a pipe with a single
126  * byte in it.  This pipe must be initialized before the first fork() in order
127  * to work.  Then, verbosef() will block on a read() until it is able to
128  * retrieve the byte.  After doing its business, it will put a byte back into
129  * the pipe.
130  *
131  * This is completely silly and largely unnecessary.
132  */
133 static int inited = 0;
134 static int lockpipe[2];
135
136 static void unlock(void);
137
138 static void
139 initlock(void)
140 {
141    if (pipe(lockpipe) == -1)
142       err(1, "pipe(lockpipe)");
143    inited = 1;
144    unlock();
145 }
146
147 static void
148 lock(void)
149 {
150    char buf[1];
151
152    if (!inited) initlock();
153    if (read(lockpipe[0], buf, 1) != 1) {
154       fprintf(stderr, "lock failed!\n");
155       pidfile_unlink();
156       exit(1);
157    }
158 }
159
160 static void
161 unlock(void)
162 {
163    char c = 0;
164
165    if (write(lockpipe[1], &c, 1) != 1) {
166       fprintf(stderr, "unlock failed!\n");
167       pidfile_unlink();
168       exit(1);
169    }
170 }
171
172 void
173 verbosef(const char *format, ...)
174 {
175    va_list va;
176
177    if (!opt_want_verbose) return;
178    va_start(va, format);
179    if (opt_want_syslog)
180       to_syslog(NULL, 0, format, va);
181    else {
182       lock();
183       fprintf(stderr, "darkstat (%05d): ", (int)getpid());
184       vfprintf(stderr, format, va);
185       fprintf(stderr, "\n");
186       unlock();
187    }
188    va_end(va);
189 }
190
191 void
192 dverbosef(const char *format _unused_, ...)
193 {
194    /* disabled / do-nothing verbosef */
195 }
196
197 /* vim:set ts=3 sw=3 tw=78 expandtab: */