dma(8): Upgrade to v0.7.
[dragonfly.git] / libexec / dma / util.c
CommitLineData
1da0a9f2
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>
c8b07ee5
SW
36#include <sys/file.h>
37
38#include <ctype.h>
1da0a9f2
SS
39#include <errno.h>
40#include <fcntl.h>
41#include <netdb.h>
42#include <pwd.h>
c8b07ee5
SW
43#include <setjmp.h>
44#include <signal.h>
1da0a9f2
SS
45#include <stdio.h>
46#include <syslog.h>
47#include <unistd.h>
48
49#include "dma.h"
50
51const char *
52hostname(void)
53{
c8b07ee5
SW
54#ifndef HOST_NAME_MAX
55#define HOST_NAME_MAX 255
56#endif
57 static char name[HOST_NAME_MAX+1];
58 static int initialized = 0;
59 char *s;
1da0a9f2
SS
60
61 if (initialized)
62 return (name);
63
c8b07ee5
SW
64 if (config.mailname == NULL || !*config.mailname)
65 goto local;
66
67 if (config.mailname[0] == '/') {
68 /*
69 * If the mailname looks like an absolute path,
70 * treat it as a file.
71 */
72 FILE *fp;
73
74 fp = fopen(config.mailname, "r");
75 if (fp == NULL)
76 goto local;
77
78 s = fgets(name, sizeof(name), fp);
79 fclose(fp);
80 if (s == NULL)
81 goto local;
82
83 for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s)
84 /* NOTHING */;
85 *s = 0;
86
87 if (!*name)
88 goto local;
89
90 initialized = 1;
91 return (name);
92 } else {
ca259d14 93 snprintf(name, sizeof(name), "%s", config.mailname);
1da0a9f2
SS
94 initialized = 1;
95 return (name);
96 }
c8b07ee5
SW
97
98local:
1da0a9f2 99 if (gethostname(name, sizeof(name)) != 0)
c8b07ee5
SW
100 *name = 0;
101 /*
102 * gethostname() is allowed to truncate name without NUL-termination
103 * and at the same time not return an error.
104 */
105 name[sizeof(name) - 1] = 0;
106
107 for (s = name; *s != 0 && (isalnum(*s) || strchr("_.-", *s)); ++s)
108 /* NOTHING */;
109 *s = 0;
110
111 if (!*name)
112 snprintf(name, sizeof(name), "unknown-hostname");
113
1da0a9f2 114 initialized = 1;
c8b07ee5 115 return (name);
1da0a9f2
SS
116}
117
118void
119setlogident(const char *fmt, ...)
120{
c8b07ee5 121 static char tag[50];
1da0a9f2 122
c8b07ee5 123 snprintf(tag, sizeof(tag), "%s", logident_base);
1da0a9f2
SS
124 if (fmt != NULL) {
125 va_list ap;
c8b07ee5 126 char sufx[50];
1da0a9f2
SS
127
128 va_start(ap, fmt);
c8b07ee5 129 vsnprintf(sufx, sizeof(sufx), fmt, ap);
1da0a9f2 130 va_end(ap);
c8b07ee5 131 snprintf(tag, sizeof(tag), "%s[%s]", logident_base, sufx);
1da0a9f2
SS
132 }
133 closelog();
c8b07ee5 134 openlog(tag, 0, LOG_MAIL);
1da0a9f2
SS
135}
136
137void
138errlog(int exitcode, const char *fmt, ...)
139{
140 int oerrno = errno;
141 va_list ap;
c8b07ee5 142 char outs[ERRMSG_SIZE];
1da0a9f2 143
c8b07ee5 144 outs[0] = 0;
1da0a9f2
SS
145 if (fmt != NULL) {
146 va_start(ap, fmt);
c8b07ee5 147 vsnprintf(outs, sizeof(outs), fmt, ap);
1da0a9f2
SS
148 va_end(ap);
149 }
150
c8b07ee5
SW
151 errno = oerrno;
152 if (*outs != 0) {
1da0a9f2
SS
153 syslog(LOG_ERR, "%s: %m", outs);
154 fprintf(stderr, "%s: %s: %s\n", getprogname(), outs, strerror(oerrno));
155 } else {
156 syslog(LOG_ERR, "%m");
157 fprintf(stderr, "%s: %s\n", getprogname(), strerror(oerrno));
158 }
159
160 exit(exitcode);
161}
162
163void
164errlogx(int exitcode, const char *fmt, ...)
165{
166 va_list ap;
c8b07ee5 167 char outs[ERRMSG_SIZE];
1da0a9f2 168
c8b07ee5 169 outs[0] = 0;
1da0a9f2
SS
170 if (fmt != NULL) {
171 va_start(ap, fmt);
c8b07ee5 172 vsnprintf(outs, sizeof(outs), fmt, ap);
1da0a9f2
SS
173 va_end(ap);
174 }
175
c8b07ee5 176 if (*outs != 0) {
1da0a9f2
SS
177 syslog(LOG_ERR, "%s", outs);
178 fprintf(stderr, "%s: %s\n", getprogname(), outs);
179 } else {
180 syslog(LOG_ERR, "Unknown error");
181 fprintf(stderr, "%s: Unknown error\n", getprogname());
182 }
183
184 exit(exitcode);
185}
186
c8b07ee5 187static int
1da0a9f2
SS
188check_username(const char *name, uid_t ckuid)
189{
190 struct passwd *pwd;
191
192 if (name == NULL)
c8b07ee5 193 return (0);
1da0a9f2
SS
194 pwd = getpwnam(name);
195 if (pwd == NULL || pwd->pw_uid != ckuid)
c8b07ee5
SW
196 return (0);
197 snprintf(username, sizeof(username), "%s", name);
198 return (1);
1da0a9f2
SS
199}
200
201void
202set_username(void)
203{
204 struct passwd *pwd;
1da0a9f2 205
c8b07ee5
SW
206 useruid = getuid();
207 if (check_username(getlogin(), useruid))
1da0a9f2 208 return;
c8b07ee5 209 if (check_username(getenv("LOGNAME"), useruid))
1da0a9f2 210 return;
c8b07ee5 211 if (check_username(getenv("USER"), useruid))
1da0a9f2 212 return;
c8b07ee5
SW
213 pwd = getpwuid(useruid);
214 if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0') {
215 if (check_username(pwd->pw_name, useruid))
1da0a9f2 216 return;
1da0a9f2 217 }
c8b07ee5 218 snprintf(username, sizeof(username), "uid=%ld", (long)useruid);
1da0a9f2
SS
219}
220
221void
222deltmp(void)
223{
224 struct stritem *t;
225
226 SLIST_FOREACH(t, &tmpfs, next) {
227 unlink(t->str);
228 }
229}
230
c8b07ee5
SW
231static sigjmp_buf sigbuf;
232static int sigbuf_valid;
233
234static void
235sigalrm_handler(int signo)
236{
237 (void)signo; /* so that gcc doesn't complain */
238 if (sigbuf_valid)
239 siglongjmp(sigbuf, 1);
240}
241
242int
243do_timeout(int timeout, int dojmp)
244{
245 struct sigaction act;
246 int ret = 0;
247
248 sigemptyset(&act.sa_mask);
249 act.sa_flags = 0;
250
251 if (timeout) {
252 act.sa_handler = sigalrm_handler;
253 if (sigaction(SIGALRM, &act, NULL) != 0)
254 syslog(LOG_WARNING, "can not set signal handler: %m");
255 if (dojmp) {
256 ret = sigsetjmp(sigbuf, 1);
257 if (ret)
258 goto disable;
259 /* else just programmed */
260 sigbuf_valid = 1;
261 }
262
263 alarm(timeout);
264 } else {
265disable:
266 alarm(0);
267
268 act.sa_handler = SIG_IGN;
269 if (sigaction(SIGALRM, &act, NULL) != 0)
270 syslog(LOG_WARNING, "can not remove signal handler: %m");
271 sigbuf_valid = 0;
272 }
273
274 return (ret);
275}
276
1da0a9f2
SS
277int
278open_locked(const char *fname, int flags, ...)
279{
280 int mode = 0;
281
282 if (flags & O_CREAT) {
283 va_list ap;
284 va_start(ap, flags);
285 mode = va_arg(ap, int);
286 va_end(ap);
287 }
288
289#ifndef O_EXLOCK
290 int fd, save_errno;
291
292 fd = open(fname, flags, mode);
293 if (fd < 0)
294 return(fd);
295 if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
296 save_errno = errno;
297 close(fd);
298 errno = save_errno;
299 return(-1);
300 }
301 return(fd);
302#else
303 return(open(fname, flags|O_EXLOCK, mode));
304#endif
305}
306
307char *
308rfc822date(void)
309{
310 static char str[50];
311 size_t error;
312 time_t now;
313
314 now = time(NULL);
315 error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
316 localtime(&now));
317 if (error == 0)
318 strcpy(str, "(date fail)");
319 return (str);
320}
321
322int
323strprefixcmp(const char *str, const char *prefix)
324{
325 return (strncasecmp(str, prefix, strlen(prefix)));
326}
327
c8b07ee5
SW
328void
329init_random(void)
330{
331 unsigned int seed;
332 int rf;
333
334 rf = open("/dev/urandom", O_RDONLY);
335 if (rf == -1)
336 rf = open("/dev/random", O_RDONLY);
337
338 if (!(rf != -1 && read(rf, &seed, sizeof(seed)) == sizeof(seed)))
339 seed = (time(NULL) ^ getpid()) + (uintptr_t)&seed;
340
341 srandom(seed);
342
343 if (rf != -1)
344 close(rf);
345}