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