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
Showing
1 changed file
with
215 additions
and
157 deletions
... | @@ -34,48 +34,7 @@ | ... | @@ -34,48 +34,7 @@ |
34 | #endif | 34 | #endif |
35 | #include <mu_asprintf.h> | 35 | #include <mu_asprintf.h> |
36 | 36 | ||
37 | typedef struct _node { | 37 | list_t environment = NULL; |
38 | /* for the msglist expander */ | ||
39 | int data; | ||
40 | /* for the environment table */ | ||
41 | struct mail_env_entry env_entry; | ||
42 | struct _node *next; | ||
43 | } node; | ||
44 | |||
45 | static node *environment = NULL; | ||
46 | |||
47 | /* | ||
48 | * add a new node to the list | ||
49 | */ | ||
50 | static node * | ||
51 | util_ll_add (node *c, int data) | ||
52 | { | ||
53 | c->next = xmalloc (sizeof (node)); | ||
54 | c->data = data; | ||
55 | c->next->env_entry.var = NULL; | ||
56 | c->next->env_entry.set = 0; | ||
57 | c->next->env_entry.value.number = 0; | ||
58 | c->next->next = NULL; | ||
59 | return c->next; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * free a linked list | ||
64 | * Unused so far | ||
65 | */ | ||
66 | #if 0 | ||
67 | static void | ||
68 | util_ll_free (node *c) | ||
69 | { | ||
70 | node *t = c; | ||
71 | while (t != NULL) | ||
72 | { | ||
73 | c = t; | ||
74 | t = t->next; | ||
75 | free (c); | ||
76 | } | ||
77 | } | ||
78 | #endif | ||
79 | 38 | ||
80 | /* | 39 | /* |
81 | * expands command into its command and arguments, then runs command | 40 | * expands command into its command and arguments, then runs command |
... | @@ -124,7 +83,7 @@ util_do_command (const char *c, ...) | ... | @@ -124,7 +83,7 @@ util_do_command (const char *c, ...) |
124 | 83 | ||
125 | if (argcv_get (cmd, delim, NULL, &argc, &argv) == 0 && argc > 0) | 84 | if (argcv_get (cmd, delim, NULL, &argc, &argv) == 0 && argc > 0) |
126 | { | 85 | { |
127 | struct mail_command_entry entry; | 86 | struct mail_command_entry *entry; |
128 | char *p; | 87 | char *p; |
129 | 88 | ||
130 | /* Special case: a number alone implies "print" */ | 89 | /* Special case: a number alone implies "print" */ |
... | @@ -136,10 +95,9 @@ util_do_command (const char *c, ...) | ... | @@ -136,10 +95,9 @@ util_do_command (const char *c, ...) |
136 | free (p); | 95 | free (p); |
137 | } | 96 | } |
138 | 97 | ||
139 | entry = util_find_entry (mail_command_table, argv[0]); | 98 | command = util_command_get (argv[0]); |
140 | command = entry.func; | ||
141 | /* Make sure we are not in any if/else */ | 99 | /* Make sure we are not in any if/else */ |
142 | exec = !(if_cond () == 0 && (entry.flags & EF_FLOW) == 0); | 100 | exec = !(if_cond () == 0 && (entry->flags & EF_FLOW) == 0); |
143 | } | 101 | } |
144 | free (cmd); | 102 | free (cmd); |
145 | } | 103 | } |
... | @@ -248,32 +206,109 @@ util_range_msg (size_t low, size_t high, int flags, | ... | @@ -248,32 +206,109 @@ util_range_msg (size_t low, size_t high, int flags, |
248 | function_t * | 206 | function_t * |
249 | util_command_get (const char *cmd) | 207 | util_command_get (const char *cmd) |
250 | { | 208 | { |
251 | struct mail_command_entry entry = util_find_entry (mail_command_table, cmd); | 209 | const struct mail_command_entry *entry = mail_find_command (cmd); |
252 | return entry.func; | 210 | return entry ? entry->func : NULL; |
253 | } | 211 | } |
254 | 212 | ||
255 | /* | 213 | /* |
256 | * returns the mail_command_entry structure for the command matching cmd | 214 | * returns the mail_command_entry structure for the command matching cmd |
257 | */ | 215 | */ |
258 | struct mail_command_entry | 216 | void * |
259 | util_find_entry (const struct mail_command_entry *table, const char *cmd) | 217 | util_find_entry (void *table, size_t nmemb, size_t size, const char *cmd) |
260 | { | 218 | { |
261 | int i = 0, ll = 0, sl = 0; | 219 | int i; |
262 | int len = strlen (cmd); | 220 | int len = strlen (cmd); |
221 | char *p; | ||
222 | |||
223 | for (p = table, i = 0; i < nmemb; i++, p += size) | ||
224 | { | ||
225 | struct mail_command *cp = (struct mail_command *)p; | ||
226 | int ll = strlen (cp->longname); | ||
227 | int sl = strlen (cp->shortname); | ||
228 | |||
229 | if (sl > ll && !strncmp (cp->shortname, cmd, sl)) | ||
230 | return p; | ||
231 | else if (sl == len && !strcmp (cp->shortname, cmd)) | ||
232 | return p; | ||
233 | else if (sl < len && !strncmp (cp->longname, cmd, len)) | ||
234 | return p; | ||
235 | } | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | int | ||
240 | util_help (void *table, size_t nmemb, size_t size, const char *word) | ||
241 | { | ||
242 | if (!word) | ||
243 | { | ||
244 | int i = 0; | ||
245 | FILE *out = stdout; | ||
246 | char *p; | ||
247 | |||
248 | if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0) | ||
249 | out = popen (getenv ("PAGER"), "w"); | ||
250 | |||
251 | |||
252 | for (p = table, i = 0; i < nmemb; i++, p += size) | ||
253 | { | ||
254 | struct mail_command *cp = (struct mail_command *)p; | ||
255 | fprintf (out, "%s\n", cp->synopsis); | ||
256 | } | ||
257 | |||
258 | if (out != stdout) | ||
259 | pclose (out); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | int status = 0; | ||
266 | struct mail_command *cp = util_find_entry (table, nmemb, size, word); | ||
267 | if (cp) | ||
268 | fprintf (stdout, "%s\n", cp->synopsis); | ||
269 | else | ||
270 | { | ||
271 | status = 1; | ||
272 | fprintf (stdout, _("Unknown command: %s\n"), word); | ||
273 | } | ||
274 | return status; | ||
275 | } | ||
276 | return 1; | ||
277 | } | ||
263 | 278 | ||
264 | while (table[i].shortname != 0) | 279 | int |
280 | util_command_list (void *table, size_t nmemb, size_t size) | ||
281 | { | ||
282 | int i; | ||
283 | char *p; | ||
284 | int cols = util_getcols (); | ||
285 | int pos; | ||
286 | |||
287 | for (p = table, i = 0; i < nmemb; i++, p += size) | ||
265 | { | 288 | { |
266 | sl = strlen (table[i].shortname); | 289 | const char *cmd; |
267 | ll = strlen (table[i].longname); | 290 | struct mail_command *cp = (struct mail_command *)p; |
268 | if (sl > ll && !strncmp (table[i].shortname, cmd, sl)) | 291 | int len = strlen (cp->longname); |
269 | return table[i]; | 292 | if (len < 1) |
270 | else if (sl == len && !strcmp (table[i].shortname, cmd)) | 293 | { |
271 | return table[i]; | 294 | cmd = cp->shortname; |
272 | else if (sl < len && !strncmp (table[i].longname, cmd, len)) | 295 | len = strlen (cmd); |
273 | return table[i]; | 296 | } |
274 | i++; | 297 | else |
298 | cmd = cp->longname; | ||
299 | |||
300 | pos += len + 1; | ||
301 | |||
302 | if (pos >= cols) | ||
303 | { | ||
304 | pos = len + 1; | ||
305 | fprintf (ofile, "\n%s ", cmd); | ||
306 | } | ||
307 | else | ||
308 | fprintf (ofile, "%s ", cmd); | ||
275 | } | 309 | } |
276 | return table[i]; | 310 | fprintf (ofile, "\n"); |
311 | return 0; | ||
277 | } | 312 | } |
278 | 313 | ||
279 | /* | 314 | /* |
... | @@ -426,85 +461,141 @@ util_getenv (void *ptr, const char *variable, mail_env_data_t type, int warn) | ... | @@ -426,85 +461,141 @@ util_getenv (void *ptr, const char *variable, mail_env_data_t type, int warn) |
426 | return 0; | 461 | return 0; |
427 | } | 462 | } |
428 | 463 | ||
464 | static int | ||
465 | env_comp (const void *a, const void *b) | ||
466 | { | ||
467 | const struct mail_env_entry *epa = a; | ||
468 | const struct mail_env_entry *epb = b; | ||
469 | |||
470 | return strcmp (epa->var, epb->var); | ||
471 | } | ||
472 | |||
429 | /* Find environment entry var. If not found and CREATE is not null, then | 473 | /* Find environment entry var. If not found and CREATE is not null, then |
430 | create the (unset and untyped) variable */ | 474 | create the (unset and untyped) variable */ |
431 | struct mail_env_entry * | 475 | struct mail_env_entry * |
432 | util_find_env (const char *variable, int create) | 476 | util_find_env (const char *var, int create) |
433 | { | 477 | { |
434 | node *ep; | 478 | struct mail_env_entry entry, *p; |
435 | /* Annoying, variable "ask" is equivalent to "asksub". */ | ||
436 | static const char *asksub = "asksub"; | ||
437 | const char *var = variable; | ||
438 | size_t len = strlen (var); | ||
439 | node *t; | ||
440 | |||
441 | if (len < 1) | ||
442 | return NULL; | ||
443 | 479 | ||
444 | /* Catch "ask" --> "asksub". */ | 480 | if (strcmp (var, "ask") == 0) |
445 | if (len == strlen ("ask") && !strcmp ("ask", var)) | 481 | entry.var = "asksub"; |
482 | else | ||
483 | entry.var = var; | ||
484 | |||
485 | if (environment == NULL) | ||
446 | { | 486 | { |
447 | var = asksub; | 487 | list_create (&environment); |
448 | len = strlen (var); | 488 | list_set_comparator (environment, env_comp); |
449 | } | 489 | } |
450 | 490 | ||
451 | if (environment == NULL) | 491 | if (list_locate (environment, &entry, (void**)&p)) |
452 | { | 492 | { |
453 | if (!create) | 493 | if (!create) |
454 | return 0; | 494 | return 0; |
455 | environment = xmalloc (sizeof (node)); | 495 | |
456 | environment->env_entry.var = NULL; | 496 | p = xmalloc (sizeof *p); |
457 | environment->env_entry.set = 0; | 497 | p->var = xstrdup (entry.var); |
458 | environment->env_entry.value.number = 0; | 498 | list_prepend (environment, p); |
459 | environment->next = NULL; | 499 | p->set = 0; |
500 | p->type = Mail_env_whatever; | ||
501 | p->value.number = 0; | ||
460 | } | 502 | } |
461 | 503 | ||
462 | for (ep = environment; ep->next; ep = ep->next) | 504 | return p; |
505 | } | ||
506 | |||
507 | struct var_iterator | ||
508 | { | ||
509 | const char *prefix; | ||
510 | int prefixlen; | ||
511 | iterator_t itr; | ||
512 | }; | ||
513 | |||
514 | const char * | ||
515 | var_iterate_next (var_iterator_t itr) | ||
516 | { | ||
517 | struct mail_env_entry *ep; | ||
518 | |||
519 | while (!iterator_is_done (itr->itr)) | ||
463 | { | 520 | { |
464 | if (strlen (ep->env_entry.var) == len && | 521 | if (iterator_current (itr->itr, (void **)&ep)) |
465 | !strcmp (var, ep->env_entry.var)) | 522 | return NULL; |
466 | return &ep->env_entry; | 523 | iterator_next (itr->itr); |
524 | |||
525 | if (strlen (ep->var) >= itr->prefixlen | ||
526 | && strncmp (ep->var, itr->prefix, itr->prefixlen) == 0) | ||
527 | return ep->var; | ||
467 | } | 528 | } |
529 | return NULL; | ||
530 | } | ||
468 | 531 | ||
469 | ep->env_entry.var = strdup (var); | 532 | const char * |
470 | ep->env_entry.set = 0; | 533 | var_iterate_first (const char *prefix, var_iterator_t *pitr) |
471 | ep->env_entry.type = Mail_env_whatever; | 534 | { |
472 | ep->env_entry.value.number = 0; | 535 | if (environment) |
473 | t = ep; | 536 | { |
474 | ep = util_ll_add (ep, 0); | 537 | var_iterator_t itr = xmalloc (sizeof *itr); |
475 | return &t->env_entry; | 538 | itr->prefix = prefix; |
539 | itr->prefixlen = strlen (prefix); | ||
540 | list_get_iterator (environment, &itr->itr); | ||
541 | iterator_first (itr->itr); | ||
542 | *pitr = itr; | ||
543 | return var_iterate_next (itr); | ||
544 | } | ||
545 | *pitr = NULL; | ||
546 | return NULL; | ||
547 | } | ||
548 | |||
549 | void | ||
550 | var_iterate_end (var_iterator_t *itr) | ||
551 | { | ||
552 | iterator_destroy (&(*itr)->itr); | ||
553 | free (*itr); | ||
554 | *itr = NULL; | ||
476 | } | 555 | } |
477 | 556 | ||
478 | /* print the environment */ | 557 | /* print the environment */ |
558 | static int | ||
559 | envp_comp (const void *a, const void *b) | ||
560 | { | ||
561 | const struct mail_env_entry **epa = a; | ||
562 | const struct mail_env_entry **epb = b; | ||
563 | |||
564 | return strcmp ((*epa)->var, (*epb)->var); | ||
565 | } | ||
566 | |||
479 | int | 567 | int |
480 | util_printenv (int set) | 568 | util_printenv (int set) |
481 | { | 569 | { |
482 | node *ep; | 570 | struct mail_env_entry **ep; |
483 | for (ep = environment; ep != NULL; ep = ep->next) | 571 | size_t i, count = 0; |
572 | |||
573 | list_count (environment, &count); | ||
574 | ep = xcalloc (count, sizeof *ep); | ||
575 | list_to_array (environment, ep, count, NULL); | ||
576 | qsort (ep, count, sizeof *ep, envp_comp); | ||
577 | for (i = 0; i < count; i++) | ||
484 | { | 578 | { |
485 | if (ep->env_entry.set == set) | 579 | fprintf (ofile, "%s", ep[i]->var); |
580 | switch (ep[i]->type) | ||
486 | { | 581 | { |
487 | fprintf (ofile, "%s", ep->env_entry.var); | 582 | case Mail_env_number: |
488 | switch (ep->env_entry.type) | 583 | fprintf (ofile, "=%d", ep[i]->value.number); |
489 | { | 584 | break; |
490 | case Mail_env_number: | 585 | |
491 | fprintf (ofile, "=%d", ep->env_entry.value.number); | 586 | case Mail_env_string: |
492 | break; | 587 | fprintf (ofile, "=\"%s\"", ep[i]->value.string); |
493 | 588 | break; | |
494 | case Mail_env_string: | 589 | |
495 | fprintf (ofile, "=\"%s\"", ep->env_entry.value.string); | 590 | case Mail_env_boolean: |
496 | break; | 591 | break; |
497 | 592 | ||
498 | case Mail_env_boolean: | 593 | case Mail_env_whatever: |
499 | break; | 594 | fprintf (ofile, _("oops?")); |
500 | |||
501 | case Mail_env_whatever: | ||
502 | fprintf (ofile, _("oops?")); | ||
503 | } | ||
504 | fprintf (ofile, "\n"); | ||
505 | } | 595 | } |
596 | fprintf (ofile, "\n"); | ||
506 | } | 597 | } |
507 | return 0; | 598 | free (ep); |
508 | } | 599 | } |
509 | 600 | ||
510 | /* Initialize environment entry: clear set indicator and free any memory | 601 | /* 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, | ... | @@ -576,7 +667,7 @@ util_setenv (const char *variable, void *value, mail_env_data_t type, |
576 | int rc; | 667 | int rc; |
577 | char *err; | 668 | char *err; |
578 | 669 | ||
579 | if (rc = munre_set_regex (value, 0, &err)) | 670 | if ((rc = munre_set_regex (value, 0, &err))) |
580 | { | 671 | { |
581 | fprintf (stderr, "%s", mu_strerror (rc)); | 672 | fprintf (stderr, "%s", mu_strerror (rc)); |
582 | if (err) | 673 | if (err) |
... | @@ -658,7 +749,8 @@ util_folder_path (const char *name) | ... | @@ -658,7 +749,8 @@ util_folder_path (const char *name) |
658 | { | 749 | { |
659 | char *folder; | 750 | char *folder; |
660 | char *tmp; | 751 | char *tmp; |
661 | 752 | char *p; | |
753 | |||
662 | if (util_getenv (&folder, "folder", Mail_env_string, 1)) | 754 | if (util_getenv (&folder, "folder", Mail_env_string, 1)) |
663 | return NULL; | 755 | return NULL; |
664 | 756 | ||
... | @@ -667,7 +759,7 @@ util_folder_path (const char *name) | ... | @@ -667,7 +759,7 @@ util_folder_path (const char *name) |
667 | if (name[0] == '+') | 759 | if (name[0] == '+') |
668 | name++; | 760 | name++; |
669 | 761 | ||
670 | if (folder[0] != '/' && folder[1] != '~') | 762 | if (folder[0] != '/' && folder[0] != '~') |
671 | { | 763 | { |
672 | char *home = mu_get_homedir (); | 764 | char *home = mu_get_homedir (); |
673 | tmp = xmalloc (strlen (home) + 1 + | 765 | tmp = xmalloc (strlen (home) + 1 + |
... | @@ -681,9 +773,10 @@ util_folder_path (const char *name) | ... | @@ -681,9 +773,10 @@ util_folder_path (const char *name) |
681 | strlen (name) + 1); | 773 | strlen (name) + 1); |
682 | sprintf (tmp, "%s/%s", folder, name); | 774 | sprintf (tmp, "%s/%s", folder, name); |
683 | } | 775 | } |
684 | name = tmp; | 776 | p = util_fullpath (tmp); |
685 | 777 | free (tmp); | |
686 | return (char*) name; | 778 | |
779 | return p; | ||
687 | } | 780 | } |
688 | 781 | ||
689 | char * | 782 | char * |
... | @@ -1005,41 +1098,6 @@ util_error (va_alist) | ... | @@ -1005,41 +1098,6 @@ util_error (va_alist) |
1005 | va_end(ap); | 1098 | va_end(ap); |
1006 | } | 1099 | } |
1007 | 1100 | ||
1008 | int | ||
1009 | util_help (const struct mail_command_entry *table, char *word) | ||
1010 | { | ||
1011 | if (!word) | ||
1012 | { | ||
1013 | int i = 0; | ||
1014 | FILE *out = stdout; | ||
1015 | |||
1016 | if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0) | ||
1017 | out = popen (getenv ("PAGER"), "w"); | ||
1018 | |||
1019 | while (table[i].synopsis != 0) | ||
1020 | fprintf (out, "%s\n", table[i++].synopsis); | ||
1021 | |||
1022 | if (out != stdout) | ||
1023 | pclose (out); | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | else | ||
1028 | { | ||
1029 | int status = 0; | ||
1030 | struct mail_command_entry entry = util_find_entry(table, word); | ||
1031 | if (entry.synopsis != NULL) | ||
1032 | fprintf (stdout, "%s\n", entry.synopsis); | ||
1033 | else | ||
1034 | { | ||
1035 | status = 1; | ||
1036 | fprintf (stdout, _("Unknown command: %s\n"), word); | ||
1037 | } | ||
1038 | return status; | ||
1039 | } | ||
1040 | return 1; | ||
1041 | } | ||
1042 | |||
1043 | static int | 1101 | static int |
1044 | util_descend_subparts (message_t mesg, msgset_t *msgset, message_t *part) | 1102 | util_descend_subparts (message_t mesg, msgset_t *msgset, message_t *part) |
1045 | { | 1103 | { | ... | ... |
-
Please register or sign in to post a comment