show.c revision 104141
1243730Srwatson/*-
2243730Srwatson * Copyright (c) 1991, 1993
3243730Srwatson *	The Regents of the University of California.  All rights reserved.
4243730Srwatson *
5243730Srwatson * This code is derived from software contributed to Berkeley by
6243730Srwatson * Kenneth Almquist.
7243730Srwatson *
8243730Srwatson * Redistribution and use in source and binary forms, with or without
9243730Srwatson * modification, are permitted provided that the following conditions
10243730Srwatson * are met:
11243730Srwatson * 1. Redistributions of source code must retain the above copyright
12243730Srwatson *    notice, this list of conditions and the following disclaimer.
13243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright
14243730Srwatson *    notice, this list of conditions and the following disclaimer in the
15243730Srwatson *    documentation and/or other materials provided with the distribution.
16243730Srwatson * 3. All advertising materials mentioning features or use of this software
17243730Srwatson *    must display the following acknowledgement:
18243730Srwatson *	This product includes software developed by the University of
19243730Srwatson *	California, Berkeley and its contributors.
20243730Srwatson * 4. Neither the name of the University nor the names of its contributors
21243730Srwatson *    may be used to endorse or promote products derived from this software
22243730Srwatson *    without specific prior written permission.
23243730Srwatson *
24243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27243730Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29243734Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34243730Srwatson * SUCH DAMAGE.
35243730Srwatson */
36243730Srwatson
37243730Srwatson#ifndef lint
38243730Srwatson#if 0
39243730Srwatsonstatic char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
40243730Srwatson#endif
41243730Srwatson#endif /* not lint */
42243730Srwatson#include <sys/cdefs.h>
43243734Srwatson__FBSDID("$FreeBSD: head/bin/sh/show.c 104141 2002-09-29 12:38:25Z tjr $");
44243730Srwatson
45243730Srwatson#include <stdio.h>
46243730Srwatson#include <stdarg.h>
47243730Srwatson#include <errno.h>
48243730Srwatson
49243730Srwatson#include "shell.h"
50243730Srwatson#include "parser.h"
51243730Srwatson#include "nodes.h"
52243730Srwatson#include "mystring.h"
53243730Srwatson#include "show.h"
54243730Srwatson
55243730Srwatson
56243730Srwatson#ifdef DEBUG
57243730Srwatsonstatic void shtree(union node *, int, char *, FILE*);
58243730Srwatsonstatic void shcmd(union node *, FILE *);
59243730Srwatsonstatic void sharg(union node *, FILE *);
60243730Srwatsonstatic void indent(int, char *, FILE *);
61243730Srwatsonstatic void trstring(char *);
62243730Srwatson
63243730Srwatson
64243730Srwatsonvoid
65243730Srwatsonshowtree(union node *n)
66243730Srwatson{
67243730Srwatson	trputs("showtree called\n");
68243730Srwatson	shtree(n, 1, NULL, stdout);
69243730Srwatson}
70243730Srwatson
71243730Srwatson
72243730Srwatsonstatic void
73243730Srwatsonshtree(union node *n, int ind, char *pfx, FILE *fp)
74243730Srwatson{
75243730Srwatson	struct nodelist *lp;
76243730Srwatson	char *s;
77243730Srwatson
78243730Srwatson	if (n == NULL)
79243730Srwatson		return;
80243730Srwatson
81243730Srwatson	indent(ind, pfx, fp);
82243730Srwatson	switch(n->type) {
83243730Srwatson	case NSEMI:
84243730Srwatson		s = "; ";
85243730Srwatson		goto binop;
86243730Srwatson	case NAND:
87243730Srwatson		s = " && ";
88243730Srwatson		goto binop;
89243730Srwatson	case NOR:
90243730Srwatson		s = " || ";
91243730Srwatsonbinop:
92243730Srwatson		shtree(n->nbinary.ch1, ind, NULL, fp);
93243730Srwatson	   /*    if (ind < 0) */
94243730Srwatson			fputs(s, fp);
95243730Srwatson		shtree(n->nbinary.ch2, ind, NULL, fp);
96243730Srwatson		break;
97243730Srwatson	case NCMD:
98243730Srwatson		shcmd(n, fp);
99243730Srwatson		if (ind >= 0)
100243730Srwatson			putc('\n', fp);
101243730Srwatson		break;
102243730Srwatson	case NPIPE:
103243730Srwatson		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
104243730Srwatson			shcmd(lp->n, fp);
105243730Srwatson			if (lp->next)
106243730Srwatson				fputs(" | ", fp);
107243730Srwatson		}
108243730Srwatson		if (n->npipe.backgnd)
109243730Srwatson			fputs(" &", fp);
110243730Srwatson		if (ind >= 0)
111243730Srwatson			putc('\n', fp);
112243730Srwatson		break;
113243730Srwatson	default:
114243730Srwatson		fprintf(fp, "<node type %d>", n->type);
115243730Srwatson		if (ind >= 0)
116243730Srwatson			putc('\n', fp);
117243730Srwatson		break;
118243730Srwatson	}
119243730Srwatson}
120243730Srwatson
121243730Srwatson
122243730Srwatson
123243730Srwatsonstatic void
124243730Srwatsonshcmd(union node *cmd, FILE *fp)
125243730Srwatson{
126243730Srwatson	union node *np;
127243730Srwatson	int first;
128243730Srwatson	char *s;
129243730Srwatson	int dftfd;
130243730Srwatson
131243730Srwatson	first = 1;
132243730Srwatson	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
133243730Srwatson		if (! first)
134243730Srwatson			putchar(' ');
135243730Srwatson		sharg(np, fp);
136243730Srwatson		first = 0;
137243730Srwatson	}
138243730Srwatson	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
139243730Srwatson		if (! first)
140243730Srwatson			putchar(' ');
141243730Srwatson		switch (np->nfile.type) {
142243730Srwatson			case NTO:	s = ">";  dftfd = 1; break;
143243730Srwatson			case NAPPEND:	s = ">>"; dftfd = 1; break;
144243730Srwatson			case NTOFD:	s = ">&"; dftfd = 1; break;
145243730Srwatson			case NCLOBBER:	s = ">|"; dftfd = 1; break;
146243730Srwatson			case NFROM:	s = "<";  dftfd = 0; break;
147243730Srwatson			case NFROMTO:	s = "<>"; dftfd = 0; break;
148243730Srwatson			case NFROMFD:	s = "<&"; dftfd = 0; break;
149243730Srwatson			default:  	s = "*error*"; dftfd = 0; break;
150243730Srwatson		}
151243730Srwatson		if (np->nfile.fd != dftfd)
152243730Srwatson			fprintf(fp, "%d", np->nfile.fd);
153243730Srwatson		fputs(s, fp);
154243730Srwatson		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
155243730Srwatson			if (np->ndup.dupfd >= 0)
156243730Srwatson				fprintf(fp, "%d", np->ndup.dupfd);
157243730Srwatson			else
158243730Srwatson				fprintf(fp, "-");
159243730Srwatson		} else {
160243730Srwatson			sharg(np->nfile.fname, fp);
161243730Srwatson		}
162243730Srwatson		first = 0;
163243730Srwatson	}
164243730Srwatson}
165243730Srwatson
166243730Srwatson
167243730Srwatson
168243730Srwatsonstatic void
169243730Srwatsonsharg(union node *arg, FILE *fp)
170243730Srwatson{
171243730Srwatson	char *p;
172243730Srwatson	struct nodelist *bqlist;
173243730Srwatson	int subtype;
174243730Srwatson
175243730Srwatson	if (arg->type != NARG) {
176243730Srwatson		printf("<node type %d>\n", arg->type);
177243730Srwatson		fflush(stdout);
178243730Srwatson		abort();
179243730Srwatson	}
180243730Srwatson	bqlist = arg->narg.backquote;
181243730Srwatson	for (p = arg->narg.text ; *p ; p++) {
182243730Srwatson		switch (*p) {
183243730Srwatson		case CTLESC:
184243730Srwatson			putc(*++p, fp);
185243730Srwatson			break;
186243730Srwatson		case CTLVAR:
187243730Srwatson			putc('$', fp);
188243730Srwatson			putc('{', fp);
189243730Srwatson			subtype = *++p;
190243730Srwatson			if (subtype == VSLENGTH)
191243730Srwatson				putc('#', fp);
192243730Srwatson
193243730Srwatson			while (*p != '=')
194243730Srwatson				putc(*p++, fp);
195243730Srwatson
196243730Srwatson			if (subtype & VSNUL)
197243730Srwatson				putc(':', fp);
198243730Srwatson
199243730Srwatson			switch (subtype & VSTYPE) {
200243730Srwatson			case VSNORMAL:
201243730Srwatson				putc('}', fp);
202243730Srwatson				break;
203243730Srwatson			case VSMINUS:
204243730Srwatson				putc('-', fp);
205243730Srwatson				break;
206243730Srwatson			case VSPLUS:
207				putc('+', fp);
208				break;
209			case VSQUESTION:
210				putc('?', fp);
211				break;
212			case VSASSIGN:
213				putc('=', fp);
214				break;
215			case VSTRIMLEFT:
216				putc('#', fp);
217				break;
218			case VSTRIMLEFTMAX:
219				putc('#', fp);
220				putc('#', fp);
221				break;
222			case VSTRIMRIGHT:
223				putc('%', fp);
224				break;
225			case VSTRIMRIGHTMAX:
226				putc('%', fp);
227				putc('%', fp);
228				break;
229			case VSLENGTH:
230				break;
231			default:
232				printf("<subtype %d>", subtype);
233			}
234			break;
235		case CTLENDVAR:
236		     putc('}', fp);
237		     break;
238		case CTLBACKQ:
239		case CTLBACKQ|CTLQUOTE:
240			putc('$', fp);
241			putc('(', fp);
242			shtree(bqlist->n, -1, NULL, fp);
243			putc(')', fp);
244			break;
245		default:
246			putc(*p, fp);
247			break;
248		}
249	}
250}
251
252
253static void
254indent(int amount, char *pfx, FILE *fp)
255{
256	int i;
257
258	for (i = 0 ; i < amount ; i++) {
259		if (pfx && i == amount - 1)
260			fputs(pfx, fp);
261		putc('\t', fp);
262	}
263}
264
265
266/*
267 * Debugging stuff.
268 */
269
270
271FILE *tracefile;
272
273#if DEBUG == 2
274int debug = 1;
275#else
276int debug = 0;
277#endif
278
279
280void
281trputc(int c)
282{
283	if (tracefile == NULL)
284		return;
285	putc(c, tracefile);
286	if (c == '\n')
287		fflush(tracefile);
288}
289
290
291void
292sh_trace(const char *fmt, ...)
293{
294	va_list va;
295	va_start(va, fmt);
296	if (tracefile != NULL) {
297		(void) vfprintf(tracefile, fmt, va);
298		if (strchr(fmt, '\n'))
299			(void) fflush(tracefile);
300	}
301	va_end(va);
302}
303
304
305void
306trputs(char *s)
307{
308	if (tracefile == NULL)
309		return;
310	fputs(s, tracefile);
311	if (strchr(s, '\n'))
312		fflush(tracefile);
313}
314
315
316static void
317trstring(char *s)
318{
319	char *p;
320	char c;
321
322	if (tracefile == NULL)
323		return;
324	putc('"', tracefile);
325	for (p = s ; *p ; p++) {
326		switch (*p) {
327		case '\n':  c = 'n';  goto backslash;
328		case '\t':  c = 't';  goto backslash;
329		case '\r':  c = 'r';  goto backslash;
330		case '"':  c = '"';  goto backslash;
331		case '\\':  c = '\\';  goto backslash;
332		case CTLESC:  c = 'e';  goto backslash;
333		case CTLVAR:  c = 'v';  goto backslash;
334		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
335		case CTLBACKQ:  c = 'q';  goto backslash;
336		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
337backslash:	  putc('\\', tracefile);
338			putc(c, tracefile);
339			break;
340		default:
341			if (*p >= ' ' && *p <= '~')
342				putc(*p, tracefile);
343			else {
344				putc('\\', tracefile);
345				putc(*p >> 6 & 03, tracefile);
346				putc(*p >> 3 & 07, tracefile);
347				putc(*p & 07, tracefile);
348			}
349			break;
350		}
351	}
352	putc('"', tracefile);
353}
354
355
356void
357trargs(char **ap)
358{
359	if (tracefile == NULL)
360		return;
361	while (*ap) {
362		trstring(*ap++);
363		if (*ap)
364			putc(' ', tracefile);
365		else
366			putc('\n', tracefile);
367	}
368	fflush(tracefile);
369}
370
371
372void
373opentrace(void)
374{
375	char s[100];
376	char *getenv();
377	int flags;
378
379	if (!debug)
380		return;
381#ifdef not_this_way
382	{
383		char *p;
384		if ((p = getenv("HOME")) == NULL) {
385			if (geteuid() == 0)
386				p = "/";
387			else
388				p = "/tmp";
389		}
390		scopy(p, s);
391		strcat(s, "/trace");
392	}
393#else
394	scopy("./trace", s);
395#endif /* not_this_way */
396	if ((tracefile = fopen(s, "a")) == NULL) {
397		fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
398		return;
399	}
400	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
401		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
402	fputs("\nTracing started.\n", tracefile);
403	fflush(tracefile);
404}
405#endif /* DEBUG */
406