11590Srgrimes/*
21590Srgrimes * Copyright (c) 1980, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
301590Srgrimes#ifndef lint
3174769Smikeh#if 0
321590Srgrimesstatic char sccsid[] = "@(#)vars.c	8.1 (Berkeley) 6/6/93";
3374769Smikeh#endif
341590Srgrimes#endif /* not lint */
3599112Sobrien#include <sys/cdefs.h>
3699112Sobrien__FBSDID("$FreeBSD$");
371590Srgrimes
381590Srgrimes#include "rcv.h"
391590Srgrimes#include "extern.h"
401590Srgrimes
411590Srgrimes/*
421590Srgrimes * Mail -- a mail program
431590Srgrimes *
441590Srgrimes * Variable handling stuff.
451590Srgrimes */
461590Srgrimes
471590Srgrimes/*
481590Srgrimes * Assign a value to a variable.
491590Srgrimes */
501590Srgrimesvoid
51216564Scharnierassign(const char *name, const char *value)
521590Srgrimes{
5377274Smikeh	struct var *vp;
5477274Smikeh	int h;
551590Srgrimes
561590Srgrimes	h = hash(name);
571590Srgrimes	vp = lookup(name);
5877274Smikeh	if (vp == NULL) {
5977274Smikeh		vp = calloc(sizeof(*vp), 1);
601590Srgrimes		vp->v_name = vcopy(name);
611590Srgrimes		vp->v_link = variables[h];
621590Srgrimes		variables[h] = vp;
631590Srgrimes	}
641590Srgrimes	else
651590Srgrimes		vfree(vp->v_value);
661590Srgrimes	vp->v_value = vcopy(value);
671590Srgrimes}
681590Srgrimes
691590Srgrimes/*
701590Srgrimes * Free up a variable string.  We do not bother to allocate
711590Srgrimes * strings whose value is "" since they are expected to be frequent.
721590Srgrimes * Thus, we cannot free same!
731590Srgrimes */
741590Srgrimesvoid
75216564Scharniervfree(char *cp)
761590Srgrimes{
7777274Smikeh	if (*cp != '\0')
7877274Smikeh		(void)free(cp);
791590Srgrimes}
801590Srgrimes
811590Srgrimes/*
821590Srgrimes * Copy a variable value into permanent (ie, not collected after each
831590Srgrimes * command) space.  Do not bother to alloc space for ""
841590Srgrimes */
851590Srgrimes
861590Srgrimeschar *
87216564Scharniervcopy(const char *str)
881590Srgrimes{
891590Srgrimes	char *new;
901590Srgrimes	unsigned len;
911590Srgrimes
921590Srgrimes	if (*str == '\0')
9377274Smikeh		return ("");
941590Srgrimes	len = strlen(str) + 1;
951590Srgrimes	if ((new = malloc(len)) == NULL)
9674769Smikeh		err(1, "Out of memory");
9777274Smikeh	bcopy(str, new, (int)len);
9877274Smikeh	return (new);
991590Srgrimes}
1001590Srgrimes
1011590Srgrimes/*
1021590Srgrimes * Get the value of a variable and return it.
1031590Srgrimes * Look in the environment if its not available locally.
1041590Srgrimes */
1051590Srgrimes
1061590Srgrimeschar *
107216564Scharniervalue(const char *name)
1081590Srgrimes{
10977274Smikeh	struct var *vp;
1101590Srgrimes
11177274Smikeh	if ((vp = lookup(name)) == NULL)
11277274Smikeh		return (getenv(name));
11377274Smikeh	return (vp->v_value);
1141590Srgrimes}
1151590Srgrimes
1161590Srgrimes/*
1171590Srgrimes * Locate a variable and return its variable
1181590Srgrimes * node.
1191590Srgrimes */
1201590Srgrimes
1211590Srgrimesstruct var *
122216564Scharnierlookup(const char *name)
1231590Srgrimes{
12477274Smikeh	struct var *vp;
1251590Srgrimes
12677274Smikeh	for (vp = variables[hash(name)]; vp != NULL; vp = vp->v_link)
1271590Srgrimes		if (*vp->v_name == *name && equal(vp->v_name, name))
12877274Smikeh			return (vp);
12977274Smikeh	return (NULL);
1301590Srgrimes}
1311590Srgrimes
1321590Srgrimes/*
1331590Srgrimes * Locate a group name and return it.
1341590Srgrimes */
1351590Srgrimes
1361590Srgrimesstruct grouphead *
137216564Scharnierfindgroup(char name[])
1381590Srgrimes{
13977274Smikeh	struct grouphead *gh;
1401590Srgrimes
14177274Smikeh	for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link)
1421590Srgrimes		if (*gh->g_name == *name && equal(gh->g_name, name))
14377274Smikeh			return (gh);
14477274Smikeh	return (NULL);
1451590Srgrimes}
1461590Srgrimes
1471590Srgrimes/*
1481590Srgrimes * Print a group out on stdout
1491590Srgrimes */
1501590Srgrimesvoid
151216564Scharnierprintgroup(char name[])
1521590Srgrimes{
15377274Smikeh	struct grouphead *gh;
15477274Smikeh	struct group *gp;
1551590Srgrimes
15677274Smikeh	if ((gh = findgroup(name)) == NULL) {
1571590Srgrimes		printf("\"%s\": not a group\n", name);
1581590Srgrimes		return;
1591590Srgrimes	}
1601590Srgrimes	printf("%s\t", gh->g_name);
16177274Smikeh	for (gp = gh->g_list; gp != NULL; gp = gp->ge_link)
1621590Srgrimes		printf(" %s", gp->ge_name);
16377274Smikeh	printf("\n");
1641590Srgrimes}
1651590Srgrimes
1661590Srgrimes/*
1671590Srgrimes * Hash the passed string and return an index into
1681590Srgrimes * the variable or group hash table.
1691590Srgrimes */
1701590Srgrimesint
171216564Scharnierhash(const char *name)
1721590Srgrimes{
17377274Smikeh	int h = 0;
1741590Srgrimes
17577274Smikeh	while (*name != '\0') {
1761590Srgrimes		h <<= 2;
1771590Srgrimes		h += *name++;
1781590Srgrimes	}
1791590Srgrimes	if (h < 0 && (h = -h) < 0)
1801590Srgrimes		h = 0;
1811590Srgrimes	return (h % HSHSIZE);
1821590Srgrimes}
183