1*8a16b7a1SPedro F. Giffuni /*-
2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro F. Giffuni *
49b50d902SRodney W. Grimes * Copyright (c) 1980, 1993
59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved.
69b50d902SRodney W. Grimes *
79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions
99b50d902SRodney W. Grimes * are met:
109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software
179b50d902SRodney W. Grimes * without specific prior written permission.
189b50d902SRodney W. Grimes *
199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299b50d902SRodney W. Grimes * SUCH DAMAGE.
309b50d902SRodney W. Grimes */
319b50d902SRodney W. Grimes
329b50d902SRodney W. Grimes #include "rcv.h"
339b50d902SRodney W. Grimes #include "extern.h"
349b50d902SRodney W. Grimes
359b50d902SRodney W. Grimes /*
369b50d902SRodney W. Grimes * Mail -- a mail program
379b50d902SRodney W. Grimes *
389b50d902SRodney W. Grimes * Variable handling stuff.
399b50d902SRodney W. Grimes */
409b50d902SRodney W. Grimes
419b50d902SRodney W. Grimes /*
429b50d902SRodney W. Grimes * Assign a value to a variable.
439b50d902SRodney W. Grimes */
449b50d902SRodney W. Grimes void
assign(const char * name,const char * value)456d8484b0SPhilippe Charnier assign(const char *name, const char *value)
469b50d902SRodney W. Grimes {
479ce73e90SMike Heffner struct var *vp;
489ce73e90SMike Heffner int h;
499b50d902SRodney W. Grimes
509b50d902SRodney W. Grimes h = hash(name);
519b50d902SRodney W. Grimes vp = lookup(name);
529ce73e90SMike Heffner if (vp == NULL) {
5320a50e9cSPedro F. Giffuni if ((vp = calloc(1, sizeof(*vp))) == NULL)
5420a50e9cSPedro F. Giffuni err(1, "Out of memory");
559b50d902SRodney W. Grimes vp->v_name = vcopy(name);
569b50d902SRodney W. Grimes vp->v_link = variables[h];
579b50d902SRodney W. Grimes variables[h] = vp;
589b50d902SRodney W. Grimes }
599b50d902SRodney W. Grimes else
609b50d902SRodney W. Grimes vfree(vp->v_value);
619b50d902SRodney W. Grimes vp->v_value = vcopy(value);
629b50d902SRodney W. Grimes }
639b50d902SRodney W. Grimes
649b50d902SRodney W. Grimes /*
659b50d902SRodney W. Grimes * Free up a variable string. We do not bother to allocate
669b50d902SRodney W. Grimes * strings whose value is "" since they are expected to be frequent.
679b50d902SRodney W. Grimes * Thus, we cannot free same!
689b50d902SRodney W. Grimes */
699b50d902SRodney W. Grimes void
vfree(char * cp)706d8484b0SPhilippe Charnier vfree(char *cp)
719b50d902SRodney W. Grimes {
729ce73e90SMike Heffner if (*cp != '\0')
739ce73e90SMike Heffner (void)free(cp);
749b50d902SRodney W. Grimes }
759b50d902SRodney W. Grimes
769b50d902SRodney W. Grimes /*
779b50d902SRodney W. Grimes * Copy a variable value into permanent (ie, not collected after each
789b50d902SRodney W. Grimes * command) space. Do not bother to alloc space for ""
799b50d902SRodney W. Grimes */
809b50d902SRodney W. Grimes
819b50d902SRodney W. Grimes char *
vcopy(const char * str)826d8484b0SPhilippe Charnier vcopy(const char *str)
839b50d902SRodney W. Grimes {
849b50d902SRodney W. Grimes char *new;
859b50d902SRodney W. Grimes unsigned len;
869b50d902SRodney W. Grimes
879b50d902SRodney W. Grimes if (*str == '\0')
889ce73e90SMike Heffner return ("");
899b50d902SRodney W. Grimes len = strlen(str) + 1;
909b50d902SRodney W. Grimes if ((new = malloc(len)) == NULL)
910c3a8314SMike Heffner err(1, "Out of memory");
929b50d902SRodney W. Grimes bcopy(str, new, (int)len);
939ce73e90SMike Heffner return (new);
949b50d902SRodney W. Grimes }
959b50d902SRodney W. Grimes
969b50d902SRodney W. Grimes /*
979b50d902SRodney W. Grimes * Get the value of a variable and return it.
989b50d902SRodney W. Grimes * Look in the environment if its not available locally.
999b50d902SRodney W. Grimes */
1009b50d902SRodney W. Grimes
1019b50d902SRodney W. Grimes char *
value(const char * name)1026d8484b0SPhilippe Charnier value(const char *name)
1039b50d902SRodney W. Grimes {
1049ce73e90SMike Heffner struct var *vp;
1059b50d902SRodney W. Grimes
1069ce73e90SMike Heffner if ((vp = lookup(name)) == NULL)
1079b50d902SRodney W. Grimes return (getenv(name));
1089b50d902SRodney W. Grimes return (vp->v_value);
1099b50d902SRodney W. Grimes }
1109b50d902SRodney W. Grimes
1119b50d902SRodney W. Grimes /*
1129b50d902SRodney W. Grimes * Locate a variable and return its variable
1139b50d902SRodney W. Grimes * node.
1149b50d902SRodney W. Grimes */
1159b50d902SRodney W. Grimes
1169b50d902SRodney W. Grimes struct var *
lookup(const char * name)1176d8484b0SPhilippe Charnier lookup(const char *name)
1189b50d902SRodney W. Grimes {
1199ce73e90SMike Heffner struct var *vp;
1209b50d902SRodney W. Grimes
1219ce73e90SMike Heffner for (vp = variables[hash(name)]; vp != NULL; vp = vp->v_link)
1229b50d902SRodney W. Grimes if (*vp->v_name == *name && equal(vp->v_name, name))
1239b50d902SRodney W. Grimes return (vp);
1249ce73e90SMike Heffner return (NULL);
1259b50d902SRodney W. Grimes }
1269b50d902SRodney W. Grimes
1279b50d902SRodney W. Grimes /*
1289b50d902SRodney W. Grimes * Locate a group name and return it.
1299b50d902SRodney W. Grimes */
1309b50d902SRodney W. Grimes
1319b50d902SRodney W. Grimes struct grouphead *
findgroup(char name[])1326d8484b0SPhilippe Charnier findgroup(char name[])
1339b50d902SRodney W. Grimes {
1349ce73e90SMike Heffner struct grouphead *gh;
1359b50d902SRodney W. Grimes
1369ce73e90SMike Heffner for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link)
1379b50d902SRodney W. Grimes if (*gh->g_name == *name && equal(gh->g_name, name))
1389b50d902SRodney W. Grimes return (gh);
1399ce73e90SMike Heffner return (NULL);
1409b50d902SRodney W. Grimes }
1419b50d902SRodney W. Grimes
1429b50d902SRodney W. Grimes /*
1439b50d902SRodney W. Grimes * Print a group out on stdout
1449b50d902SRodney W. Grimes */
1459b50d902SRodney W. Grimes void
printgroup(char name[])1466d8484b0SPhilippe Charnier printgroup(char name[])
1479b50d902SRodney W. Grimes {
1489ce73e90SMike Heffner struct grouphead *gh;
1499ce73e90SMike Heffner struct group *gp;
1509b50d902SRodney W. Grimes
1519ce73e90SMike Heffner if ((gh = findgroup(name)) == NULL) {
1529b50d902SRodney W. Grimes printf("\"%s\": not a group\n", name);
1539b50d902SRodney W. Grimes return;
1549b50d902SRodney W. Grimes }
1559b50d902SRodney W. Grimes printf("%s\t", gh->g_name);
1569ce73e90SMike Heffner for (gp = gh->g_list; gp != NULL; gp = gp->ge_link)
1579b50d902SRodney W. Grimes printf(" %s", gp->ge_name);
1589ce73e90SMike Heffner printf("\n");
1599b50d902SRodney W. Grimes }
1609b50d902SRodney W. Grimes
1619b50d902SRodney W. Grimes /*
1629b50d902SRodney W. Grimes * Hash the passed string and return an index into
1639b50d902SRodney W. Grimes * the variable or group hash table.
1649b50d902SRodney W. Grimes */
1659b50d902SRodney W. Grimes int
hash(const char * name)1666d8484b0SPhilippe Charnier hash(const char *name)
1679b50d902SRodney W. Grimes {
1689ce73e90SMike Heffner int h = 0;
1699b50d902SRodney W. Grimes
1709ce73e90SMike Heffner while (*name != '\0') {
1719b50d902SRodney W. Grimes h <<= 2;
1729b50d902SRodney W. Grimes h += *name++;
1739b50d902SRodney W. Grimes }
1749b50d902SRodney W. Grimes if (h < 0 && (h = -h) < 0)
1759b50d902SRodney W. Grimes h = 0;
1769b50d902SRodney W. Grimes return (h % HSHSIZE);
1779b50d902SRodney W. Grimes }
178