xref: /netbsd-src/bin/sh/alias.c (revision 64c7eea502b9f127dcc882c7dc461222380181b9)
1*64c7eea5Skre /*	$NetBSD: alias.c,v 1.22 2023/02/24 19:04:54 kre Exp $	*/
249f0ad86Scgd 
3488499c5Sjtc /*-
4488499c5Sjtc  * Copyright (c) 1993
5488499c5Sjtc  *	The Regents of the University of California.  All rights reserved.
6488499c5Sjtc  *
7488499c5Sjtc  * This code is derived from software contributed to Berkeley by
8488499c5Sjtc  * Kenneth Almquist.
9488499c5Sjtc  *
10488499c5Sjtc  * Redistribution and use in source and binary forms, with or without
11488499c5Sjtc  * modification, are permitted provided that the following conditions
12488499c5Sjtc  * are met:
13488499c5Sjtc  * 1. Redistributions of source code must retain the above copyright
14488499c5Sjtc  *    notice, this list of conditions and the following disclaimer.
15488499c5Sjtc  * 2. Redistributions in binary form must reproduce the above copyright
16488499c5Sjtc  *    notice, this list of conditions and the following disclaimer in the
17488499c5Sjtc  *    documentation and/or other materials provided with the distribution.
18b5b29542Sagc  * 3. Neither the name of the University nor the names of its contributors
19488499c5Sjtc  *    may be used to endorse or promote products derived from this software
20488499c5Sjtc  *    without specific prior written permission.
21488499c5Sjtc  *
22488499c5Sjtc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23488499c5Sjtc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24488499c5Sjtc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25488499c5Sjtc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26488499c5Sjtc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27488499c5Sjtc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28488499c5Sjtc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29488499c5Sjtc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30488499c5Sjtc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31488499c5Sjtc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32488499c5Sjtc  * SUCH DAMAGE.
33488499c5Sjtc  */
34488499c5Sjtc 
35cd799663Schristos #include <sys/cdefs.h>
36488499c5Sjtc #ifndef lint
3749f0ad86Scgd #if 0
3807bae7edSchristos static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
3949f0ad86Scgd #else
40*64c7eea5Skre __RCSID("$NetBSD: alias.c,v 1.22 2023/02/24 19:04:54 kre Exp $");
4149f0ad86Scgd #endif
42488499c5Sjtc #endif /* not lint */
43488499c5Sjtc 
4407bae7edSchristos #include <stdlib.h>
45488499c5Sjtc #include "shell.h"
46488499c5Sjtc #include "input.h"
47488499c5Sjtc #include "output.h"
48488499c5Sjtc #include "error.h"
49488499c5Sjtc #include "memalloc.h"
50488499c5Sjtc #include "mystring.h"
51488499c5Sjtc #include "alias.h"
52488499c5Sjtc #include "options.h"	/* XXX for argptr (should remove?) */
534fc4fe2eSchristos #include "builtins.h"
54c02b3bbdSchristos #include "var.h"
55488499c5Sjtc 
56488499c5Sjtc #define ATABSIZE 39
57488499c5Sjtc 
58488499c5Sjtc struct alias *atab[ATABSIZE];
59488499c5Sjtc 
60c02b3bbdSchristos STATIC void setalias(char *, char *);
6132c623ffSrillig STATIC int by_name(const void *, const void *);
6232c623ffSrillig STATIC void list_aliases(void);
63c02b3bbdSchristos STATIC int unalias(char *);
64021ba509Skre STATIC struct alias **freealias(struct alias **, int);
65f0321293Schristos STATIC struct alias **hashalias(const char *);
663dbd8601Skre STATIC int countaliases(void);
67488499c5Sjtc 
68488499c5Sjtc STATIC
695dad1439Scgd void
setalias(char * name,char * val)70c02b3bbdSchristos setalias(char *name, char *val)
71488499c5Sjtc {
72488499c5Sjtc 	struct alias *ap, **app;
73488499c5Sjtc 
74154c1ed7Skre 	(void) unalias(name);	/* old one (if any) is now gone */
75488499c5Sjtc 	app = hashalias(name);
76154c1ed7Skre 
77488499c5Sjtc 	INTOFF;
78488499c5Sjtc 	ap = ckmalloc(sizeof (struct alias));
79488499c5Sjtc 	ap->name = savestr(name);
806a6f2f47Sstacktic 	ap->flag = 0;
81488499c5Sjtc 	ap->val = savestr(val);
82488499c5Sjtc 	ap->next = *app;
83488499c5Sjtc 	*app = ap;
84488499c5Sjtc 	INTON;
85488499c5Sjtc }
86488499c5Sjtc 
87021ba509Skre STATIC struct alias **
freealias(struct alias ** app,int force)88021ba509Skre freealias(struct alias **app, int force)
89021ba509Skre {
90021ba509Skre 	struct alias *ap = *app;
91021ba509Skre 
92021ba509Skre 	if (ap == NULL)
93021ba509Skre 		return app;
94021ba509Skre 
95021ba509Skre 	/*
96021ba509Skre 	 * if the alias is currently in use (i.e. its
97021ba509Skre 	 * buffer is being used by the input routine) we
98021ba509Skre 	 * just null out the name instead of discarding it.
99021ba509Skre 	 * If we encounter it later, when it is idle,
100021ba509Skre 	 * we will finish freeing it then.
101021ba509Skre 	 *
102021ba509Skre 	 * Unless we want to simply free everything (INIT)
103021ba509Skre 	 */
104021ba509Skre 	if (ap->flag & ALIASINUSE && !force) {
105021ba509Skre 		*ap->name = '\0';
106021ba509Skre 		return &ap->next;
107021ba509Skre 	}
108021ba509Skre 
109021ba509Skre 	INTOFF;
110021ba509Skre 	*app = ap->next;
111021ba509Skre 	ckfree(ap->name);
112021ba509Skre 	ckfree(ap->val);
113021ba509Skre 	ckfree(ap);
114021ba509Skre 	INTON;
115021ba509Skre 
116021ba509Skre 	return app;
117021ba509Skre }
118021ba509Skre 
119488499c5Sjtc STATIC int
unalias(char * name)120c02b3bbdSchristos unalias(char *name)
121488499c5Sjtc {
122488499c5Sjtc 	struct alias *ap, **app;
123488499c5Sjtc 
124488499c5Sjtc 	app = hashalias(name);
125021ba509Skre 	while ((ap = *app) != NULL) {
126488499c5Sjtc 		if (equal(name, ap->name)) {
127021ba509Skre 			(void) freealias(app, 0);
128c074191fSkre 			return 0;
129488499c5Sjtc 		}
130021ba509Skre 		app = &ap->next;
131488499c5Sjtc 	}
132488499c5Sjtc 
133c074191fSkre 	return 1;
134488499c5Sjtc }
135488499c5Sjtc 
136488499c5Sjtc #ifdef mkinit
137021ba509Skre MKINIT void rmaliases(int);
138488499c5Sjtc 
139488499c5Sjtc SHELLPROC {
140021ba509Skre 	rmaliases(1);
141488499c5Sjtc }
142488499c5Sjtc #endif
143488499c5Sjtc 
144488499c5Sjtc void
rmaliases(int force)145021ba509Skre rmaliases(int force)
146c02b3bbdSchristos {
147021ba509Skre 	struct alias **app;
148488499c5Sjtc 	int i;
149488499c5Sjtc 
150488499c5Sjtc 	INTOFF;
151488499c5Sjtc 	for (i = 0; i < ATABSIZE; i++) {
152021ba509Skre 		app = &atab[i];
153021ba509Skre 		while (*app)
154021ba509Skre 			app = freealias(app, force);
155488499c5Sjtc 	}
156488499c5Sjtc 	INTON;
157488499c5Sjtc }
158488499c5Sjtc 
159488499c5Sjtc struct alias *
lookupalias(const char * name,int check)160f0321293Schristos lookupalias(const char *name, int check)
161488499c5Sjtc {
162488499c5Sjtc 	struct alias *ap = *hashalias(name);
163488499c5Sjtc 
164021ba509Skre 	while (ap != NULL) {
165488499c5Sjtc 		if (equal(name, ap->name)) {
166488499c5Sjtc 			if (check && (ap->flag & ALIASINUSE))
167c074191fSkre 				return NULL;
168c074191fSkre 			return ap;
169488499c5Sjtc 		}
170021ba509Skre 		ap = ap->next;
171488499c5Sjtc 	}
172488499c5Sjtc 
173c074191fSkre 	return NULL;
174488499c5Sjtc }
175488499c5Sjtc 
176f0321293Schristos const char *
alias_text(void * dummy __unused,const char * name)177f0321293Schristos alias_text(void *dummy __unused, const char *name)
178c02b3bbdSchristos {
179c02b3bbdSchristos 	struct alias *ap;
180c02b3bbdSchristos 
181c02b3bbdSchristos 	ap = lookupalias(name, 0);
182c02b3bbdSchristos 	if (ap == NULL)
183c02b3bbdSchristos 		return NULL;
184c02b3bbdSchristos 	return ap->val;
185c02b3bbdSchristos }
186c02b3bbdSchristos 
18732c623ffSrillig STATIC int
by_name(const void * a,const void * b)18832c623ffSrillig by_name(const void *a, const void *b)
18932c623ffSrillig {
19032c623ffSrillig 
19132c623ffSrillig 	return strcmp(
19232c623ffSrillig 		(*(const struct alias * const *)a)->name,
19332c623ffSrillig 		(*(const struct alias * const *)b)->name);
19432c623ffSrillig }
19532c623ffSrillig 
19632c623ffSrillig STATIC void
list_aliases(void)19732c623ffSrillig list_aliases(void)
19832c623ffSrillig {
1993dbd8601Skre 	int i, j, n;
20032c623ffSrillig 	const struct alias **aliases;
20132c623ffSrillig 	const struct alias *ap;
20232c623ffSrillig 
203021ba509Skre 	INTOFF;
204021ba509Skre 	n = countaliases();
2053dbd8601Skre 	aliases = stalloc(n * (int)(sizeof aliases[0]));
20632c623ffSrillig 
20732c623ffSrillig 	j = 0;
20832c623ffSrillig 	for (i = 0; i < ATABSIZE; i++)
20932c623ffSrillig 		for (ap = atab[i]; ap != NULL; ap = ap->next)
21032c623ffSrillig 			if (ap->name[0] != '\0')
21132c623ffSrillig 				aliases[j++] = ap;
212021ba509Skre 	if (j != n)
213021ba509Skre 		error("Alias count botch");
214021ba509Skre 	INTON;
21532c623ffSrillig 
21632c623ffSrillig 	qsort(aliases, n, sizeof aliases[0], by_name);
21732c623ffSrillig 
21832c623ffSrillig 	for (i = 0; i < n; i++) {
21932c623ffSrillig 		out1fmt("alias %s=", aliases[i]->name);
22032c623ffSrillig 		print_quoted(aliases[i]->val);
22132c623ffSrillig 		out1c('\n');
22232c623ffSrillig 	}
22332c623ffSrillig 
2243dbd8601Skre 	stunalloc(aliases);
22532c623ffSrillig }
22632c623ffSrillig 
227021ba509Skre /*
228021ba509Skre  * Count how many aliases are defined (skipping any
229021ba509Skre  * that have been deleted, but don't know it yet).
230021ba509Skre  * Use this opportunity to clean up any of those
231021ba509Skre  * zombies that are no longer needed.
232021ba509Skre  */
2333dbd8601Skre STATIC int
countaliases(void)234021ba509Skre countaliases(void)
235021ba509Skre {
236021ba509Skre 	struct alias *ap, **app;
237021ba509Skre 	size_t n;
238021ba509Skre 	int i;
239021ba509Skre 
240021ba509Skre 	n = 0;
241021ba509Skre 	for (i = 0; i < ATABSIZE; i++)
242021ba509Skre 		for (app = &atab[i]; (ap = *app) != NULL;) {
243021ba509Skre 			if (ap->name[0] != '\0')
244021ba509Skre 				n++;
245021ba509Skre 			else {
246021ba509Skre 				app = freealias(app, 0);
247021ba509Skre 				continue;
248021ba509Skre 			}
249021ba509Skre 			app = &ap->next;
250021ba509Skre 		}
251021ba509Skre 
252021ba509Skre 	return n;
253021ba509Skre }
254021ba509Skre 
2555dad1439Scgd int
aliascmd(int argc,char ** argv)256*64c7eea5Skre aliascmd(int argc, char **argv)	/* ARGSUSED */
257488499c5Sjtc {
258488499c5Sjtc 	char *n, *v;
259488499c5Sjtc 	int ret = 0;
260488499c5Sjtc 	struct alias *ap;
261488499c5Sjtc 
262*64c7eea5Skre 	(void) nextopt(NULL);	/* consume possible "--" */
263*64c7eea5Skre 
264*64c7eea5Skre 	if (*argptr == NULL) {
26532c623ffSrillig 		list_aliases();
266c074191fSkre 		return 0;
267488499c5Sjtc 	}
26832c623ffSrillig 
269*64c7eea5Skre 	while ((n = *argptr++) != NULL) {
2703d8b8b2eSchristos 		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
271488499c5Sjtc 			if ((ap = lookupalias(n, 0)) == NULL) {
272488499c5Sjtc 				outfmt(out2, "alias: %s not found\n", n);
273488499c5Sjtc 				ret = 1;
274c02b3bbdSchristos 			} else {
275c02b3bbdSchristos 				out1fmt("alias %s=", n);
276c02b3bbdSchristos 				print_quoted(ap->val);
277c02b3bbdSchristos 				out1c('\n');
2783d8b8b2eSchristos 			}
279c02b3bbdSchristos 		} else {
280488499c5Sjtc 			*v++ = '\0';
281488499c5Sjtc 			setalias(n, v);
282488499c5Sjtc 		}
283488499c5Sjtc 	}
284488499c5Sjtc 
285c074191fSkre 	return ret;
286488499c5Sjtc }
287488499c5Sjtc 
2885dad1439Scgd int
unaliascmd(int argc,char ** argv)289c02b3bbdSchristos unaliascmd(int argc, char **argv)
290488499c5Sjtc {
291488499c5Sjtc 	int i;
292488499c5Sjtc 
293488499c5Sjtc 	while ((i = nextopt("a")) != '\0') {
294488499c5Sjtc 		if (i == 'a') {
295021ba509Skre 			rmaliases(0);
296c074191fSkre 			return 0;
297488499c5Sjtc 		}
298488499c5Sjtc 	}
299021ba509Skre 
300021ba509Skre 	(void)countaliases();	/* delete any dead ones */
301488499c5Sjtc 	for (i = 0; *argptr; argptr++)
302021ba509Skre 		i |= unalias(*argptr);
303488499c5Sjtc 
304c074191fSkre 	return i;
305488499c5Sjtc }
306488499c5Sjtc 
307488499c5Sjtc STATIC struct alias **
hashalias(const char * p)308f0321293Schristos hashalias(const char *p)
309488499c5Sjtc {
310488499c5Sjtc 	unsigned int hashval;
311488499c5Sjtc 
3124401d6e5Skre 	hashval = *(const unsigned char *)p << 4;
313488499c5Sjtc 	while (*p)
314488499c5Sjtc 		hashval += *p++;
315488499c5Sjtc 	return &atab[hashval % ATABSIZE];
316488499c5Sjtc }
317