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) {
59302968Spfg		if ((vp = calloc(1, sizeof(*vp))) == NULL)
60302968Spfg			err(1, "Out of memory");
611590Srgrimes		vp->v_name = vcopy(name);
621590Srgrimes		vp->v_link = variables[h];
631590Srgrimes		variables[h] = vp;
641590Srgrimes	}
651590Srgrimes	else
661590Srgrimes		vfree(vp->v_value);
671590Srgrimes	vp->v_value = vcopy(value);
681590Srgrimes}
691590Srgrimes
701590Srgrimes/*
711590Srgrimes * Free up a variable string.  We do not bother to allocate
721590Srgrimes * strings whose value is "" since they are expected to be frequent.
731590Srgrimes * Thus, we cannot free same!
741590Srgrimes */
751590Srgrimesvoid
76216564Scharniervfree(char *cp)
771590Srgrimes{
7877274Smikeh	if (*cp != '\0')
7977274Smikeh		(void)free(cp);
801590Srgrimes}
811590Srgrimes
821590Srgrimes/*
831590Srgrimes * Copy a variable value into permanent (ie, not collected after each
841590Srgrimes * command) space.  Do not bother to alloc space for ""
851590Srgrimes */
861590Srgrimes
871590Srgrimeschar *
88216564Scharniervcopy(const char *str)
891590Srgrimes{
901590Srgrimes	char *new;
911590Srgrimes	unsigned len;
921590Srgrimes
931590Srgrimes	if (*str == '\0')
9477274Smikeh		return ("");
951590Srgrimes	len = strlen(str) + 1;
961590Srgrimes	if ((new = malloc(len)) == NULL)
9774769Smikeh		err(1, "Out of memory");
9877274Smikeh	bcopy(str, new, (int)len);
9977274Smikeh	return (new);
1001590Srgrimes}
1011590Srgrimes
1021590Srgrimes/*
1031590Srgrimes * Get the value of a variable and return it.
1041590Srgrimes * Look in the environment if its not available locally.
1051590Srgrimes */
1061590Srgrimes
1071590Srgrimeschar *
108216564Scharniervalue(const char *name)
1091590Srgrimes{
11077274Smikeh	struct var *vp;
1111590Srgrimes
11277274Smikeh	if ((vp = lookup(name)) == NULL)
11377274Smikeh		return (getenv(name));
11477274Smikeh	return (vp->v_value);
1151590Srgrimes}
1161590Srgrimes
1171590Srgrimes/*
1181590Srgrimes * Locate a variable and return its variable
1191590Srgrimes * node.
1201590Srgrimes */
1211590Srgrimes
1221590Srgrimesstruct var *
123216564Scharnierlookup(const char *name)
1241590Srgrimes{
12577274Smikeh	struct var *vp;
1261590Srgrimes
12777274Smikeh	for (vp = variables[hash(name)]; vp != NULL; vp = vp->v_link)
1281590Srgrimes		if (*vp->v_name == *name && equal(vp->v_name, name))
12977274Smikeh			return (vp);
13077274Smikeh	return (NULL);
1311590Srgrimes}
1321590Srgrimes
1331590Srgrimes/*
1341590Srgrimes * Locate a group name and return it.
1351590Srgrimes */
1361590Srgrimes
1371590Srgrimesstruct grouphead *
138216564Scharnierfindgroup(char name[])
1391590Srgrimes{
14077274Smikeh	struct grouphead *gh;
1411590Srgrimes
14277274Smikeh	for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link)
1431590Srgrimes		if (*gh->g_name == *name && equal(gh->g_name, name))
14477274Smikeh			return (gh);
14577274Smikeh	return (NULL);
1461590Srgrimes}
1471590Srgrimes
1481590Srgrimes/*
1491590Srgrimes * Print a group out on stdout
1501590Srgrimes */
1511590Srgrimesvoid
152216564Scharnierprintgroup(char name[])
1531590Srgrimes{
15477274Smikeh	struct grouphead *gh;
15577274Smikeh	struct group *gp;
1561590Srgrimes
15777274Smikeh	if ((gh = findgroup(name)) == NULL) {
1581590Srgrimes		printf("\"%s\": not a group\n", name);
1591590Srgrimes		return;
1601590Srgrimes	}
1611590Srgrimes	printf("%s\t", gh->g_name);
16277274Smikeh	for (gp = gh->g_list; gp != NULL; gp = gp->ge_link)
1631590Srgrimes		printf(" %s", gp->ge_name);
16477274Smikeh	printf("\n");
1651590Srgrimes}
1661590Srgrimes
1671590Srgrimes/*
1681590Srgrimes * Hash the passed string and return an index into
1691590Srgrimes * the variable or group hash table.
1701590Srgrimes */
1711590Srgrimesint
172216564Scharnierhash(const char *name)
1731590Srgrimes{
17477274Smikeh	int h = 0;
1751590Srgrimes
17677274Smikeh	while (*name != '\0') {
1771590Srgrimes		h <<= 2;
1781590Srgrimes		h += *name++;
1791590Srgrimes	}
1801590Srgrimes	if (h < 0 && (h = -h) < 0)
1811590Srgrimes		h = 0;
1821590Srgrimes	return (h % HSHSIZE);
1831590Srgrimes}
184