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