]> git.ipfire.org Git - people/ms/dma.git/blame - util.c
errlog: preserve errno
[people/ms/dma.git] / util.c
CommitLineData
de13a881
SS
1/*
2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/param.h>
9b921550
SS
36#include <sys/file.h>
37
27905878 38#include <ctype.h>
de13a881
SS
39#include <errno.h>
40#include <fcntl.h>
41#include <netdb.h>
42#include <pwd.h>
a71122e7
SS
43#include <setjmp.h>
44#include <signal.h>
de13a881
SS
45#include <stdio.h>
46#include <syslog.h>
47#include <unistd.h>
48
49#include "dma.h"
50
51const char *
52hostname(void)
53{
d6240370 54 static char name[HOST_NAME_MAX+1];
3b322ad4 55 static int initialized = 0;
c3fb272b 56 char *s;
de13a881
SS
57
58 if (initialized)
59 return (name);
60
27905878
SS
61 if (config.mailname == NULL || !*config.mailname)
62 goto local;
63
64 if (config.mailname[0] == '/') {
65 /*
66 * If the mailname looks like an absolute path,
67 * treat it as a file.
68 */
69 FILE *fp;
27905878
SS
70
71 fp = fopen(config.mailname, "r");
72 if (fp == NULL)
73 goto local;
74
c3fb272b 75 s = fgets(name, sizeof(name), fp);
27905878 76 fclose(fp);
c3fb272b 77 if (s == NULL)
27905878
SS
78 goto local;
79
c3fb272b
SS
80 for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s)
81 /* NOTHING */;
82 *s = 0;
27905878
SS
83
84 if (!*name)
85 goto local;
86
87 initialized = 1;
88 return (name);
89 } else {
a0c4afa6 90 snprintf(name, sizeof(name), "%s", config.mailname);
de13a881
SS
91 initialized = 1;
92 return (name);
93 }
27905878
SS
94
95local:
de13a881 96 if (gethostname(name, sizeof(name)) != 0)
c3fb272b 97 *name = 0;
d6240370
SS
98 /*
99 * gethostname() is allowed to truncate name without NUL-termination
100 * and at the same time not return an error.
101 */
102 name[sizeof(name) - 1] = 0;
c3fb272b
SS
103
104 for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s)
105 /* NOTHING */;
106 *s = 0;
107
108 if (!*name)
109 snprintf(name, sizeof(name), "unknown-hostname");
110
de13a881 111 initialized = 1;
27905878 112 return (name);
de13a881
SS
113}
114
115void
116setlogident(const char *fmt, ...)
117{
42916656 118 static char tag[50];
de13a881 119
249ee966 120 snprintf(tag, sizeof(tag), "%s", logident_base);
de13a881
SS
121 if (fmt != NULL) {
122 va_list ap;
249ee966 123 char sufx[50];
de13a881
SS
124
125 va_start(ap, fmt);
249ee966 126 vsnprintf(sufx, sizeof(sufx), fmt, ap);
de13a881 127 va_end(ap);
249ee966 128 snprintf(tag, sizeof(tag), "%s[%s]", logident_base, sufx);
de13a881
SS
129 }
130 closelog();
249ee966 131 openlog(tag, 0, LOG_MAIL);
de13a881
SS
132}
133
134void
135errlog(int exitcode, const char *fmt, ...)
136{
137 int oerrno = errno;
138 va_list ap;
249ee966 139 char outs[ERRMSG_SIZE];
de13a881 140
249ee966 141 outs[0] = 0;
de13a881
SS
142 if (fmt != NULL) {
143 va_start(ap, fmt);
249ee966 144 vsnprintf(outs, sizeof(outs), fmt, ap);
de13a881
SS
145 va_end(ap);
146 }
147
65da520c 148 errno = oerrno;
249ee966 149 if (*outs != 0) {
de13a881
SS
150 syslog(LOG_ERR, "%s: %m", outs);
151 fprintf(stderr, "%s: %s: %s\n", getprogname(), outs, strerror(oerrno));
152 } else {
153 syslog(LOG_ERR, "%m");
154 fprintf(stderr, "%s: %s\n", getprogname(), strerror(oerrno));
155 }
156
157 exit(exitcode);
158}
159
160void
161errlogx(int exitcode, const char *fmt, ...)
162{
163 va_list ap;
249ee966 164 char outs[ERRMSG_SIZE];
de13a881 165
249ee966 166 outs[0] = 0;
de13a881
SS
167 if (fmt != NULL) {
168 va_start(ap, fmt);
249ee966 169 vsnprintf(outs, sizeof(outs), fmt, ap);
de13a881
SS
170 va_end(ap);
171 }
172
249ee966 173 if (*outs != 0) {
de13a881
SS
174 syslog(LOG_ERR, "%s", outs);
175 fprintf(stderr, "%s: %s\n", getprogname(), outs);
176 } else {
177 syslog(LOG_ERR, "Unknown error");
178 fprintf(stderr, "%s: Unknown error\n", getprogname());
179 }
180
181 exit(exitcode);
182}
183
249ee966 184static int
de13a881
SS
185check_username(const char *name, uid_t ckuid)
186{
187 struct passwd *pwd;
188
189 if (name == NULL)
249ee966 190 return (0);
de13a881
SS
191 pwd = getpwnam(name);
192 if (pwd == NULL || pwd->pw_uid != ckuid)
249ee966
SS
193 return (0);
194 snprintf(username, sizeof(username), "%s", name);
195 return (1);
de13a881
SS
196}
197
198void
199set_username(void)
200{
201 struct passwd *pwd;
de13a881 202
75fdf182
SS
203 useruid = getuid();
204 if (check_username(getlogin(), useruid))
de13a881 205 return;
75fdf182 206 if (check_username(getenv("LOGNAME"), useruid))
de13a881 207 return;
75fdf182 208 if (check_username(getenv("USER"), useruid))
de13a881 209 return;
75fdf182 210 pwd = getpwuid(useruid);
249ee966 211 if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0') {
75fdf182 212 if (check_username(pwd->pw_name, useruid))
de13a881 213 return;
de13a881 214 }
75fdf182 215 snprintf(username, sizeof(username), "uid=%ld", (long)useruid);
de13a881
SS
216}
217
218void
219deltmp(void)
220{
221 struct stritem *t;
222
223 SLIST_FOREACH(t, &tmpfs, next) {
224 unlink(t->str);
225 }
226}
227
a71122e7
SS
228static sigjmp_buf sigbuf;
229static int sigbuf_valid;
230
231static void
232sigalrm_handler(int signo)
233{
234 (void)signo; /* so that gcc doesn't complain */
235 if (sigbuf_valid)
236 siglongjmp(sigbuf, 1);
237}
238
239int
240do_timeout(int timeout, int dojmp)
241{
242 struct sigaction act;
243 int ret = 0;
244
245 sigemptyset(&act.sa_mask);
246 act.sa_flags = 0;
247
248 if (timeout) {
249 act.sa_handler = sigalrm_handler;
250 if (sigaction(SIGALRM, &act, NULL) != 0)
251 syslog(LOG_WARNING, "can not set signal handler: %m");
252 if (dojmp) {
253 ret = sigsetjmp(sigbuf, 1);
254 if (ret)
255 goto disable;
256 /* else just programmed */
257 sigbuf_valid = 1;
258 }
259
260 alarm(timeout);
261 } else {
262disable:
263 alarm(0);
264
265 act.sa_handler = SIG_IGN;
266 if (sigaction(SIGALRM, &act, NULL) != 0)
267 syslog(LOG_WARNING, "can not remove signal handler: %m");
268 sigbuf_valid = 0;
269 }
270
271 return (ret);
272}
273
de13a881
SS
274int
275open_locked(const char *fname, int flags, ...)
276{
277 int mode = 0;
278
279 if (flags & O_CREAT) {
280 va_list ap;
281 va_start(ap, flags);
282 mode = va_arg(ap, int);
283 va_end(ap);
284 }
285
286#ifndef O_EXLOCK
287 int fd, save_errno;
288
289 fd = open(fname, flags, mode);
290 if (fd < 0)
291 return(fd);
292 if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
293 save_errno = errno;
294 close(fd);
295 errno = save_errno;
296 return(-1);
297 }
298 return(fd);
299#else
300 return(open(fname, flags|O_EXLOCK, mode));
301#endif
302}
303
304char *
305rfc822date(void)
306{
307 static char str[50];
308 size_t error;
309 time_t now;
310
311 now = time(NULL);
312 error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
313 localtime(&now));
314 if (error == 0)
315 strcpy(str, "(date fail)");
316 return (str);
317}
318
319int
320strprefixcmp(const char *str, const char *prefix)
321{
322 return (strncasecmp(str, prefix, strlen(prefix)));
323}
324
ee613428
SS
325void
326init_random(void)
327{
328 unsigned int seed;
329 int rf;
330
331 rf = open("/dev/urandom", O_RDONLY);
332 if (rf == -1)
333 rf = open("/dev/random", O_RDONLY);
334
335 if (!(rf != -1 && read(rf, &seed, sizeof(seed)) == sizeof(seed)))
336 seed = (time(NULL) ^ getpid()) + (uintptr_t)&seed;
337
338 srandom(seed);
339
340 if (rf != -1)
341 close(rf);
342}