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