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 259