diff options
author | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-02-14 18:37:13 +0000 |
---|---|---|
committer | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-02-14 18:37:13 +0000 |
commit | 429780f3a931abd6d29e80616a6abb156e879e9d (patch) | |
tree | 112f7642c540f04a25b578628da624f6f2680365 | |
parent | b0b4b10dbc7b5d1203b085c2fd3d8bef652935b4 (diff) |
Implement makemap -t and -o, for output type and dest resp.; ok gilles@
-rw-r--r-- | usr.sbin/smtpd/makemap.8 | 37 | ||||
-rw-r--r-- | usr.sbin/smtpd/makemap.c | 260 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 9 |
3 files changed, 182 insertions, 124 deletions
diff --git a/usr.sbin/smtpd/makemap.8 b/usr.sbin/smtpd/makemap.8 index ae3b737d799..a8bf6f207bd 100644 --- a/usr.sbin/smtpd/makemap.8 +++ b/usr.sbin/smtpd/makemap.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: makemap.8,v 1.3 2008/12/17 22:59:36 jacekm Exp $ +.\" $OpenBSD: makemap.8,v 1.4 2009/02/14 18:37:12 jacekm Exp $ .\" Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. .\" All rights reserved. .\" Copyright (c) 1988, 1991, 1993 @@ -11,7 +11,7 @@ .\" .\" $Sendmail: makemap.8,v 8.30 2002/06/27 23:41:04 gshapiro Exp $ .\" -.Dd $Mdocdate: December 17 2008 $ +.Dd $Mdocdate: February 14 2009 $ .Dt MAKEMAP 8 .Os .Sh NAME @@ -20,6 +20,8 @@ .Nd create database maps for smtpd .Sh SYNOPSIS .Nm makemap +.Op Fl t Ar type +.Op Fl o Ar dbfile .Ar file .Nm newaliases .Sh DESCRIPTION @@ -29,7 +31,12 @@ creates the database maps used by the keyed map lookups in It reads input from .Ar file and outputs them to -.Ar file.db . +.Ar dbfile . +If +.Ar dbfile +is not specified, output file name is made by appending .db +to +.Ar file . .Pp In all cases, .Nm @@ -38,6 +45,26 @@ reads lines from consisting of words separated by whitespace. The first is the database key, the remaining specify mapped value. +Database key and value may optionally be separated +using colon character. +.Pp +The +.Ar type +argument specifies format of resulting map file. +Default map format is suitable for storing simple, unstructured +key-to-value string associations. +However, if mapped value has special meaning, +as in case of virtual domains definition file, +suitable +.Ar type +argument must be provided. +Available output types are: +.Bl -tag -width "aliases" +.It Cm aliases +Mapped value is comma-separated list of mail destinations. +This format can be used for building user aliases and +virtual domains database files. +.El .Pp .Ex -std makemap .Pp @@ -51,7 +78,9 @@ in order for the change to take effect. .Sh FILES .Bl -tag -width "/etc/mail/aliasesXXX" -compact .It Pa /etc/mail/aliases -The mail aliases file. +List of user mail aliases. +.It Pa /etc/mail/virtual +List of hosted virtual domains. .El .Sh SEE ALSO .Xr editmap 8 , diff --git a/usr.sbin/smtpd/makemap.c b/usr.sbin/smtpd/makemap.c index d80be1ed0eb..50e0b228787 100644 --- a/usr.sbin/smtpd/makemap.c +++ b/usr.sbin/smtpd/makemap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: makemap.c,v 1.7 2009/01/01 16:15:47 jacekm Exp $ */ +/* $OpenBSD: makemap.c,v 1.8 2009/02/14 18:37:12 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -42,42 +42,72 @@ extern char *__progname; __dead void usage(void); int parse_map(char *); int parse_entry(char *, size_t, size_t); +int make_plain(DBT *, char *); +int make_aliases(DBT *, char *); -DB *db; -char *source; -int dbputs; +DB *db; +char *source; +char *oflag; +int dbputs; enum program { P_MAKEMAP, P_NEWALIASES } mode; +enum output_type { + T_PLAIN, + T_ALIASES +} type; + int main(int argc, char *argv[]) { - char dbname[MAXPATHLEN]; - char dest[MAXPATHLEN]; + char dbname[MAXPATHLEN]; + char *opts; + int ch; mode = strcmp(__progname, "newaliases") ? P_MAKEMAP : P_NEWALIASES; - - switch (mode) { - case P_MAKEMAP: - if (argc != 2) - usage(); - source = argv[1]; - break; - case P_NEWALIASES: - if (argc != 1) + type = T_PLAIN; + opts = "ho:t:"; + if (mode == P_NEWALIASES) + opts = "h"; + + while ((ch = getopt(argc, argv, opts)) != -1) { + switch (ch) { + case 'o': + oflag = optarg; + break; + case 't': + if (strcmp(optarg, "aliases") == 0) + type = T_ALIASES; + else + errx(1, "unsupported type '%s'", optarg); + break; + default: usage(); + } + } + argc -= optind; + argv += optind; + + if (mode == P_NEWALIASES) { if (geteuid()) errx(1, "need root privileges"); + if (argc != 0) + usage(); + type = T_ALIASES; source = PATH_ALIASES; - break; - default: - abort(); + } else { + if (argc != 1) + usage(); + source = argv[0]; } - if (! bsnprintf(dbname, MAXPATHLEN, "%s.db.XXXXXXXXXXX", source)) + if (oflag == NULL && asprintf(&oflag, "%s.db", source) == -1) + err(1, "asprintf"); + + if (! bsnprintf(dbname, MAXPATHLEN, "%s.XXXXXXXXXXX", oflag)) errx(1, "path too long"); if (mkstemp(dbname) == -1) err(1, "mkstemp"); @@ -101,18 +131,13 @@ main(int argc, char *argv[]) goto bad; } - if (! bsnprintf(dest, MAXPATHLEN, "%s.db", source)) { - warnx("path too long"); - goto bad; - } - - if (rename(dbname, dest) == -1) { + if (rename(dbname, oflag) == -1) { warn("rename"); goto bad; } if (dbputs == 0) - warnx("warning: empty map created: %s", dest); + warnx("warning: empty map created: %s", oflag); return 0; bad: @@ -123,11 +148,11 @@ bad: int parse_map(char *filename) { - FILE *fp; - char *line; - size_t len; - size_t lineno = 0; - char delim[] = { '\\', '\\', '#' }; + FILE *fp; + char *line; + size_t len; + size_t lineno = 0; + char delim[] = { '\\', '\\', '#' }; fp = fopen(filename, "r"); if (fp == NULL) { @@ -136,8 +161,6 @@ parse_map(char *filename) } while ((line = fparseln(fp, &len, &lineno, delim, 0)) != NULL) { - if (len == 0) - continue; if (! parse_entry(line, len, lineno)) { free(line); fclose(fp); @@ -153,123 +176,124 @@ parse_map(char *filename) int parse_entry(char *line, size_t len, size_t lineno) { - char *name; - char *rcpt; - char *endp; - char *subrcpt; - DBT key; - DBT val; - - /* Blank lines are OK. */ - while (isspace(*line)) - line++; - if (*line == '\0') + DBT key; + DBT val; + char *keyp; + char *valp; + + keyp = line; + while (isspace(*keyp)) + keyp++; + if (*keyp == '\0') return 1; - name = line; - switch (mode) { - case P_MAKEMAP: - rcpt = strchr(line, ' '); - if (rcpt == NULL) - rcpt = strchr(line, '\t'); + valp = keyp; + strsep(&valp, " \t:"); + if (valp == NULL || valp == keyp) + goto bad; + + /* Check for dups. */ + key.data = keyp; + key.size = strlen(keyp) + 1; + if (db->get(db, &key, &val, 0) == 0) { + warnx("%s:%zd: duplicate entry for %s", source, lineno, keyp); + return 0; + } + + switch (type) { + case T_PLAIN: + if (! make_plain(&val, valp)) + goto bad; break; - case P_NEWALIASES: - rcpt = strchr(line, ':'); + case T_ALIASES: + if (! make_aliases(&val, valp)) + goto bad; break; - default: - abort(); } - if (rcpt == NULL) - goto bad; - *rcpt++ = '\0'; - /* name: strip initial whitespace. */ - while (isspace(*name)) - ++name; - if (*name == '\0') - goto bad; + if (db->put(db, &key, &val, 0) == -1) { + warn("dbput"); + return 0; + } + dbputs++; - /* name: strip trailing whitespace. */ - endp = name + strlen(name) - 1; - while (name < endp && isspace(*endp)) - *endp-- = '\0'; + free(val.data); - /* Check for dups. */ - key.data = name; - key.size = strlen(name) + 1; - if (db->get(db, &key, &val, 0) == 0) { - warnx("%s:%zd: duplicate entry for %s", source, lineno, name); + return 1; + +bad: + warnx("%s:%zd: invalid entry", source, lineno); + return 0; +} + +int +make_plain(DBT *val, char *text) +{ + struct alias *a; + + a = calloc(1, sizeof(struct alias)); + if (a == NULL) + err(1, "calloc"); + + a->type = ALIAS_TEXT; + val->data = a; + val->size = strlcpy(a->u.text, text, sizeof(a->u.text)); + + if (val->size >= sizeof(a->u.text)) { + free(a); return 0; } - /* At this point name and rcpt are non-zero nul-terminated strings. */ - while ((subrcpt = strsep(&rcpt, ",")) != NULL) { - struct alias alias; - void *p; + return (val->size); +} + +int +make_aliases(DBT *val, char *text) +{ + struct alias a; + char *subrcpt; + char *endp; + val->data = NULL; + val->size = 0; + + while ((subrcpt = strsep(&text, ",")) != NULL) { /* subrcpt: strip initial whitespace. */ while (isspace(*subrcpt)) ++subrcpt; if (*subrcpt == '\0') - goto bad; + goto error; /* subrcpt: strip trailing whitespace. */ endp = subrcpt + strlen(subrcpt) - 1; while (subrcpt < endp && isspace(*endp)) *endp-- = '\0'; - if (! alias_parse(&alias, subrcpt)) - goto bad; - - key.data = name; - key.size = strlen(name) + 1; - val.data = NULL; - val.size = 0; - if (db->get(db, &key, &val, 0) == -1) { - warn("dbget"); - return 0; - } - - p = calloc(1, val.size + sizeof(struct alias)); - if (p == NULL) { - warn("calloc"); - return 0; - } - memcpy(p, val.data, val.size); - memcpy((u_int8_t *)p + val.size, &alias, sizeof(struct alias)); - - val.data = p; - val.size += sizeof(struct alias); - if (db->put(db, &key, &val, 0) == -1) { - warn("dbput"); - free(p); - return 0; - } + if (! alias_parse(&a, subrcpt)) + goto error; - dbputs++; - free(p); + val->data = realloc(val->data, val->size + sizeof(a)); + if (val->data == NULL) + err(1, "get_targets: realloc"); + memcpy((u_int8_t *)val->data + val->size, &a, sizeof(a)); + val->size += sizeof(a); } - return 1; + return (val->size); + +error: + free(val->data); -bad: - /* The actual line is not printed; it may be mangled by above code. */ - warnx("%s:%zd: invalid entry", source, lineno); return 0; } void usage(void) { - switch (mode) { - case P_MAKEMAP: - fprintf(stderr, "usage: %s file\n", __progname); - break; - case P_NEWALIASES: + if (mode == P_NEWALIASES) fprintf(stderr, "usage: %s\n", __progname); - break; - default: - abort(); - } + else + fprintf(stderr, "usage: %s [-t type] [-o dbfile] file\n", + __progname); exit(1); } diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index de87462f5bd..85b2249136c 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.68 2009/01/30 21:52:55 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.69 2009/02/14 18:37:12 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -34,6 +34,9 @@ /* return and forward path size */ #define MAX_PATH_SIZE 256 +/* makemap mapped value text length */ +#define MAX_MAKEMAP_SIZE 256 + /*#define SMTPD_CONNECT_TIMEOUT (60)*/ #define SMTPD_CONNECT_TIMEOUT (10) #define SMTPD_QUEUE_INTERVAL (15 * 60) @@ -376,7 +379,8 @@ enum alias_type { ALIAS_FILENAME, ALIAS_FILTER, ALIAS_INCLUDE, - ALIAS_ADDRESS + ALIAS_ADDRESS, + ALIAS_TEXT }; struct alias { @@ -386,6 +390,7 @@ struct alias { char username[MAXLOGNAME]; char filename[MAXPATHLEN]; char filter[MAXPATHLEN]; + char text[MAX_MAKEMAP_SIZE]; struct path path; } u; }; |