diff options
Diffstat (limited to 'modules/mailutils/mailutils.c')
-rw-r--r-- | modules/mailutils/mailutils.c | 180 |
1 files changed, 115 insertions, 65 deletions
diff --git a/modules/mailutils/mailutils.c b/modules/mailutils/mailutils.c index 10018c4..03966c1 100644 --- a/modules/mailutils/mailutils.c +++ b/modules/mailutils/mailutils.c @@ -25,6 +25,7 @@ #include <smap/diag.h> #include <smap/module.h> #include <smap/parseopt.h> +#include <smap/wordsplit.h> static char *dfl_positive_reply = "OK"; static char *dfl_negative_reply = "NOTFOUND"; @@ -66,58 +67,97 @@ _mu_smap_db_free(struct _mu_smap_db *db) free(db); } +static void +free_env(char **env) +{ + int i; + for (i = 0; env[i]; i++) + free(env[i]); +} + static char * -expand_reply_text(const char *arg, struct _mu_smap_result *res) +mkvar(const char *name, const char *val) { - int rc; - mu_vartab_t vtab; - char *reply = NULL; - char buf[512]; - struct mu_auth_data *auth = res->auth; + char *ptr = malloc(strlen(name) + strlen(val) + 2); + if (ptr) { + strcpy(ptr, name); + strcat(ptr, "="); + strcat(ptr, val); + } + return ptr; +} - if (!arg) - return NULL; - mu_vartab_create(&vtab); - mu_vartab_define(vtab, "db", res->db, 0); - mu_vartab_define(vtab, "key", res->key, 0); - mu_vartab_define(vtab, "map", res->map, 0); - mu_vartab_define(vtab, MU_AUTH_NAME, auth ? auth->name : "", 0); - mu_vartab_define(vtab, MU_AUTH_PASSWD, auth ? auth->passwd : "", 0); - if (!auth) - strcpy(buf, "-1"); - else +static int +mkenv(char **env, struct _mu_smap_result *res) +{ + int i = 0; + struct mu_auth_data *auth = res->auth; + char buf[512]; + +#define MKVAR(n, v) \ + do { \ + if (!(env[i++] = mkvar(n, v))) \ + return 1; \ + } while (0) + + MKVAR("db", res->db); + MKVAR("key", res->key); + MKVAR("map", res->map); + if (auth) { + MKVAR(MU_AUTH_NAME, auth->name); + MKVAR(MU_AUTH_PASSWD, auth->passwd); snprintf(buf, sizeof buf, "%lu", (unsigned long) auth->uid); - mu_vartab_define(vtab, MU_AUTH_UID, buf, 0); - if (!auth) - strcpy(buf, "-1"); - else + MKVAR(MU_AUTH_UID, buf); snprintf(buf, sizeof buf, "%lu", (unsigned long) auth->gid); - mu_vartab_define(vtab, MU_AUTH_GID, buf, 0); - mu_vartab_define(vtab, MU_AUTH_GECOS, - auth ? auth->gecos : "", 0); - mu_vartab_define(vtab, MU_AUTH_DIR, auth ? auth->dir : "", 0); - mu_vartab_define(vtab, MU_AUTH_SHELL, auth ? auth->shell : "", 0); - mu_vartab_define(vtab, MU_AUTH_MAILBOX, - (auth && auth->mailbox) ? auth->mailbox : - res->url ? mu_url_to_string(res->url) : "", 0); - if (!auth) - strcpy(buf, "NONE"); - else + MKVAR(MU_AUTH_GID, buf); + MKVAR(MU_AUTH_GECOS, auth->gecos); + MKVAR(MU_AUTH_DIR, auth->dir); + MKVAR(MU_AUTH_SHELL, auth->shell); + MKVAR(MU_AUTH_MAILBOX, + auth->mailbox ? auth->mailbox : + res->url ? mu_url_to_string(res->url) : ""); snprintf(buf, sizeof buf, "%lu", (unsigned long) auth->quota); - mu_vartab_define(vtab, MU_AUTH_QUOTA, buf, 0); - snprintf(buf, sizeof buf, "%lu", (unsigned long) res->mbsize); - mu_vartab_define(vtab, "mbsize", buf, 0); - snprintf(buf, sizeof buf, "%lu", (unsigned long) res->msgsize); - mu_vartab_define(vtab, "msgsize", buf, 0); - + MKVAR(MU_AUTH_QUOTA, buf); + snprintf(buf, sizeof buf, "%lu", (unsigned long) res->mbsize); + MKVAR("mbsize", buf); + snprintf(buf, sizeof buf, "%lu", (unsigned long) res->msgsize); + MKVAR("msgsize", buf); + } if (res->diag) - mu_vartab_define(vtab, "diag", res->diag, 1); - rc = mu_vartab_expand(vtab, arg, &reply); + MKVAR("diag", res->diag); + + env[i] = NULL; + return 0; +} + +static int +expand_reply_text(const char *arg, struct _mu_smap_result *res, char **repl) +{ + int rc; + char *env[16]; + struct wordsplit ws; + + if (mkenv(env, res)) { + mu_error("not enough memory"); + free_env(env); + return 1; + } + + ws.ws_env = (const char **) env; + ws.ws_error = smap_error; + rc = wordsplit(arg, &ws, + WRDSF_NOSPLIT | + WRDSF_NOCMD | + WRDSF_ENV | + WRDSF_ERROR | + WRDSF_SHOWERR); + free_env(env); if (rc) - mu_error("cannot expand string `%s': %s", - arg, mu_strerror (rc)); - mu_vartab_destroy(&vtab); - return reply; + return 1; + *repl = ws.ws_wordv[0]; + ws.ws_wordv = NULL; + wordsplit_free(&ws); + return 0; } static int @@ -130,7 +170,8 @@ _mu_auth_query(smap_database_t dbp, struct mu_auth_data *auth = mu_get_auth_by_name(key); struct _mu_smap_result res; char *reply; - + int rc; + res.db = mdb->id; res.map = map; res.key = key; @@ -140,14 +181,16 @@ _mu_auth_query(smap_database_t dbp, res.diag = NULL; res.url = NULL; if (!auth) - reply = expand_reply_text(mdb->negative_reply, &res); + rc = expand_reply_text(mdb->negative_reply, &res, &reply); else { - reply = expand_reply_text(mdb->positive_reply, &res); + rc = expand_reply_text(mdb->positive_reply, &res, &reply); mu_auth_data_free(auth); } - smap_stream_printf(ostr, "%s\n", reply); - free(reply); - return 0; + if (rc == 0) { + smap_stream_printf(ostr, "%s\n", reply); + free(reply); + } + return rc; } static int @@ -181,32 +224,34 @@ switch_user_id(struct mu_auth_data *auth, int user) return rc; } -static char * +static int checksize(struct _mu_smap_db *mdb, smap_stream_t ostr, - const char *user, struct _mu_smap_result *res) + const char *user, struct _mu_smap_result *res, + char **preply) { struct mu_auth_data *auth; mu_mailbox_t mbox; int status; - char *reply_txt = NULL; + + *preply = NULL; auth = mu_get_auth_by_name(user); res->auth = auth; if (!auth) { res->diag = "user not found"; smap_debug(dbgid, 1, ("%s: user not found", user)); - return NULL; + return 0; } if (switch_user_id(auth, 1)) { res->diag = "local system error"; - return NULL; + return 0; } status = mu_mailbox_create_default(&mbox, auth->mailbox); if (status) { res->diag = "local system error"; mu_error("could not create mailbox `%s': %s", auth->mailbox, mu_strerror(status)); - return NULL; + return 0; } mu_mailbox_get_url(mbox, &res->url); @@ -245,14 +290,15 @@ checksize(struct _mu_smap_db *mdb, smap_stream_t ostr, stat = mdb->positive_reply; res->diag = "QUOTAOK"; } - reply_txt = expand_reply_text(stat, res); + if (expand_reply_text(stat, res, preply)) + return 1; } switch_user_id(auth, 0); mu_mailbox_close(mbox); } mu_mailbox_destroy(&mbox); mu_auth_data_free(auth); - return reply_txt; + return 0; } static int @@ -267,7 +313,8 @@ _mu_mbq_query(smap_database_t dbp, size_t len; struct _mu_smap_result res; char *reply; - + int rc; + memset(&res, 0, sizeof(res)); res.db = mdb->id; res.map = map; @@ -290,13 +337,16 @@ _mu_mbq_query(smap_database_t dbp, ("ignoring junk after %s", user + len)); } - reply = checksize(mdb, ostr, user, &res); - if (!reply) - reply = expand_reply_text(mdb->onerror_reply, &res); - smap_stream_printf(ostr, "%s\n", reply); - free(reply); + rc = checksize(mdb, ostr, user, &res, &reply); + + if (!rc && !reply) + rc = expand_reply_text(mdb->onerror_reply, &res, &reply); + if (rc == 0) { + smap_stream_printf(ostr, "%s\n", reply); + free(reply); + } free(user); - return 0; + return rc; } |