]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/sh/alias.c
zfs: merge openzfs/zfs@95f71c019
[FreeBSD/FreeBSD.git] / bin / sh / alias.c
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)alias.c     8.3 (Berkeley) 5/4/95";
36 #endif
37 #endif /* not lint */
38 #include <sys/cdefs.h>
39 #include <stdlib.h>
40 #include "shell.h"
41 #include "output.h"
42 #include "error.h"
43 #include "memalloc.h"
44 #include "mystring.h"
45 #include "alias.h"
46 #include "options.h"
47 #include "builtins.h"
48
49 #define ATABSIZE 39
50
51 static struct alias *atab[ATABSIZE];
52 static int aliases;
53
54 static void setalias(const char *, const char *);
55 static int unalias(const char *);
56 static struct alias **hashalias(const char *);
57
58 static
59 void
60 setalias(const char *name, const char *val)
61 {
62         struct alias *ap, **app;
63
64         unalias(name);
65         app = hashalias(name);
66         INTOFF;
67         ap = ckmalloc(sizeof (struct alias));
68         ap->name = savestr(name);
69         ap->val = savestr(val);
70         ap->flag = 0;
71         ap->next = *app;
72         *app = ap;
73         aliases++;
74         INTON;
75 }
76
77 static void
78 freealias(struct alias *ap)
79 {
80         ckfree(ap->name);
81         ckfree(ap->val);
82         ckfree(ap);
83 }
84
85 static int
86 unalias(const char *name)
87 {
88         struct alias *ap, **app;
89
90         app = hashalias(name);
91
92         for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
93                 if (equal(name, ap->name)) {
94                         /*
95                          * if the alias is currently in use (i.e. its
96                          * buffer is being used by the input routine) we
97                          * just null out the name instead of freeing it.
98                          * We could clear it out later, but this situation
99                          * is so rare that it hardly seems worth it.
100                          */
101                         if (ap->flag & ALIASINUSE)
102                                 *ap->name = '\0';
103                         else {
104                                 INTOFF;
105                                 *app = ap->next;
106                                 freealias(ap);
107                                 INTON;
108                         }
109                         aliases--;
110                         return (0);
111                 }
112         }
113
114         return (1);
115 }
116
117 static void
118 rmaliases(void)
119 {
120         struct alias *ap, **app;
121         int i;
122
123         INTOFF;
124         for (i = 0; i < ATABSIZE; i++) {
125                 app = &atab[i];
126                 while (*app) {
127                         ap = *app;
128                         if (ap->flag & ALIASINUSE) {
129                                 *ap->name = '\0';
130                                 app = &(*app)->next;
131                         } else {
132                                 *app = ap->next;
133                                 freealias(ap);
134                         }
135                 }
136         }
137         aliases = 0;
138         INTON;
139 }
140
141 struct alias *
142 lookupalias(const char *name, int check)
143 {
144         struct alias *ap;
145
146         if (aliases == 0)
147                 return (NULL);
148         for (ap = *hashalias(name); ap; ap = ap->next) {
149                 if (equal(name, ap->name)) {
150                         if (check && (ap->flag & ALIASINUSE))
151                                 return (NULL);
152                         return (ap);
153                 }
154         }
155
156         return (NULL);
157 }
158
159 static int
160 comparealiases(const void *p1, const void *p2)
161 {
162         const struct alias *const *a1 = p1;
163         const struct alias *const *a2 = p2;
164
165         return strcmp((*a1)->name, (*a2)->name);
166 }
167
168 static void
169 printalias(const struct alias *a)
170 {
171         out1fmt("%s=", a->name);
172         out1qstr(a->val);
173         out1c('\n');
174 }
175
176 static void
177 printaliases(void)
178 {
179         int i, j;
180         struct alias **sorted, *ap;
181
182         INTOFF;
183         sorted = ckmalloc(aliases * sizeof(*sorted));
184         j = 0;
185         for (i = 0; i < ATABSIZE; i++)
186                 for (ap = atab[i]; ap; ap = ap->next)
187                         if (*ap->name != '\0')
188                                 sorted[j++] = ap;
189         qsort(sorted, aliases, sizeof(*sorted), comparealiases);
190         for (i = 0; i < aliases; i++) {
191                 printalias(sorted[i]);
192                 if (int_pending())
193                         break;
194         }
195         ckfree(sorted);
196         INTON;
197 }
198
199 int
200 aliascmd(int argc __unused, char **argv __unused)
201 {
202         char *n, *v;
203         int ret = 0;
204         struct alias *ap;
205
206         nextopt("");
207
208         if (*argptr == NULL) {
209                 printaliases();
210                 return (0);
211         }
212         while ((n = *argptr++) != NULL) {
213                 if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
214                         if ((ap = lookupalias(n, 0)) == NULL) {
215                                 warning("%s: not found", n);
216                                 ret = 1;
217                         } else
218                                 printalias(ap);
219                 else {
220                         *v++ = '\0';
221                         setalias(n, v);
222                 }
223         }
224
225         return (ret);
226 }
227
228 int
229 unaliascmd(int argc __unused, char **argv __unused)
230 {
231         int i;
232
233         while ((i = nextopt("a")) != '\0') {
234                 if (i == 'a') {
235                         rmaliases();
236                         return (0);
237                 }
238         }
239         for (i = 0; *argptr; argptr++)
240                 i |= unalias(*argptr);
241
242         return (i);
243 }
244
245 static struct alias **
246 hashalias(const char *p)
247 {
248         unsigned int hashval;
249
250         hashval = (unsigned char)*p << 4;
251         while (*p)
252                 hashval+= *p++;
253         return &atab[hashval % ATABSIZE];
254 }