makeconfig: small tweaks
[s-mailx.git] / vars.c
blob210027d42b4893042bddc7b1b00ec4a7f72ef555
1 /*
2 * S-nail - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 Steffen "Daode" Nurpmeso.
6 */
7 /*
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
40 #include "rcv.h"
41 #include "extern.h"
44 * Mail -- a mail program
46 * Variable handling stuff.
49 static char *canonify(const char *vn);
50 static void vfree(char *cp);
51 static struct var *lookup(const char *name, int h);
52 static void remove_grouplist(struct grouphead *gh);
55 * If a variable name begins with a lowercase-character and contains at
56 * least one '@', it is converted to all-lowercase. This is necessary
57 * for lookups of names based on email addresses.
59 * Following the standard, only the part following the last '@' should
60 * be lower-cased, but practice has established otherwise here.
62 static char *
63 canonify(const char *vn)
65 const char *vp;
67 if (upperchar(*vn))
68 return ((char*)vn);
69 for (vp = vn; *vp && *vp != '@'; vp++)
71 return ((*vp == '@') ? i_strdup(vn) : (char*)vn);
75 * Assign a value to a variable.
77 void
78 assign(const char *name, const char *value)
80 struct var *vp;
81 int h;
83 name = canonify(name);
84 h = hash(name);
86 vp = lookup(name, h);
87 if (vp == NULL) {
88 vp = (struct var*)scalloc(1, sizeof *vp);
89 vp->v_name = vcopy(name);
90 vp->v_link = variables[h];
91 variables[h] = vp;
93 else
94 vfree(vp->v_value);
95 vp->v_value = vcopy(value);
99 * Free up a variable string. We do not bother to allocate
100 * strings whose value is "" since they are expected to be frequent.
101 * Thus, we cannot free same!
103 static void
104 vfree(char *cp)
106 if (*cp)
107 free(cp);
111 * Copy a variable value into permanent (ie, not collected after each
112 * command) space. Do not bother to alloc space for ""
115 char *
116 vcopy(const char *str)
118 char *news;
119 unsigned len;
121 if (*str == '\0')
122 return "";
123 len = strlen(str) + 1;
124 news = smalloc(len);
125 memcpy(news, str, (int)len);
126 return (news);
130 * Get the value of a variable and return it.
131 * Look in the environment if its not available locally.
134 char *
135 value(const char *name)
137 struct var *vp;
138 char *vs;
140 name = canonify(name);
141 if ((vp = lookup(name, -1)) == NULL) {
142 if ((vs = getenv(name)) != NULL && *vs)
143 vs = savestr(vs);
144 return (vs);
146 return (vp->v_value);
150 * Locate a variable and return its variable node.
152 static struct var *
153 lookup(const char *name, int h)
155 struct var **vap, *lvp, *vp;
157 vap = variables + ((h >= 0) ? h : hash(name));
159 for (lvp = NULL, vp = *vap; vp != NULL; lvp = vp, vp = vp->v_link)
160 if (*vp->v_name == *name && strcmp(vp->v_name, name) == 0) {
161 /* Relink as head, hope it "sorts on usage" over time */
162 if (lvp != NULL) {
163 lvp->v_link = vp->v_link;
164 vp->v_link = *vap;
165 *vap = vp;
167 return (vp);
169 return (NULL);
173 * Locate a group name and return it.
176 struct grouphead *
177 findgroup(char *name)
179 struct grouphead *gh;
181 for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link)
182 if (*gh->g_name == *name && strcmp(gh->g_name, name) == 0)
183 return(gh);
184 return(NULL);
188 * Print a group out on stdout
190 void
191 printgroup(char *name)
193 struct grouphead *gh;
194 struct group *gp;
196 if ((gh = findgroup(name)) == NULL) {
197 printf(catgets(catd, CATSET, 202, "\"%s\": not a group\n"),
198 name);
199 return;
201 printf("%s\t", gh->g_name);
202 for (gp = gh->g_list; gp != NULL; gp = gp->ge_link)
203 printf(" %s", gp->ge_name);
204 putchar('\n');
208 * Hash the passed string and return an index into
209 * the variable or group hash table.
210 * Use Chris Torek's hash algorithm.
212 int
213 hash(const char *name)
215 int h = 0;
217 while (*name) {
218 h *= 33;
219 h += *name++;
221 if (h < 0 && (h = -h) < 0)
222 h = 0;
223 return (h % HSHSIZE);
226 int
227 unset_internal(const char *name)
229 int h;
230 struct var *vp;
232 name = canonify(name);
233 h = hash(name);
235 if ((vp = lookup(name, h)) == NULL) {
236 if (! sourcing && ! unset_allow_undefined) {
237 printf(tr(203, "\"%s\": undefined variable\n"), name);
238 return (1);
240 return (0);
243 /* Always listhead after lookup() */
244 variables[h] = variables[h]->v_link;
245 vfree(vp->v_name);
246 vfree(vp->v_value);
247 free(vp);
248 return (0);
251 static void
252 remove_grouplist(struct grouphead *gh)
254 struct group *gp, *gq;
256 if ((gp = gh->g_list) != NULL) {
257 for (; gp; gp = gq) {
258 gq = gp->ge_link;
259 vfree(gp->ge_name);
260 free(gp);
265 void
266 remove_group(const char *name)
268 struct grouphead *gh, *gp = NULL;
269 int h = hash(name);
271 for (gh = groups[h]; gh != NULL; gh = gh->g_link) {
272 if (*gh->g_name == *name && strcmp(gh->g_name, name) == 0) {
273 remove_grouplist(gh);
274 vfree(gh->g_name);
275 if (gp != NULL)
276 gp->g_link = gh->g_link;
277 else
278 groups[h] = NULL;
279 free(gh);
280 break;
282 gp = gh;