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