summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-02-14 18:37:13 +0000
committerJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-02-14 18:37:13 +0000
commit429780f3a931abd6d29e80616a6abb156e879e9d (patch)
tree112f7642c540f04a25b578628da624f6f2680365
parentb0b4b10dbc7b5d1203b085c2fd3d8bef652935b4 (diff)
Implement makemap -t and -o, for output type and dest resp.; ok gilles@
-rw-r--r--usr.sbin/smtpd/makemap.837
-rw-r--r--usr.sbin/smtpd/makemap.c260
-rw-r--r--usr.sbin/smtpd/smtpd.h9
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;
};