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