2 * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
3 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
5 * This code is derived from software contributed to The DragonFly Project
6 * by Simon Schubert <2@0x2c.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/param.h>
56 #define HOST_NAME_MAX 255
58 static char name
[HOST_NAME_MAX
+1];
59 static int initialized
= 0;
65 if (config
.mailname
== NULL
|| !*config
.mailname
)
68 if (config
.mailname
[0] == '/') {
70 * If the mailname looks like an absolute path,
75 fp
= fopen(config
.mailname
, "r");
79 s
= fgets(name
, sizeof(name
), fp
);
84 for (s
= name
; *s
!= 0 && (isalnum(*s
) || strchr("_.-", *s
)); ++s
)
94 snprintf(name
, sizeof(name
), "%s", config
.mailname
);
100 if (gethostname(name
, sizeof(name
)) != 0)
103 * gethostname() is allowed to truncate name without NUL-termination
104 * and at the same time not return an error.
106 name
[sizeof(name
) - 1] = 0;
108 for (s
= name
; *s
!= 0 && (isalnum(*s
) || strchr("_.-", *s
)); ++s
)
113 snprintf(name
, sizeof(name
), "unknown-hostname");
120 setlogident(const char *fmt
, ...)
124 snprintf(tag
, sizeof(tag
), "%s", logident_base
);
130 vsnprintf(sufx
, sizeof(sufx
), fmt
, ap
);
132 snprintf(tag
, sizeof(tag
), "%s[%s]", logident_base
, sufx
);
135 openlog(tag
, 0, LOG_MAIL
);
139 errlog(int exitcode
, const char *fmt
, ...)
143 char outs
[ERRMSG_SIZE
];
148 vsnprintf(outs
, sizeof(outs
), fmt
, ap
);
154 syslog(LOG_ERR
, "%s: %m", outs
);
155 fprintf(stderr
, "%s: %s: %s\n", getprogname(), outs
, strerror(oerrno
));
157 syslog(LOG_ERR
, "%m");
158 fprintf(stderr
, "%s: %s\n", getprogname(), strerror(oerrno
));
165 errlogx(int exitcode
, const char *fmt
, ...)
168 char outs
[ERRMSG_SIZE
];
173 vsnprintf(outs
, sizeof(outs
), fmt
, ap
);
178 syslog(LOG_ERR
, "%s", outs
);
179 fprintf(stderr
, "%s: %s\n", getprogname(), outs
);
181 syslog(LOG_ERR
, "Unknown error");
182 fprintf(stderr
, "%s: Unknown error\n", getprogname());
189 check_username(const char *name
, uid_t ckuid
)
195 pwd
= getpwnam(name
);
196 if (pwd
== NULL
|| pwd
->pw_uid
!= ckuid
)
198 snprintf(username
, sizeof(username
), "%s", name
);
208 if (check_username(getlogin(), useruid
))
210 if (check_username(getenv("LOGNAME"), useruid
))
212 if (check_username(getenv("USER"), useruid
))
214 pwd
= getpwuid(useruid
);
215 if (pwd
!= NULL
&& pwd
->pw_name
!= NULL
&& pwd
->pw_name
[0] != '\0') {
216 if (check_username(pwd
->pw_name
, useruid
))
219 snprintf(username
, sizeof(username
), "uid=%ld", (long)useruid
);
227 SLIST_FOREACH(t
, &tmpfs
, next
) {
232 static sigjmp_buf sigbuf
;
233 static int sigbuf_valid
;
236 sigalrm_handler(int signo
)
238 (void)signo
; /* so that gcc doesn't complain */
240 siglongjmp(sigbuf
, 1);
244 do_timeout(int timeout
, int dojmp
)
246 struct sigaction act
;
249 sigemptyset(&act
.sa_mask
);
253 act
.sa_handler
= sigalrm_handler
;
254 if (sigaction(SIGALRM
, &act
, NULL
) != 0)
255 syslog(LOG_WARNING
, "can not set signal handler: %m");
257 ret
= sigsetjmp(sigbuf
, 1);
260 /* else just programmed */
269 act
.sa_handler
= SIG_IGN
;
270 if (sigaction(SIGALRM
, &act
, NULL
) != 0)
271 syslog(LOG_WARNING
, "can not remove signal handler: %m");
279 open_locked(const char *fname
, int flags
, ...)
283 if (flags
& O_CREAT
) {
286 mode
= va_arg(ap
, int);
293 fd
= open(fname
, flags
, mode
);
296 if (flock(fd
, LOCK_EX
|((flags
& O_NONBLOCK
)? LOCK_NB
: 0)) < 0) {
304 return(open(fname
, flags
|O_EXLOCK
, mode
));
316 error
= strftime(str
, sizeof(str
), "%a, %d %b %Y %T %z",
319 strcpy(str
, "(date fail)");
324 strprefixcmp(const char *str
, const char *prefix
)
326 return (strncasecmp(str
, prefix
, strlen(prefix
)));
335 rf
= open("/dev/urandom", O_RDONLY
);
337 rf
= open("/dev/random", O_RDONLY
);
339 if (!(rf
!= -1 && read(rf
, &seed
, sizeof(seed
)) == sizeof(seed
)))
340 seed
= (time(NULL
) ^ getpid()) + (uintptr_t)&seed
;