show.c revision 1.15 1 /* $NetBSD: show.c,v 1.15 1997/07/04 21:02:22 christos 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.15 1997/07/04 21:02:22 christos 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 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 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 default: s = "*error*"; dftfd = 0; break;
161 }
162 if (np->nfile.fd != dftfd)
163 fprintf(fp, "%d", np->nfile.fd);
164 fputs(s, fp);
165 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
166 fprintf(fp, "%d", np->ndup.dupfd);
167 } else {
168 sharg(np->nfile.fname, fp);
169 }
170 first = 0;
171 }
172 }
173
174
175
176 static void
177 sharg(arg, fp)
178 union node *arg;
179 FILE *fp;
180 {
181 char *p;
182 struct nodelist *bqlist;
183 int subtype;
184
185 if (arg->type != NARG) {
186 printf("<node type %d>\n", arg->type);
187 fflush(stdout);
188 abort();
189 }
190 bqlist = arg->narg.backquote;
191 for (p = arg->narg.text ; *p ; p++) {
192 switch (*p) {
193 case CTLESC:
194 putc(*++p, fp);
195 break;
196 case CTLVAR:
197 putc('$', fp);
198 putc('{', fp);
199 subtype = *++p;
200 if (subtype == VSLENGTH)
201 putc('#', fp);
202
203 while (*p != '=')
204 putc(*p++, fp);
205
206 if (subtype & VSNUL)
207 putc(':', fp);
208
209 switch (subtype & VSTYPE) {
210 case VSNORMAL:
211 putc('}', fp);
212 break;
213 case VSMINUS:
214 putc('-', fp);
215 break;
216 case VSPLUS:
217 putc('+', fp);
218 break;
219 case VSQUESTION:
220 putc('?', fp);
221 break;
222 case VSASSIGN:
223 putc('=', fp);
224 break;
225 case VSTRIMLEFT:
226 putc('#', fp);
227 break;
228 case VSTRIMLEFTMAX:
229 putc('#', fp);
230 putc('#', fp);
231 break;
232 case VSTRIMRIGHT:
233 putc('%', fp);
234 break;
235 case VSTRIMRIGHTMAX:
236 putc('%', fp);
237 putc('%', fp);
238 break;
239 case VSLENGTH:
240 break;
241 default:
242 printf("<subtype %d>", subtype);
243 }
244 break;
245 case CTLENDVAR:
246 putc('}', fp);
247 break;
248 case CTLBACKQ:
249 case CTLBACKQ|CTLQUOTE:
250 putc('$', fp);
251 putc('(', fp);
252 shtree(bqlist->n, -1, NULL, fp);
253 putc(')', fp);
254 break;
255 default:
256 putc(*p, fp);
257 break;
258 }
259 }
260 }
261
262
263 static void
264 indent(amount, pfx, fp)
265 int amount;
266 char *pfx;
267 FILE *fp;
268 {
269 int i;
270
271 for (i = 0 ; i < amount ; i++) {
272 if (pfx && i == amount - 1)
273 fputs(pfx, fp);
274 putc('\t', fp);
275 }
276 }
277 #endif
278
279
280
281 /*
282 * Debugging stuff.
283 */
284
285
286 FILE *tracefile;
287
288 #if DEBUG == 2
289 int debug = 1;
290 #else
291 int debug = 0;
292 #endif
293
294
295 #ifdef DEBUG
296 void
297 trputc(c)
298 int c;
299 {
300 if (tracefile == NULL)
301 return;
302 putc(c, tracefile);
303 if (c == '\n')
304 fflush(tracefile);
305 }
306 #endif
307
308 void
309 #ifdef __STDC__
310 trace(const char *fmt, ...)
311 #else
312 trace(va_alist)
313 va_dcl
314 #endif
315 {
316 #ifdef DEBUG
317 va_list va;
318 #ifdef __STDC__
319 va_start(va, fmt);
320 #else
321 char *fmt;
322 va_start(va);
323 fmt = va_arg(va, char *);
324 #endif
325 if (tracefile != NULL) {
326 (void) vfprintf(tracefile, fmt, va);
327 if (strchr(fmt, '\n'))
328 (void) fflush(tracefile);
329 }
330 va_end(va);
331 #endif
332 }
333
334
335 #ifdef DEBUG
336 void
337 trputs(s)
338 char *s;
339 {
340 if (tracefile == NULL)
341 return;
342 fputs(s, tracefile);
343 if (strchr(s, '\n'))
344 fflush(tracefile);
345 }
346
347
348 static void
349 trstring(s)
350 char *s;
351 {
352 char *p;
353 char c;
354
355 if (tracefile == NULL)
356 return;
357 putc('"', tracefile);
358 for (p = s ; *p ; p++) {
359 switch (*p) {
360 case '\n': c = 'n'; goto backslash;
361 case '\t': c = 't'; goto backslash;
362 case '\r': c = 'r'; goto backslash;
363 case '"': c = '"'; goto backslash;
364 case '\\': c = '\\'; goto backslash;
365 case CTLESC: c = 'e'; goto backslash;
366 case CTLVAR: c = 'v'; goto backslash;
367 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
368 case CTLBACKQ: c = 'q'; goto backslash;
369 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
370 backslash: putc('\\', tracefile);
371 putc(c, tracefile);
372 break;
373 default:
374 if (*p >= ' ' && *p <= '~')
375 putc(*p, tracefile);
376 else {
377 putc('\\', tracefile);
378 putc(*p >> 6 & 03, tracefile);
379 putc(*p >> 3 & 07, tracefile);
380 putc(*p & 07, tracefile);
381 }
382 break;
383 }
384 }
385 putc('"', tracefile);
386 }
387 #endif
388
389
390 void
391 trargs(ap)
392 char **ap;
393 {
394 #ifdef DEBUG
395 if (tracefile == NULL)
396 return;
397 while (*ap) {
398 trstring(*ap++);
399 if (*ap)
400 putc(' ', tracefile);
401 else
402 putc('\n', tracefile);
403 }
404 fflush(tracefile);
405 #endif
406 }
407
408
409 #ifdef DEBUG
410 void
411 opentrace() {
412 char s[100];
413 char *getenv();
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