summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-08-11 07:30:45 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-08-11 07:30:45 +0000
commit9a1d162e76c05616bc4f1fedc98825f5ace01aed (patch)
treeb4f03b06e2f393cc267332cd843c26f8cdd2a7d1
parent8e8f1a173abe3c1cd65124007640b1c19186effc (diff)
downloadmailutils-9a1d162e76c05616bc4f1fedc98825f5ace01aed.tar.gz
mailutils-9a1d162e76c05616bc4f1fedc98825f5ace01aed.tar.bz2
Rewritten mail variables support using list_t.
(util_find_entry,util_help): Rewritten to work with opaque data tables (util_command_list): New function (var_iterate_first,var_iterate_next,var_iterate_end): New functions (util_folder_path): Convert folder to full name
-rw-r--r--mail/util.c372
1 files changed, 215 insertions, 157 deletions
diff --git a/mail/util.c b/mail/util.c
index 8bd34c401..f2f42418d 100644
--- a/mail/util.c
+++ b/mail/util.c
@@ -34,48 +34,7 @@
#endif
#include <mu_asprintf.h>
-typedef struct _node {
- /* for the msglist expander */
- int data;
- /* for the environment table */
- struct mail_env_entry env_entry;
- struct _node *next;
-} node;
-
-static node *environment = NULL;
-
-/*
- * add a new node to the list
- */
-static node *
-util_ll_add (node *c, int data)
-{
- c->next = xmalloc (sizeof (node));
- c->data = data;
- c->next->env_entry.var = NULL;
- c->next->env_entry.set = 0;
- c->next->env_entry.value.number = 0;
- c->next->next = NULL;
- return c->next;
-}
-
-/*
- * free a linked list
- * Unused so far
- */
-#if 0
-static void
-util_ll_free (node *c)
-{
- node *t = c;
- while (t != NULL)
- {
- c = t;
- t = t->next;
- free (c);
- }
-}
-#endif
+list_t environment = NULL;
/*
* expands command into its command and arguments, then runs command
@@ -124,7 +83,7 @@ util_do_command (const char *c, ...)
if (argcv_get (cmd, delim, NULL, &argc, &argv) == 0 && argc > 0)
{
- struct mail_command_entry entry;
+ struct mail_command_entry *entry;
char *p;
/* Special case: a number alone implies "print" */
@@ -136,10 +95,9 @@ util_do_command (const char *c, ...)
free (p);
}
- entry = util_find_entry (mail_command_table, argv[0]);
- command = entry.func;
+ command = util_command_get (argv[0]);
/* Make sure we are not in any if/else */
- exec = !(if_cond () == 0 && (entry.flags & EF_FLOW) == 0);
+ exec = !(if_cond () == 0 && (entry->flags & EF_FLOW) == 0);
}
free (cmd);
}
@@ -248,32 +206,109 @@ util_range_msg (size_t low, size_t high, int flags,
function_t *
util_command_get (const char *cmd)
{
- struct mail_command_entry entry = util_find_entry (mail_command_table, cmd);
- return entry.func;
+ const struct mail_command_entry *entry = mail_find_command (cmd);
+ return entry ? entry->func : NULL;
}
/*
* returns the mail_command_entry structure for the command matching cmd
*/
-struct mail_command_entry
-util_find_entry (const struct mail_command_entry *table, const char *cmd)
+void *
+util_find_entry (void *table, size_t nmemb, size_t size, const char *cmd)
{
- int i = 0, ll = 0, sl = 0;
+ int i;
int len = strlen (cmd);
+ char *p;
+
+ for (p = table, i = 0; i < nmemb; i++, p += size)
+ {
+ struct mail_command *cp = (struct mail_command *)p;
+ int ll = strlen (cp->longname);
+ int sl = strlen (cp->shortname);
+
+ if (sl > ll && !strncmp (cp->shortname, cmd, sl))
+ return p;
+ else if (sl == len && !strcmp (cp->shortname, cmd))
+ return p;
+ else if (sl < len && !strncmp (cp->longname, cmd, len))
+ return p;
+ }
+ return NULL;
+}
+
+int
+util_help (void *table, size_t nmemb, size_t size, const char *word)
+{
+ if (!word)
+ {
+ int i = 0;
+ FILE *out = stdout;
+ char *p;
+
+ if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0)
+ out = popen (getenv ("PAGER"), "w");
+
+
+ for (p = table, i = 0; i < nmemb; i++, p += size)
+ {
+ struct mail_command *cp = (struct mail_command *)p;
+ fprintf (out, "%s\n", cp->synopsis);
+ }
+
+ if (out != stdout)
+ pclose (out);
+
+ return 0;
+ }
+ else
+ {
+ int status = 0;
+ struct mail_command *cp = util_find_entry (table, nmemb, size, word);
+ if (cp)
+ fprintf (stdout, "%s\n", cp->synopsis);
+ else
+ {
+ status = 1;
+ fprintf (stdout, _("Unknown command: %s\n"), word);
+ }
+ return status;
+ }
+ return 1;
+}
- while (table[i].shortname != 0)
+int
+util_command_list (void *table, size_t nmemb, size_t size)
+{
+ int i;
+ char *p;
+ int cols = util_getcols ();
+ int pos;
+
+ for (p = table, i = 0; i < nmemb; i++, p += size)
{
- sl = strlen (table[i].shortname);
- ll = strlen (table[i].longname);
- if (sl > ll && !strncmp (table[i].shortname, cmd, sl))
- return table[i];
- else if (sl == len && !strcmp (table[i].shortname, cmd))
- return table[i];
- else if (sl < len && !strncmp (table[i].longname, cmd, len))
- return table[i];
- i++;
+ const char *cmd;
+ struct mail_command *cp = (struct mail_command *)p;
+ int len = strlen (cp->longname);
+ if (len < 1)
+ {
+ cmd = cp->shortname;
+ len = strlen (cmd);
+ }
+ else
+ cmd = cp->longname;
+
+ pos += len + 1;
+
+ if (pos >= cols)
+ {
+ pos = len + 1;
+ fprintf (ofile, "\n%s ", cmd);
+ }
+ else
+ fprintf (ofile, "%s ", cmd);
}
- return table[i];
+ fprintf (ofile, "\n");
+ return 0;
}
/*
@@ -426,85 +461,141 @@ util_getenv (void *ptr, const char *variable, mail_env_data_t type, int warn)
return 0;
}
+static int
+env_comp (const void *a, const void *b)
+{
+ const struct mail_env_entry *epa = a;
+ const struct mail_env_entry *epb = b;
+
+ return strcmp (epa->var, epb->var);
+}
+
/* Find environment entry var. If not found and CREATE is not null, then
create the (unset and untyped) variable */
struct mail_env_entry *
-util_find_env (const char *variable, int create)
+util_find_env (const char *var, int create)
{
- node *ep;
- /* Annoying, variable "ask" is equivalent to "asksub". */
- static const char *asksub = "asksub";
- const char *var = variable;
- size_t len = strlen (var);
- node *t;
-
- if (len < 1)
- return NULL;
+ struct mail_env_entry entry, *p;
- /* Catch "ask" --> "asksub". */
- if (len == strlen ("ask") && !strcmp ("ask", var))
+ if (strcmp (var, "ask") == 0)
+ entry.var = "asksub";
+ else
+ entry.var = var;
+
+ if (environment == NULL)
{
- var = asksub;
- len = strlen (var);
+ list_create (&environment);
+ list_set_comparator (environment, env_comp);
}
-
- if (environment == NULL)
+
+ if (list_locate (environment, &entry, (void**)&p))
{
if (!create)
return 0;
- environment = xmalloc (sizeof (node));
- environment->env_entry.var = NULL;
- environment->env_entry.set = 0;
- environment->env_entry.value.number = 0;
- environment->next = NULL;
+
+ p = xmalloc (sizeof *p);
+ p->var = xstrdup (entry.var);
+ list_prepend (environment, p);
+ p->set = 0;
+ p->type = Mail_env_whatever;
+ p->value.number = 0;
}
- for (ep = environment; ep->next; ep = ep->next)
+ return p;
+}
+
+struct var_iterator
+{
+ const char *prefix;
+ int prefixlen;
+ iterator_t itr;
+};
+
+const char *
+var_iterate_next (var_iterator_t itr)
+{
+ struct mail_env_entry *ep;
+
+ while (!iterator_is_done (itr->itr))
{
- if (strlen (ep->env_entry.var) == len &&
- !strcmp (var, ep->env_entry.var))
- return &ep->env_entry;
+ if (iterator_current (itr->itr, (void **)&ep))
+ return NULL;
+ iterator_next (itr->itr);
+
+ if (strlen (ep->var) >= itr->prefixlen
+ && strncmp (ep->var, itr->prefix, itr->prefixlen) == 0)
+ return ep->var;
}
+ return NULL;
+}
- ep->env_entry.var = strdup (var);
- ep->env_entry.set = 0;
- ep->env_entry.type = Mail_env_whatever;
- ep->env_entry.value.number = 0;
- t = ep;
- ep = util_ll_add (ep, 0);
- return &t->env_entry;
+const char *
+var_iterate_first (const char *prefix, var_iterator_t *pitr)
+{
+ if (environment)
+ {
+ var_iterator_t itr = xmalloc (sizeof *itr);
+ itr->prefix = prefix;
+ itr->prefixlen = strlen (prefix);
+ list_get_iterator (environment, &itr->itr);
+ iterator_first (itr->itr);
+ *pitr = itr;
+ return var_iterate_next (itr);
+ }
+ *pitr = NULL;
+ return NULL;
+}
+
+void
+var_iterate_end (var_iterator_t *itr)
+{
+ iterator_destroy (&(*itr)->itr);
+ free (*itr);
+ *itr = NULL;
}
/* print the environment */
+static int
+envp_comp (const void *a, const void *b)
+{
+ const struct mail_env_entry **epa = a;
+ const struct mail_env_entry **epb = b;
+
+ return strcmp ((*epa)->var, (*epb)->var);
+}
+
int
util_printenv (int set)
{
- node *ep;
- for (ep = environment; ep != NULL; ep = ep->next)
+ struct mail_env_entry **ep;
+ size_t i, count = 0;
+
+ list_count (environment, &count);
+ ep = xcalloc (count, sizeof *ep);
+ list_to_array (environment, ep, count, NULL);
+ qsort (ep, count, sizeof *ep, envp_comp);
+ for (i = 0; i < count; i++)
{
- if (ep->env_entry.set == set)
+ fprintf (ofile, "%s", ep[i]->var);
+ switch (ep[i]->type)
{
- fprintf (ofile, "%s", ep->env_entry.var);
- switch (ep->env_entry.type)
- {
- case Mail_env_number:
- fprintf (ofile, "=%d", ep->env_entry.value.number);
- break;
-
- case Mail_env_string:
- fprintf (ofile, "=\"%s\"", ep->env_entry.value.string);
- break;
-
- case Mail_env_boolean:
- break;
-
- case Mail_env_whatever:
- fprintf (ofile, _("oops?"));
- }
- fprintf (ofile, "\n");
+ case Mail_env_number:
+ fprintf (ofile, "=%d", ep[i]->value.number);
+ break;
+
+ case Mail_env_string:
+ fprintf (ofile, "=\"%s\"", ep[i]->value.string);
+ break;
+
+ case Mail_env_boolean:
+ break;
+
+ case Mail_env_whatever:
+ fprintf (ofile, _("oops?"));
}
+ fprintf (ofile, "\n");
}
- return 0;
+ free (ep);
}
/* Initialize environment entry: clear set indicator and free any memory
@@ -576,7 +667,7 @@ util_setenv (const char *variable, void *value, mail_env_data_t type,
int rc;
char *err;
- if (rc = munre_set_regex (value, 0, &err))
+ if ((rc = munre_set_regex (value, 0, &err)))
{
fprintf (stderr, "%s", mu_strerror (rc));
if (err)
@@ -658,7 +749,8 @@ util_folder_path (const char *name)
{
char *folder;
char *tmp;
-
+ char *p;
+
if (util_getenv (&folder, "folder", Mail_env_string, 1))
return NULL;
@@ -667,7 +759,7 @@ util_folder_path (const char *name)
if (name[0] == '+')
name++;
- if (folder[0] != '/' && folder[1] != '~')
+ if (folder[0] != '/' && folder[0] != '~')
{
char *home = mu_get_homedir ();
tmp = xmalloc (strlen (home) + 1 +
@@ -681,9 +773,10 @@ util_folder_path (const char *name)
strlen (name) + 1);
sprintf (tmp, "%s/%s", folder, name);
}
- name = tmp;
-
- return (char*) name;
+ p = util_fullpath (tmp);
+ free (tmp);
+
+ return p;
}
char *
@@ -1005,41 +1098,6 @@ util_error (va_alist)
va_end(ap);
}
-int
-util_help (const struct mail_command_entry *table, char *word)
-{
- if (!word)
- {
- int i = 0;
- FILE *out = stdout;
-
- if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0)
- out = popen (getenv ("PAGER"), "w");
-
- while (table[i].synopsis != 0)
- fprintf (out, "%s\n", table[i++].synopsis);
-
- if (out != stdout)
- pclose (out);
-
- return 0;
- }
- else
- {
- int status = 0;
- struct mail_command_entry entry = util_find_entry(table, word);
- if (entry.synopsis != NULL)
- fprintf (stdout, "%s\n", entry.synopsis);
- else
- {
- status = 1;
- fprintf (stdout, _("Unknown command: %s\n"), word);
- }
- return status;
- }
- return 1;
-}
-
static int
util_descend_subparts (message_t mesg, msgset_t *msgset, message_t *part)
{

Return to:

Send suggestions and report system problems to the System administrator.