11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Kenneth Almquist.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 4. Neither the name of the University nor the names of its contributors
171556Srgrimes *    may be used to endorse or promote products derived from this software
181556Srgrimes *    without specific prior written permission.
191556Srgrimes *
201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301556Srgrimes * SUCH DAMAGE.
311556Srgrimes */
321556Srgrimes
331556Srgrimes#ifndef lint
3436150Scharnier#if 0
3536150Scharnierstatic char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
3636150Scharnier#endif
371556Srgrimes#endif /* not lint */
3899110Sobrien#include <sys/cdefs.h>
3999110Sobrien__FBSDID("$FreeBSD$");
401556Srgrimes
4117987Speter#include <stdlib.h>
421556Srgrimes#include "shell.h"
431556Srgrimes#include "output.h"
441556Srgrimes#include "error.h"
451556Srgrimes#include "memalloc.h"
461556Srgrimes#include "mystring.h"
471556Srgrimes#include "alias.h"
481556Srgrimes#include "options.h"	/* XXX for argptr (should remove?) */
49223060Sjilles#include "builtins.h"
501556Srgrimes
511556Srgrimes#define ATABSIZE 39
521556Srgrimes
53213760Sobrienstatic struct alias *atab[ATABSIZE];
54213760Sobrienstatic int aliases;
551556Srgrimes
56213811Sobrienstatic void setalias(const char *, const char *);
57213811Sobrienstatic int unalias(const char *);
58213811Sobrienstatic struct alias **hashalias(const char *);
591556Srgrimes
60213811Sobrienstatic
6117987Spetervoid
62200956Sjillessetalias(const char *name, const char *val)
6317987Speter{
641556Srgrimes	struct alias *ap, **app;
651556Srgrimes
661556Srgrimes	app = hashalias(name);
671556Srgrimes	for (ap = *app; ap; ap = ap->next) {
681556Srgrimes		if (equal(name, ap->name)) {
691556Srgrimes			INTOFF;
701556Srgrimes			ckfree(ap->val);
711556Srgrimes			ap->val	= savestr(val);
721556Srgrimes			INTON;
731556Srgrimes			return;
741556Srgrimes		}
751556Srgrimes	}
761556Srgrimes	/* not found */
771556Srgrimes	INTOFF;
781556Srgrimes	ap = ckmalloc(sizeof (struct alias));
791556Srgrimes	ap->name = savestr(name);
801556Srgrimes	ap->val = savestr(val);
8163223Ssada	ap->flag = 0;
821556Srgrimes	ap->next = *app;
831556Srgrimes	*app = ap;
84190284Sstefanf	aliases++;
851556Srgrimes	INTON;
861556Srgrimes}
871556Srgrimes
88213811Sobrienstatic int
89179639Srseunalias(const char *name)
9090111Simp{
911556Srgrimes	struct alias *ap, **app;
921556Srgrimes
931556Srgrimes	app = hashalias(name);
941556Srgrimes
951556Srgrimes	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
961556Srgrimes		if (equal(name, ap->name)) {
971556Srgrimes			/*
981556Srgrimes			 * if the alias is currently in use (i.e. its
991556Srgrimes			 * buffer is being used by the input routine) we
1001556Srgrimes			 * just null out the name instead of freeing it.
1011556Srgrimes			 * We could clear it out later, but this situation
1021556Srgrimes			 * is so rare that it hardly seems worth it.
1031556Srgrimes			 */
1041556Srgrimes			if (ap->flag & ALIASINUSE)
1051556Srgrimes				*ap->name = '\0';
1061556Srgrimes			else {
1071556Srgrimes				INTOFF;
1081556Srgrimes				*app = ap->next;
1091556Srgrimes				ckfree(ap->name);
1101556Srgrimes				ckfree(ap->val);
1111556Srgrimes				ckfree(ap);
1121556Srgrimes				INTON;
1131556Srgrimes			}
114190284Sstefanf			aliases--;
1151556Srgrimes			return (0);
1161556Srgrimes		}
1171556Srgrimes	}
1181556Srgrimes
1191556Srgrimes	return (1);
1201556Srgrimes}
1211556Srgrimes
122218306Sjillesstatic void
12390111Simprmaliases(void)
12490111Simp{
1251556Srgrimes	struct alias *ap, *tmp;
1261556Srgrimes	int i;
1271556Srgrimes
1281556Srgrimes	INTOFF;
1291556Srgrimes	for (i = 0; i < ATABSIZE; i++) {
1301556Srgrimes		ap = atab[i];
1311556Srgrimes		atab[i] = NULL;
1321556Srgrimes		while (ap) {
1331556Srgrimes			ckfree(ap->name);
1341556Srgrimes			ckfree(ap->val);
1351556Srgrimes			tmp = ap;
1361556Srgrimes			ap = ap->next;
1371556Srgrimes			ckfree(tmp);
1381556Srgrimes		}
1391556Srgrimes	}
140190284Sstefanf	aliases = 0;
1411556Srgrimes	INTON;
1421556Srgrimes}
1431556Srgrimes
1441556Srgrimesstruct alias *
145200956Sjilleslookupalias(const char *name, int check)
14617987Speter{
1471556Srgrimes	struct alias *ap = *hashalias(name);
1481556Srgrimes
1491556Srgrimes	for (; ap; ap = ap->next) {
1501556Srgrimes		if (equal(name, ap->name)) {
1511556Srgrimes			if (check && (ap->flag & ALIASINUSE))
1521556Srgrimes				return (NULL);
1531556Srgrimes			return (ap);
1541556Srgrimes		}
1551556Srgrimes	}
1561556Srgrimes
1571556Srgrimes	return (NULL);
1581556Srgrimes}
1591556Srgrimes
160213811Sobrienstatic int
161190284Sstefanfcomparealiases(const void *p1, const void *p2)
162190284Sstefanf{
163190284Sstefanf	const struct alias *const *a1 = p1;
164190284Sstefanf	const struct alias *const *a2 = p2;
165190284Sstefanf
166190284Sstefanf	return strcmp((*a1)->name, (*a2)->name);
167190284Sstefanf}
168190284Sstefanf
169213811Sobrienstatic void
170190284Sstefanfprintalias(const struct alias *a)
171190284Sstefanf{
172190284Sstefanf	out1fmt("%s=", a->name);
173190284Sstefanf	out1qstr(a->val);
174190284Sstefanf	out1c('\n');
175190284Sstefanf}
176190284Sstefanf
177213811Sobrienstatic void
178190284Sstefanfprintaliases(void)
179190284Sstefanf{
180190284Sstefanf	int i, j;
181190284Sstefanf	struct alias **sorted, *ap;
182190284Sstefanf
183264478Sjilles	INTOFF;
184190284Sstefanf	sorted = ckmalloc(aliases * sizeof(*sorted));
185190284Sstefanf	j = 0;
186190284Sstefanf	for (i = 0; i < ATABSIZE; i++)
187190284Sstefanf		for (ap = atab[i]; ap; ap = ap->next)
188190284Sstefanf			if (*ap->name != '\0')
189190284Sstefanf				sorted[j++] = ap;
190190284Sstefanf	qsort(sorted, aliases, sizeof(*sorted), comparealiases);
191264478Sjilles	for (i = 0; i < aliases; i++) {
192190284Sstefanf		printalias(sorted[i]);
193264478Sjilles		if (int_pending())
194264478Sjilles			break;
195264478Sjilles	}
196190284Sstefanf	ckfree(sorted);
197264478Sjilles	INTON;
198190284Sstefanf}
199190284Sstefanf
20017987Speterint
201254849Sjillesaliascmd(int argc __unused, char **argv __unused)
20217987Speter{
2031556Srgrimes	char *n, *v;
2041556Srgrimes	int ret = 0;
2051556Srgrimes	struct alias *ap;
2061556Srgrimes
207254849Sjilles	nextopt("");
208254849Sjilles
209254849Sjilles	if (*argptr == NULL) {
210190284Sstefanf		printaliases();
2111556Srgrimes		return (0);
2121556Srgrimes	}
213254849Sjilles	while ((n = *argptr++) != NULL) {
2141556Srgrimes		if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
2151556Srgrimes			if ((ap = lookupalias(n, 0)) == NULL) {
216222684Sjilles				warning("%s: not found", n);
2171556Srgrimes				ret = 1;
218190284Sstefanf			} else
219190284Sstefanf				printalias(ap);
2201556Srgrimes		else {
2211556Srgrimes			*v++ = '\0';
2221556Srgrimes			setalias(n, v);
2231556Srgrimes		}
2241556Srgrimes	}
2251556Srgrimes
2261556Srgrimes	return (ret);
2271556Srgrimes}
2281556Srgrimes
22917987Speterint
23090111Simpunaliascmd(int argc __unused, char **argv __unused)
23117987Speter{
2321556Srgrimes	int i;
2338855Srgrimes
2341556Srgrimes	while ((i = nextopt("a")) != '\0') {
2351556Srgrimes		if (i == 'a') {
2361556Srgrimes			rmaliases();
2371556Srgrimes			return (0);
2381556Srgrimes		}
2391556Srgrimes	}
2401556Srgrimes	for (i = 0; *argptr; argptr++)
241149743Sstefanf		i |= unalias(*argptr);
2421556Srgrimes
2431556Srgrimes	return (i);
2441556Srgrimes}
2451556Srgrimes
246213811Sobrienstatic struct alias **
247179639Srsehashalias(const char *p)
24890111Simp{
2491556Srgrimes	unsigned int hashval;
2501556Srgrimes
2511556Srgrimes	hashval = *p << 4;
2521556Srgrimes	while (*p)
2531556Srgrimes		hashval+= *p++;
2541556Srgrimes	return &atab[hashval % ATABSIZE];
2551556Srgrimes}
256