show.c revision 1.22 1 /* $NetBSD: show.c,v 1.22 2002/05/25 23:09:06 wiz 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.22 2002/05/25 23:09:06 wiz Exp $");
45 #endif
46 #endif /* not lint */
47
48 #include <stdio.h>
49 #include <stdarg.h>
50
51 #include "shell.h"
52 #include "parser.h"
53 #include "nodes.h"
54 #include "mystring.h"
55 #include "show.h"
56
57
58 #ifdef DEBUG
59 static void shtree __P((union node *, int, char *, FILE*));
60 static void shcmd __P((union node *, FILE *));
61 static void sharg __P((union node *, FILE *));
62 static void indent __P((int, char *, FILE *));
63 static void trstring __P((char *));
64
65
66 void
67 showtree(n)
68 union node *n;
69 {
70 trputs("showtree called\n");
71 shtree(n, 1, NULL, stdout);
72 }
73
74
75 static void
76 shtree(n, ind, pfx, fp)
77 union node *n;
78 int ind;
79 char *pfx;
80 FILE *fp;
81 {
82 struct nodelist *lp;
83 const char *s;
84
85 if (n == NULL)
86 return;
87
88 indent(ind, pfx, fp);
89 switch(n->type) {
90 case NSEMI:
91 s = "; ";
92 goto binop;
93 case NAND:
94 s = " && ";
95 goto binop;
96 case NOR:
97 s = " || ";
98 binop:
99 shtree(n->nbinary.ch1, ind, NULL, fp);
100 /* if (ind < 0) */
101 fputs(s, fp);
102 shtree(n->nbinary.ch2, ind, NULL, fp);
103 break;
104 case NCMD:
105 shcmd(n, fp);
106 if (ind >= 0)
107 putc('\n', fp);
108 break;
109 case NPIPE:
110 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
111 shcmd(lp->n, fp);
112 if (lp->next)
113 fputs(" | ", fp);
114 }
115 if (n->npipe.backgnd)
116 fputs(" &", fp);
117 if (ind >= 0)
118 putc('\n', fp);
119 break;
120 default:
121 fprintf(fp, "<node type %d>", n->type);
122 if (ind >= 0)
123 putc('\n', fp);
124 break;
125 }
126 }
127
128
129
130 static void
131 shcmd(cmd, fp)
132 union node *cmd;
133 FILE *fp;
134 {
135 union node *np;
136 int first;
137 const char *s;
138 int dftfd;
139
140 first = 1;
141 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
142 if (! first)
143 putchar(' ');
144 sharg(np, fp);
145 first = 0;
146 }
147 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
148 if (! first)
149 putchar(' ');
150 switch (np->nfile.type) {
151 case NTO: s = ">"; dftfd = 1; break;
152 case NCLOBBER: s = ">|"; dftfd = 1; break;
153 case NAPPEND: s = ">>"; dftfd = 1; break;
154 case NTOFD: s = ">&"; dftfd = 1; break;
155 case NFROM: s = "<"; dftfd = 0; break;
156 case NFROMFD: s = "<&"; dftfd = 0; break;
157 case NFROMTO: s = "<>"; dftfd = 0; break;
158 default: s = "*error*"; dftfd = 0; break;
159 }
160 if (np->nfile.fd != dftfd)
161 fprintf(fp, "%d", np->nfile.fd);
162 fputs(s, fp);
163 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
164 fprintf(fp, "%d", np->ndup.dupfd);
165 } else {
166 sharg(np->nfile.fname, fp);
167 }
168 first = 0;
169 }
170 }
171
172
173
174 static void
175 sharg(arg, fp)
176 union node *arg;
177 FILE *fp;
178 {
179 char *p;
180 struct nodelist *bqlist;
181 int subtype;
182
183 if (arg->type != NARG) {
184 printf("<node type %d>\n", arg->type);
185 fflush(stdout);
186 abort();
187 }
188 bqlist = arg->narg.backquote;
189 for (p = arg->narg.text ; *p ; p++) {
190 switch (*p) {
191 case CTLESC:
192 putc(*++p, fp);
193 break;
194 case CTLVAR:
195 putc('$', fp);
196 putc('{', fp);
197 subtype = *++p;
198 if (subtype == VSLENGTH)
199 putc('#', fp);
200
201 while (*p != '=')
202 putc(*p++, fp);
203
204 if (subtype & VSNUL)
205 putc(':', fp);
206
207 switch (subtype & VSTYPE) {
208 case VSNORMAL:
209 putc('}', fp);
210 break;
211 case VSMINUS:
212 putc('-', fp);
213 break;
214 case VSPLUS:
215 putc('+', fp);
216 break;
217 case VSQUESTION:
218 putc('?', fp);
219 break;
220 case VSASSIGN:
221 putc('=', fp);
222 break;
223 case VSTRIMLEFT:
224 putc('#', fp);
225 break;
226 case VSTRIMLEFTMAX:
227 putc('#', fp);
228 putc('#', fp);
229 break;
230 case VSTRIMRIGHT:
231 putc('%', fp);
232 break;
233 case VSTRIMRIGHTMAX:
234 putc('%', fp);
235 putc('%', fp);
236 break;
237 case VSLENGTH:
238 break;
239 default:
240 printf("<subtype %d>", subtype);
241 }
242 break;
243 case CTLENDVAR:
244 putc('}', fp);
245 break;
246 case CTLBACKQ:
247 case CTLBACKQ|CTLQUOTE:
248 putc('$', fp);
249 putc('(', fp);
250 shtree(bqlist->n, -1, NULL, fp);
251 putc(')', fp);
252 break;
253 default:
254 putc(*p, fp);
255 break;
256 }
257 }
258 }
259
260
261 static void
262 indent(amount, pfx, fp)
263 int amount;
264 char *pfx;
265 FILE *fp;
266 {
267 int i;
268
269 for (i = 0 ; i < amount ; i++) {
270 if (pfx && i == amount - 1)
271 fputs(pfx, fp);
272 putc('\t', fp);
273 }
274 }
275 #endif
276
277
278
279 /*
280 * Debugging stuff.
281 */
282
283
284 FILE *tracefile;
285
286 #if DEBUG == 2
287 int debug = 1;
288 #else
289 int debug = 0;
290 #endif
291
292
293 #ifdef DEBUG
294 void
295 trputc(c)
296 int c;
297 {
298 if (tracefile == NULL)
299 return;
300 putc(c, tracefile);
301 if (c == '\n')
302 fflush(tracefile);
303 }
304 #endif
305
306 void
307 trace(const char *fmt, ...)
308 {
309 #ifdef DEBUG
310 va_list va;
311
312 va_start(va, fmt);
313 if (tracefile != NULL) {
314 (void) vfprintf(tracefile, fmt, va);
315 if (strchr(fmt, '\n'))
316 (void) fflush(tracefile);
317 }
318 va_end(va);
319 #endif
320 }
321
322
323 #ifdef DEBUG
324 void
325 trputs(s)
326 const char *s;
327 {
328 if (tracefile == NULL)
329 return;
330 fputs(s, tracefile);
331 if (strchr(s, '\n'))
332 fflush(tracefile);
333 }
334
335
336 static void
337 trstring(s)
338 char *s;
339 {
340 char *p;
341 char c;
342
343 if (tracefile == NULL)
344 return;
345 putc('"', tracefile);
346 for (p = s ; *p ; p++) {
347 switch (*p) {
348 case '\n': c = 'n'; goto backslash;
349 case '\t': c = 't'; goto backslash;
350 case '\r': c = 'r'; goto backslash;
351 case '"': c = '"'; goto backslash;
352 case '\\': c = '\\'; goto backslash;
353 case CTLESC: c = 'e'; goto backslash;
354 case CTLVAR: c = 'v'; goto backslash;
355 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
356 case CTLBACKQ: c = 'q'; goto backslash;
357 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
358 backslash: putc('\\', tracefile);
359 putc(c, tracefile);
360 break;
361 default:
362 if (*p >= ' ' && *p <= '~')
363 putc(*p, tracefile);
364 else {
365 putc('\\', tracefile);
366 putc(*p >> 6 & 03, tracefile);
367 putc(*p >> 3 & 07, tracefile);
368 putc(*p & 07, tracefile);
369 }
370 break;
371 }
372 }
373 putc('"', tracefile);
374 }
375 #endif
376
377
378 void
379 trargs(ap)
380 char **ap;
381 {
382 #ifdef DEBUG
383 if (tracefile == NULL)
384 return;
385 while (*ap) {
386 trstring(*ap++);
387 if (*ap)
388 putc(' ', tracefile);
389 else
390 putc('\n', tracefile);
391 }
392 fflush(tracefile);
393 #endif
394 }
395
396
397 #ifdef DEBUG
398 void
399 opentrace() {
400 char s[100];
401 #ifdef O_APPEND
402 int flags;
403 #endif
404
405 if (!debug)
406 return;
407 #ifdef not_this_way
408 {
409 char *p;
410 if ((p = getenv("HOME")) == NULL) {
411 if (geteuid() == 0)
412 p = "/";
413 else
414 p = "/tmp";
415 }
416 scopy(p, s);
417 strcat(s, "/trace");
418 }
419 #else
420 scopy("./trace", s);
421 #endif /* not_this_way */
422 if ((tracefile = fopen(s, "a")) == NULL) {
423 fprintf(stderr, "Can't open %s\n", s);
424 return;
425 }
426 #ifdef O_APPEND
427 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
428 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
429 #endif
430 fputs("\nTracing started.\n", tracefile);
431 fflush(tracefile);
432 }
433 #endif /* DEBUG */
434