Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/bin/sh/alias.c
39536 views
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
#include <stdlib.h>
34
#include "shell.h"
35
#include "output.h"
36
#include "error.h"
37
#include "memalloc.h"
38
#include "mystring.h"
39
#include "alias.h"
40
#include "options.h"
41
#include "builtins.h"
42
43
#define ATABSIZE 39
44
45
static struct alias *atab[ATABSIZE];
46
static int aliases;
47
48
static void setalias(const char *, const char *);
49
static int unalias(const char *);
50
static size_t hashalias(const char *);
51
52
static
53
void
54
setalias(const char *name, const char *val)
55
{
56
struct alias *ap, **app;
57
58
unalias(name);
59
app = &atab[hashalias(name)];
60
INTOFF;
61
ap = ckmalloc(sizeof (struct alias));
62
ap->name = savestr(name);
63
ap->val = savestr(val);
64
ap->flag = 0;
65
ap->next = *app;
66
*app = ap;
67
aliases++;
68
INTON;
69
}
70
71
static void
72
freealias(struct alias *ap)
73
{
74
ckfree(ap->name);
75
ckfree(ap->val);
76
ckfree(ap);
77
}
78
79
static int
80
unalias(const char *name)
81
{
82
struct alias *ap, **app;
83
84
app = &atab[hashalias(name)];
85
86
for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
87
if (equal(name, ap->name)) {
88
/*
89
* if the alias is currently in use (i.e. its
90
* buffer is being used by the input routine) we
91
* just null out the name instead of freeing it.
92
* We could clear it out later, but this situation
93
* is so rare that it hardly seems worth it.
94
*/
95
if (ap->flag & ALIASINUSE)
96
*ap->name = '\0';
97
else {
98
INTOFF;
99
*app = ap->next;
100
freealias(ap);
101
INTON;
102
}
103
aliases--;
104
return (0);
105
}
106
}
107
108
return (1);
109
}
110
111
static void
112
rmaliases(void)
113
{
114
struct alias *ap, **app;
115
int i;
116
117
INTOFF;
118
for (i = 0; i < ATABSIZE; i++) {
119
app = &atab[i];
120
while (*app) {
121
ap = *app;
122
if (ap->flag & ALIASINUSE) {
123
*ap->name = '\0';
124
app = &(*app)->next;
125
} else {
126
*app = ap->next;
127
freealias(ap);
128
}
129
}
130
}
131
aliases = 0;
132
INTON;
133
}
134
135
struct alias *
136
lookupalias(const char *name, int check)
137
{
138
struct alias *ap;
139
140
if (aliases == 0)
141
return (NULL);
142
for (ap = atab[hashalias(name)]; ap; ap = ap->next) {
143
if (equal(name, ap->name)) {
144
if (check && (ap->flag & ALIASINUSE))
145
return (NULL);
146
return (ap);
147
}
148
}
149
150
return (NULL);
151
}
152
153
static int
154
comparealiases(const void *p1, const void *p2)
155
{
156
const struct alias *const *a1 = p1;
157
const struct alias *const *a2 = p2;
158
159
return strcmp((*a1)->name, (*a2)->name);
160
}
161
162
static void
163
printalias(const struct alias *a)
164
{
165
out1fmt("%s=", a->name);
166
out1qstr(a->val);
167
out1c('\n');
168
}
169
170
static void
171
printaliases(void)
172
{
173
int i, j;
174
struct alias **sorted, *ap;
175
176
INTOFF;
177
sorted = ckmalloc(aliases * sizeof(*sorted));
178
j = 0;
179
for (i = 0; i < ATABSIZE; i++)
180
for (ap = atab[i]; ap; ap = ap->next)
181
if (*ap->name != '\0')
182
sorted[j++] = ap;
183
qsort(sorted, aliases, sizeof(*sorted), comparealiases);
184
for (i = 0; i < aliases; i++) {
185
printalias(sorted[i]);
186
if (int_pending())
187
break;
188
}
189
ckfree(sorted);
190
INTON;
191
}
192
193
int
194
aliascmd(int argc __unused, char **argv __unused)
195
{
196
char *n, *v;
197
int ret = 0;
198
struct alias *ap;
199
200
nextopt("");
201
202
if (*argptr == NULL) {
203
printaliases();
204
return (0);
205
}
206
while ((n = *argptr++) != NULL) {
207
if (n[0] == '\0') {
208
warning("'': not found");
209
ret = 1;
210
continue;
211
}
212
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
213
if ((ap = lookupalias(n, 0)) == NULL) {
214
warning("%s: not found", n);
215
ret = 1;
216
} else
217
printalias(ap);
218
else {
219
*v++ = '\0';
220
setalias(n, v);
221
}
222
}
223
224
return (ret);
225
}
226
227
int
228
unaliascmd(int argc __unused, char **argv __unused)
229
{
230
int i;
231
232
while ((i = nextopt("a")) != '\0') {
233
if (i == 'a') {
234
rmaliases();
235
return (0);
236
}
237
}
238
for (i = 0; *argptr; argptr++)
239
i |= unalias(*argptr);
240
241
return (i);
242
}
243
244
static size_t
245
hashalias(const char *p)
246
{
247
unsigned int hashval;
248
249
hashval = (unsigned char)*p << 4;
250
while (*p)
251
hashval+= *p++;
252
return (hashval % ATABSIZE);
253
}
254
255
const struct alias *
256
iteralias(const struct alias *index)
257
{
258
size_t i = 0;
259
260
if (index != NULL) {
261
if (index->next != NULL)
262
return (index->next);
263
i = hashalias(index->name) + 1;
264
}
265
for (; i < ATABSIZE; i++)
266
if (atab[i] != NULL)
267
return (atab[i]);
268
269
return (NULL);
270
}
271
272