1 /* @(#)hashcmd.c 1.34 19/11/19 Copyright 1986-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)hashcmd.c 1.34 19/11/19 Copyright 1986-2019 J. Schilling";
6 #endif
7 /*
8 * bsh - Commands dealing with #<letter> commands
9 *
10 * Copyright (c) 1986-2019 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/stdio.h>
27 #include "bsh.h"
28 #include "node.h"
29 #include "str.h"
30 #include "strsubs.h"
31 #include "abbtab.h"
32 #include "abbrev.h"
33 #include "ctype.h"
34 #include <schily/stdlib.h>
35 #include <schily/fcntl.h> /* To get F_GETFD/F_SETFD */
36
37 extern abidx_t deftab; /* Variable is defined in abbrev.c */
38
39 extern int delim;
40 extern int ttyflg;
41 extern int MVERSION;
42 extern int mVERSION;
43 extern char dVERSION[];
44 extern char *initav0;
45 extern char *cmdfname;
46 extern Tnode *lastcmd; /* Used by ancient #e command */
47
48 EXPORT void hashcmd __PR((FILE ** std));
49 LOCAL void shcmd __PR((FILE ** std, char *name));
50 LOCAL void abballusage __PR((FILE ** std));
51 LOCAL void abbusage __PR((FILE ** std, int cmd));
52 LOCAL char *nameok __PR((char *n));
53
54 /*
55 * Parse and execute a hashmark command
56 */
57 EXPORT void
hashcmd(std)58 hashcmd(std)
59 FILE *std[];
60 {
61 int cmd;
62 char *name;
63 char *name2;
64 char *val;
65 int bflg = 0;
66 int delflg = 0;
67 int histflg = 0;
68 abidx_t tab = deftab;
69
70 quote();
71 cmd = nextch(); /* First skip '#' */
72 skipwhite();
73 if (!ttyflg && (iswhite(cmd) || argend(nl, 0))) /* Kommentar */
74 cmd = ' ';
75 else
76 cmd = tolower(delim);
77 if (cmd != ' ' && argend(nl, 0)) {
78 fprintf(std[2], relmsg, MVERSION, mVERSION, dVERSION, HOST_CPU, HOST_VENDOR, HOST_OS);
79
80 unquote();
81 return;
82 } else if (cmd == 'b') {
83 bflg = AB_BEGIN;
84 }
85
86 if (cmd == '!') {
87 nextch();
88 } else if (cmd != ' ') {
89 nextch();
90 while (!argend(spaces, 0)) {
91 delim = tolower(delim);
92 switch (delim) {
93
94 case 'g':
95 tab = GLOBAL_AB;
96 break;
97 case 'l':
98 tab = LOCAL_AB;
99 break;
100 case 'b':
101 if (cmd == 'p') {
102 bflg = AB_BEGIN;
103 break;
104 }
105 goto err;
106 case 'a':
107 if (cmd == 'p') {
108 bflg = 0;
109 break;
110 }
111 goto err;
112 case 'd':
113 if (cmd == 'x')
114 delflg++;
115 break;
116 case 'h':
117 if (cmd == 'l') {
118 histflg = AB_HISTORY;
119 break;
120 }
121 default:
122 err:
123 berror("%s", ebadmodifier);
124 abbusage(std, cmd);
125 eatline();
126 return;
127 }
128 nextch();
129 }
130 }
131 skipwhite();
132 if (cmd != ' ')
133 name = pstring(spaces, 0); /* Get next word */
134 else
135 name = NULL;
136 if (name != NULL && streql(name, helpname)) {
137 free(name);
138 abbusage(std, cmd);
139 eatline();
140 return;
141 }
142 switch (cmd) {
143
144 case 'a':
145 case 'b':
146 case 'p':
147 if (nameok(name)) {
148 skipwhite();
149 val = pstring(nl, 0);
150 if (val == NULL)
151 val = makestr(nullstr);
152 if (cmd == 'p')
153 ab_push(tab, makestr(name), val, bflg);
154 else
155 ab_insert(tab, makestr(name), val, bflg);
156 }
157 else
158 abbusage(std, cmd);
159 break;
160 case 'd':
161 if (nameok(name)) {
162 do {
163 if (name == NULL)
164 break;
165 ab_delete(tab, name, AB_NOFLAG);
166 free(name);
167 skipwhite();
168 } while ((name = pstring(spaces, 0)) != NULL);
169 }
170 else
171 abbusage(std, cmd);
172 break;
173 case 'e':
174 eatline();
175 execute(lastcmd, 0, gstd);
176 return;
177 case 'l':
178 if (name == NULL) {
179 ab_dump(tab, std[1], histflg);
180 } else {
181 do {
182 ab_list(tab, name, std[1], histflg);
183 free(name);
184 skipwhite();
185 } while ((name = pstring(spaces, 0)) != NULL);
186 }
187 break;
188 case 'v':
189 if (name != NULL) {
190 if (streql(name, on)) {
191 vflg = TRUE;
192 } else if (streql(name, off)) {
193 vflg = FALSE;
194 } else {
195 berror(ebadopt, "v", name);
196 abbusage(std, cmd);
197 }
198 }
199 else
200 fprintf(std[1], "Verbose %s.\n", vflg?on:off);
201 break;
202 case 's':
203 deftab = tab;
204 fprintf(std[1], "Default: %s\n",
205 deftab == GLOBAL_AB?
206 globalname:localname);
207 break;
208 case '?':
209 case 'h':
210 abballusage(std);
211 break;
212 case 'q':
213 delim = EOF;
214 break;
215 case 'x':
216 if (name == NULL) {
217 ev_list(std[1]);
218 } else {
219 if (!strchr(name, '=')) {
220 if (delflg) {
221 ev_delete(name);
222 } else if ((val = getcurenv(name)) != NULL) {
223 fprintf(std[1], "%s=%s\n", name, val);
224 break;
225 }
226 } else {
227 val = pstring(nl, 0);
228 name2 = concat(name, val, (char *)NULL);
229 free(name);
230 if (val)
231 free(val);
232 ev_insert(name2);
233 }
234 }
235 break;
236 case '!':
237 if (ttyflg) {
238 berror("%s", eshonly);
239 abbusage(std, cmd);
240 break;
241 }
242 if (name == NULL)
243 break;
244 if (streql(fbasename(name), fbasename(initav0))) {
245 break;
246 }
247 if (cmdfname != NULL) /* Can do this only on commandfiles */
248 shcmd(std, name);
249 break;
250 case ' ':
251 break; /* Kommentar */
252 default:
253 berror("%s", enocmd);
254 abballusage(std);
255 break;
256 }
257 if (name)
258 free(name);
259 eatline();
260 }
261
262 LOCAL void
shcmd(std,name)263 shcmd(std, name)
264 FILE *std[];
265 char *name;
266 {
267 register int i;
268 register Tnode *lst;
269 register Tnode *lp;
270 Argvec *vp;
271
272 lst = lp = allocnode(STRING, (Tnode *) name, (Tnode *) NULL);
273 while ((lp->tn_right.tn_node = pword()) != NULL)
274 lp = lp->tn_right.tn_node;
275 vav[0] = cmdfname;
276 for (i = 0; i < vac; i++) {
277 lp->tn_right.tn_node = allocnode(STRING, (Tnode *) vav[i],
278 (Tnode *) NULL);
279 lp = lp->tn_right.tn_node;
280 }
281
282 #ifndef F_SETFD
283 /*
284 * If we canno set the close on exec() flag, we need
285 * to close the files manually.
286 */
287 fclose(cmdfp);
288 if (protfile != (FILE *)NULL)
289 fclose(protfile);
290 #endif
291 vp = scan(lst);
292 start(vp, std, 0); /* no return */
293 }
294
295 LOCAL void
abballusage(std)296 abballusage(std)
297 register FILE *std[];
298 {
299 register int i;
300
301 for (i = 0; abbtab[i].a_c != '\0'; i++) {
302 fprintf(std[2], "%s\n", abbtab[i].a_msg);
303 }
304 }
305
306 LOCAL void
abbusage(std,cmd)307 abbusage(std, cmd)
308 FILE *std[];
309 register int cmd;
310 {
311 register int i;
312
313 for (i = 0; abbtab[i].a_c != '\0'; i++) {
314 if (abbtab[i].a_c == cmd) {
315 fprintf(std[2], "%s%s\n", usage, abbtab[i].a_msg);
316 break;
317 }
318 }
319 if (abbtab[i].a_c == '\0') {
320 fprintf(std[2], "%s\n", enocmd);
321 abballusage(std);
322 }
323 }
324
325 LOCAL char *
nameok(n)326 nameok(n)
327 char *n;
328 {
329 if (n == NULL)
330 berror("%s", emissabbrev);
331 return (n);
332 }
333