xref: /minix3/bin/sh/alias.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: alias.c,v 1.15 2014/06/18 18:17:30 christos Exp $	*/
2d90bee97SLionel Sambuc 
3d90bee97SLionel Sambuc /*-
4d90bee97SLionel Sambuc  * Copyright (c) 1993
5d90bee97SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
6d90bee97SLionel Sambuc  *
7d90bee97SLionel Sambuc  * This code is derived from software contributed to Berkeley by
8d90bee97SLionel Sambuc  * Kenneth Almquist.
9d90bee97SLionel Sambuc  *
10d90bee97SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11d90bee97SLionel Sambuc  * modification, are permitted provided that the following conditions
12d90bee97SLionel Sambuc  * are met:
13d90bee97SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15d90bee97SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17d90bee97SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18d90bee97SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
19d90bee97SLionel Sambuc  *    may be used to endorse or promote products derived from this software
20d90bee97SLionel Sambuc  *    without specific prior written permission.
21d90bee97SLionel Sambuc  *
22d90bee97SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23d90bee97SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24d90bee97SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25d90bee97SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26d90bee97SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27d90bee97SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28d90bee97SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29d90bee97SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30d90bee97SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31d90bee97SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32d90bee97SLionel Sambuc  * SUCH DAMAGE.
33d90bee97SLionel Sambuc  */
34d90bee97SLionel Sambuc 
35d90bee97SLionel Sambuc #include <sys/cdefs.h>
36d90bee97SLionel Sambuc #ifndef lint
37d90bee97SLionel Sambuc #if 0
38d90bee97SLionel Sambuc static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
39d90bee97SLionel Sambuc #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: alias.c,v 1.15 2014/06/18 18:17:30 christos Exp $");
41d90bee97SLionel Sambuc #endif
42d90bee97SLionel Sambuc #endif /* not lint */
43d90bee97SLionel Sambuc 
44d90bee97SLionel Sambuc #include <stdlib.h>
45d90bee97SLionel Sambuc #include "shell.h"
46d90bee97SLionel Sambuc #include "input.h"
47d90bee97SLionel Sambuc #include "output.h"
48d90bee97SLionel Sambuc #include "error.h"
49d90bee97SLionel Sambuc #include "memalloc.h"
50d90bee97SLionel Sambuc #include "mystring.h"
51d90bee97SLionel Sambuc #include "alias.h"
52d90bee97SLionel Sambuc #include "options.h"	/* XXX for argptr (should remove?) */
53d90bee97SLionel Sambuc #include "builtins.h"
54d90bee97SLionel Sambuc #include "var.h"
55d90bee97SLionel Sambuc 
56d90bee97SLionel Sambuc #define ATABSIZE 39
57d90bee97SLionel Sambuc 
58d90bee97SLionel Sambuc struct alias *atab[ATABSIZE];
59d90bee97SLionel Sambuc 
60d90bee97SLionel Sambuc STATIC void setalias(char *, char *);
61d90bee97SLionel Sambuc STATIC int unalias(char *);
62*0a6a1f1dSLionel Sambuc STATIC struct alias **hashalias(const char *);
63d90bee97SLionel Sambuc 
64d90bee97SLionel Sambuc STATIC
65d90bee97SLionel Sambuc void
setalias(char * name,char * val)66d90bee97SLionel Sambuc setalias(char *name, char *val)
67d90bee97SLionel Sambuc {
68d90bee97SLionel Sambuc 	struct alias *ap, **app;
69d90bee97SLionel Sambuc 
70d90bee97SLionel Sambuc 	app = hashalias(name);
71d90bee97SLionel Sambuc 	for (ap = *app; ap; ap = ap->next) {
72d90bee97SLionel Sambuc 		if (equal(name, ap->name)) {
73d90bee97SLionel Sambuc 			INTOFF;
74d90bee97SLionel Sambuc 			ckfree(ap->val);
75d90bee97SLionel Sambuc 			ap->val	= savestr(val);
76d90bee97SLionel Sambuc 			INTON;
77d90bee97SLionel Sambuc 			return;
78d90bee97SLionel Sambuc 		}
79d90bee97SLionel Sambuc 	}
80d90bee97SLionel Sambuc 	/* not found */
81d90bee97SLionel Sambuc 	INTOFF;
82d90bee97SLionel Sambuc 	ap = ckmalloc(sizeof (struct alias));
83d90bee97SLionel Sambuc 	ap->name = savestr(name);
84d90bee97SLionel Sambuc 	ap->flag = 0;
85d90bee97SLionel Sambuc 	/*
86d90bee97SLionel Sambuc 	 * XXX - HACK: in order that the parser will not finish reading the
87d90bee97SLionel Sambuc 	 * alias value off the input before processing the next alias, we
88d90bee97SLionel Sambuc 	 * dummy up an extra space at the end of the alias.  This is a crock
89d90bee97SLionel Sambuc 	 * and should be re-thought.  The idea (if you feel inclined to help)
90d90bee97SLionel Sambuc 	 * is to avoid alias recursions.  The mechanism used is: when
91d90bee97SLionel Sambuc 	 * expanding an alias, the value of the alias is pushed back on the
92d90bee97SLionel Sambuc 	 * input as a string and a pointer to the alias is stored with the
93d90bee97SLionel Sambuc 	 * string.  The alias is marked as being in use.  When the input
94d90bee97SLionel Sambuc 	 * routine finishes reading the string, it markes the alias not
95d90bee97SLionel Sambuc 	 * in use.  The problem is synchronization with the parser.  Since
96d90bee97SLionel Sambuc 	 * it reads ahead, the alias is marked not in use before the
97d90bee97SLionel Sambuc 	 * resulting token(s) is next checked for further alias sub.  The
98d90bee97SLionel Sambuc 	 * H A C K is that we add a little fluff after the alias value
99d90bee97SLionel Sambuc 	 * so that the string will not be exhausted.  This is a good
100d90bee97SLionel Sambuc 	 * idea ------- ***NOT***
101d90bee97SLionel Sambuc 	 */
102d90bee97SLionel Sambuc #ifdef notyet
103d90bee97SLionel Sambuc 	ap->val = savestr(val);
104d90bee97SLionel Sambuc #else /* hack */
105d90bee97SLionel Sambuc 	{
106d90bee97SLionel Sambuc 	int len = strlen(val);
107d90bee97SLionel Sambuc 	ap->val = ckmalloc(len + 2);
108d90bee97SLionel Sambuc 	memcpy(ap->val, val, len);
109d90bee97SLionel Sambuc 	ap->val[len] = ' ';	/* fluff */
110d90bee97SLionel Sambuc 	ap->val[len+1] = '\0';
111d90bee97SLionel Sambuc 	}
112d90bee97SLionel Sambuc #endif
113d90bee97SLionel Sambuc 	ap->next = *app;
114d90bee97SLionel Sambuc 	*app = ap;
115d90bee97SLionel Sambuc 	INTON;
116d90bee97SLionel Sambuc }
117d90bee97SLionel Sambuc 
118d90bee97SLionel Sambuc STATIC int
unalias(char * name)119d90bee97SLionel Sambuc unalias(char *name)
120d90bee97SLionel Sambuc {
121d90bee97SLionel Sambuc 	struct alias *ap, **app;
122d90bee97SLionel Sambuc 
123d90bee97SLionel Sambuc 	app = hashalias(name);
124d90bee97SLionel Sambuc 
125d90bee97SLionel Sambuc 	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
126d90bee97SLionel Sambuc 		if (equal(name, ap->name)) {
127d90bee97SLionel Sambuc 			/*
128d90bee97SLionel Sambuc 			 * if the alias is currently in use (i.e. its
129d90bee97SLionel Sambuc 			 * buffer is being used by the input routine) we
130d90bee97SLionel Sambuc 			 * just null out the name instead of freeing it.
131d90bee97SLionel Sambuc 			 * We could clear it out later, but this situation
132d90bee97SLionel Sambuc 			 * is so rare that it hardly seems worth it.
133d90bee97SLionel Sambuc 			 */
134d90bee97SLionel Sambuc 			if (ap->flag & ALIASINUSE)
135d90bee97SLionel Sambuc 				*ap->name = '\0';
136d90bee97SLionel Sambuc 			else {
137d90bee97SLionel Sambuc 				INTOFF;
138d90bee97SLionel Sambuc 				*app = ap->next;
139d90bee97SLionel Sambuc 				ckfree(ap->name);
140d90bee97SLionel Sambuc 				ckfree(ap->val);
141d90bee97SLionel Sambuc 				ckfree(ap);
142d90bee97SLionel Sambuc 				INTON;
143d90bee97SLionel Sambuc 			}
144d90bee97SLionel Sambuc 			return (0);
145d90bee97SLionel Sambuc 		}
146d90bee97SLionel Sambuc 	}
147d90bee97SLionel Sambuc 
148d90bee97SLionel Sambuc 	return (1);
149d90bee97SLionel Sambuc }
150d90bee97SLionel Sambuc 
151d90bee97SLionel Sambuc #ifdef mkinit
152d90bee97SLionel Sambuc MKINIT void rmaliases(void);
153d90bee97SLionel Sambuc 
154d90bee97SLionel Sambuc SHELLPROC {
155d90bee97SLionel Sambuc 	rmaliases();
156d90bee97SLionel Sambuc }
157d90bee97SLionel Sambuc #endif
158d90bee97SLionel Sambuc 
159d90bee97SLionel Sambuc void
rmaliases(void)160d90bee97SLionel Sambuc rmaliases(void)
161d90bee97SLionel Sambuc {
162d90bee97SLionel Sambuc 	struct alias *ap, *tmp;
163d90bee97SLionel Sambuc 	int i;
164d90bee97SLionel Sambuc 
165d90bee97SLionel Sambuc 	INTOFF;
166d90bee97SLionel Sambuc 	for (i = 0; i < ATABSIZE; i++) {
167d90bee97SLionel Sambuc 		ap = atab[i];
168d90bee97SLionel Sambuc 		atab[i] = NULL;
169d90bee97SLionel Sambuc 		while (ap) {
170d90bee97SLionel Sambuc 			ckfree(ap->name);
171d90bee97SLionel Sambuc 			ckfree(ap->val);
172d90bee97SLionel Sambuc 			tmp = ap;
173d90bee97SLionel Sambuc 			ap = ap->next;
174d90bee97SLionel Sambuc 			ckfree(tmp);
175d90bee97SLionel Sambuc 		}
176d90bee97SLionel Sambuc 	}
177d90bee97SLionel Sambuc 	INTON;
178d90bee97SLionel Sambuc }
179d90bee97SLionel Sambuc 
180d90bee97SLionel Sambuc struct alias *
lookupalias(const char * name,int check)181*0a6a1f1dSLionel Sambuc lookupalias(const char *name, int check)
182d90bee97SLionel Sambuc {
183d90bee97SLionel Sambuc 	struct alias *ap = *hashalias(name);
184d90bee97SLionel Sambuc 
185d90bee97SLionel Sambuc 	for (; ap; ap = ap->next) {
186d90bee97SLionel Sambuc 		if (equal(name, ap->name)) {
187d90bee97SLionel Sambuc 			if (check && (ap->flag & ALIASINUSE))
188d90bee97SLionel Sambuc 				return (NULL);
189d90bee97SLionel Sambuc 			return (ap);
190d90bee97SLionel Sambuc 		}
191d90bee97SLionel Sambuc 	}
192d90bee97SLionel Sambuc 
193d90bee97SLionel Sambuc 	return (NULL);
194d90bee97SLionel Sambuc }
195d90bee97SLionel Sambuc 
196*0a6a1f1dSLionel Sambuc const char *
alias_text(void * dummy __unused,const char * name)197*0a6a1f1dSLionel Sambuc alias_text(void *dummy __unused, const char *name)
198d90bee97SLionel Sambuc {
199d90bee97SLionel Sambuc 	struct alias *ap;
200d90bee97SLionel Sambuc 
201d90bee97SLionel Sambuc 	ap = lookupalias(name, 0);
202d90bee97SLionel Sambuc 	if (ap == NULL)
203d90bee97SLionel Sambuc 		return NULL;
204d90bee97SLionel Sambuc 	return ap->val;
205d90bee97SLionel Sambuc }
206d90bee97SLionel Sambuc 
207d90bee97SLionel Sambuc /*
208d90bee97SLionel Sambuc  * TODO - sort output
209d90bee97SLionel Sambuc  */
210d90bee97SLionel Sambuc int
aliascmd(int argc,char ** argv)211d90bee97SLionel Sambuc aliascmd(int argc, char **argv)
212d90bee97SLionel Sambuc {
213d90bee97SLionel Sambuc 	char *n, *v;
214d90bee97SLionel Sambuc 	int ret = 0;
215d90bee97SLionel Sambuc 	struct alias *ap;
216d90bee97SLionel Sambuc 
217d90bee97SLionel Sambuc 	if (argc == 1) {
218d90bee97SLionel Sambuc 		int i;
219d90bee97SLionel Sambuc 
220d90bee97SLionel Sambuc 		for (i = 0; i < ATABSIZE; i++)
221d90bee97SLionel Sambuc 			for (ap = atab[i]; ap; ap = ap->next) {
222d90bee97SLionel Sambuc 				if (*ap->name != '\0') {
223d90bee97SLionel Sambuc 					out1fmt("alias %s=", ap->name);
224d90bee97SLionel Sambuc 					print_quoted(ap->val);
225d90bee97SLionel Sambuc 					out1c('\n');
226d90bee97SLionel Sambuc 				}
227d90bee97SLionel Sambuc 			}
228d90bee97SLionel Sambuc 		return (0);
229d90bee97SLionel Sambuc 	}
230d90bee97SLionel Sambuc 	while ((n = *++argv) != NULL) {
231d90bee97SLionel Sambuc 		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
232d90bee97SLionel Sambuc 			if ((ap = lookupalias(n, 0)) == NULL) {
233d90bee97SLionel Sambuc 				outfmt(out2, "alias: %s not found\n", n);
234d90bee97SLionel Sambuc 				ret = 1;
235d90bee97SLionel Sambuc 			} else {
236d90bee97SLionel Sambuc 				out1fmt("alias %s=", n);
237d90bee97SLionel Sambuc 				print_quoted(ap->val);
238d90bee97SLionel Sambuc 				out1c('\n');
239d90bee97SLionel Sambuc 			}
240d90bee97SLionel Sambuc 		} else {
241d90bee97SLionel Sambuc 			*v++ = '\0';
242d90bee97SLionel Sambuc 			setalias(n, v);
243d90bee97SLionel Sambuc 		}
244d90bee97SLionel Sambuc 	}
245d90bee97SLionel Sambuc 
246d90bee97SLionel Sambuc 	return (ret);
247d90bee97SLionel Sambuc }
248d90bee97SLionel Sambuc 
249d90bee97SLionel Sambuc int
unaliascmd(int argc,char ** argv)250d90bee97SLionel Sambuc unaliascmd(int argc, char **argv)
251d90bee97SLionel Sambuc {
252d90bee97SLionel Sambuc 	int i;
253d90bee97SLionel Sambuc 
254d90bee97SLionel Sambuc 	while ((i = nextopt("a")) != '\0') {
255d90bee97SLionel Sambuc 		if (i == 'a') {
256d90bee97SLionel Sambuc 			rmaliases();
257d90bee97SLionel Sambuc 			return (0);
258d90bee97SLionel Sambuc 		}
259d90bee97SLionel Sambuc 	}
260d90bee97SLionel Sambuc 	for (i = 0; *argptr; argptr++)
261d90bee97SLionel Sambuc 		i = unalias(*argptr);
262d90bee97SLionel Sambuc 
263d90bee97SLionel Sambuc 	return (i);
264d90bee97SLionel Sambuc }
265d90bee97SLionel Sambuc 
266d90bee97SLionel Sambuc STATIC struct alias **
hashalias(const char * p)267*0a6a1f1dSLionel Sambuc hashalias(const char *p)
268d90bee97SLionel Sambuc {
269d90bee97SLionel Sambuc 	unsigned int hashval;
270d90bee97SLionel Sambuc 
271d90bee97SLionel Sambuc 	hashval = *p << 4;
272d90bee97SLionel Sambuc 	while (*p)
273d90bee97SLionel Sambuc 		hashval+= *p++;
274d90bee97SLionel Sambuc 	return &atab[hashval % ATABSIZE];
275d90bee97SLionel Sambuc }
276