praliases.c revision 64565
1/* 2 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14#ifndef lint 15static char copyright[] = 16"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ 17 All rights reserved.\n\ 18 Copyright (c) 1983 Eric P. Allman. All rights reserved.\n\ 19 Copyright (c) 1988, 1993\n\ 20 The Regents of the University of California. All rights reserved.\n"; 21#endif /* ! lint */ 22 23#ifndef lint 24static char id[] = "@(#)$Id: praliases.c,v 8.59.4.10 2000/07/18 05:41:39 gshapiro Exp $"; 25#endif /* ! lint */ 26 27/* $FreeBSD: head/contrib/sendmail/praliases/praliases.c 64565 2000-08-12 22:19:16Z gshapiro $ */ 28 29#include <sys/types.h> 30#include <ctype.h> 31#include <stdlib.h> 32#include <unistd.h> 33#ifdef EX_OK 34# undef EX_OK /* unistd.h may have another use for this */ 35#endif /* EX_OK */ 36#include <sysexits.h> 37 38 39#ifndef NOT_SENDMAIL 40# define NOT_SENDMAIL 41#endif /* ! NOT_SENDMAIL */ 42#include <sendmail/sendmail.h> 43#include <sendmail/pathnames.h> 44#include <libsmdb/smdb.h> 45 46static void praliases __P((char *, int, char **)); 47 48uid_t RealUid; 49gid_t RealGid; 50char *RealUserName; 51uid_t RunAsUid; 52uid_t RunAsGid; 53char *RunAsUserName; 54int Verbose = 2; 55bool DontInitGroups = FALSE; 56uid_t TrustedUid = 0; 57BITMAP256 DontBlameSendmail; 58 59extern void syserr __P((const char *, ...)); 60 61 62int 63main(argc, argv) 64 int argc; 65 char **argv; 66{ 67 char *cfile; 68 char *filename = NULL; 69 FILE *cfp; 70 int ch; 71 char afilebuf[MAXLINE]; 72 char buf[MAXLINE]; 73 struct passwd *pw; 74 static char rnamebuf[MAXNAME]; 75 extern char *optarg; 76 extern int optind; 77 78 79 clrbitmap(DontBlameSendmail); 80 RunAsUid = RealUid = getuid(); 81 RunAsGid = RealGid = getgid(); 82 pw = getpwuid(RealUid); 83 if (pw != NULL) 84 { 85 if (strlen(pw->pw_name) > MAXNAME - 1) 86 pw->pw_name[MAXNAME] = 0; 87 snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); 88 } 89 else 90 (void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", 91 (int) RealUid); 92 RunAsUserName = RealUserName = rnamebuf; 93 94 cfile = _PATH_SENDMAILCF; 95 while ((ch = getopt(argc, argv, "C:f:")) != -1) 96 { 97 switch ((char)ch) { 98 case 'C': 99 cfile = optarg; 100 break; 101 case 'f': 102 filename = optarg; 103 break; 104 case '?': 105 default: 106 (void)fprintf(stderr, 107 "usage: praliases [-C cffile] [-f aliasfile]\n"); 108 exit(EX_USAGE); 109 } 110 } 111 argc -= optind; 112 argv += optind; 113 114 if (filename != NULL) 115 { 116 praliases(filename, argc, argv); 117 exit(EX_OK); 118 } 119 120 if ((cfp = fopen(cfile, "r")) == NULL) 121 { 122 fprintf(stderr, "praliases: %s: %s\n", 123 cfile, errstring(errno)); 124 exit(EX_NOINPUT); 125 } 126 127 while (fgets(buf, sizeof(buf), cfp) != NULL) 128 { 129 register char *b, *p; 130 131 b = strchr(buf, '\n'); 132 if (b != NULL) 133 *b = '\0'; 134 135 b = buf; 136 switch (*b++) 137 { 138 case 'O': /* option -- see if alias file */ 139 if (strncasecmp(b, " AliasFile", 10) == 0 && 140 !(isascii(b[10]) && isalnum(b[10]))) 141 { 142 /* new form -- find value */ 143 b = strchr(b, '='); 144 if (b == NULL) 145 continue; 146 while (isascii(*++b) && isspace(*b)) 147 continue; 148 } 149 else if (*b++ != 'A') 150 { 151 /* something else boring */ 152 continue; 153 } 154 155 /* this is the A or AliasFile option -- save it */ 156 if (strlcpy(afilebuf, b, sizeof afilebuf) >= 157 sizeof afilebuf) 158 { 159 fprintf(stderr, 160 "praliases: AliasFile filename too long: %.30s\n", 161 b); 162 (void) fclose(cfp); 163 exit(EX_CONFIG); 164 } 165 b = afilebuf; 166 167 for (p = b; p != NULL; ) 168 { 169 while (isascii(*p) && isspace(*p)) 170 p++; 171 if (*p == '\0') 172 break; 173 b = p; 174 175 p = strpbrk(p, " ,/"); 176 177 /* find end of spec */ 178 if (p != NULL) 179 { 180 bool quoted = FALSE; 181 182 for (; *p != '\0'; p++) 183 { 184 /* 185 ** Don't break into a quoted 186 ** string. 187 */ 188 189 if (*p == '"') 190 quoted = !quoted; 191 else if (*p == ',' && !quoted) 192 break; 193 } 194 195 /* No more alias specs follow */ 196 if (*p == '\0') 197 { 198 /* chop trailing whitespace */ 199 while (isascii(*p) && 200 isspace(*p) && 201 p > b) 202 p--; 203 *p = '\0'; 204 p = NULL; 205 } 206 } 207 208 if (p != NULL) 209 { 210 char *e = p - 1; 211 212 /* chop trailing whitespace */ 213 while (isascii(*e) && 214 isspace(*e) && 215 e > b) 216 e--; 217 *++e = '\0'; 218 *p++ = '\0'; 219 } 220 praliases(b, argc, argv); 221 } 222 223 default: 224 continue; 225 } 226 } 227 (void) fclose(cfp); 228 exit(EX_OK); 229 /* NOTREACHED */ 230 return EX_OK; 231} 232 233static void 234praliases(filename, argc, argv) 235 char *filename; 236 int argc; 237 char **argv; 238{ 239 int result; 240 char *colon; 241 char *db_name; 242 char *db_type; 243 SMDB_DATABASE *database = NULL; 244 SMDB_CURSOR *cursor = NULL; 245 SMDB_DBENT db_key, db_value; 246 SMDB_DBPARAMS params; 247 SMDB_USER_INFO user_info; 248 249 colon = strchr(filename, ':'); 250 if (colon == NULL) 251 { 252 db_name = filename; 253 db_type = SMDB_TYPE_DEFAULT; 254 } 255 else 256 { 257 *colon = '\0'; 258 db_name = colon + 1; 259 db_type = filename; 260 } 261 262 /* clean off arguments */ 263 for (;;) 264 { 265 while (isascii(*db_name) && isspace(*db_name)) 266 db_name++; 267 if (*db_name != '-') 268 break; 269 while (*db_name != '\0' && 270 !(isascii(*db_name) && isspace(*db_name))) 271 db_name++; 272 } 273 274 if (*db_name == '\0' || (db_type != NULL && *db_type == '\0')) 275 { 276 if (colon != NULL) 277 *colon = ':'; 278 fprintf(stderr, "praliases: illegal alias specification: %s\n", 279 filename); 280 goto fatal; 281 } 282 283 memset(¶ms, '\0', sizeof params); 284 params.smdbp_cache_size = 1024 * 1024; 285 286 user_info.smdbu_id = RunAsUid; 287 user_info.smdbu_group_id = RunAsGid; 288 strlcpy(user_info.smdbu_name, RunAsUserName, SMDB_MAX_USER_NAME_LEN); 289 290 result = smdb_open_database(&database, db_name, O_RDONLY, 0, 291 SFF_ROOTOK, db_type, &user_info, ¶ms); 292 if (result != SMDBE_OK) 293 { 294 fprintf(stderr, "praliases: %s: open: %s\n", 295 db_name, errstring(result)); 296 goto fatal; 297 } 298 299 if (argc == 0) 300 { 301 memset(&db_key, '\0', sizeof db_key); 302 memset(&db_value, '\0', sizeof db_value); 303 304 result = database->smdb_cursor(database, &cursor, 0); 305 if (result != SMDBE_OK) 306 { 307 fprintf(stderr, "praliases: %s: set cursor: %s\n", 308 db_name, errstring(result)); 309 goto fatal; 310 } 311 312 while ((result = cursor->smdbc_get(cursor, &db_key, &db_value, 313 SMDB_CURSOR_GET_NEXT)) == 314 SMDBE_OK) 315 { 316#if 0 317 /* skip magic @:@ entry */ 318 if (db_key.data.size == 2 && 319 db_key.data.data[0] == '@' && 320 db_key.data.data[1] == '\0' && 321 db_value.data.size == 2 && 322 db_value.data.data[0] == '@' && 323 db_value.data.data[1] == '\0') 324 continue; 325#endif /* 0 */ 326 327 printf("%.*s:%.*s\n", 328 (int) db_key.data.size, 329 (char *) db_key.data.data, 330 (int) db_value.data.size, 331 (char *) db_value.data.data); 332 } 333 334 if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY) 335 { 336 fprintf(stderr, 337 "praliases: %s: get value at cursor: %s\n", 338 db_name, errstring(result)); 339 goto fatal; 340 } 341 } 342 else for (; *argv != NULL; ++argv) 343 { 344 memset(&db_key, '\0', sizeof db_key); 345 memset(&db_value, '\0', sizeof db_value); 346 db_key.data.data = *argv; 347 db_key.data.size = strlen(*argv) + 1; 348 if (database->smdb_get(database, &db_key, 349 &db_value, 0) == SMDBE_OK) 350 { 351 printf("%.*s:%.*s\n", 352 (int) db_key.data.size, 353 (char *) db_key.data.data, 354 (int) db_value.data.size, 355 (char *) db_value.data.data); 356 } 357 else 358 printf("%s: No such key\n", (char *) db_key.data.data); 359 } 360 361 fatal: 362 if (cursor != NULL) 363 (void) cursor->smdbc_close(cursor); 364 if (database != NULL) 365 (void) database->smdb_close(database); 366 if (colon != NULL) 367 *colon = ':'; 368 return; 369} 370 371/*VARARGS1*/ 372void 373#ifdef __STDC__ 374message(const char *msg, ...) 375#else /* __STDC__ */ 376message(msg, va_alist) 377 const char *msg; 378 va_dcl 379#endif /* __STDC__ */ 380{ 381 const char *m; 382 VA_LOCAL_DECL 383 384 m = msg; 385 if (isascii(m[0]) && isdigit(m[0]) && 386 isascii(m[1]) && isdigit(m[1]) && 387 isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') 388 m += 4; 389 VA_START(msg); 390 (void) vfprintf(stderr, m, ap); 391 VA_END; 392 (void) fprintf(stderr, "\n"); 393} 394 395/*VARARGS1*/ 396void 397#ifdef __STDC__ 398syserr(const char *msg, ...) 399#else /* __STDC__ */ 400syserr(msg, va_alist) 401 const char *msg; 402 va_dcl 403#endif /* __STDC__ */ 404{ 405 const char *m; 406 VA_LOCAL_DECL 407 408 m = msg; 409 if (isascii(m[0]) && isdigit(m[0]) && 410 isascii(m[1]) && isdigit(m[1]) && 411 isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') 412 m += 4; 413 VA_START(msg); 414 (void) vfprintf(stderr, m, ap); 415 VA_END; 416 (void) fprintf(stderr, "\n"); 417} 418