1 /* $NetBSD: vars.c,v 1.19 2023/09/08 14:22:04 shm Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)vars.c 8.1 (Berkeley) 6/6/93"; 36 #else 37 __RCSID("$NetBSD: vars.c,v 1.19 2023/09/08 14:22:04 shm Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include "rcv.h" 42 #include <util.h> 43 44 #include "extern.h" 45 46 /* 47 * Mail -- a mail program 48 * 49 * Variable handling stuff. 50 */ 51 52 /* 53 * Free up a variable string. We do not bother to allocate 54 * strings whose value is "" since they are expected to be frequent. 55 * Thus, we cannot free same! 56 */ 57 PUBLIC void 58 v_free(char *cp) 59 { 60 if (*cp) 61 free(cp); 62 } 63 64 /* 65 * Copy a variable value into permanent (ie, not collected after each 66 * command) space. Do not bother to alloc space for "" 67 */ 68 PUBLIC char * 69 vcopy(const char str[]) 70 { 71 char *new; 72 size_t len; 73 74 if (*str == '\0') 75 return estrdup(""); 76 len = strlen(str) + 1; 77 new = emalloc(len); 78 (void)memmove(new, str, len); 79 return new; 80 } 81 82 /* 83 * Hash the passed string and return an index into 84 * the variable or group hash table. 85 */ 86 PUBLIC int 87 hash(const char *name) 88 { 89 unsigned int h = 0; 90 91 while (*name) { 92 h <<= 2; 93 h += *name++; 94 } 95 return h % HSHSIZE; 96 } 97 98 /* 99 * Locate a variable and return its variable 100 * node. 101 */ 102 PUBLIC struct var * 103 lookup(const char name[]) 104 { 105 struct var *vp; 106 107 for (vp = variables[hash(name)]; vp != NULL; vp = vp->v_link) 108 if (*vp->v_name == *name && equal(vp->v_name, name)) 109 return vp; 110 return NULL; 111 } 112 113 /* 114 * Assign a value to a variable. 115 */ 116 PUBLIC void 117 assign(const char name[], const char values[]) 118 { 119 struct var *vp; 120 int h; 121 122 h = hash(name); 123 vp = lookup(name); 124 if (vp == NULL) { 125 vp = ecalloc(1, sizeof(*vp)); 126 vp->v_name = vcopy(name); 127 vp->v_link = variables[h]; 128 variables[h] = vp; 129 } 130 else 131 v_free(vp->v_value); 132 vp->v_value = vcopy(values); 133 } 134 135 /* 136 * Get the value of a variable and return it. 137 * Look in the environment if its not available locally. 138 */ 139 PUBLIC char * 140 value(const char name[]) 141 { 142 struct var *vp; 143 144 if ((vp = lookup(name)) == NULL) 145 return getenv(name); 146 return vp->v_value; 147 } 148 149 /* 150 * Locate a group name and return it. 151 */ 152 PUBLIC struct grouphead * 153 findgroup(const char name[]) 154 { 155 struct grouphead *gh; 156 157 for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link) 158 if (*gh->g_name == *name && equal(gh->g_name, name)) 159 return gh; 160 return NULL; 161 } 162 163 /* 164 * Print a group out on stdout 165 */ 166 PUBLIC void 167 printgroup(const char name[]) 168 { 169 struct grouphead *gh; 170 struct group *gp; 171 172 if ((gh = findgroup(name)) == NULL) { 173 (void)printf("\"%s\": not a group\n", name); 174 return; 175 } 176 (void)printf("%s\t", gh->g_name); 177 for (gp = gh->g_list; gp != NULL; gp = gp->ge_link) 178 (void)printf(" %s", gp->ge_name); 179 (void)putchar('\n'); 180 } 181