diff options
Diffstat (limited to 'usr/src/cmd/sendmail/aux/praliases.c')
-rw-r--r-- | usr/src/cmd/sendmail/aux/praliases.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/usr/src/cmd/sendmail/aux/praliases.c b/usr/src/cmd/sendmail/aux/praliases.c new file mode 100644 index 0000000000..b44be6721f --- /dev/null +++ b/usr/src/cmd/sendmail/aux/praliases.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sm/gen.h> + +SM_IDSTR(copyright, +"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1983 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n") + +SM_IDSTR(id, "@(#)$Id: praliases.c,v 8.91 2001/03/29 21:15:53 rodney Exp $") + +#include <sys/types.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include <sysexits.h> + + +#ifndef NOT_SENDMAIL +# define NOT_SENDMAIL +#endif /* ! NOT_SENDMAIL */ +#include <sendmail/sendmail.h> +#include <sendmail/pathnames.h> +#include <libsmdb/smdb.h> + +static void praliases __P((char *, int, char **)); + +uid_t RealUid; +gid_t RealGid; +char *RealUserName; +uid_t RunAsUid; +uid_t RunAsGid; +char *RunAsUserName; +int Verbose = 2; +bool DontInitGroups = false; +uid_t TrustedUid = 0; +BITMAP256 DontBlameSendmail; + +# define DELIMITERS " ,/" +# define PATH_SEPARATOR ':' + +int +main(argc, argv) + int argc; + char **argv; +{ + char *cfile; + char *filename = NULL; + SM_FILE_T *cfp; + int ch; + char afilebuf[MAXLINE]; + char buf[MAXLINE]; + struct passwd *pw; + static char rnamebuf[MAXNAME]; + extern char *optarg; + extern int optind; + + clrbitmap(DontBlameSendmail); + RunAsUid = RealUid = getuid(); + RunAsGid = RealGid = getgid(); + pw = getpwuid(RealUid); + if (pw != NULL) + { + if (strlen(pw->pw_name) > MAXNAME - 1) + pw->pw_name[MAXNAME] = 0; + sm_snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); + } + else + (void) sm_snprintf(rnamebuf, sizeof rnamebuf, + "Unknown UID %d", (int) RealUid); + RunAsUserName = RealUserName = rnamebuf; + + cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL); + while ((ch = getopt(argc, argv, "C:f:")) != -1) + { + switch ((char)ch) { + case 'C': + cfile = optarg; + break; + case 'f': + filename = optarg; + break; + case '?': + default: + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "usage: praliases [-C cffile] [-f aliasfile]\n"); + exit(EX_USAGE); + } + } + argc -= optind; + argv += optind; + + if (filename != NULL) + { + praliases(filename, argc, argv); + exit(EX_OK); + } + + if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY, + NULL)) == NULL) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: %s: %s\n", cfile, + sm_errstring(errno)); + exit(EX_NOINPUT); + } + + while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL) + { + register char *b, *p; + + b = strchr(buf, '\n'); + if (b != NULL) + *b = '\0'; + + b = buf; + switch (*b++) + { + case 'O': /* option -- see if alias file */ + if (sm_strncasecmp(b, " AliasFile", 10) == 0 && + !(isascii(b[10]) && isalnum(b[10]))) + { + /* new form -- find value */ + b = strchr(b, '='); + if (b == NULL) + continue; + while (isascii(*++b) && isspace(*b)) + continue; + } + else if (*b++ != 'A') + { + /* something else boring */ + continue; + } + + /* this is the A or AliasFile option -- save it */ + if (sm_strlcpy(afilebuf, b, sizeof afilebuf) >= + sizeof afilebuf) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: AliasFile filename too long: %.30s\n", + b); + (void) sm_io_close(cfp, SM_TIME_DEFAULT); + exit(EX_CONFIG); + } + b = afilebuf; + + for (p = b; p != NULL; ) + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + break; + b = p; + + p = strpbrk(p, DELIMITERS); + + /* find end of spec */ + if (p != NULL) + { + bool quoted = false; + + for (; *p != '\0'; p++) + { + /* + ** Don't break into a quoted + ** string. + */ + + if (*p == '"') + quoted = !quoted; + else if (*p == ',' && !quoted) + break; + } + + /* No more alias specs follow */ + if (*p == '\0') + { + /* chop trailing whitespace */ + while (isascii(*p) && + isspace(*p) && + p > b) + p--; + *p = '\0'; + p = NULL; + } + } + + if (p != NULL) + { + char *e = p - 1; + + /* chop trailing whitespace */ + while (isascii(*e) && + isspace(*e) && + e > b) + e--; + *++e = '\0'; + *p++ = '\0'; + } + praliases(b, argc, argv); + } + + default: + continue; + } + } + (void) sm_io_close(cfp, SM_TIME_DEFAULT); + exit(EX_OK); + /* NOTREACHED */ + return EX_OK; +} + +static void +praliases(filename, argc, argv) + char *filename; + int argc; + char **argv; +{ + int result; + char *colon; + char *db_name; + char *db_type; + SMDB_DATABASE *database = NULL; + SMDB_CURSOR *cursor = NULL; + SMDB_DBENT db_key, db_value; + SMDB_DBPARAMS params; + SMDB_USER_INFO user_info; + + colon = strchr(filename, PATH_SEPARATOR); + if (colon == NULL) + { + db_name = filename; + db_type = SMDB_TYPE_DEFAULT; + } + else + { + *colon = '\0'; + db_name = colon + 1; + db_type = filename; + } + + /* clean off arguments */ + for (;;) + { + while (isascii(*db_name) && isspace(*db_name)) + db_name++; + + if (*db_name != '-') + break; + while (*db_name != '\0' && + !(isascii(*db_name) && isspace(*db_name))) + db_name++; + } + + /* Skip non-file based DB types */ + if (db_type != NULL && *db_type != '\0') + { + if (db_type != SMDB_TYPE_DEFAULT && + strcmp(db_type, "hash") != 0 && + strcmp(db_type, "btree") != 0 && + strcmp(db_type, "dbm") != 0) + { + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: Skipping non-file based alias type %s\n", + db_type); + return; + } + } + + if (*db_name == '\0' || (db_type != NULL && *db_type == '\0')) + { + if (colon != NULL) + *colon = ':'; + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: illegal alias specification: %s\n", filename); + goto fatal; + } + + memset(¶ms, '\0', sizeof params); + params.smdbp_cache_size = 1024 * 1024; + + user_info.smdbu_id = RunAsUid; + user_info.smdbu_group_id = RunAsGid; + (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName, + SMDB_MAX_USER_NAME_LEN); + + result = smdb_open_database(&database, db_name, O_RDONLY, 0, + SFF_ROOTOK, db_type, &user_info, ¶ms); + if (result != SMDBE_OK) + { + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: %s: open: %s\n", + db_name, sm_errstring(result)); + goto fatal; + } + + if (argc == 0) + { + memset(&db_key, '\0', sizeof db_key); + memset(&db_value, '\0', sizeof db_value); + + result = database->smdb_cursor(database, &cursor, 0); + if (result != SMDBE_OK) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: %s: set cursor: %s\n", db_name, + sm_errstring(result)); + goto fatal; + } + + while ((result = cursor->smdbc_get(cursor, &db_key, &db_value, + SMDB_CURSOR_GET_NEXT)) == + SMDBE_OK) + { +#if 0 + /* skip magic @:@ entry */ + if (db_key.size == 2 && + db_key.data[0] == '@' && + db_key.data[1] == '\0' && + db_value.size == 2 && + db_value.data[0] == '@' && + db_value.data[1] == '\0') + continue; +#endif /* 0 */ + + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "%.*s:%.*s\n", + (int) db_key.size, + (char *) db_key.data, + (int) db_value.size, + (char *) db_value.data); + } + + if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY) + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "praliases: %s: get value at cursor: %s\n", + db_name, sm_errstring(result)); + goto fatal; + } + } + else for (; *argv != NULL; ++argv) + { + int get_res; + + memset(&db_key, '\0', sizeof db_key); + memset(&db_value, '\0', sizeof db_value); + db_key.data = *argv; + db_key.size = strlen(*argv); + get_res = database->smdb_get(database, &db_key, &db_value, 0); + if (get_res == SMDBE_NOT_FOUND) + { + db_key.size++; + get_res = database->smdb_get(database, &db_key, + &db_value, 0); + } + if (get_res == SMDBE_OK) + { + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "%.*s:%.*s\n", + (int) db_key.size, + (char *) db_key.data, + (int) db_value.size, + (char *) db_value.data); + } + else + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "%s: No such key\n", + (char *)db_key.data); + } + + fatal: + if (cursor != NULL) + (void) cursor->smdbc_close(cursor); + if (database != NULL) + (void) database->smdb_close(database); + if (colon != NULL) + *colon = ':'; + return; +} |