X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=init.c;h=734f88e2aa1e7dfa340e57e0eaabbb6896afbdf6;hp=ab083b86119fa126aee149130ddadf81d9239be1;hb=0995d7520848a31481107d897b9a930bff222ce7;hpb=955b6b84c6eabd42a96ff0176003ef72d49d9c38 diff --git a/init.c b/init.c index ab083b8..734f88e 100644 --- a/init.c +++ b/init.c @@ -53,6 +53,15 @@ #include #include +#define CHECK_PAGER \ + if ((CurrentMenu == MENU_PAGER) && \ + (!option || (option->flags & R_RESORT))) \ + { \ + snprintf (err->data, err->dsize, \ + _("Not available in this menu.")); \ + return (-1); \ + } else + /* * prototypes */ @@ -88,6 +97,10 @@ static int check_history (const char* option, unsigned long val, /* this checks that numbers are >= 0 */ static int check_num (const char* option, unsigned long val, char* errbuf, size_t errlen); +#ifdef DEBUG +static int check_debug (const char* option, unsigned long val, + char* errbuf, size_t errlen); +#endif /* use this to check only */ static int check_special (const char* option, unsigned long val, @@ -109,6 +122,9 @@ static struct { #endif { "history", check_history }, { "pager_index_lines", check_num }, +#ifdef DEBUG + { "debug_level", check_debug }, +#endif /* last */ { NULL, NULL } }; @@ -123,6 +139,7 @@ static void rx_to_string (char* dst, size_t dstlen, struct option_t* option); static void magic_to_string (char* dst, size_t dstlen, struct option_t* option); static void addr_to_string (char* dst, size_t dstlen, struct option_t* option); static void user_to_string (char* dst, size_t dstlen, struct option_t* option); +static void sys_to_string (char* dst, size_t dstlen, struct option_t* option); /* protos for config type handles: convert to value from string */ static int bool_from_string (struct option_t* dst, const char* val, @@ -166,6 +183,7 @@ static struct { { DT_SYN, NULL, NULL }, { DT_ADDR, addr_to_string, addr_from_string }, { DT_USER, user_to_string, user_from_string }, + { DT_SYS, sys_to_string, NULL }, }; static void bool_to_string (char* dst, size_t dstlen, @@ -191,7 +209,7 @@ static int bool_from_string (struct option_t* dst, const char* val, set_option (dst->data); else unset_option (dst->data); - return (0); + return (1); } static void num_to_string (char* dst, size_t dstlen, @@ -246,6 +264,49 @@ static void user_to_string (char* dst, size_t dstlen, NONULL (((char*) option->data))); } +static void sys_to_string (char* dst, size_t dstlen, + struct option_t* option) { + char* val = NULL, *t = NULL; + int clean = 0; + + /* get some $muttng_ values dynamically */ + if (ascii_strcmp ("muttng_pwd", option->option) == 0) { + val = mem_malloc (_POSIX_PATH_MAX); + val = getcwd (val, _POSIX_PATH_MAX-1); + clean = 1; + } else if (ascii_strcmp ("muttng_folder_path", option->option) == 0 && + CurrentFolder && *CurrentFolder) { + val = CurrentFolder; + } else if (ascii_strcmp ("muttng_folder_name", option->option) == 0 && + CurrentFolder && *CurrentFolder) { + + size_t Maildirlength = str_len (Maildir); + + /* + * if name starts with $folder, just strip it to keep hierarchy + * $folder=imap://host, path=imap://host/inbox/b -> inbox/b + */ + if (Maildirlength > 0 && str_ncmp (CurrentFolder, Maildir, + Maildirlength) == 0 && + str_len (CurrentFolder) > Maildirlength) { + val = CurrentFolder + Maildirlength; + if (Maildir[strlen(Maildir)-1]!='/') + val += 1; + /* if not $folder, just use everything after last / */ + } else if ((t = strrchr (CurrentFolder, '/')) != NULL) + val = t+1; + /* default: use as-is */ + else + val = CurrentFolder; + + } else + val = option->init; + + snprintf (dst, dstlen, "%s=\"%s\"", option->option, NONULL (val)); + if (clean) + mem_free (&val); +} + static int path_from_string (struct option_t* dst, const char* val, char* errbuf, size_t errlen) { char path[_POSIX_PATH_MAX]; @@ -279,14 +340,19 @@ static int str_from_string (struct option_t* dst, const char* val, static int user_from_string (struct option_t* dst, const char* val, char* errbuf, size_t errlen) { + /* if dst == NULL, we may get here in case the user did unset it, + * see parse_set() where item is free()'d before coming here; so + * just silently ignore it */ if (!dst) - return (0); + return (1); if (str_len ((char*) dst->data) == 0) dst->data = (unsigned long) str_dup (val); else { char* s = (char*) dst->data; str_replace (&s, val); } + if (str_len (dst->init) == 0) + dst->init = str_dup ((char*) dst->data); return (1); } @@ -401,9 +467,10 @@ static int rx_from_string (struct option_t* dst, const char* val, regerror (e, rx, errbuf, errlen); regfree (rx); mem_free (&rx); + return (0); } - if (p->pattern) { + if (p->rx) { regfree (p->rx); mem_free (&p->rx); } @@ -456,7 +523,7 @@ static int magic_from_string (struct option_t* dst, const char* val, static void addr_to_string (char* dst, size_t dstlen, struct option_t* option) { - char s[STRING]; + char s[HUGE_STRING]; s[0] = '\0'; rfc822_write_address (s, sizeof (s), *((ADDRESS**) option->data), 0); snprintf (dst, dstlen, "%s=\"%s\"", option->option, NONULL (s)); @@ -464,10 +531,11 @@ static void addr_to_string (char* dst, size_t dstlen, static int addr_from_string (struct option_t* dst, const char* val, char* errbuf, size_t errlen) { - if (!dst || !val || !*val) + if (!dst) return (0); rfc822_free_address ((ADDRESS**) dst->data); - *((ADDRESS**) dst->data) = rfc822_parse_adrlist (NULL, val); + if (val && *val) + *((ADDRESS**) dst->data) = rfc822_parse_adrlist (NULL, val); return (1); } @@ -772,7 +840,7 @@ static int parse_ifdef (BUFFER * tmp, BUFFER * s, unsigned long data, mutt_extract_token (tmp, s, 0); /* is the item defined as a variable or a function? */ - if ((option = hash_find (ConfigOptions, tmp->data))) + if ((option = hash_find (ConfigOptions, tmp->data)) != NULL) res = 1; else { for (i = 0; !res && i < MENU_MAX; i++) { @@ -790,23 +858,16 @@ static int parse_ifdef (BUFFER * tmp, BUFFER * s, unsigned long data, } } /* check for feature_* */ - if (!res) { - char *p = NULL; - + if (!res && ascii_strncasecmp (tmp->data, "feature_", 8) == 0 && + (j = str_len (tmp->data)) > 8) { i = 0; - j = str_len (tmp->data); - /* need at least input of 'feature_X' */ - if (j >= 7) { - p = tmp->data + 7; - j -= 7; - while (Features[i].name) { - if (str_len (Features[i].name) == j && - ascii_strncasecmp (Features[i].name, p, j)) { - res = 1; - break; - } - i++; + while (Features[i]) { + if (str_len (Features[i]) == j-8 && + ascii_strncasecmp (Features[i], tmp->data+8, j-8) == 0) { + res = 1; + break; } + i++; } } @@ -817,9 +878,10 @@ static int parse_ifdef (BUFFER * tmp, BUFFER * s, unsigned long data, snprintf (err->data, err->dsize, _("ifndef: too few arguments")); return (-1); } + mutt_extract_token (tmp, s, M_TOKEN_SPACE); - if ((data && res) || (!data && !res)) { + if (data == res) { if (mutt_parse_rc_line (tmp->data, &token, err) == -1) { mutt_error ("Error: %s", err->data); mem_free (&token.data); @@ -1018,6 +1080,247 @@ static int parse_lists (BUFFER * buf, BUFFER * s, unsigned long data, return 0; } +/* always wise to do what someone else did before */ +static void _attachments_clean (void) { + int i; + if (Context && Context->msgcount) { + for (i = 0; i < Context->msgcount; i++) + Context->hdrs[i]->attach_valid = 0; + } +} + +static int parse_attach_list (BUFFER *buf, BUFFER *s, LIST **ldata, + BUFFER *err) { + ATTACH_MATCH *a; + LIST *listp, *lastp; + char *p; + char *tmpminor; + int len; + + /* Find the last item in the list that data points to. */ + lastp = NULL; + debug_print (5, ("parse_attach_list: ldata = %08x, *ldata = %08x\n", + (unsigned int)ldata, (unsigned int)*ldata)); + for (listp = *ldata; listp; listp = listp->next) { + a = (ATTACH_MATCH *)listp->data; + debug_print (5, ("parse_attach_list: skipping %s/%s\n", a->major, a->minor)); + lastp = listp; + } + + do { + mutt_extract_token (buf, s, 0); + + if (!buf->data || *buf->data == '\0') + continue; + + a = mem_malloc(sizeof(ATTACH_MATCH)); + + /* some cheap hacks that I expect to remove */ + if (!str_casecmp(buf->data, "any")) + a->major = str_dup("*/.*"); + else if (!str_casecmp(buf->data, "none")) + a->major = str_dup("cheap_hack/this_should_never_match"); + else + a->major = str_dup(buf->data); + + if ((p = strchr(a->major, '/'))) { + *p = '\0'; + ++p; + a->minor = p; + } else { + a->minor = "unknown"; + } + + len = str_len (a->minor); + tmpminor = mem_malloc(len+3); + strcpy(&tmpminor[1], a->minor); /* __STRCPY_CHECKED__ */ + tmpminor[0] = '^'; + tmpminor[len+1] = '$'; + tmpminor[len+2] = '\0'; + + a->major_int = mutt_check_mime_type(a->major); + regcomp(&a->minor_rx, tmpminor, REG_ICASE|REG_EXTENDED); + + mem_free (&tmpminor); + + debug_print (5, ("parse_attach_list: added %s/%s [%d]\n", + a->major, a->minor, a->major_int)); + + listp = mem_malloc(sizeof(LIST)); + listp->data = (char *)a; + listp->next = NULL; + if (lastp) { + lastp->next = listp; + } else { + *ldata = listp; + } + lastp = listp; + } + while (MoreArgs (s)); + + _attachments_clean(); + return 0; +} + +static int parse_unattach_list (BUFFER *buf, BUFFER *s, LIST **ldata, BUFFER *err) { + ATTACH_MATCH *a; + LIST *lp, *lastp, *newlp; + char *tmp; + int major; + char *minor; + + do { + mutt_extract_token (buf, s, 0); + + if (!str_casecmp(buf->data, "any")) + tmp = str_dup("*/.*"); + else if (!str_casecmp(buf->data, "none")) + tmp = str_dup("cheap_hack/this_should_never_match"); + else + tmp = str_dup(buf->data); + + if ((minor = strchr(tmp, '/'))) { + *minor = '\0'; + ++minor; + } else { + minor = "unknown"; + } + major = mutt_check_mime_type(tmp); + + /* We must do our own walk here because remove_from_list() will only + * remove the LIST->data, not anything pointed to by the LIST->data. */ + lastp = NULL; + for(lp = *ldata; lp; ) { + a = (ATTACH_MATCH *)lp->data; + debug_print(5, ("parse_unattach_list: check %s/%s [%d] : %s/%s [%d]\n", + a->major, a->minor, a->major_int, tmp, minor, major)); + if (a->major_int == major && !str_casecmp(minor, a->minor)) { + debug_print(5, ("parse_unattach_list: removed %s/%s [%d]\n", + a->major, a->minor, a->major_int)); + regfree(&a->minor_rx); + mem_free(&a->major); + + /* Relink backward */ + if (lastp) + lastp->next = lp->next; + else + *ldata = lp->next; + + newlp = lp->next; + mem_free(&lp->data); /* same as a */ + mem_free(&lp); + lp = newlp; + continue; + } + + lastp = lp; + lp = lp->next; + } + } + while (MoreArgs (s)); + + mem_free (&tmp); + _attachments_clean(); + return 0; +} + +static int print_attach_list (LIST *lp, char op, char *name) { + while (lp) { + printf("attachments %c%s %s/%s\n", op, name, + ((ATTACH_MATCH *)lp->data)->major, + ((ATTACH_MATCH *)lp->data)->minor); + lp = lp->next; + } + + return 0; +} + +static int parse_attachments (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { + char op, *category; + LIST **listp; + + mutt_extract_token(buf, s, 0); + if (!buf->data || *buf->data == '\0') { + strfcpy(err->data, _("attachments: no disposition"), err->dsize); + return -1; + } + + category = buf->data; + op = *category++; + + if (op == '?') { + mutt_endwin (NULL); + fflush (stdout); + printf("\nCurrent attachments settings:\n\n"); + print_attach_list(AttachAllow, '+', "A"); + print_attach_list(AttachExclude, '-', "A"); + print_attach_list(InlineAllow, '+', "I"); + print_attach_list(InlineExclude, '-', "I"); + set_option (OPTFORCEREDRAWINDEX); + set_option (OPTFORCEREDRAWPAGER); + mutt_any_key_to_continue (NULL); + return 0; + } + + if (op != '+' && op != '-') { + op = '+'; + category--; + } + if (!str_ncasecmp(category, "attachment", strlen(category))) { + if (op == '+') + listp = &AttachAllow; + else + listp = &AttachExclude; + } + else if (!str_ncasecmp(category, "inline", strlen(category))) { + if (op == '+') + listp = &InlineAllow; + else + listp = &InlineExclude; + } else { + strfcpy(err->data, _("attachments: invalid disposition"), err->dsize); + return -1; + } + + return parse_attach_list(buf, s, listp, err); +} + +static int parse_unattachments (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { + char op, *p; + LIST **listp; + + mutt_extract_token(buf, s, 0); + if (!buf->data || *buf->data == '\0') { + strfcpy(err->data, _("unattachments: no disposition"), err->dsize); + return -1; + } + + p = buf->data; + op = *p++; + if (op != '+' && op != '-') { + op = '+'; + p--; + } + if (!str_ncasecmp(p, "attachment", strlen(p))) { + if (op == '+') + listp = &AttachAllow; + else + listp = &AttachExclude; + } + else if (!str_ncasecmp(p, "inline", strlen(p))) { + if (op == '+') + listp = &InlineAllow; + else + listp = &InlineExclude; + } + else { + strfcpy(err->data, _("unattachments: invalid disposition"), err->dsize); + return -1; + } + + return parse_unattach_list(buf, s, listp, err); +} + static int parse_unlists (BUFFER * buf, BUFFER * s, unsigned long data, BUFFER * err) { @@ -1167,7 +1470,8 @@ static int parse_alias (BUFFER * buf, BUFFER * s, unsigned long data, if (DebugLevel >= 2) { ADDRESS *a; - for (a = tmp->addr; a; a = a->next) { + /* A group is terminated with an empty address, so check a->mailbox */ + for (a = tmp->addr; a && a->mailbox; a = a->next) { if (!a->group) debug_print (2, ("%s\n", a->mailbox)); else @@ -1295,17 +1599,81 @@ static void mutt_set_default (const char* name, void* p, unsigned long more) { return; ptr = hash_find (ConfigOptions, (char*) ptr->data); } - if (!ptr || *ptr->init) + if (!ptr || *ptr->init || !FuncTable[DTYPE (ptr->type)].opt_from_string) return; mutt_option_value (ptr->option, buf, sizeof (buf)); if (str_len (ptr->init) == 0 && buf && *buf) ptr->init = str_dup (buf); } +static struct option_t* add_option (const char* name, const char* init, + short type, short dup) { + struct option_t* option = mem_calloc (1, sizeof (struct option_t)); + + debug_print (1, ("adding $%s\n", name)); + + option->option = str_dup (name); + option->type = type; + if (init) + option->init = dup ? str_dup (init) : (char*) init; + return (option); +} + +/* creates new option_t* of type DT_USER for $user_ var */ +static struct option_t* add_user_option (const char* name) { + return (add_option (name, NULL, DT_USER, 1)); +} + +/* free()'s option_t* */ +static void del_option (void* p) { + struct option_t* ptr = (struct option_t*) p; + char* s = (char*) ptr->data; + debug_print (1, ("removing option '%s' from table\n", NONULL (ptr->option))); + mem_free (&ptr->option); + mem_free (&s); + mem_free (&ptr->init); + mem_free (&ptr); +} + +static int init_expand (char** dst, struct option_t* src) { + BUFFER token, in; + size_t len = 0; + + mem_free (dst); + + if (DTYPE(src->type) == DT_STR || + DTYPE(src->type) == DT_PATH) { + /* only expand for string as it's the only place where + * we want to expand vars right now */ + if (src->init && *src->init) { + memset (&token, 0, sizeof (BUFFER)); + memset (&in, 0, sizeof (BUFFER)); + len = str_len (src->init) + 2; + in.data = mem_malloc (len+1); + snprintf (in.data, len, "\"%s\"", src->init); + in.dptr = in.data; + in.dsize = len; + mutt_extract_token (&token, &in, 0); + if (token.data && *token.data) + *dst = str_dup (token.data); + else + *dst = str_dup (""); + mem_free (&in.data); + mem_free (&token.data); + } else + *dst = str_dup (""); + } else + /* for non-string: take value as is */ + *dst = str_dup (src->init); + return (1); +} + /* if additional data more == 1, we want to resolve synonyms */ -static void mutt_restore_default (const char* name, void* p, unsigned long more) { +static void mutt_restore_default (const char* name, void* p, + unsigned long more) { char errbuf[STRING]; struct option_t* ptr = (struct option_t*) p; + char* init = NULL; if (DTYPE (ptr->type) == DT_SYN) { if (!more) @@ -1314,12 +1682,18 @@ static void mutt_restore_default (const char* name, void* p, unsigned long more) } if (!ptr) return; - if (FuncTable[DTYPE (ptr->type)].opt_from_string (ptr, ptr->init, errbuf, - sizeof (errbuf)) < 0) { - mutt_endwin (NULL); - fprintf (stderr, _("Invalid default setting found. Please report this " - "error:\n\"%s\"\n"), errbuf); - exit (1); + if (FuncTable[DTYPE (ptr->type)].opt_from_string) { + init_expand (&init, ptr); + if (!FuncTable[DTYPE (ptr->type)].opt_from_string (ptr, init, errbuf, + sizeof (errbuf))) { + if (!option (OPTNOCURSES)) + mutt_endwin (NULL); + fprintf (stderr, _("Invalid default setting for $%s found: \"%s\".\n" + "Please report this error: \"%s\"\n"), + ptr->option, NONULL (init), errbuf); + exit (1); + } + mem_free (&init); } if (ptr->flags & R_INDEX) @@ -1387,6 +1761,19 @@ static int check_num (const char* option, unsigned long p, return (1); } +#ifdef DEBUG +static int check_debug (const char* option, unsigned long p, + char* errbuf, size_t errlen) { + if ((int) p <= DEBUG_MAX_LEVEL && + (int) p >= DEBUG_MIN_LEVEL) + return (1); + + if (errbuf) + snprintf (errbuf, errlen, _("'%d' is invalid for $%s"), (int) p, option); + return (0); +} +#endif + static int check_history (const char* option, unsigned long p, char* errbuf, size_t errlen) { if (!check_num ("history", p, errbuf, errlen)) @@ -1432,14 +1819,6 @@ static const struct mapping_t* get_sortmap (struct option_t* option) { return (map); } -/* creates new option_t* of type DT_USER for $user_ var */ -static struct option_t* add_user_option (const char* name) { - struct option_t* option = mem_calloc (1, sizeof (struct option_t)); - option->option = str_dup (name); - option->type = DT_USER; - return (option); -} - static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, BUFFER * err) { @@ -1482,11 +1861,14 @@ static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, } /* see if we need to add $user_ var */ - if (!option && !reset && !unset && - ascii_strncasecmp ("user_", tmp->data, 5) == 0) { - debug_print (1, ("adding user option '%s'\n", tmp->data)); - option = add_user_option (tmp->data); - hash_insert (ConfigOptions, option->option, option, 0); + if (!option && ascii_strncmp ("user_", tmp->data, 5) == 0) { + /* there's no option named like this yet so only add one + * if the action isn't any of: reset, unset, query */ + if (!(reset || unset || query || *s->dptr != '=')) { + debug_print (1, ("adding user option '%s'\n", tmp->data)); + option = add_user_option (tmp->data); + hash_insert (ConfigOptions, option->option, option, 0); + } } if (!option && !(reset && str_cmp ("all", tmp->data) == 0)) { @@ -1507,11 +1889,27 @@ static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, } if (!str_cmp ("all", tmp->data)) { + if (CurrentMenu == MENU_PAGER) { + snprintf (err->data, err->dsize, _("Not available in this menu.")); + return (-1); + } hash_map (ConfigOptions, mutt_restore_default, 1); + set_option (OPTFORCEREDRAWINDEX); + set_option (OPTFORCEREDRAWPAGER); + set_option (OPTSORTSUBTHREADS); + set_option (OPTNEEDRESORT); + set_option (OPTRESORTINIT); + set_option (OPTREDRAWTREE); return (0); } - else + else if (!FuncTable[DTYPE (option->type)].opt_from_string) { + snprintf (err->data, err->dsize, _("$%s is read-only"), option->option); + r = -1; + break; + } else { + CHECK_PAGER; mutt_restore_default (NULL, option, 1); + } } else if (DTYPE (option->type) == DT_BOOL) { /* XXX this currently ignores the function table @@ -1539,6 +1937,7 @@ static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, return 0; } + CHECK_PAGER; if (unset) unset_option (option->data); else if (inv) @@ -1553,20 +1952,29 @@ static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, DTYPE (option->type) == DT_NUM || DTYPE (option->type) == DT_SORT || DTYPE (option->type) == DT_RX || - DTYPE (option->type) == DT_USER) { + DTYPE (option->type) == DT_USER || + DTYPE (option->type) == DT_SYS) { /* XXX maybe we need to get unset into handlers? */ if (DTYPE (option->type) == DT_STR || DTYPE (option->type) == DT_PATH || DTYPE (option->type) == DT_ADDR || - DTYPE (option->type) == DT_USER) { + DTYPE (option->type) == DT_USER || + DTYPE (option->type) == DT_SYS) { if (unset) { - if (DTYPE (option->type) == DT_ADDR) + CHECK_PAGER; + if (!FuncTable[DTYPE (option->type)].opt_from_string) { + snprintf (err->data, err->dsize, _("$%s is read-only"), + option->option); + r = -1; + break; + } else if (DTYPE (option->type) == DT_ADDR) rfc822_free_address ((ADDRESS **) option->data); - else if (DTYPE (option->type) == DT_USER) { - void* p = (void*) option->data; - mem_free (&p); - } else + else if (DTYPE (option->type) == DT_USER) + /* to unset $user_ means remove */ + hash_delete (ConfigOptions, option->option, + option, del_option); + else mem_free ((void *) option->data); break; } @@ -1578,11 +1986,20 @@ static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, break; } - s->dptr++; - mutt_extract_token (tmp, s, 0); - if (!FuncTable[DTYPE (option->type)].opt_from_string - (option, tmp->data, err->data, err->dsize)) + /* the $muttng_ variables are read-only */ + if (!FuncTable[DTYPE (option->type)].opt_from_string) { + snprintf (err->data, err->dsize, _("$%s is read-only"), + option->option); r = -1; + break; + } else { + CHECK_PAGER; + s->dptr++; + mutt_extract_token (tmp, s, 0); + if (!FuncTable[DTYPE (option->type)].opt_from_string + (option, tmp->data, err->data, err->dsize)) + r = -1; + } } else if (DTYPE (option->type) == DT_QUAD) { @@ -1592,6 +2009,7 @@ static int parse_set (BUFFER * tmp, BUFFER * s, unsigned long data, } if (*s->dptr == '=') { + CHECK_PAGER; s->dptr++; mutt_extract_token (tmp, s, 0); if (ascii_strcasecmp ("yes", tmp->data) == 0) @@ -1753,6 +2171,8 @@ int mutt_parse_rc_line ( /* const */ char *line, BUFFER * token, BUFFER * err) *err->data = 0; + debug_print (1, ("expand '%s'\n", line)); + SKIPWS (expn.dptr); while (*expn.dptr) { if (*expn.dptr == '#') @@ -2161,10 +2581,17 @@ void mutt_init (int skip_sys_rc, LIST * commands) err.data = error; err.dsize = sizeof (error); - /* use 3*sizeof(muttvars) to have some room for $user_ vars */ + /* use 3*sizeof(muttvars) instead of 2*sizeof() + * to have some room for $user_ vars */ ConfigOptions = hash_create (sizeof (MuttVars) * 3); - for (i = 0; MuttVars[i].option; i++) - hash_insert (ConfigOptions, MuttVars[i].option, &MuttVars[i], 0); + for (i = 0; MuttVars[i].option; i++) { + if (DTYPE (MuttVars[i].type) != DT_SYS) + hash_insert (ConfigOptions, MuttVars[i].option, &MuttVars[i], 0); + else + hash_insert (ConfigOptions, MuttVars[i].option, + add_option (MuttVars[i].option, MuttVars[i].init, + DT_SYS, 0), 0); + } /* * XXX - use something even more difficult to predict? @@ -2187,6 +2614,7 @@ void mutt_init (int skip_sys_rc, LIST * commands) Realname = str_dup (mutt_gecos_name (rnbuf, sizeof (rnbuf), pw)); Shell = str_dup (pw->pw_shell); + endpwent (); } else { if (!Homedir) { @@ -2398,7 +2826,7 @@ void mutt_init (int skip_sys_rc, LIST * commands) /* Read the user's initialization file. */ if (access (Muttrc, F_OK) != -1) { if (!option (OPTNOCURSES)) - endwin (); + mutt_endwin (NULL); if (source_rc (Muttrc, &err) != 0) { fputs (err.data, stderr); fputc ('\n', stderr);