c66657fcbf565fbff496351520d0014db530021c
[dragonfly.git] / libexec / dma / 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 <errno.h>
37 #include <fcntl.h>
38 #include <netdb.h>
39 #include <pwd.h>
40 #include <stdio.h>
41 #include <syslog.h>
42 #include <unistd.h>
43
44 #include "dma.h"
45
46 const char *
47 hostname(void)
48 {
49         static char name[MAXHOSTNAMELEN+1];
50         int initialized = 0;
51         FILE *fp;
52         size_t len;
53
54         if (initialized)
55                 return (name);
56
57         if (config->mailname != NULL && config->mailname[0] != '\0') {
58                 snprintf(name, sizeof(name), "%s", config->mailname);
59                 initialized = 1;
60                 return (name);
61         }
62         if (config->mailnamefile != NULL && config->mailnamefile[0] != '\0') {
63                 fp = fopen(config->mailnamefile, "r");
64                 if (fp != NULL) {
65                         if (fgets(name, sizeof(name), fp) != NULL) {
66                                 len = strlen(name);
67                                 while (len > 0 &&
68                                     (name[len - 1] == '\r' ||
69                                      name[len - 1] == '\n'))
70                                         name[--len] = '\0';
71                                 if (name[0] != '\0') {
72                                         initialized = 1;
73                                         return (name);
74                                 }
75                         }
76                         fclose(fp);
77                 }
78         }
79         if (gethostname(name, sizeof(name)) != 0)
80                 strcpy(name, "(unknown hostname)");
81         initialized = 1;
82         return name;
83 }
84
85 void
86 setlogident(const char *fmt, ...)
87 {
88         char *tag = NULL;
89
90         if (fmt != NULL) {
91                 va_list ap;
92                 char *sufx;
93
94                 va_start(ap, fmt);
95                 vasprintf(&sufx, fmt, ap);
96                 if (sufx != NULL) {
97                         asprintf(&tag, "%s[%s]", logident_base, sufx);
98                         free(sufx);
99                 }
100                 va_end(ap);
101         }
102         closelog();
103         openlog(tag != NULL ? tag : logident_base, 0, LOG_MAIL);
104 }
105
106 void
107 errlog(int exitcode, const char *fmt, ...)
108 {
109         int oerrno = errno;
110         va_list ap;
111         char *outs = NULL;
112
113         if (fmt != NULL) {
114                 va_start(ap, fmt);
115                 vasprintf(&outs, fmt, ap);
116                 va_end(ap);
117         }
118
119         if (outs != NULL) {
120                 syslog(LOG_ERR, "%s: %m", outs);
121                 fprintf(stderr, "%s: %s: %s\n", getprogname(), outs, strerror(oerrno));
122         } else {
123                 syslog(LOG_ERR, "%m");
124                 fprintf(stderr, "%s: %s\n", getprogname(), strerror(oerrno));
125         }
126
127         exit(exitcode);
128 }
129
130 void
131 errlogx(int exitcode, const char *fmt, ...)
132 {
133         va_list ap;
134         char *outs = NULL;
135
136         if (fmt != NULL) {
137                 va_start(ap, fmt);
138                 vasprintf(&outs, fmt, ap);
139                 va_end(ap);
140         }
141
142         if (outs != NULL) {
143                 syslog(LOG_ERR, "%s", outs);
144                 fprintf(stderr, "%s: %s\n", getprogname(), outs);
145         } else {
146                 syslog(LOG_ERR, "Unknown error");
147                 fprintf(stderr, "%s: Unknown error\n", getprogname());
148         }
149
150         exit(exitcode);
151 }
152
153 static const char *
154 check_username(const char *name, uid_t ckuid)
155 {
156         struct passwd *pwd;
157
158         if (name == NULL)
159                 return (NULL);
160         pwd = getpwnam(name);
161         if (pwd == NULL || pwd->pw_uid != ckuid)
162                 return (NULL);
163         return (name);
164 }
165
166 void
167 set_username(void)
168 {
169         struct passwd *pwd;
170         char *u = NULL;
171         uid_t uid;
172
173         uid = getuid();
174         username = check_username(getlogin(), uid);
175         if (username != NULL)
176                 return;
177         username = check_username(getenv("LOGNAME"), uid);
178         if (username != NULL)
179                 return;
180         username = check_username(getenv("USER"), uid);
181         if (username != NULL)
182                 return;
183         pwd = getpwuid(uid);
184         if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0' &&
185             (u = strdup(pwd->pw_name)) != NULL) {
186                 username = check_username(u, uid);
187                 if (username != NULL)
188                         return;
189                 else
190                         free(u);
191         }
192         asprintf(__DECONST(void *, &username), "%ld", (long)uid);
193         if (username != NULL)
194                 return;
195         username = "unknown-or-invalid-username";
196 }
197
198 void
199 deltmp(void)
200 {
201         struct stritem *t;
202
203         SLIST_FOREACH(t, &tmpfs, next) {
204                 unlink(t->str);
205         }
206 }
207
208 int
209 open_locked(const char *fname, int flags, ...)
210 {
211         int mode = 0;
212
213         if (flags & O_CREAT) {
214                 va_list ap;
215                 va_start(ap, flags);
216                 mode = va_arg(ap, int);
217                 va_end(ap);
218         }
219
220 #ifndef O_EXLOCK
221         int fd, save_errno;
222
223         fd = open(fname, flags, mode);
224         if (fd < 0)
225                 return(fd);
226         if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
227                 save_errno = errno;
228                 close(fd);
229                 errno = save_errno;
230                 return(-1);
231         }
232         return(fd);
233 #else
234         return(open(fname, flags|O_EXLOCK, mode));
235 #endif
236 }
237
238 char *
239 rfc822date(void)
240 {
241         static char str[50];
242         size_t error;
243         time_t now;
244
245         now = time(NULL);
246         error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
247                        localtime(&now));
248         if (error == 0)
249                 strcpy(str, "(date fail)");
250         return (str);
251 }
252
253 int
254 strprefixcmp(const char *str, const char *prefix)
255 {
256         return (strncasecmp(str, prefix, strlen(prefix)));
257 }
258