names.c: fix compiler warnings
[s-mailx.git] / vars.c
blob79ee78d25396cc97eb7696c4a68c7e3f548382c5
1 /*
2 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 */
6 /*
7 * Copyright (c) 1980, 1993
8 * The Regents of the University of California. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #ifndef lint
40 #ifdef DOSCCS
41 static char sccsid[] = "@(#)vars.c 2.12 (gritter) 10/1/08";
42 #endif
43 #endif /* not lint */
45 #include "rcv.h"
46 #include "extern.h"
49 * Mail -- a mail program
51 * Variable handling stuff.
54 static char *canonify(const char *vn);
55 static void vfree(char *cp);
56 static struct var *lookup(const char *name);
57 static void remove_grouplist(struct grouphead *gh);
60 * If a variable name begins with a lowercase-character and contains at
61 * least one '@', it is converted to all-lowercase. This is necessary
62 * for lookups of names based on email addresses.
64 * Following the standard, only the part following the last '@' should
65 * be lower-cased, but practice has established otherwise here.
67 static char *
68 canonify(const char *vn)
70 const char *vp;
72 if (upperchar(*vn&0377))
73 return (char *)vn;
74 for (vp = vn; *vp && *vp != '@'; vp++);
75 if (*vp == '@')
76 return i_strdup(vn);
77 return (char *)vn;
81 * Assign a value to a variable.
83 void
84 assign(const char *name, const char *value)
86 struct var *vp;
87 int h;
89 name = canonify(name);
90 h = hash(name);
91 vp = lookup(name);
92 if (vp == NULL) {
93 vp = (struct var *)scalloc(1, sizeof *vp);
94 vp->v_name = vcopy(name);
95 vp->v_link = variables[h];
96 variables[h] = vp;
98 else
99 vfree(vp->v_value);
100 vp->v_value = vcopy(value);
104 * Free up a variable string. We do not bother to allocate
105 * strings whose value is "" since they are expected to be frequent.
106 * Thus, we cannot free same!
108 static void
109 vfree(char *cp)
111 if (*cp)
112 free(cp);
116 * Copy a variable value into permanent (ie, not collected after each
117 * command) space. Do not bother to alloc space for ""
120 char *
121 vcopy(const char *str)
123 char *new;
124 unsigned len;
126 if (*str == '\0')
127 return "";
128 len = strlen(str) + 1;
129 new = smalloc(len);
130 memcpy(new, str, (int) len);
131 return new;
135 * Get the value of a variable and return it.
136 * Look in the environment if its not available locally.
139 char *
140 value(const char *name)
142 struct var *vp;
143 char *vs;
145 name = canonify(name);
146 if ((vp = lookup(name)) == NULL) {
147 if ((vs = getenv(name)) != NULL && *vs)
148 vs = savestr(vs);
149 return vs;
151 return vp->v_value;
155 * Locate a variable and return its variable
156 * node.
159 static struct var *
160 lookup(const char *name)
162 struct var *vp;
164 for (vp = variables[hash(name)]; vp != NULL; vp = vp->v_link)
165 if (*vp->v_name == *name && equal(vp->v_name, name))
166 return(vp);
167 return(NULL);
171 * Locate a group name and return it.
174 struct grouphead *
175 findgroup(char *name)
177 struct grouphead *gh;
179 for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link)
180 if (*gh->g_name == *name && equal(gh->g_name, name))
181 return(gh);
182 return(NULL);
186 * Print a group out on stdout
188 void
189 printgroup(char *name)
191 struct grouphead *gh;
192 struct group *gp;
194 if ((gh = findgroup(name)) == NULL) {
195 printf(catgets(catd, CATSET, 202, "\"%s\": not a group\n"),
196 name);
197 return;
199 printf("%s\t", gh->g_name);
200 for (gp = gh->g_list; gp != NULL; gp = gp->ge_link)
201 printf(" %s", gp->ge_name);
202 putchar('\n');
206 * Hash the passed string and return an index into
207 * the variable or group hash table.
209 int
210 hash(const char *name)
212 int h = 0;
214 while (*name) {
215 h <<= 2;
216 h += *name++;
218 if (h < 0 && (h = -h) < 0)
219 h = 0;
220 return (h % HSHSIZE);
223 int
224 unset_internal(const char *name)
226 struct var *vp, *vp2;
227 int h;
229 name = canonify(name);
230 if ((vp2 = lookup(name)) == NULL) {
231 if (!sourcing && !unset_allow_undefined) {
232 printf(catgets(catd, CATSET, 203,
233 "\"%s\": undefined variable\n"), name);
234 return 1;
236 return 0;
238 h = hash(name);
239 if (vp2 == variables[h]) {
240 variables[h] = variables[h]->v_link;
241 vfree(vp2->v_name);
242 vfree(vp2->v_value);
243 free(vp2);
244 return 0;
246 for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link);
247 vp->v_link = vp2->v_link;
248 vfree(vp2->v_name);
249 vfree(vp2->v_value);
250 free(vp2);
251 return 0;
254 static void
255 remove_grouplist(struct grouphead *gh)
257 struct group *gp, *gq;
259 if ((gp = gh->g_list) != NULL) {
260 for (; gp; gp = gq) {
261 gq = gp->ge_link;
262 vfree(gp->ge_name);
263 free(gp);
268 void
269 remove_group(const char *name)
271 struct grouphead *gh, *gp = NULL;
272 int h = hash(name);
274 for (gh = groups[h]; gh != NULL; gh = gh->g_link) {
275 if (*gh->g_name == *name && equal(gh->g_name, name)) {
276 remove_grouplist(gh);
277 vfree(gh->g_name);
278 if (gp != NULL)
279 gp->g_link = gh->g_link;
280 else
281 groups[h] = NULL;
282 free(gh);
283 break;
285 gp = gh;