summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-01-18 17:39:16 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-01-19 08:58:20 +0200
commit9ba835fbb5a937735f51925c2170bbc748820fcf (patch)
tree01ebe749a4b4b2ac3e139cb140b34a6459774c5d
parent012c66ddbbf4c852f2f26e1c075e7ddb808559c1 (diff)
downloadmailutils-9ba835fbb5a937735f51925c2170bbc748820fcf.tar.gz
mailutils-9ba835fbb5a937735f51925c2170bbc748820fcf.tar.bz2
Provide functions for expanding string using mu_assoc_t table.
The functions are used wherever variables can be expected, most notably in configuration statements, such as ldap, namespace (imap4d), etc. Apart from expanding variables it also provides command expansion $(command args...) The commands currently available are: domainpart ARG splits its argument on the first occurrence of @ and returns the part after it. localpart ARG splits its argument on the first occurrence of @ and returns the part before it. shell CMD ARG... runs shell command CMD and returns its output * include/mailutils/cstr.h (mu_str_expand, mu_str_vexpand): New protos. * libmailutils/string/expvar.c: New file. * libmailutils/string/Makefile.am: Add expvar.c * libmailutils/tests/exp.c: New file. * libmailutils/tests/Makefile.am: Add exp.c * imap4d/imap4d.c (namespace_cfg_init): Fix docstring. * imap4d/namespace.c (namespace_translate_name): Use mu_str_expand. * libmailutils/mailbox/mbx_default.c (mu_construct_user_mailbox_url): Use mu_str_vexpand. * libmu_auth/ldap.c (_mu_ldap_search): Likewise. * libmu_auth/radius.c (_expand_query): Likewise. * libmu_auth/sql.c (mu_sql_expand_query): Likewise. * mu/shell.c (mutool_prompt_env): Remove. (shell_prompt): Rewrite (input_line_interactive): Use mu_str_expand. (mutool_shell_prompt_assoc): New function. * mu/mu.h (mutool_shell_prompt_assoc): New proto. * mu/imap.c (imap_prompt_env): Use mutool_shell_prompt_assoc. * mu/pop.c (pop_prompt_env): Likewise. * mu/smtp.c (smtp_prompt_env): Likewise.
-rw-r--r--imap4d/imap4d.c1
-rw-r--r--imap4d/namespace.c82
-rw-r--r--include/mailutils/cstr.h3
-rw-r--r--libmailutils/mailbox/mbx_default.c32
-rw-r--r--libmailutils/string/Makefile.am1
-rw-r--r--libmailutils/string/expvar.c341
-rw-r--r--libmailutils/tests/Makefile.am1
-rw-r--r--libmailutils/tests/exp.c51
-rw-r--r--libmu_auth/ldap.c40
-rw-r--r--libmu_auth/radius.c39
-rw-r--r--libmu_auth/sql.c32
-rw-r--r--mu/imap.c43
-rw-r--r--mu/mu.h2
-rw-r--r--mu/pop.c34
-rw-r--r--mu/shell.c64
-rw-r--r--mu/smtp.c33
16 files changed, 557 insertions, 242 deletions
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index eca84c9d6..ceded08b8 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -517,6 +517,7 @@ namespace_cfg_init (void)
if (mu_create_canned_section ("prefix", &section))
abort ();
section->docstring = N_("Define a single prefix");
+ section->label = N_("string");
mu_cfg_section_add_params (section, prefix_param);
section->parser = prefix_section_parser;
diff --git a/imap4d/namespace.c b/imap4d/namespace.c
index cf5e550bf..242549a8e 100644
--- a/imap4d/namespace.c
+++ b/imap4d/namespace.c
@@ -153,28 +153,6 @@ namespace_init (void)
mu_assoc_sort_r (prefixes, cmplen, NULL);
}
-static int
-expand_vars (char **env, char const *input, char **output)
-{
- struct mu_wordsplit ws;
- size_t wordc;
- char **wordv;
-
- ws.ws_env = (const char **) env;
- if (mu_wordsplit (input, &ws,
- MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
- MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
- {
- mu_error (_("cannot expand line `%s': %s"), input,
- mu_wordsplit_strerror (&ws));
- return 1;
- }
- mu_wordsplit_get_words (&ws, &wordc, &wordv);
- *output = wordv[0];
- mu_wordsplit_free (&ws);
- return 0;
-}
-
static char *
prefix_translate_name (struct namespace_prefix const *pfx, char const *name,
size_t namelen, int url)
@@ -290,23 +268,12 @@ extract_username (char const *name, struct namespace_prefix const *pfx)
return user;
}
-enum
- {
- ENV_USER = 1,
- ENV_HOME = 3,
- ENV_NULL = 4
- };
-
-#define ENV_INITIALIZER \
- { [ENV_USER-1] = "user", [ENV_HOME-1] = "home", [ENV_NULL] = NULL }
-
char *
namespace_translate_name (char const *name, int url,
struct namespace_prefix const **return_pfx)
{
char *res = NULL;
struct namespace_prefix const *pfx;
- char *env[] = ENV_INITIALIZER;
if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
{
@@ -318,44 +285,65 @@ namespace_translate_name (char const *name, int url,
if (res)
{
+ mu_assoc_t assoc;
+ int rc;
char *dir;
+ rc = mu_assoc_create (&assoc, 0);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_create", NULL, rc);
+ free (res);
+ imap4d_bye (ERR_NO_MEM);
+ }
+
switch (pfx->ns)
{
case NS_PRIVATE:
- env[ENV_USER] = auth_data->name;
- env[ENV_HOME] = real_homedir;
+ mu_assoc_install (assoc, "user", auth_data->name);
+ mu_assoc_install (assoc, "home", real_homedir);
break;
case NS_OTHER:
{
struct mu_auth_data *adata;
- env[ENV_USER] = extract_username (name, pfx);
- adata = mu_get_auth_by_name (env[ENV_USER]);
+ char *user = extract_username (name, pfx);
+ mu_assoc_install (assoc, "user", user);
+ adata = mu_get_auth_by_name (user);
if (adata)
{
- env[ENV_HOME] = mu_strdup (adata->dir);
+ mu_assoc_install (assoc, "home", mu_strdup (adata->dir));
mu_auth_data_free (adata);
}
+ mu_assoc_set_destroy_item (assoc, mu_list_free_item);
}
break;
case NS_SHARED:
break;
}
-
- if (expand_vars (env, res, &dir))
- imap4d_bye (ERR_NO_MEM);
+
+ rc = mu_str_expand (&dir, res, assoc);
free (res);
- res = dir;
- trim_delim (res, '/');
-
- if (pfx->ns == NS_OTHER)
+ mu_assoc_destroy (&assoc);
+ if (rc)
{
- free (env[ENV_USER]);
- free (env[ENV_HOME]);
+ if (rc == MU_ERR_FAILURE)
+ {
+ mu_error (_("cannot expand line `%s': %s"), res, dir);
+ free (dir);
+ }
+ else
+ {
+ mu_error (_("cannot expand line `%s': %s"), res,
+ mu_strerror (rc));
+ }
+ imap4d_bye (ERR_NO_MEM);
}
+ res = dir;
+ trim_delim (res, '/');
+
if (return_pfx)
*return_pfx = pfx;
}
diff --git a/include/mailutils/cstr.h b/include/mailutils/cstr.h
index 6ad331740..ec909d31d 100644
--- a/include/mailutils/cstr.h
+++ b/include/mailutils/cstr.h
@@ -58,6 +58,9 @@ int mu_c_str_unescape (char const *str, char const *chr, char const *xtab,
int mu_c_str_unescape_trans (char const *str, char const *trans,
char **ret_str);
+
+int mu_str_expand (char **output, char const *input, mu_assoc_t assoc);
+int mu_str_vexpand (char **output, char const *input, ...);
#ifdef __cplusplus
}
diff --git a/libmailutils/mailbox/mbx_default.c b/libmailutils/mailbox/mbx_default.c
index 6ece82560..dad953569 100644
--- a/libmailutils/mailbox/mbx_default.c
+++ b/libmailutils/mailbox/mbx_default.c
@@ -38,7 +38,7 @@
#include <mailutils/mu_auth.h>
#include <mailutils/folder.h>
#include <mailutils/auth.h>
-#include <mailutils/wordsplit.h>
+#include <mailutils/cstr.h>
#include <mailutils/io.h>
#include <mailutils/sys/mailbox.h>
@@ -158,32 +158,22 @@ mu_construct_user_mailbox_url (char **pout, const char *name)
{
int rc;
const char *pat = mu_mailbox_url ();
- const char *env[3];
- struct mu_wordsplit ws;
-
- env[0] = "user";
- env[1] = (char*) name;
- env[2] = NULL;
- ws.ws_env = env;
- rc = mu_wordsplit (pat, &ws,
- MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
- MU_WRDSF_ENV | MU_WRDSF_ENV_KV);
+ char *result;
+ rc = mu_str_vexpand (&result, pat, "user", name, NULL);
if (rc)
{
- mu_error (_("cannot expand line `%s': %s"), pat,
- mu_wordsplit_strerror (&ws));
+ if (rc == MU_ERR_FAILURE)
+ {
+ mu_error (_("cannot expand line `%s': %s"), pat, result);
+ free (result);
+ }
+ else
+ mu_error (_("cannot expand line `%s': %s"), pat, mu_strerror (rc));
return rc;
}
- if (ws.ws_wordc == 0)
- /* FIXME: a special return code maybe? */
- *pout = strdup ("");
- else
- *pout = strdup (ws.ws_wordv[0]);
- mu_wordsplit_free (&ws);
- if (!*pout)
- return ENOMEM;
+ *pout = result;
return 0;
}
diff --git a/libmailutils/string/Makefile.am b/libmailutils/string/Makefile.am
index 035accf20..76d8421d0 100644
--- a/libmailutils/string/Makefile.am
+++ b/libmailutils/string/Makefile.am
@@ -25,6 +25,7 @@ libstring_la_SOURCES = \
cstrunescape.c\
cstrlower.c\
cstrupper.c\
+ expvar.c\
hexstr.c\
safefilename.c\
stpcpy.c\
diff --git a/libmailutils/string/expvar.c b/libmailutils/string/expvar.c
new file mode 100644
index 000000000..a9361ef85
--- /dev/null
+++ b/libmailutils/string/expvar.c
@@ -0,0 +1,341 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2003, 2005-2007, 2009-2012, 2014-2017 Free
+ Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/errno.h>
+#include <mailutils/error.h>
+#include <mailutils/io.h>
+#include <mailutils/nls.h>
+#include <mailutils/assoc.h>
+#include <mailutils/cstr.h>
+#include <mailutils/cctype.h>
+#include <mailutils/wordsplit.h>
+
+static int
+exp_getvar (char **ret, const char *vptr, size_t vlen, void *data)
+{
+ int rc;
+ char *varname, *s = NULL;
+ mu_assoc_t assoc = data;
+
+ if (mu_assoc_is_empty (assoc))
+ return MU_WRDSE_UNDEF;
+
+ varname = malloc (vlen + 1);
+ if (!varname)
+ return MU_WRDSE_NOSPACE;
+ memcpy (varname, vptr, vlen);
+ varname[vlen] = 0;
+
+ rc = mu_assoc_lookup (assoc, varname, &s);
+ free (varname);
+
+ switch (rc)
+ {
+ case 0:
+ rc = MU_WRDSE_OK;
+ break;
+
+ case MU_ERR_NOENT:
+ rc = MU_WRDSE_UNDEF;
+ break;
+
+ case MU_ERR_BUFSPACE:
+ case ENOMEM:
+ rc = MU_WRDSE_NOSPACE;
+ break;
+
+ default:
+ s = (char*) mu_strerror (rc);
+ rc = MU_WRDSE_USERERR;
+ }
+
+ if (s)
+ {
+ s = strdup (s);
+ if (!s)
+ return MU_WRDSE_NOSPACE;
+ *ret = s;
+ }
+
+ return rc;
+}
+
+static int
+exp_localpart (int argc, char **argv, char **result)
+{
+ size_t len = strcspn (argv[1], "@");
+ char *s;
+
+ s = malloc (len + 1);
+ if (!s)
+ return MU_WRDSE_NOSPACE;
+ memcpy (s, argv[1], len);
+ s[len] = 0;
+
+ *result = s;
+ return MU_WRDSE_OK;
+}
+
+static int
+exp_domainpart (int argc, char **argv, char **result)
+{
+ char *s = strchr (argv[1], '@');
+
+ if (s)
+ s++;
+ else
+ s = "";
+
+ s = strdup (s);
+ if (!s)
+ return MU_WRDSE_NOSPACE;
+
+ *result = s;
+
+ return MU_WRDSE_OK;
+}
+
+static int
+exp_shell (char **ret, char const *str, size_t len, void *closure)
+{
+ FILE *fp;
+ char *cmd;
+ int c, lastc;
+ char *buffer = NULL;
+ size_t bufsize = 0;
+ size_t buflen = 0;
+
+ cmd = malloc (len + 1);
+ if (!cmd)
+ return MU_WRDSE_NOSPACE;
+ memcpy (cmd, str, len);
+ cmd[len] = 0;
+
+ fp = popen (cmd, "r");
+ if (!fp)
+ {
+ ret = NULL;
+ if (mu_asprintf (ret, "can't run %s: %s", cmd, mu_strerror (errno)))
+ return MU_WRDSE_NOSPACE;
+ else
+ return MU_WRDSE_USERERR;
+ }
+
+ while ((c = fgetc (fp)) != EOF)
+ {
+ lastc = c;
+ if (c == '\n')
+ c = ' ';
+ if (buflen == bufsize)
+ {
+ char *p;
+
+ if (bufsize == 0)
+ bufsize = 80;
+ else
+ bufsize *= 2;
+ p = realloc (buffer, bufsize);
+ if (!p)
+ {
+ free (buffer);
+ free (cmd);
+ return MU_WRDSE_NOSPACE;
+ }
+ buffer = p;
+ }
+ buffer[buflen++] = c;
+ }
+
+ if (buffer)
+ {
+ if (lastc == '\n')
+ --buflen;
+ buffer[buflen] = 0;
+ }
+
+ pclose (fp);
+ free (cmd);
+
+ *ret = buffer;
+ return MU_WRDSE_OK;
+}
+
+struct exp_command
+{
+ char *name;
+ int minarg;
+ int maxarg;
+ int (*exp) (int argc, char **argv, char **ret);
+};
+
+static struct exp_command exp_command_tab[] = {
+ { "localpart", 2, 2, exp_localpart },
+ { "domainpart", 2, 2, exp_domainpart },
+ { NULL }
+};
+
+static struct exp_command *
+findcom (char const *name)
+{
+ struct exp_command *cp;
+
+ for (cp = exp_command_tab; cp->name; cp++)
+ if (strcmp (name, cp->name) == 0)
+ return cp;
+
+ return NULL;
+}
+
+static int
+checkargc (struct exp_command *cmd, int argc)
+{
+ if (cmd->minarg && argc < cmd->minarg)
+ return 1;
+ else if (cmd->maxarg && argc > cmd->maxarg)
+ return 1;
+ return 0;
+}
+
+#define SHELL_CMD "shell"
+
+static int
+exp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure)
+{
+ int argc;
+ struct exp_command *cmd;
+ char *result = NULL;
+ int rc;
+
+ if (strcmp (argv[0], SHELL_CMD) == 0)
+ {
+ len -= sizeof SHELL_CMD;
+ str += sizeof SHELL_CMD;
+ while (len > 0 && mu_isspace (*str))
+ {
+ len--;
+ str++;
+ }
+
+ if (len == 0)
+ {
+ if (mu_asprintf (ret, _("%s: bad number of arguments"), argv[0]))
+ return MU_WRDSE_NOSPACE;
+ return MU_WRDSE_USERERR;
+ }
+ return exp_shell (ret, str, len, closure);
+ }
+
+ cmd = findcom (argv[0]);
+ if (!cmd)
+ {
+ if (mu_asprintf (ret, _("%s: unknown function"), argv[0]))
+ return MU_WRDSE_NOSPACE;
+ return MU_WRDSE_USERERR;
+ }
+
+ for (argc = 0; argv[argc]; argc++)
+ ;
+
+ if (checkargc (cmd, argc))
+ {
+ if (mu_asprintf (ret, _("%s: bad number of arguments"), argv[0]))
+ return MU_WRDSE_NOSPACE;
+ return MU_WRDSE_USERERR;
+ }
+
+ rc = cmd->exp (argc, argv, &result);
+ if (rc == MU_WRDSE_USERERR && result == NULL)
+ {
+ if (mu_asprintf (ret, _("%s: command expansion error"), argv[0]))
+ return MU_WRDSE_NOSPACE;
+ return MU_WRDSE_USERERR;
+ }
+
+ if (rc == MU_WRDSE_OK || rc == MU_WRDSE_USERERR)
+ *ret = result;
+
+ return rc;
+}
+
+int
+mu_str_expand (char **output, char const *input, mu_assoc_t assoc)
+{
+ struct mu_wordsplit ws;
+ size_t wordc;
+ char **wordv;
+
+ ws.ws_getvar = exp_getvar;
+ ws.ws_command = exp_runcmd;
+ ws.ws_closure = assoc;
+ ws.ws_options = MU_WRDSO_ARGV;
+
+ if (mu_wordsplit (input, &ws,
+ MU_WRDSF_NOSPLIT | MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE
+ | MU_WRDSF_OPTIONS))
+ {
+ char *p = strdup (mu_wordsplit_strerror (&ws));
+ if (p)
+ *output = p;
+ return MU_ERR_FAILURE;
+ }
+ mu_wordsplit_get_words (&ws, &wordc, &wordv);
+ *output = wordv[0];
+ mu_wordsplit_free (&ws);
+ return 0;
+}
+
+int
+mu_str_vexpand (char **output, char const *input, ...)
+{
+ int rc;
+ mu_assoc_t assoc;
+ char *p[2];
+ int i;
+ va_list ap;
+
+ rc = mu_assoc_create (&assoc, 0);
+ if (rc)
+ return rc;
+
+ va_start (ap, input);
+ i = 0;
+ while ((p[i] = va_arg (ap, char *)) != NULL)
+ {
+ if (i == 1)
+ {
+ rc = mu_assoc_install (assoc, p[0], p[1]);
+ if (rc)
+ {
+ mu_assoc_destroy (&assoc);
+ return rc;
+ }
+ }
+ i = (i + 1) % 2;
+ }
+ va_end (ap);
+
+ rc = mu_str_expand (output, input, assoc);
+ mu_assoc_destroy (&assoc);
+ return rc;
+}
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 86cca83cd..b31b5ac79 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -46,6 +46,7 @@ noinst_PROGRAMS = \
debugspec\
decode2047\
encode2047\
+ exp\
fltst\
fsaf\
fsaftomod\
diff --git a/libmailutils/tests/exp.c b/libmailutils/tests/exp.c
new file mode 100644
index 000000000..35a52d00b
--- /dev/null
+++ b/libmailutils/tests/exp.c
@@ -0,0 +1,51 @@
+#include <mailutils/mailutils.h>
+
+int
+main (int argc, char **argv)
+{
+ mu_assoc_t assc;
+ char *p;
+ int i;
+
+ MU_ASSERT (mu_assoc_create (&assc, 0));
+
+ for (i = 1; i < argc; i++)
+ {
+ p = strchr (argv[i], '=');
+ if (p)
+ {
+ *p++ = 0;
+ MU_ASSERT (mu_assoc_install (assc, argv[i], p));
+ }
+ else if (strcmp (argv[i], "--") == 0)
+ {
+ i++;
+ break;
+ }
+ else
+ break;
+ }
+
+ for (; i < argc; i++)
+ {
+ int rc = mu_str_expand (&p, argv[i], assc);
+ switch (rc)
+ {
+ case 0:
+ printf ("%s\n", p);
+ free (p);
+ break;
+
+ case MU_ERR_FAILURE:
+ mu_error ("%s", p);
+ free (p);
+ break;
+
+ default:
+ mu_error ("%s", mu_strerror (rc));
+ }
+ }
+
+ return 0;
+}
+
diff --git a/libmu_auth/ldap.c b/libmu_auth/ldap.c
index b9594f000..298b5ba98 100644
--- a/libmu_auth/ldap.c
+++ b/libmu_auth/ldap.c
@@ -598,38 +598,34 @@ _mu_ldap_search (LDAP *ld, const char *filter_pat, const char *key,
size_t nattrs;
LDAPMessage *res, *msg;
ber_int_t msgid;
- const char *env[3];
- struct mu_wordsplit ws;
-
+ char *filter_str;
+
rc = _construct_attr_array (&nattrs, &attrs);
if (rc)
return rc;
- env[0] = "user";
- env[1] = key;
- env[2] = NULL;
-
- ws.ws_env = env;
- if (mu_wordsplit (filter_pat, &ws,
- MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
- MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
- {
- mu_error (_("cannot expand line `%s': %s"), filter_pat,
- mu_wordsplit_strerror (&ws));
- return MU_ERR_FAILURE;
- }
- else if (ws.ws_wordc == 0)
+ rc = mu_str_vexpand (&filter_str, filter_pat, "user", key, NULL);
+ if (rc)
{
- mu_error (_("expanding %s yields empty string"), filter_pat);
- mu_wordsplit_free (&ws);
mu_argcv_free (nattrs, attrs);
- return MU_ERR_FAILURE;
+ if (rc == MU_ERR_FAILURE)
+ {
+ mu_error (_("cannot expand line `%s': %s"), filter_pat,
+ filter_str);
+ free (filter_str);
+ }
+ else
+ {
+ mu_error (_("cannot expand line `%s': %s"), filter_pat,
+ mu_strerror (rc));
+ }
+ return rc;
}
rc = ldap_search_ext (ld, ldap_param.base, LDAP_SCOPE_SUBTREE,
- ws.ws_wordv[0], attrs, 0,
+ filter_str, attrs, 0,
NULL, NULL, NULL, -1, &msgid);
- mu_wordsplit_free (&ws);
+ free (filter_str);
mu_argcv_free (nattrs, attrs);
if (rc != LDAP_SUCCESS)
diff --git a/libmu_auth/radius.c b/libmu_auth/radius.c
index 08a00c738..acd563411 100644
--- a/libmu_auth/radius.c
+++ b/libmu_auth/radius.c
@@ -35,6 +35,7 @@
#include <mailutils/iterator.h>
#include <mailutils/mailbox.h>
#include <mailutils/radius.h>
+#include <mailutils/cstr.h>
#include <mailutils/wordsplit.h>
#include <mailutils/mu_auth.h>
#include <mailutils/error.h>
@@ -275,35 +276,25 @@ module_init (void *ptr)
static char *
_expand_query (const char *query, const char *ustr, const char *passwd)
{
- struct mu_wordsplit ws;
- const char *env[2 * 2 + 1];
char *ret;
-
- env[0] = "user";
- env[1] = (char*) ustr;
- env[2] = "passwd";
- env[3] = (char*) passwd;
- env[4] = NULL;
-
- ws.ws_env = env;
- if (mu_wordsplit (query, &ws,
- MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
- MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
- {
- mu_error (_("cannot expand line `%s': %s"), query,
- mu_wordsplit_strerror (&ws));
- return NULL;
- }
- else if (ws.ws_wordc == 0)
+ int rc;
+
+ rc = mu_str_vexpand (&ret, query,
+ "user", ustr,
+ "passwd", passwd,
+ NULL);
+ if (rc)
{
- mu_error (_("expanding %s yields empty string"), query);
- mu_wordsplit_free (&ws);
+ if (rc == MU_ERR_FAILURE)
+ {
+ mu_error (_("cannot expand line `%s': %s"), query, ret);
+ free (ret);
+ }
+ else
+ mu_error (_("cannot expand line `%s': %s"), query, mu_strerror (rc));
return NULL;
}
- ret = grad_emalloc (strlen (ws.ws_wordv[0]) + 1);
- strcpy (ret, ws.ws_wordv[0]);
- mu_wordsplit_free (&ws);
return ret;
}
diff --git a/libmu_auth/sql.c b/libmu_auth/sql.c
index bff0842a5..d69c36c52 100644
--- a/libmu_auth/sql.c
+++ b/libmu_auth/sql.c
@@ -187,37 +187,27 @@ sql_escape_string (const char *ustr)
char *
mu_sql_expand_query (const char *query, const char *ustr)
{
+ int rc;
char *res;
char *esc_ustr;
- struct mu_wordsplit ws;
- const char *env[2 + 1];
if (!query)
return NULL;
esc_ustr = sql_escape_string (ustr);
- env[0] = "user";
- env[1] = (char*) ustr;
- env[2] = NULL;
-
- ws.ws_env = env;
- if (mu_wordsplit (query, &ws,
- MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
- MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
- {
- mu_error (_("cannot expand line `%s': %s"), query,
- mu_wordsplit_strerror (&ws));
- return NULL;
- }
- else if (ws.ws_wordc == 0)
+ rc = mu_str_vexpand (&res, query, "user", esc_ustr, NULL);
+ free (esc_ustr);
+ if (rc)
{
- mu_error (_("expanding %s yields empty string"), query);
- mu_wordsplit_free (&ws);
+ if (rc == MU_ERR_FAILURE)
+ {
+ mu_error (_("cannot expand line `%s': %s"), query, res);
+ free (res);
+ }
+ else
+ mu_error (_("cannot expand line `%s': %s"), query, mu_strerror (rc));
return NULL;
}
- res = strdup (ws.ws_wordv[0]);
- mu_wordsplit_free (&ws);
- free (esc_ustr);
return res;
}
diff --git a/mu/imap.c b/mu/imap.c
index b6008423a..34e4ef2d7 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -121,37 +121,20 @@ static char **connect_argv;
static char *username;
static void
-imap_prompt_env ()
+imap_prompt_env (void)
{
+ mu_assoc_t assoc = mutool_shell_prompt_assoc ();
enum mu_imap_session_state state = current_imap_state ();
- if (!mutool_prompt_env)
- mutool_prompt_env = mu_calloc (2*7 + 1, sizeof(mutool_prompt_env[0]));
-
- mutool_prompt_env[0] = "user";
- mutool_prompt_env[1] = (state >= MU_IMAP_SESSION_AUTH && username) ?
- username : "[nouser]";
-
- mutool_prompt_env[2] = "host";
- mutool_prompt_env[3] = connect_argv ? host : "[nohost]";
-
- mutool_prompt_env[4] = "program-name";
- mutool_prompt_env[5] = (char*) mu_program_name;
-
- mutool_prompt_env[6] = "canonical-program-name";
- mutool_prompt_env[7] = "mu";
-
- mutool_prompt_env[8] = "package";
- mutool_prompt_env[9] = PACKAGE;
-
- mutool_prompt_env[10] = "version";
- mutool_prompt_env[11] = PACKAGE_VERSION;
+ const char *p;
+
+ if (state >= MU_IMAP_SESSION_AUTH && username)
+ mu_assoc_install (assoc, "user", username);
- mutool_prompt_env[12] = "status";
- if (mu_imap_session_state_str (state,
- (const char **) &mutool_prompt_env[13]))
- mutool_prompt_env[12] = NULL;
+ if (connect_argv)
+ mu_assoc_install (assoc, "host", host);
- mutool_prompt_env[14] = NULL;
+ if (mu_imap_session_state_str (state, &p) == 0)
+ mu_assoc_install (assoc, "status", (void*) p);
}
/* Callbacks */
@@ -724,7 +707,11 @@ com_login (int argc, char **argv)
memset (pwd, 0, strlen (pwd));
free (passbuf);
if (status == 0)
- imap_prompt_env ();
+ {
+ free (username);
+ username = mu_strdup (argv[1]);
+ imap_prompt_env ();
+ }
else
report_failure ("login", status);
return 0;
diff --git a/mu/mu.h b/mu/mu.h
index 6f286f212..712cafe1a 100644
--- a/mu/mu.h
+++ b/mu/mu.h
@@ -43,8 +43,8 @@ struct mutool_command
};
extern char *mutool_shell_prompt;
-extern char **mutool_prompt_env;
extern int mutool_shell_interactive;
+mu_assoc_t mutool_shell_prompt_assoc (void);
int mutool_shell (const char *name, struct mutool_command *cmd);
mu_stream_t mutool_open_pager (void);
diff --git a/mu/pop.c b/mu/pop.c
index 22af12959..cf4d60f06 100644
--- a/mu/pop.c
+++ b/mu/pop.c
@@ -56,35 +56,17 @@ pop_session_str (enum pop_session_status stat)
}
static void
-pop_prompt_env ()
+pop_prompt_env (void)
{
- if (!mutool_prompt_env)
- mutool_prompt_env = mu_calloc (2*7 + 1, sizeof(mutool_prompt_env[0]));
+ mu_assoc_t assoc = mutool_shell_prompt_assoc ();
- mutool_prompt_env[0] = "user";
- mutool_prompt_env[1] = (pop_session_status == pop_session_logged_in) ?
- username : "[nouser]";
-
- mutool_prompt_env[2] = "host";
- mutool_prompt_env[3] = (pop_session_status != pop_session_disconnected) ?
- host : "[nohost]";
-
- mutool_prompt_env[4] = "program-name";
- mutool_prompt_env[5] = (char*) mu_program_name;
-
- mutool_prompt_env[6] = "canonical-program-name";
- mutool_prompt_env[7] = "mu";
-
- mutool_prompt_env[8] = "package";
- mutool_prompt_env[9] = PACKAGE;
-
- mutool_prompt_env[10] = "version";
- mutool_prompt_env[11] = PACKAGE_VERSION;
-
- mutool_prompt_env[12] = "status";
- mutool_prompt_env[13] = (char*) pop_session_str (pop_session_status);
+ if (pop_session_status == pop_session_logged_in)
+ mu_assoc_install (assoc, "user", username);
+ if (pop_session_status != pop_session_disconnected)
+ mu_assoc_install (assoc, "host", host);
- mutool_prompt_env[14] = NULL;
+ mu_assoc_install (assoc, "status",
+ pop_session_str (pop_session_status));
}
diff --git a/mu/shell.c b/mu/shell.c
index c1d8415b8..358306f9b 100644
--- a/mu/shell.c
+++ b/mu/shell.c
@@ -24,7 +24,7 @@
#endif
char *mutool_shell_prompt;
-char **mutool_prompt_env;
+static mu_assoc_t mutool_prompt_assoc;
int mutool_shell_interactive;
@@ -63,7 +63,7 @@ static int shell_history (int, char **);
#endif
struct mutool_command default_comtab[] = {
- { "prompt", 1, 2, CMD_COALESCE_EXTRA_ARGS, shell_prompt,
+ { "prompt", 1, 2, 0, shell_prompt,
N_("STRING"),
N_("set command prompt") },
{ "exit", 1, 1, 0, shell_exit, NULL, N_("exit program") },
@@ -244,16 +244,8 @@ shell_help (int argc, char **argv)
static int
shell_prompt (int argc, char **argv)
{
- mu_wordsplit_t ws;
-
- if (mu_wordsplit (argv[1], &ws, MU_WRDSF_NOSPLIT | MU_WRDSF_DEFFLAGS))
- mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws));
- else
- {
- free (mutool_shell_prompt);
- mutool_shell_prompt = mu_strdup (ws.ws_wordv[0]);
- }
- mu_wordsplit_free (&ws);
+ free (mutool_shell_prompt);
+ mutool_shell_prompt = mu_strdup (argv[1]);
return 0;
}
@@ -593,23 +585,22 @@ execute_line (char *line)
static char *
input_line_interactive ()
{
- char *line;
- int wsflags = MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD;
- struct mu_wordsplit ws;
+ char *line, *prompt;
+ int rc;
report_signals ();
- if (mutool_prompt_env)
+ rc = mu_str_expand (&prompt, mutool_shell_prompt, mutool_prompt_assoc);
+ if (rc)
{
- ws.ws_env = (const char **)mutool_prompt_env;
- wsflags |= MU_WRDSF_ENV | MU_WRDSF_ENV_KV;
- }
- if (mu_wordsplit (mutool_shell_prompt, &ws, wsflags))
- line = readline (mutool_shell_prompt);
- else
- {
- line = readline (ws.ws_wordv[0]);
- mu_wordsplit_free (&ws);
+ if (rc == MU_ERR_FAILURE)
+ mu_error (_("cannot expand prompt: %s"), prompt);
+ else
+ mu_error (_("cannot expand prompt: %s"), mu_strerror (rc));
+ exit (1);
}
+
+ line = readline (prompt);
+ free (prompt);
return line;
}
@@ -634,6 +625,29 @@ shell_exit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
return 0;
}
+mu_assoc_t
+mutool_shell_pr