make depend
[darkstat] / err.c
1 /* darkstat 3
2 * copyright (c) 2001-2011 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 "err.h"
21 #include "opt.h"
22 #include "pidfile.h"
23 #include "bsd.h" /* for strlcpy */
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
33 static void to_syslog(const char *type, const int want_err,
34 const char *format, va_list va) _printflike_(3, 0);
35
36 static void
37 to_syslog(const char *type, const int want_err,
38 const char *format, va_list va)
39 {
40 char buf[512];
41 size_t pos = 0;
42 int saved_errno = errno;
43
44 if (type != NULL) {
45 strlcpy(buf, type, sizeof(buf));
46 pos = strlen(buf);
47 }
48 vsnprintf(buf+pos, sizeof(buf)-pos, format, va);
49 if (want_err) {
50 strlcat(buf, ": ", sizeof(buf));
51 strlcat(buf, strerror(saved_errno), sizeof(buf));
52 }
53 syslog(LOG_DEBUG, "%s", buf);
54 }
55
56 void
57 err(const int code, const char *format, ...)
58 {
59 va_list va;
60
61 va_start(va, format);
62 if (opt_want_syslog)
63 to_syslog("ERROR: ", 1, format, va);
64 else {
65 fprintf(stderr, "%5d: error: ", (int)getpid());
66 vfprintf(stderr, format, va);
67 fprintf(stderr, ": %s\n", strerror(errno));
68 }
69 va_end(va);
70 pidfile_unlink();
71 exit(code);
72 }
73
74 void
75 errx(const int code, const char *format, ...)
76 {
77 va_list va;
78
79 va_start(va, format);
80 if (opt_want_syslog)
81 to_syslog("ERROR: ", 0, format, va);
82 else {
83 fprintf(stderr, "%5d: error: ", (int)getpid());
84 vfprintf(stderr, format, va);
85 fprintf(stderr, "\n");
86 }
87 va_end(va);
88 pidfile_unlink();
89 exit(code);
90 }
91
92 void
93 warn(const char *format, ...)
94 {
95 va_list va;
96
97 va_start(va, format);
98 if (opt_want_syslog)
99 to_syslog("WARNING: ", 1, format, va);
100 else {
101 fprintf(stderr, "%5d: warning: ", (int)getpid());
102 vfprintf(stderr, format, va);
103 fprintf(stderr, ": %s\n", strerror(errno));
104 }
105 va_end(va);
106 }
107
108 void
109 warnx(const char *format, ...)
110 {
111 va_list va;
112
113 va_start(va, format);
114 if (opt_want_syslog)
115 to_syslog("WARNING: ", 0, format, va);
116 else {
117 fprintf(stderr, "%5d: warning: ", (int)getpid());
118 vfprintf(stderr, format, va);
119 fprintf(stderr, "\n");
120 }
121 va_end(va);
122 }
123
124 /* We interlock verbosef() between processes by using a pipe with a single
125 * byte in it. This pipe must be initialized before the first fork() in order
126 * to work. Then, verbosef() will block on a read() until it is able to
127 * retrieve the byte. After doing its business, it will put a byte back into
128 * the pipe.
129 *
130 * This is completely silly and largely unnecessary.
131 */
132 static int inited = 0;
133 static int lockpipe[2];
134
135 static void unlock(void);
136
137 static void
138 initlock(void)
139 {
140 if (pipe(lockpipe) == -1)
141 err(1, "pipe(lockpipe)");
142 inited = 1;
143 unlock();
144 }
145
146 static void
147 lock(void)
148 {
149 char buf[1];
150
151 if (!inited) initlock();
152 if (read(lockpipe[0], buf, 1) != 1) {
153 fprintf(stderr, "lock failed!\n");
154 pidfile_unlink();
155 exit(1);
156 }
157 }
158
159 static void
160 unlock(void)
161 {
162 char c = 0;
163
164 if (write(lockpipe[1], &c, 1) != 1) {
165 fprintf(stderr, "unlock failed!\n");
166 pidfile_unlink();
167 exit(1);
168 }
169 }
170
171 void
172 verbosef(const char *format, ...)
173 {
174 va_list va;
175
176 if (!opt_want_verbose) return;
177 va_start(va, format);
178 if (opt_want_syslog)
179 to_syslog(NULL, 0, format, va);
180 else {
181 lock();
182 fprintf(stderr, "darkstat (%05d): ", (int)getpid());
183 vfprintf(stderr, format, va);
184 fprintf(stderr, "\n");
185 unlock();
186 }
187 va_end(va);
188 }
189
190 void
191 dverbosef(const char *format _unused_, ...)
192 {
193 /* disabled / do-nothing verbosef */
194 }
195
196 /* vim:set ts=3 sw=3 tw=78 expandtab: */