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