Commit | Line | Data |
---|---|---|
3d987f16 KB |
1 | /*- |
2 | * Copyright (c) 1993 | |
3 | * The Regents of the University of California. All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Kenneth Almquist. | |
7 | * | |
8 | * %sccs.include.redist.c% | |
9 | */ | |
10 | ||
11 | #ifndef lint | |
8515c79c | 12 | static char sccsid[] = "@(#)alias.c 8.1 (Berkeley) %G%"; |
3d987f16 KB |
13 | #endif /* not lint */ |
14 | ||
6ff9baf8 MT |
15 | #include "shell.h" |
16 | #include "input.h" | |
17 | #include "output.h" | |
18 | #include "error.h" | |
19 | #include "memalloc.h" | |
20 | #include "mystring.h" | |
21 | #include "alias.h" | |
22 | #include "options.h" /* XXX for argptr (should remove?) */ | |
23 | ||
24 | #define ATABSIZE 39 | |
25 | ||
26 | struct alias *atab[ATABSIZE]; | |
27 | ||
28 | STATIC struct alias **hashalias __P((char *)); | |
29 | ||
30 | STATIC | |
31 | setalias(name, val) | |
32 | char *name, *val; | |
33 | { | |
34 | struct alias *ap, **app; | |
35 | ||
36 | app = hashalias(name); | |
37 | for (ap = *app; ap; ap = ap->next) { | |
38 | if (equal(name, ap->name)) { | |
39 | INTOFF; | |
40 | ckfree(ap->val); | |
41 | ap->val = savestr(val); | |
42 | INTON; | |
43 | return; | |
44 | } | |
45 | } | |
46 | /* not found */ | |
47 | INTOFF; | |
48 | ap = ckmalloc(sizeof (struct alias)); | |
49 | ap->name = savestr(name); | |
50 | /* | |
51 | * XXX - HACK: in order that the parser will not finish reading the | |
52 | * alias value off the input before processing the next alias, we | |
53 | * dummy up an extra space at the end of the alias. This is a crock | |
54 | * and should be re-thought. The idea (if you feel inclined to help) | |
55 | * is to avoid alias recursions. The mechanism used is: when | |
56 | * expanding an alias, the value of the alias is pushed back on the | |
57 | * input as a string and a pointer to the alias is stored with the | |
58 | * string. The alias is marked as being in use. When the input | |
59 | * routine finishes reading the string, it markes the alias not | |
60 | * in use. The problem is synchronization with the parser. Since | |
61 | * it reads ahead, the alias is marked not in use before the | |
62 | * resulting token(s) is next checked for further alias sub. The | |
63 | * H A C K is that we add a little fluff after the alias value | |
64 | * so that the string will not be exhausted. This is a good | |
65 | * idea ------- ***NOT*** | |
66 | */ | |
67 | #ifdef notyet | |
68 | ap->val = savestr(val); | |
69 | #else /* hack */ | |
70 | { | |
71 | int len = strlen(val); | |
72 | ap->val = ckmalloc(len + 2); | |
73 | bcopy(val, ap->val, len); | |
74 | ap->val[len] = ' '; /* fluff */ | |
75 | ap->val[len+1] = '\0'; | |
76 | } | |
77 | #endif | |
78 | ap->next = *app; | |
79 | *app = ap; | |
80 | INTON; | |
81 | } | |
82 | ||
83 | STATIC int | |
84 | unalias(name) | |
85 | char *name; | |
86 | { | |
87 | struct alias *ap, **app; | |
88 | ||
89 | app = hashalias(name); | |
90 | ||
91 | for (ap = *app; ap; app = &(ap->next), ap = ap->next) { | |
92 | if (equal(name, ap->name)) { | |
93 | /* | |
94 | * if the alias is currently in use (i.e. its | |
95 | * buffer is being used by the input routine) we | |
96 | * just null out the name instead of freeing it. | |
97 | * We could clear it out later, but this situation | |
98 | * is so rare that it hardly seems worth it. | |
99 | */ | |
100 | if (ap->flag & ALIASINUSE) | |
101 | *ap->name = '\0'; | |
102 | else { | |
103 | INTOFF; | |
104 | *app = ap->next; | |
105 | ckfree(ap->name); | |
106 | ckfree(ap->val); | |
107 | ckfree(ap); | |
108 | INTON; | |
109 | } | |
110 | return (0); | |
111 | } | |
112 | } | |
113 | ||
114 | return (1); | |
115 | } | |
116 | ||
117 | #ifdef mkinit | |
118 | MKINIT void rmaliases(); | |
119 | ||
120 | SHELLPROC { | |
121 | rmaliases(); | |
122 | } | |
123 | #endif | |
124 | ||
125 | void | |
126 | rmaliases() { | |
127 | struct alias *ap, *tmp; | |
128 | int i; | |
129 | ||
130 | INTOFF; | |
131 | for (i = 0; i < ATABSIZE; i++) { | |
132 | ap = atab[i]; | |
133 | atab[i] = NULL; | |
134 | while (ap) { | |
135 | ckfree(ap->name); | |
136 | ckfree(ap->val); | |
137 | tmp = ap; | |
138 | ap = ap->next; | |
139 | ckfree(tmp); | |
140 | } | |
141 | } | |
142 | INTON; | |
143 | } | |
144 | ||
145 | struct alias * | |
146 | lookupalias(name, check) | |
147 | char *name; | |
148 | { | |
149 | struct alias *ap = *hashalias(name); | |
150 | ||
151 | for (; ap; ap = ap->next) { | |
152 | if (equal(name, ap->name)) { | |
153 | if (check && (ap->flag & ALIASINUSE)) | |
154 | return (NULL); | |
155 | return (ap); | |
156 | } | |
157 | } | |
158 | ||
159 | return (NULL); | |
160 | } | |
161 | ||
162 | /* | |
163 | * TODO - sort output | |
164 | */ | |
165 | aliascmd(argc, argv) | |
166 | char **argv; | |
167 | { | |
168 | char *n, *v; | |
169 | int ret = 0; | |
170 | struct alias *ap; | |
171 | ||
172 | if (argc == 1) { | |
173 | int i; | |
174 | ||
175 | for (i = 0; i < ATABSIZE; i++) | |
176 | for (ap = atab[i]; ap; ap = ap->next) { | |
177 | if (*ap->name != '\0') | |
178 | out1fmt("alias %s=%s\n", ap->name, ap->val); | |
179 | } | |
180 | return (0); | |
181 | } | |
182 | while (n = *++argv) { | |
183 | if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ | |
184 | if ((ap = lookupalias(n, 0)) == NULL) { | |
185 | outfmt(out2, "alias: %s not found\n", n); | |
186 | ret = 1; | |
187 | } else | |
188 | out1fmt("alias %s=%s\n", n, ap->val); | |
189 | else { | |
190 | *v++ = '\0'; | |
191 | setalias(n, v); | |
192 | } | |
193 | } | |
194 | ||
195 | return (ret); | |
196 | } | |
197 | ||
198 | unaliascmd(argc, argv) | |
199 | char **argv; | |
200 | { | |
201 | int i; | |
202 | ||
203 | while ((i = nextopt("a")) != '\0') { | |
204 | if (i == 'a') { | |
205 | rmaliases(); | |
206 | return (0); | |
207 | } | |
208 | } | |
209 | for (i = 0; *argptr; argptr++) | |
210 | i = unalias(*argptr); | |
211 | ||
212 | return (i); | |
213 | } | |
214 | ||
6ff9baf8 MT |
215 | STATIC struct alias ** |
216 | hashalias(p) | |
217 | register char *p; | |
218 | { | |
219 | unsigned int hashval; | |
220 | ||
221 | hashval = *p << 4; | |
222 | while (*p) | |
223 | hashval+= *p++; | |
224 | return &atab[hashval % ATABSIZE]; | |
225 | } |