Imported Debian patch 3.0.715-1
[darkstat-debian] / 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 #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: */