show.c revision 99110
150477Speter/*-
233548Sjkh * Copyright (c) 1991, 1993
32893Sdfr *	The Regents of the University of California.  All rights reserved.
42893Sdfr *
533548Sjkh * This code is derived from software contributed to Berkeley by
633548Sjkh * Kenneth Almquist.
72893Sdfr *
82893Sdfr * Redistribution and use in source and binary forms, with or without
92893Sdfr * modification, are permitted provided that the following conditions
102893Sdfr * are met:
112893Sdfr * 1. Redistributions of source code must retain the above copyright
122893Sdfr *    notice, this list of conditions and the following disclaimer.
132893Sdfr * 2. Redistributions in binary form must reproduce the above copyright
142893Sdfr *    notice, this list of conditions and the following disclaimer in the
152893Sdfr *    documentation and/or other materials provided with the distribution.
162893Sdfr * 3. All advertising materials mentioning features or use of this software
172893Sdfr *    must display the following acknowledgement:
182893Sdfr *	This product includes software developed by the University of
192893Sdfr *	California, Berkeley and its contributors.
202893Sdfr * 4. Neither the name of the University nor the names of its contributors
212893Sdfr *    may be used to endorse or promote products derived from this software
222893Sdfr *    without specific prior written permission.
232893Sdfr *
242893Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
252893Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
262893Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
272893Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
282893Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
292893Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
302893Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
312893Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
322893Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
332893Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
342893Sdfr * SUCH DAMAGE.
35139776Simp */
362893Sdfr
378876Srgrimes#ifndef lint
382893Sdfr#if 0
392893Sdfrstatic char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
408876Srgrimes#endif
412893Sdfr#endif /* not lint */
428876Srgrimes#include <sys/cdefs.h>
432893Sdfr__FBSDID("$FreeBSD: head/bin/sh/show.c 99110 2002-06-30 05:15:05Z obrien $");
442893Sdfr
452893Sdfr#include <stdio.h>
462893Sdfr#include <stdarg.h>
478876Srgrimes#include <errno.h>
482893Sdfr
492893Sdfr#include "shell.h"
502893Sdfr#include "parser.h"
512893Sdfr#include "nodes.h"
522893Sdfr#include "mystring.h"
53171754Sbde#include "show.h"
5440651Sbde
55177785Skib
56171754Sbde#ifdef DEBUG
57171754Sbdestatic void shtree(union node *, int, char *, FILE*);
58171748Sbdestatic void shcmd(union node *, FILE *);
59171754Sbdestatic void sharg(union node *, FILE *);
60171754Sbdestatic void indent(int, char *, FILE *);
61171748Sbdestatic void trstring(char *);
622893Sdfr
63164033Srwatson
642893Sdfrvoid
65171754Sbdeshowtree(union node *n)
662893Sdfr{
672893Sdfr	trputs("showtree called\n");
68171754Sbde	shtree(n, 1, NULL, stdout);
69171754Sbde}
70171754Sbde
71171754Sbde
7277162Srustatic void
7377162Srushtree(union node *n, int ind, char *pfx, FILE *fp)
7477162Sru{
7577162Sru	struct nodelist *lp;
76171754Sbde	char *s;
772893Sdfr
78204470Skib	if (n == NULL)
79204470Skib		return;
80172757Sbde
81138471Sphk	indent(ind, pfx, fp);
82172798Sbde	switch(n->type) {
83172757Sbde	case NSEMI:
84172757Sbde		s = "; ";
85172757Sbde		goto binop;
86172757Sbde	case NAND:
87172757Sbde		s = " && ";
88138471Sphk		goto binop;
89138471Sphk	case NOR:
90138471Sphk		s = " || ";
9156674Snyanbinop:
9256674Snyan		shtree(n->nbinary.ch1, ind, NULL, fp);
9356674Snyan	   /*    if (ind < 0) */
9456674Snyan			fputs(s, fp);
9556674Snyan		shtree(n->nbinary.ch2, ind, NULL, fp);
9656674Snyan		break;
9756674Snyan	case NCMD:
9856674Snyan		shcmd(n, fp);
9956674Snyan		if (ind >= 0)
10056674Snyan			putc('\n', fp);
10156674Snyan		break;
102151897Srwatson	case NPIPE:
103151897Srwatson		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
10430309Sphk			shcmd(lp->n, fp);
105171757Sbde			if (lp->next)
106120492Sfjoe				fputs(" | ", fp);
107138471Sphk		}
108183754Sattilio		if (n->npipe.backgnd)
109170188Strhodes			fputs(" &", fp);
110138471Sphk		if (ind >= 0)
111101777Sphk			putc('\n', fp);
112101777Sphk		break;
113101777Sphk	default:
114101777Sphk		fprintf(fp, "<node type %d>", n->type);
11512338Sbde		if (ind >= 0)
116134345Stjr			putc('\n', fp);
117134345Stjr		break;
118134345Stjr	}
11933548Sjkh}
120166558Srodrigc
12133548Sjkh
12233548Sjkh
123138471Sphkstatic void
124138471Sphkshcmd(union node *cmd, FILE *fp)
12533548Sjkh{
126138471Sphk	union node *np;
127138471Sphk	int first;
128138471Sphk	char *s;
129138471Sphk	int dftfd;
130138471Sphk
131138471Sphk	first = 1;
132138471Sphk	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
133138471Sphk		if (! first)
134138471Sphk			putchar(' ');
135138471Sphk		sharg(np, fp);
136138471Sphk		first = 0;
137138471Sphk	}
138138471Sphk	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
139138471Sphk		if (! first)
140138471Sphk			putchar(' ');
141138471Sphk		switch (np->nfile.type) {
142134345Stjr			case NTO:	s = ">";  dftfd = 1; break;
143134345Stjr			case NAPPEND:	s = ">>"; dftfd = 1; break;
144134345Stjr			case NTOFD:	s = ">&"; dftfd = 1; break;
145134345Stjr			case NCLOBBER:	s = ">|"; dftfd = 1; break;
146134345Stjr			case NFROM:	s = "<";  dftfd = 0; break;
147134345Stjr			case NFROMTO:	s = "<>"; dftfd = 0; break;
148134345Stjr			case NFROMFD:	s = "<&"; dftfd = 0; break;
149134345Stjr			default:  	s = "*error*"; dftfd = 0; break;
150134345Stjr		}
151134345Stjr		if (np->nfile.fd != dftfd)
152138471Sphk			fprintf(fp, "%d", np->nfile.fd);
153138471Sphk		fputs(s, fp);
154138471Sphk		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
155138471Sphk			fprintf(fp, "%d", np->ndup.dupfd);
156138471Sphk		} else {
157138471Sphk			sharg(np->nfile.fname, fp);
158138471Sphk		}
159138471Sphk		first = 0;
160138471Sphk	}
161138471Sphk}
162152595Srodrigc
163152595Srodrigc
164138471Sphk
165138471Sphkstatic void
166152595Srodrigcsharg(union node *arg, FILE *fp)
167152595Srodrigc{
168138471Sphk	char *p;
169138471Sphk	struct nodelist *bqlist;
17033548Sjkh	int subtype;
171152610Srodrigc
172152610Srodrigc	if (arg->type != NARG) {
173152610Srodrigc		printf("<node type %d>\n", arg->type);
174138471Sphk		fflush(stdout);
175138471Sphk		abort();
17633548Sjkh	}
17733548Sjkh	bqlist = arg->narg.backquote;
17833548Sjkh	for (p = arg->narg.text ; *p ; p++) {
17933548Sjkh		switch (*p) {
18033548Sjkh		case CTLESC:
18133548Sjkh			putc(*++p, fp);
18233548Sjkh			break;
18333548Sjkh		case CTLVAR:
18433548Sjkh			putc('$', fp);
18533548Sjkh			putc('{', fp);
18633548Sjkh			subtype = *++p;
18733548Sjkh			if (subtype == VSLENGTH)
188144058Sjeff				putc('#', fp);
189191990Sattilio
19033548Sjkh			while (*p != '=')
191171757Sbde				putc(*p++, fp);
192171757Sbde
19333548Sjkh			if (subtype & VSNUL)
19433548Sjkh				putc(':', fp);
19533548Sjkh
19633548Sjkh			switch (subtype & VSTYPE) {
19733548Sjkh			case VSNORMAL:
19833548Sjkh				putc('}', fp);
199138471Sphk				break;
200191990Sattilio			case VSMINUS:
201138471Sphk				putc('-', fp);
202138471Sphk				break;
203138471Sphk			case VSPLUS:
204138471Sphk				putc('+', fp);
205138471Sphk				break;
206138471Sphk			case VSQUESTION:
207138471Sphk				putc('?', fp);
208138471Sphk				break;
209138471Sphk			case VSASSIGN:
210138471Sphk				putc('=', fp);
211138471Sphk				break;
212138471Sphk			case VSTRIMLEFT:
213138471Sphk				putc('#', fp);
214138471Sphk				break;
215138471Sphk			case VSTRIMLEFTMAX:
216138471Sphk				putc('#', fp);
217138471Sphk				putc('#', fp);
218171757Sbde				break;
219171757Sbde			case VSTRIMRIGHT:
220171757Sbde				putc('%', fp);
221171757Sbde				break;
222138471Sphk			case VSTRIMRIGHTMAX:
223171757Sbde				putc('%', fp);
224171757Sbde				putc('%', fp);
225171757Sbde				break;
226138471Sphk			case VSLENGTH:
227138471Sphk				break;
228138471Sphk			default:
229138471Sphk				printf("<subtype %d>", subtype);
230138471Sphk			}
231138471Sphk			break;
2322893Sdfr		case CTLENDVAR:
2338876Srgrimes		     putc('}', fp);
2342893Sdfr		     break;
2358876Srgrimes		case CTLBACKQ:
2362893Sdfr		case CTLBACKQ|CTLQUOTE:
23712144Sphk			putc('$', fp);
238191990Sattilio			putc('(', fp);
2392893Sdfr			shtree(bqlist->n, -1, NULL, fp);
2402893Sdfr			putc(')', fp);
241191990Sattilio			break;
24233548Sjkh		default:
24333548Sjkh			putc(*p, fp);
244132902Sphk			break;
245138689Sphk		}
246184413Strasz	}
247138471Sphk}
2482893Sdfr
249191990Sattilio
250138471Sphkstatic void
251138471Sphkindent(int amount, char *pfx, FILE *fp)
252138471Sphk{
2532893Sdfr	int i;
25433548Sjkh
25533548Sjkh	for (i = 0 ; i < amount ; i++) {
2562893Sdfr		if (pfx && i == amount - 1)
2572893Sdfr			fputs(pfx, fp);
25833548Sjkh		putc('\t', fp);
259158924Srodrigc	}
260165022Srodrigc}
261165022Srodrigc
262165022Srodrigc
263165022Srodrigc/*
264165022Srodrigc * Debugging stuff.
265165022Srodrigc */
266165022Srodrigc
267138689Sphk
268165022SrodrigcFILE *tracefile;
269138689Sphk
270137036Sphk#if DEBUG == 2
271138471Sphkint debug = 1;
272191990Sattilio#else
273133287Sphkint debug = 0;
274133287Sphk#endif
2752893Sdfr
2762893Sdfr
2772893Sdfrvoid
278132023Salfredtrputc(int c)
279138471Sphk{
280138471Sphk	if (tracefile == NULL)
281172883Sdelphij		return;
282172883Sdelphij	putc(c, tracefile);
283172883Sdelphij	if (c == '\n')
284172883Sdelphij		fflush(tracefile);
285172883Sdelphij}
286172883Sdelphij
287172883Sdelphij
288172883Sdelphijvoid
289172883Sdelphijsh_trace(const char *fmt, ...)
290172883Sdelphij{
291172883Sdelphij	va_list va;
292172883Sdelphij	va_start(va, fmt);
293137036Sphk	if (tracefile != NULL) {
294137036Sphk		(void) vfprintf(tracefile, fmt, va);
295171551Sbde		if (strchr(fmt, '\n'))
296137036Sphk			(void) fflush(tracefile);
297137036Sphk	}
298172883Sdelphij	va_end(va);
299172883Sdelphij}
300171551Sbde
301172883Sdelphij
302171551Sbdevoid
303172883Sdelphijtrputs(char *s)
304172883Sdelphij{
305172883Sdelphij	if (tracefile == NULL)
306172883Sdelphij		return;
307172883Sdelphij	fputs(s, tracefile);
308172883Sdelphij	if (strchr(s, '\n'))
309172883Sdelphij		fflush(tracefile);
310172883Sdelphij}
311172883Sdelphij
312138471Sphk
313138471Sphkstatic void
31433548Sjkhtrstring(char *s)
31533548Sjkh{
31633548Sjkh	char *p;
31733548Sjkh	char c;
318164033Srwatson
319175202Sattilio	if (tracefile == NULL)
320164033Srwatson		return;
321171757Sbde	putc('"', tracefile);
322164033Srwatson	for (p = s ; *p ; p++) {
323164033Srwatson		switch (*p) {
324164033Srwatson		case '\n':  c = 'n';  goto backslash;
325175294Sattilio		case '\t':  c = 't';  goto backslash;
326164033Srwatson		case '\r':  c = 'r';  goto backslash;
32733548Sjkh		case '"':  c = '"';  goto backslash;
328175294Sattilio		case '\\':  c = '\\';  goto backslash;
329137036Sphk		case CTLESC:  c = 'e';  goto backslash;
330137036Sphk		case CTLVAR:  c = 'v';  goto backslash;
331137036Sphk		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
332137036Sphk		case CTLBACKQ:  c = 'q';  goto backslash;
333137036Sphk		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
334137036Sphkbackslash:	  putc('\\', tracefile);
335137036Sphk			putc(c, tracefile);
336123963Sbde			break;
337172883Sdelphij		default:
338172883Sdelphij			if (*p >= ' ' && *p <= '~')
339172883Sdelphij				putc(*p, tracefile);
340172883Sdelphij			else {
341172883Sdelphij				putc('\\', tracefile);
342165836Srodrigc				putc(*p >> 6 & 03, tracefile);
343123963Sbde				putc(*p >> 3 & 07, tracefile);
344123873Strhodes				putc(*p & 07, tracefile);
345123873Strhodes			}
346172883Sdelphij			break;
34733548Sjkh		}
3482893Sdfr	}
3492893Sdfr	putc('"', tracefile);
35033548Sjkh}
351125796Sbde
3522893Sdfr
353138471Sphkvoid
354138471Sphktrargs(char **ap)
355149720Sssouhlal{
356132902Sphk	if (tracefile == NULL)
35733548Sjkh		return;
35833548Sjkh	while (*ap) {
359132902Sphk		trstring(*ap++);
360132902Sphk		if (*ap)
3618876Srgrimes			putc(' ', tracefile);
36255756Sphk		else
363149720Sssouhlal			putc('\n', tracefile);
36455756Sphk	}
3652893Sdfr	fflush(tracefile);
3662893Sdfr}
36733548Sjkh
36833548Sjkh
3692893Sdfrvoid
370184413Straszopentrace(void)
371164033Srwatson{
372184413Strasz	char s[100];
373184413Strasz	char *getenv();
374164033Srwatson#ifdef O_APPEND
375164033Srwatson	int flags;
376164033Srwatson#endif
377164033Srwatson
378164033Srwatson	if (!debug)
37933548Sjkh		return;
38033548Sjkh#ifdef not_this_way
381183754Sattilio	{
38233548Sjkh		char *p;
38333548Sjkh		if ((p = getenv("HOME")) == NULL) {
38433548Sjkh			if (geteuid() == 0)
38533548Sjkh				p = "/";
386204589Skib			else
3872893Sdfr				p = "/tmp";
388204589Skib		}
3892893Sdfr		scopy(p, s);
3902893Sdfr		strcat(s, "/trace");
3912893Sdfr	}
39233548Sjkh#else
39333548Sjkh	scopy("./trace", s);
39433548Sjkh#endif /* not_this_way */
395138471Sphk	if ((tracefile = fopen(s, "a")) == NULL) {
39633548Sjkh		fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
397134345Stjr		return;
398191990Sattilio	}
3992893Sdfr#ifdef O_APPEND
4002893Sdfr	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
401171757Sbde		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
402138471Sphk#endif
4032893Sdfr	fputs("\nTracing started.\n", tracefile);
404138471Sphk	fflush(tracefile);
4052893Sdfr}
40633548Sjkh#endif /* DEBUG */
4072893Sdfr