]> diplodocus.org Git - nmh/blob - sbr/readconfig.c
Fix invalid pointer arithmetic.
[nmh] / sbr / readconfig.c
1 /* readconfig.c -- base routine to read nmh configuration files
2 * -- such as nmh profile, context file, or mhn.defaults.
3 *
4 * This code is Copyright (c) 2002, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/utils.h>
11
12 struct procstr {
13 char *procname;
14 char **procnaddr;
15 };
16
17 static struct procstr procs[] = {
18 { "context", &context },
19 { "mh-sequences", &mh_seq },
20 { "buildmimeproc", &buildmimeproc },
21 { "fileproc", &fileproc },
22 { "formatproc", &formatproc },
23 { "incproc", &incproc },
24 { "lproc", &lproc },
25 { "mailproc", &mailproc },
26 { "mhlproc", &mhlproc },
27 { "moreproc", &moreproc },
28 { "packproc", &packproc },
29 { "postproc", &postproc },
30 { "rmmproc", &rmmproc },
31 { "sendproc", &sendproc },
32 { "showmimeproc", &showmimeproc },
33 { "showproc", &showproc },
34 { "whatnowproc", &whatnowproc },
35 { "whomproc", &whomproc },
36 { NULL, NULL }
37 };
38
39 static struct node **opp = NULL;
40
41
42 void
43 readconfig (struct node **npp, FILE *ib, const char *file, int ctx)
44 {
45 int state;
46 char *cp;
47 char name[NAMESZ], field[NMH_BUFSIZ];
48 struct node *np;
49 struct procstr *ps;
50 m_getfld_state_t gstate;
51
52 if (npp == NULL && (npp = opp) == NULL) {
53 inform("bug: readconfig called but pump not primed, continuing...");
54 return;
55 }
56
57 gstate = m_getfld_state_init(ib);
58 for (;;) {
59 int fieldsz = sizeof field;
60 switch (state = m_getfld2(&gstate, name, field, &fieldsz)) {
61 case FLD:
62 case FLDPLUS:
63 NEW(np);
64 *npp = np;
65 *(npp = &np->n_next) = NULL;
66 np->n_name = mh_xstrdup(name);
67 if (state == FLDPLUS) {
68 cp = mh_xstrdup(field);
69 while (state == FLDPLUS) {
70 fieldsz = sizeof field;
71 state = m_getfld2(&gstate, name, field, &fieldsz);
72 cp = add (field, cp);
73 }
74 np->n_field = trimcpy (cp);
75 free (cp);
76 } else {
77 np->n_field = trimcpy (field);
78 }
79 np->n_context = ctx;
80
81 /*
82 * Now scan the list of `procs' and link in the
83 * field value to the global variable.
84 */
85 for (ps = procs; ps->procname; ps++)
86 if (strcmp (np->n_name, ps->procname) == 0) {
87 *ps->procnaddr = np->n_field;
88 break;
89 }
90 continue;
91
92 case BODY:
93 adios (NULL, "no blank lines are permitted in %s", file);
94
95 case FILEEOF:
96 break;
97
98 default:
99 adios (NULL, "%s is poorly formatted", file);
100 }
101 break;
102 }
103 m_getfld_state_destroy (&gstate);
104
105 /*
106 * Special handling for the pager processes: lproc and moreproc.
107 *
108 * If they are not set by the profile, use the callers $PAGER if
109 * available, otherwise set them to DEFAULT_PAGER.
110 */
111 if (lproc == NULL) {
112 lproc = getenv("PAGER");
113 if (lproc == NULL || lproc[0] == '\0')
114 lproc = DEFAULT_PAGER;
115 }
116 if (moreproc == NULL) {
117 moreproc = getenv("PAGER");
118 if (moreproc == NULL || moreproc[0] == '\0')
119 moreproc = DEFAULT_PAGER;
120 }
121
122 if (opp == NULL) {
123 /* Check for duplicated non-null profile entries. Except
124 allow multiple profile entries named "#", because that's
125 what mh-profile(5) suggests using for comments.
126
127 Only do this check on the very first call from
128 context_read(), when opp is NULL. That way, entries in
129 mhn.defaults can be overridden without triggering
130 warnings.
131
132 Note that mhn.defaults, $MHN, $MHBUILD, $MHSHOW, and
133 $MHSTORE all put their entries into just one list, m_defs,
134 the same list that the profile uses. */
135
136 struct node *np;
137 for (np = m_defs; np; np = np->n_next) {
138 /* Yes, this is O(N^2). The profile should be small enough so
139 that's not a performance problem. */
140 if (*np->n_name && strcmp("#", np->n_name)) {
141 struct node *np2;
142 for (np2 = np->n_next; np2; np2 = np2->n_next) {
143 if (! strcasecmp (np->n_name, np2->n_name)) {
144 inform("multiple \"%s\" profile components in %s, "
145 "ignoring \"%s\", continuing...",
146 np->n_name, defpath, np2->n_field);
147 }
148 }
149 }
150 }
151 }
152
153 opp = npp;
154 }
155
156
157 void
158 add_profile_entry (const char *key, const char *value) {
159 struct node *newnode;
160
161 /* This inserts the new node at the beginning of m_defs because
162 that doesn't require traversing it or checking to see if it's
163 empty. */
164 NEW(newnode);
165 newnode->n_name = getcpy (key);
166 newnode->n_field = getcpy (value);
167 newnode->n_context = 0;
168 newnode->n_next = m_defs;
169 m_defs = newnode;
170 }