Commit | Line | Data |
---|---|---|
a9f0b747 | 1 | /*- |
8276a8e2 KB |
2 | * Copyright (c) 1991, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
a9f0b747 KB |
4 | * |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Kenneth Almquist. | |
7 | * | |
ad787160 C |
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. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
a9f0b747 KB |
35 | */ |
36 | ||
37 | #ifndef lint | |
fd88f5c5 | 38 | static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; |
a9f0b747 KB |
39 | #endif /* not lint */ |
40 | ||
41 | #include <stdio.h> | |
13b3e634 CZ |
42 | #if __STDC__ |
43 | #include <stdarg.h> | |
44 | #else | |
45 | #include <varargs.h> | |
46 | #endif | |
47 | ||
a9f0b747 KB |
48 | #include "shell.h" |
49 | #include "parser.h" | |
50 | #include "nodes.h" | |
51 | #include "mystring.h" | |
13b3e634 | 52 | #include "show.h" |
a9f0b747 KB |
53 | |
54 | ||
55 | #ifdef DEBUG | |
13b3e634 CZ |
56 | static void shtree __P((union node *, int, char *, FILE*)); |
57 | static void shcmd __P((union node *, FILE *)); | |
58 | static void sharg __P((union node *, FILE *)); | |
59 | static void indent __P((int, char *, FILE *)); | |
60 | static void trstring __P((char *)); | |
a9f0b747 KB |
61 | |
62 | ||
13b3e634 | 63 | void |
a9f0b747 KB |
64 | showtree(n) |
65 | union node *n; | |
13b3e634 | 66 | { |
a9f0b747 KB |
67 | trputs("showtree called\n"); |
68 | shtree(n, 1, NULL, stdout); | |
69 | } | |
70 | ||
71 | ||
13b3e634 | 72 | static void |
a9f0b747 KB |
73 | shtree(n, ind, pfx, fp) |
74 | union node *n; | |
13b3e634 | 75 | int ind; |
a9f0b747 KB |
76 | char *pfx; |
77 | FILE *fp; | |
13b3e634 | 78 | { |
a9f0b747 KB |
79 | struct nodelist *lp; |
80 | char *s; | |
81 | ||
17f6a06f KB |
82 | if (n == NULL) |
83 | return; | |
84 | ||
a9f0b747 KB |
85 | indent(ind, pfx, fp); |
86 | switch(n->type) { | |
87 | case NSEMI: | |
88 | s = "; "; | |
89 | goto binop; | |
90 | case NAND: | |
91 | s = " && "; | |
92 | goto binop; | |
93 | case NOR: | |
94 | s = " || "; | |
95 | binop: | |
96 | shtree(n->nbinary.ch1, ind, NULL, fp); | |
97 | /* if (ind < 0) */ | |
98 | fputs(s, fp); | |
99 | shtree(n->nbinary.ch2, ind, NULL, fp); | |
100 | break; | |
101 | case NCMD: | |
102 | shcmd(n, fp); | |
103 | if (ind >= 0) | |
104 | putc('\n', fp); | |
105 | break; | |
106 | case NPIPE: | |
107 | for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { | |
108 | shcmd(lp->n, fp); | |
109 | if (lp->next) | |
110 | fputs(" | ", fp); | |
111 | } | |
112 | if (n->npipe.backgnd) | |
113 | fputs(" &", fp); | |
114 | if (ind >= 0) | |
115 | putc('\n', fp); | |
116 | break; | |
117 | default: | |
118 | fprintf(fp, "<node type %d>", n->type); | |
119 | if (ind >= 0) | |
120 | putc('\n', fp); | |
121 | break; | |
122 | } | |
123 | } | |
124 | ||
125 | ||
126 | ||
13b3e634 | 127 | static void |
a9f0b747 KB |
128 | shcmd(cmd, fp) |
129 | union node *cmd; | |
130 | FILE *fp; | |
13b3e634 | 131 | { |
a9f0b747 KB |
132 | union node *np; |
133 | int first; | |
134 | char *s; | |
135 | int dftfd; | |
136 | ||
137 | first = 1; | |
138 | for (np = cmd->ncmd.args ; np ; np = np->narg.next) { | |
139 | if (! first) | |
140 | putchar(' '); | |
141 | sharg(np, fp); | |
142 | first = 0; | |
143 | } | |
144 | for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { | |
145 | if (! first) | |
146 | putchar(' '); | |
147 | switch (np->nfile.type) { | |
148 | case NTO: s = ">"; dftfd = 1; break; | |
149 | case NAPPEND: s = ">>"; dftfd = 1; break; | |
150 | case NTOFD: s = ">&"; dftfd = 1; break; | |
151 | case NFROM: s = "<"; dftfd = 0; break; | |
152 | case NFROMFD: s = "<&"; dftfd = 0; break; | |
13b3e634 | 153 | default: s = "*error*"; dftfd = 0; break; |
a9f0b747 KB |
154 | } |
155 | if (np->nfile.fd != dftfd) | |
156 | fprintf(fp, "%d", np->nfile.fd); | |
157 | fputs(s, fp); | |
158 | if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { | |
159 | fprintf(fp, "%d", np->ndup.dupfd); | |
160 | } else { | |
161 | sharg(np->nfile.fname, fp); | |
162 | } | |
163 | first = 0; | |
164 | } | |
165 | } | |
166 | ||
167 | ||
168 | ||
13b3e634 | 169 | static void |
a9f0b747 KB |
170 | sharg(arg, fp) |
171 | union node *arg; | |
172 | FILE *fp; | |
173 | { | |
174 | char *p; | |
175 | struct nodelist *bqlist; | |
176 | int subtype; | |
177 | ||
178 | if (arg->type != NARG) { | |
179 | printf("<node type %d>\n", arg->type); | |
180 | fflush(stdout); | |
181 | abort(); | |
182 | } | |
183 | bqlist = arg->narg.backquote; | |
184 | for (p = arg->narg.text ; *p ; p++) { | |
185 | switch (*p) { | |
186 | case CTLESC: | |
187 | putc(*++p, fp); | |
188 | break; | |
189 | case CTLVAR: | |
190 | putc('$', fp); | |
191 | putc('{', fp); | |
192 | subtype = *++p; | |
17f6a06f KB |
193 | if (subtype == VSLENGTH) |
194 | putc('#', fp); | |
195 | ||
a9f0b747 KB |
196 | while (*p != '=') |
197 | putc(*p++, fp); | |
17f6a06f | 198 | |
a9f0b747 KB |
199 | if (subtype & VSNUL) |
200 | putc(':', fp); | |
17f6a06f | 201 | |
a9f0b747 KB |
202 | switch (subtype & VSTYPE) { |
203 | case VSNORMAL: | |
204 | putc('}', fp); | |
205 | break; | |
206 | case VSMINUS: | |
207 | putc('-', fp); | |
208 | break; | |
209 | case VSPLUS: | |
210 | putc('+', fp); | |
211 | break; | |
212 | case VSQUESTION: | |
213 | putc('?', fp); | |
214 | break; | |
215 | case VSASSIGN: | |
216 | putc('=', fp); | |
217 | break; | |
17f6a06f KB |
218 | case VSTRIMLEFT: |
219 | putc('#', fp); | |
220 | break; | |
221 | case VSTRIMLEFTMAX: | |
222 | putc('#', fp); | |
223 | putc('#', fp); | |
224 | break; | |
225 | case VSTRIMRIGHT: | |
226 | putc('%', fp); | |
227 | break; | |
228 | case VSTRIMRIGHTMAX: | |
229 | putc('%', fp); | |
230 | putc('%', fp); | |
231 | break; | |
232 | case VSLENGTH: | |
233 | break; | |
a9f0b747 KB |
234 | default: |
235 | printf("<subtype %d>", subtype); | |
236 | } | |
237 | break; | |
238 | case CTLENDVAR: | |
239 | putc('}', fp); | |
240 | break; | |
241 | case CTLBACKQ: | |
242 | case CTLBACKQ|CTLQUOTE: | |
243 | putc('$', fp); | |
244 | putc('(', fp); | |
245 | shtree(bqlist->n, -1, NULL, fp); | |
246 | putc(')', fp); | |
247 | break; | |
248 | default: | |
249 | putc(*p, fp); | |
250 | break; | |
251 | } | |
252 | } | |
253 | } | |
254 | ||
255 | ||
13b3e634 | 256 | static void |
a9f0b747 | 257 | indent(amount, pfx, fp) |
13b3e634 | 258 | int amount; |
a9f0b747 KB |
259 | char *pfx; |
260 | FILE *fp; | |
13b3e634 | 261 | { |
a9f0b747 KB |
262 | int i; |
263 | ||
264 | for (i = 0 ; i < amount ; i++) { | |
265 | if (pfx && i == amount - 1) | |
266 | fputs(pfx, fp); | |
267 | putc('\t', fp); | |
268 | } | |
269 | } | |
270 | #endif | |
271 | ||
272 | ||
273 | ||
274 | /* | |
275 | * Debugging stuff. | |
276 | */ | |
277 | ||
278 | ||
279 | FILE *tracefile; | |
280 | ||
44c32b7a MT |
281 | #if DEBUG == 2 |
282 | int debug = 1; | |
283 | #else | |
284 | int debug = 0; | |
285 | #endif | |
a9f0b747 KB |
286 | |
287 | ||
13b3e634 CZ |
288 | void |
289 | trputc(c) | |
290 | int c; | |
291 | { | |
a9f0b747 KB |
292 | #ifdef DEBUG |
293 | if (tracefile == NULL) | |
294 | return; | |
295 | putc(c, tracefile); | |
296 | if (c == '\n') | |
297 | fflush(tracefile); | |
298 | #endif | |
299 | } | |
300 | ||
13b3e634 CZ |
301 | void |
302 | #if __STDC__ | |
303 | trace(const char *fmt, ...) | |
304 | #else | |
305 | trace(va_alist) | |
306 | va_dcl | |
307 | #endif | |
308 | { | |
a9f0b747 | 309 | #ifdef DEBUG |
13b3e634 CZ |
310 | va_list va; |
311 | #if __STDC__ | |
312 | va_start(va, fmt); | |
313 | #else | |
314 | char *fmt; | |
315 | va_start(va); | |
316 | fmt = va_arg(va, char *); | |
317 | #endif | |
318 | if (tracefile != NULL) { | |
319 | (void) vfprintf(tracefile, fmt, va); | |
320 | if (strchr(fmt, '\n')) | |
321 | (void) fflush(tracefile); | |
322 | } | |
323 | va_end(va); | |
a9f0b747 KB |
324 | #endif |
325 | } | |
326 | ||
327 | ||
13b3e634 | 328 | void |
a9f0b747 KB |
329 | trputs(s) |
330 | char *s; | |
13b3e634 | 331 | { |
a9f0b747 KB |
332 | #ifdef DEBUG |
333 | if (tracefile == NULL) | |
334 | return; | |
335 | fputs(s, tracefile); | |
336 | if (strchr(s, '\n')) | |
337 | fflush(tracefile); | |
338 | #endif | |
339 | } | |
340 | ||
341 | ||
13b3e634 | 342 | static void |
a9f0b747 KB |
343 | trstring(s) |
344 | char *s; | |
13b3e634 | 345 | { |
a9f0b747 KB |
346 | register char *p; |
347 | char c; | |
348 | ||
349 | #ifdef DEBUG | |
350 | if (tracefile == NULL) | |
351 | return; | |
352 | putc('"', tracefile); | |
353 | for (p = s ; *p ; p++) { | |
354 | switch (*p) { | |
355 | case '\n': c = 'n'; goto backslash; | |
356 | case '\t': c = 't'; goto backslash; | |
357 | case '\r': c = 'r'; goto backslash; | |
358 | case '"': c = '"'; goto backslash; | |
359 | case '\\': c = '\\'; goto backslash; | |
360 | case CTLESC: c = 'e'; goto backslash; | |
361 | case CTLVAR: c = 'v'; goto backslash; | |
362 | case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; | |
363 | case CTLBACKQ: c = 'q'; goto backslash; | |
364 | case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; | |
365 | backslash: putc('\\', tracefile); | |
366 | putc(c, tracefile); | |
367 | break; | |
368 | default: | |
369 | if (*p >= ' ' && *p <= '~') | |
370 | putc(*p, tracefile); | |
371 | else { | |
372 | putc('\\', tracefile); | |
373 | putc(*p >> 6 & 03, tracefile); | |
374 | putc(*p >> 3 & 07, tracefile); | |
375 | putc(*p & 07, tracefile); | |
376 | } | |
377 | break; | |
378 | } | |
379 | } | |
380 | putc('"', tracefile); | |
381 | #endif | |
382 | } | |
383 | ||
384 | ||
13b3e634 | 385 | void |
a9f0b747 KB |
386 | trargs(ap) |
387 | char **ap; | |
13b3e634 | 388 | { |
a9f0b747 KB |
389 | #ifdef DEBUG |
390 | if (tracefile == NULL) | |
391 | return; | |
392 | while (*ap) { | |
393 | trstring(*ap++); | |
394 | if (*ap) | |
395 | putc(' ', tracefile); | |
396 | else | |
397 | putc('\n', tracefile); | |
398 | } | |
399 | fflush(tracefile); | |
400 | #endif | |
401 | } | |
402 | ||
403 | ||
13b3e634 | 404 | void |
a9f0b747 KB |
405 | opentrace() { |
406 | char s[100]; | |
a9f0b747 | 407 | char *getenv(); |
13b3e634 | 408 | #ifdef O_APPEND |
a9f0b747 | 409 | int flags; |
13b3e634 | 410 | #endif |
a9f0b747 KB |
411 | |
412 | #ifdef DEBUG | |
44c32b7a MT |
413 | if (!debug) |
414 | return; | |
e2bf5c64 | 415 | #ifdef not_this_way |
13b3e634 CZ |
416 | { |
417 | char *p; | |
418 | if ((p = getenv("HOME")) == NULL) { | |
419 | if (geteuid() == 0) | |
420 | p = "/"; | |
421 | else | |
422 | p = "/tmp"; | |
423 | } | |
424 | scopy(p, s); | |
425 | strcat(s, "/trace"); | |
44c32b7a | 426 | } |
e2bf5c64 MT |
427 | #else |
428 | scopy("./trace", s); | |
429 | #endif /* not_this_way */ | |
a9f0b747 KB |
430 | if ((tracefile = fopen(s, "a")) == NULL) { |
431 | fprintf(stderr, "Can't open %s\n", s); | |
44c32b7a | 432 | return; |
a9f0b747 KB |
433 | } |
434 | #ifdef O_APPEND | |
435 | if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) | |
436 | fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); | |
437 | #endif | |
438 | fputs("\nTracing started.\n", tracefile); | |
439 | fflush(tracefile); | |
e2bf5c64 | 440 | #endif /* DEBUG */ |
a9f0b747 | 441 | } |