Commit 9ba835fb 9ba835fbb5a937735f51925c2170bbc748820fcf by Sergey Poznyakoff

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.
1 parent 012c66dd
......@@ -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;
......
......@@ -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;
}
......
......@@ -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
}
......
......@@ -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;
}
......
......@@ -25,6 +25,7 @@ libstring_la_SOURCES = \
cstrunescape.c\
cstrlower.c\
cstrupper.c\
expvar.c\
hexstr.c\
safefilename.c\
stpcpy.c\
......
/* 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;
}
......@@ -46,6 +46,7 @@ noinst_PROGRAMS = \
debugspec\
decode2047\
encode2047\
exp\
fltst\
fsaf\
fsaftomod\
......
#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;
}
......@@ -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)
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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));
}
......
......@@ -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_prompt_assoc (void)
{
if (mutool_prompt_assoc)
mu_assoc_clear (mutool_prompt_assoc);
else
{
int rc = mu_assoc_create (&mutool_prompt_assoc, 0);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_create", NULL, rc);
exit (1);
}
}
mu_assoc_install (mutool_prompt_assoc, "program-name", mu_program_name);
mu_assoc_install (mutool_prompt_assoc, "canonical-program-name",
"mailutils");
mu_assoc_install (mutool_prompt_assoc, "package", PACKAGE);
mu_assoc_install (mutool_prompt_assoc, "version", PACKAGE_VERSION);
return mutool_prompt_assoc;
}
int
mutool_shell (const char *name, struct mutool_command *cmd)
{
......
......@@ -69,39 +69,18 @@ smtp_session_str (enum smtp_session_status stat)
}
static void
smtp_prompt_env ()
smtp_prompt_env (void)
{
mu_assoc_t assoc = mutool_shell_prompt_assoc ();
const char *value;
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] = "[nouser]";
if (smtp_session_status == smtp_session_logged_in &&
mu_smtp_get_param (smtp, MU_SMTP_PARAM_USERNAME, &value) == 0)
mutool_prompt_env[1] = (char*) value;
mutool_prompt_env[2] = "host";
mutool_prompt_env[3] = (smtp_session_status != smtp_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";
mu_assoc_install (assoc, "user", value);
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*) smtp_session_str (smtp_session_status);
mutool_prompt_env[14] = NULL;
if (smtp_session_status != smtp_session_disconnected)
mu_assoc_install (assoc, "host", host);
mu_assoc_install (assoc, "status", smtp_session_str (smtp_session_status));
}
static void
......