source: trunk/src/kash/alias.c

Last change on this file was 3438, checked in by bird, 5 years ago

kash: Hammering on threaded mode.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 7.3 KB
RevLine 
[626]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
[1214]35#if 0
[626]36#ifndef lint
37static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
38#else
39__RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $");
[1214]40#endif /* not lint */
[626]41#endif
42
43#include <stdlib.h>
44#include "shell.h"
45#include "input.h"
46#include "output.h"
47#include "error.h"
48#include "memalloc.h"
49#include "mystring.h"
50#include "alias.h"
51#include "options.h" /* XXX for argptr (should remove?) */
52#include "var.h"
[882]53#include "shinstance.h"
[626]54
[882]55/*#define ATABSIZE 39
[626]56
[882]57struct alias *atab[ATABSIZE];*/
[626]58
[882]59STATIC void setalias(shinstance *, char *, char *);
60STATIC int unalias(shinstance *, char *);
61STATIC struct alias **hashalias(shinstance *, char *);
[626]62
[3438]63#ifndef SH_FORKED_MODE
64void
65subshellinitalias(shinstance *psh, shinstance *inherit)
66{
67 unsigned i;
68 unsigned left = inherit->aliases;
69 if (left == 0)
70 return;
71 for (i = 0; i < K_ELEMENTS(inherit->atab); i++)
72 {
73 struct alias const *asrc = inherit->atab[i];
74 if (asrc)
75 {
76 struct alias **ppdst = &psh->atab[i];
77 do
78 {
79 if (*asrc->name)
80 {
81 struct alias *dst = (struct alias *)ckmalloc(psh, sizeof(*dst));
82 dst->name = savestr(psh, asrc->name);
83 dst->val = savestr(psh, asrc->val);
84 dst->flag = asrc->flag;
85 *ppdst = dst;
86 ppdst = &dst->next;
87 }
88 left--;
89 asrc = asrc->next;
90 } while (asrc);
91 *ppdst = NULL;
92 if (left == 0)
93 break;
94 }
95 }
96}
97#endif /* !SH_FORKED_MODE */
98
[626]99STATIC
100void
[882]101setalias(shinstance *psh, char *name, char *val)
[626]102{
103 struct alias *ap, **app;
104
[882]105 app = hashalias(psh, name);
[626]106 for (ap = *app; ap; ap = ap->next) {
107 if (equal(name, ap->name)) {
108 INTOFF;
[2290]109 ckfree(psh, ap->val);
110 ap->val = savestr(psh, val);
[626]111 INTON;
112 return;
113 }
114 }
115 /* not found */
116 INTOFF;
[2290]117 ap = ckmalloc(psh, sizeof (struct alias));
118 ap->name = savestr(psh, name);
[626]119 /*
120 * XXX - HACK: in order that the parser will not finish reading the
121 * alias value off the input before processing the next alias, we
122 * dummy up an extra space at the end of the alias. This is a crock
123 * and should be re-thought. The idea (if you feel inclined to help)
124 * is to avoid alias recursions. The mechanism used is: when
125 * expanding an alias, the value of the alias is pushed back on the
126 * input as a string and a pointer to the alias is stored with the
127 * string. The alias is marked as being in use. When the input
128 * routine finishes reading the string, it markes the alias not
129 * in use. The problem is synchronization with the parser. Since
130 * it reads ahead, the alias is marked not in use before the
131 * resulting token(s) is next checked for further alias sub. The
132 * H A C K is that we add a little fluff after the alias value
133 * so that the string will not be exhausted. This is a good
134 * idea ------- ***NOT***
135 */
136#ifdef notyet
[2290]137 ap->val = savestr(psh, val);
[626]138#else /* hack */
139 {
[1198]140 size_t len = strlen(val);
[2290]141 ap->val = ckmalloc(psh, len + 2);
[626]142 memcpy(ap->val, val, len);
143 ap->val[len] = ' '; /* fluff */
144 ap->val[len+1] = '\0';
145 }
146#endif
147 ap->next = *app;
148 *app = ap;
[3438]149 psh->aliases++;
[626]150 INTON;
151}
152
153STATIC int
[882]154unalias(shinstance *psh, char *name)
[626]155{
156 struct alias *ap, **app;
157
[882]158 app = hashalias(psh, name);
[626]159
160 for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
161 if (equal(name, ap->name)) {
162 /*
163 * if the alias is currently in use (i.e. its
164 * buffer is being used by the input routine) we
165 * just null out the name instead of freeing it.
166 * We could clear it out later, but this situation
167 * is so rare that it hardly seems worth it.
168 */
169 if (ap->flag & ALIASINUSE)
170 *ap->name = '\0';
171 else {
172 INTOFF;
173 *app = ap->next;
[2290]174 ckfree(psh, ap->name);
175 ckfree(psh, ap->val);
176 ckfree(psh, ap);
[3438]177 psh->aliases--;
[626]178 INTON;
179 }
180 return (0);
181 }
182 }
183
184 return (1);
185}
186
187#ifdef mkinit
[882]188MKINIT void rmaliases(shinstance *psh);
[626]189
190SHELLPROC {
[882]191 rmaliases(psh);
[626]192}
193#endif
194
195void
[882]196rmaliases(shinstance *psh)
[626]197{
198 struct alias *ap, *tmp;
199 int i;
200
201 INTOFF;
202 for (i = 0; i < ATABSIZE; i++) {
[882]203 ap = psh->atab[i];
204 psh->atab[i] = NULL;
[626]205 while (ap) {
[2290]206 ckfree(psh, ap->name);
207 ckfree(psh, ap->val);
[626]208 tmp = ap;
209 ap = ap->next;
[2290]210 ckfree(psh, tmp);
[626]211 }
212 }
213 INTON;
214}
215
216struct alias *
[882]217lookupalias(shinstance *psh, char *name, int check)
[626]218{
[882]219 struct alias *ap = *hashalias(psh, name);
[626]220
221 for (; ap; ap = ap->next) {
222 if (equal(name, ap->name)) {
223 if (check && (ap->flag & ALIASINUSE))
224 return (NULL);
225 return (ap);
226 }
227 }
228
229 return (NULL);
230}
231
232char *
[882]233get_alias_text(shinstance *psh, char *name)
[626]234{
235 struct alias *ap;
236
[882]237 ap = lookupalias(psh, name, 0);
[626]238 if (ap == NULL)
239 return NULL;
240 return ap->val;
241}
242
243/*
244 * TODO - sort output
245 */
246int
[882]247aliascmd(shinstance *psh, int argc, char **argv)
[626]248{
249 char *n, *v;
250 int ret = 0;
251 struct alias *ap;
252
253 if (argc == 1) {
254 int i;
255
256 for (i = 0; i < ATABSIZE; i++)
[882]257 for (ap = psh->atab[i]; ap; ap = ap->next) {
[626]258 if (*ap->name != '\0') {
[882]259 out1fmt(psh, "alias %s=", ap->name);
260 print_quoted(psh, ap->val);
261 out1c(psh, '\n');
[626]262 }
263 }
264 return (0);
265 }
266 while ((n = *++argv) != NULL) {
267 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
[882]268 if ((ap = lookupalias(psh, n, 0)) == NULL) {
269 outfmt(psh->out2, "alias: %s not found\n", n);
[626]270 ret = 1;
271 } else {
[882]272 out1fmt(psh, "alias %s=", n);
273 print_quoted(psh, ap->val);
274 out1c(psh, '\n');
[626]275 }
276 } else {
277 *v++ = '\0';
[882]278 setalias(psh, n, v);
[626]279 }
280 }
281
282 return (ret);
283}
284
285int
[882]286unaliascmd(shinstance *psh, int argc, char **argv)
[626]287{
288 int i;
289
[882]290 while ((i = nextopt(psh, "a")) != '\0') {
[626]291 if (i == 'a') {
[882]292 rmaliases(psh);
[626]293 return (0);
294 }
295 }
[882]296 for (i = 0; *psh->argptr; psh->argptr++)
297 i = unalias(psh, *psh->argptr);
[626]298
299 return (i);
300}
301
302STATIC struct alias **
[882]303hashalias(shinstance *psh, char *p)
[626]304{
305 unsigned int hashval;
306
307 hashval = *p << 4;
308 while (*p)
309 hashval+= *p++;
[882]310 return &psh->atab[hashval % ATABSIZE];
[626]311}
Note: See TracBrowser for help on using the repository browser.