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