alias.c revision 1556
180708Sjake/*-
280708Sjake * Copyright (c) 1993
3223126Smarius *	The Regents of the University of California.  All rights reserved.
480708Sjake *
580708Sjake * This code is derived from software contributed to Berkeley by
680708Sjake * Kenneth Almquist.
780708Sjake *
880708Sjake * Redistribution and use in source and binary forms, with or without
980708Sjake * modification, are permitted provided that the following conditions
1080708Sjake * are met:
1180708Sjake * 1. Redistributions of source code must retain the above copyright
1280708Sjake *    notice, this list of conditions and the following disclaimer.
1380708Sjake * 2. Redistributions in binary form must reproduce the above copyright
1480708Sjake *    notice, this list of conditions and the following disclaimer in the
1581334Sobrien *    documentation and/or other materials provided with the distribution.
1680708Sjake * 3. All advertising materials mentioning features or use of this software
1780708Sjake *    must display the following acknowledgement:
1881334Sobrien *	This product includes software developed by the University of
1980708Sjake *	California, Berkeley and its contributors.
2080708Sjake * 4. Neither the name of the University nor the names of its contributors
2180708Sjake *    may be used to endorse or promote products derived from this software
2280708Sjake *    without specific prior written permission.
2380708Sjake *
2480708Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2580708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2680708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2780708Sjake * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2880708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2980708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3080708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3180708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3280708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33183142Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34183142Smarius * SUCH DAMAGE.
35182730Smarius */
36182730Smarius
37182730Smarius#ifndef lint
38182730Smariusstatic char sccsid[] = "@(#)alias.c	8.1 (Berkeley) 5/31/93";
3989051Sjake#endif /* not lint */
4089051Sjake
4189051Sjake#include "shell.h"
42222813Sattilio#include "input.h"
43209695Smarius#include "output.h"
44209695Smarius#include "error.h"
45245850Smarius#include "memalloc.h"
46209695Smarius#include "mystring.h"
4791157Sjake#include "alias.h"
48169730Skan#include "options.h"	/* XXX for argptr (should remove?) */
4991617Sjake
5091157Sjake#define ATABSIZE 39
51170846Smarius
52170846Smariusstruct alias *atab[ATABSIZE];
53170846Smarius
54170846SmariusSTATIC struct alias **hashalias __P((char *));
55170846Smarius
56170846SmariusSTATIC
5789051Sjakesetalias(name, val)
58169796Smarius	char *name, *val;
59170846Smarius	{
60169796Smarius	struct alias *ap, **app;
6189051Sjake
6289051Sjake	app = hashalias(name);
63178048Smarius	for (ap = *app; ap; ap = ap->next) {
64210601Smav		if (equal(name, ap->name)) {
6589051Sjake			INTOFF;
66196196Sattilio			ckfree(ap->val);
6789051Sjake			ap->val	= savestr(val);
68135943Skensmith			INTON;
6989051Sjake			return;
7089051Sjake		}
7191783Sjake	}
7289051Sjake	/* not found */
7389051Sjake	INTOFF;
7491783Sjake	ap = ckmalloc(sizeof (struct alias));
7591617Sjake	ap->name = savestr(name);
76182730Smarius	/*
7791617Sjake	 * XXX - HACK: in order that the parser will not finish reading the
7891617Sjake	 * alias value off the input before processing the next alias, we
7989051Sjake	 * dummy up an extra space at the end of the alias.  This is a crock
8089051Sjake	 * and should be re-thought.  The idea (if you feel inclined to help)
8197001Sjake	 * is to avoid alias recursions.  The mechanism used is: when
82222813Sattilio	 * expanding an alias, the value of the alias is pushed back on the
83113238Sjake	 * input as a string and a pointer to the alias is stored with the
8497001Sjake	 * string.  The alias is marked as being in use.  When the input
8597001Sjake	 * routine finishes reading the string, it markes the alias not
86211071Smarius	 * in use.  The problem is synchronization with the parser.  Since
87222813Sattilio	 * it reads ahead, the alias is marked not in use before the
88211071Smarius	 * resulting token(s) is next checked for further alias sub.  The
89211071Smarius	 * H A C K is that we add a little fluff after the alias value
90211071Smarius	 * so that the string will not be exhausted.  This is a good
9189051Sjake	 * idea ------- ***NOT***
92222813Sattilio	 */
9391783Sjake#ifdef notyet
9489051Sjake	ap->val = savestr(val);
9589051Sjake#else /* hack */
9689051Sjake	{
9789051Sjake	int len = strlen(val);
9889051Sjake	ap->val = ckmalloc(len + 2);
9989051Sjake	bcopy(val, ap->val, len);
10089051Sjake	ap->val[len] = ' ';	/* fluff */
101152022Sjhb	ap->val[len+1] = '\0';
102152022Sjhb	}
10389051Sjake#endif
10492199Sjake	ap->next = *app;
10589051Sjake	*app = ap;
106222813Sattilio	INTON;
107170846Smarius}
108211050Smarius
109211050SmariusSTATIC int
11089051Sjakeunalias(name)
111204152Smarius	char *name;
11291617Sjake	{
113108187Sjake	struct alias *ap, **app;
114211071Smarius
115108187Sjake	app = hashalias(name);
11689051Sjake
11791617Sjake	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
11891617Sjake		if (equal(name, ap->name)) {
11991617Sjake			/*
12091617Sjake			 * if the alias is currently in use (i.e. its
12191617Sjake			 * buffer is being used by the input routine) we
12291617Sjake			 * just null out the name instead of freeing it.
12391617Sjake			 * We could clear it out later, but this situation
124112399Sjake			 * is so rare that it hardly seems worth it.
125112399Sjake			 */
126112399Sjake			if (ap->flag & ALIASINUSE)
127112399Sjake				*ap->name = '\0';
12889051Sjake			else {
129211071Smarius				INTOFF;
130211071Smarius				*app = ap->next;
131211071Smarius				ckfree(ap->name);
132211071Smarius				ckfree(ap->val);
13389051Sjake				ckfree(ap);
13489051Sjake				INTON;
13589051Sjake			}
13689051Sjake			return (0);
137183142Smarius		}
138183142Smarius	}
139183142Smarius
140223126Smarius	return (1);
14189051Sjake}
142223126Smarius
143223126Smarius#ifdef mkinit
144223126SmariusMKINIT void rmaliases();
145183142Smarius
146183142SmariusSHELLPROC {
147183142Smarius	rmaliases();
148222813Sattilio}
149183142Smarius#endif
150183142Smarius
151183142Smariusvoid
152183142Smariusrmaliases() {
153183142Smarius	struct alias *ap, *tmp;
154210939Sjhb	int i;
155210939Sjhb
156210939Sjhb	INTOFF;
157210939Sjhb	for (i = 0; i < ATABSIZE; i++) {
158211050Smarius		ap = atab[i];
159210939Sjhb		atab[i] = NULL;
160210939Sjhb		while (ap) {
161108187Sjake			ckfree(ap->name);
162108187Sjake			ckfree(ap->val);
16397001Sjake			tmp = ap;
164113238Sjake			ap = ap->next;
16597001Sjake			ckfree(tmp);
16697001Sjake		}
16797001Sjake	}
16897001Sjake	INTON;
16997001Sjake}
170209695Smarius
17197001Sjakestruct alias *
172239864Smariuslookupalias(name, check)
17397001Sjake	char *name;
174223126Smarius	{
17597001Sjake	struct alias *ap = *hashalias(name);
176223126Smarius
17797001Sjake	for (; ap; ap = ap->next) {
17897001Sjake		if (equal(name, ap->name)) {
17997001Sjake			if (check && (ap->flag & ALIASINUSE))
18097001Sjake				return (NULL);
181113238Sjake			return (ap);
18297001Sjake		}
18397001Sjake	}
18497001Sjake
18597001Sjake	return (NULL);
18697001Sjake}
187209695Smarius
18897001Sjake/*
189239864Smarius * TODO - sort output
19097001Sjake */
191223126Smariusaliascmd(argc, argv)
19297001Sjake	char **argv;
193223126Smarius	{
19497001Sjake	char *n, *v;
19597001Sjake	int ret = 0;
19697001Sjake	struct alias *ap;
19789051Sjake
198211071Smarius	if (argc == 1) {
199211071Smarius		int i;
200211071Smarius
201211071Smarius		for (i = 0; i < ATABSIZE; i++)
202211071Smarius			for (ap = atab[i]; ap; ap = ap->next) {
203211071Smarius				if (*ap->name != '\0')
204211071Smarius				    out1fmt("alias %s=%s\n", ap->name, ap->val);
205211071Smarius			}
206245850Smarius		return (0);
207223126Smarius	}
208211071Smarius	while (n = *++argv) {
209211071Smarius		if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
210211071Smarius			if ((ap = lookupalias(n, 0)) == NULL) {
211211071Smarius				outfmt(out2, "alias: %s not found\n", n);
212211071Smarius				ret = 1;
213211071Smarius			} else
21491783Sjake				out1fmt("alias %s=%s\n", n, ap->val);
21589051Sjake		else {
21689051Sjake			*v++ = '\0';
217222813Sattilio			setalias(n, v);
21889051Sjake		}
21991783Sjake	}
22089051Sjake
221209695Smarius	return (ret);
222222813Sattilio}
223223126Smarius
224223126Smariusunaliascmd(argc, argv)
225222813Sattilio	char **argv;
226209695Smarius	{
22791783Sjake	int i;
228209695Smarius
22989051Sjake	while ((i = nextopt("a")) != '\0') {
230239864Smarius		if (i == 'a') {
231222813Sattilio			rmaliases();
23291783Sjake			return (0);
23391783Sjake		}
23491783Sjake	}
23592199Sjake	for (i = 0; *argptr; argptr++)
23689051Sjake		i = unalias(*argptr);
23789051Sjake
23889051Sjake	return (i);
239100718Sjake}
24089051Sjake
24189051SjakeSTATIC struct alias **
242222813Sattiliohashalias(p)
24389051Sjake	register char *p;
24491783Sjake	{
24589051Sjake	unsigned int hashval;
246209695Smarius
247222813Sattilio	hashval = *p << 4;
248223126Smarius	while (*p)
249223126Smarius		hashval+= *p++;
250222813Sattilio	return &atab[hashval % ATABSIZE];
251209695Smarius}
25291783Sjake