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