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