xref: /freebsd/usr.bin/mail/vars.c (revision 5e3934b15a2741b2de6b217e77dc9d798d740804)
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