show.c revision 18018
1139825Simp/*-
21541Srgrimes * Copyright (c) 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software contributed to Berkeley by
61541Srgrimes * Kenneth Almquist.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes * 1. Redistributions of source code must retain the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer.
131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer in the
151541Srgrimes *    documentation and/or other materials provided with the distribution.
161541Srgrimes * 3. All advertising materials mentioning features or use of this software
171541Srgrimes *    must display the following acknowledgement:
181541Srgrimes *	This product includes software developed by the University of
191541Srgrimes *	California, Berkeley and its contributors.
201541Srgrimes * 4. Neither the name of the University nor the names of its contributors
211541Srgrimes *    may be used to endorse or promote products derived from this software
221541Srgrimes *    without specific prior written permission.
231541Srgrimes *
241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3050477Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
332165Spaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3459774Sbde * SUCH DAMAGE.
352165Spaul *
36126590Sbde *	$Id: show.c,v 1.3 1996/09/01 10:21:43 peter Exp $
37133741Sjmg */
38168355Srwatson
39137804Sphk#ifndef lint
40168355Srwatsonstatic char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
4141086Struckman#endif /* not lint */
42126593Sbde
43126593Sbde#include <stdio.h>
441541Srgrimes#if __STDC__
451541Srgrimes#include <stdarg.h>
461541Srgrimes#else
471541Srgrimes#include <varargs.h>
48126591Sbde#endif
491541Srgrimes
501541Srgrimes#include "shell.h"
511541Srgrimes#include "parser.h"
521541Srgrimes#include "nodes.h"
531541Srgrimes#include "mystring.h"
541541Srgrimes#include "show.h"
5551649Sphk
561541Srgrimes
57126591Sbde#ifdef DEBUG
5889306Salfredstatic void shtree __P((union node *, int, char *, FILE*));
5989306Salfredstatic void shcmd __P((union node *, FILE *));
601541Srgrimesstatic void sharg __P((union node *, FILE *));
61138838Sphkstatic void indent __P((int, char *, FILE *));
62138838Sphkstatic void trstring __P((char *));
63168355Srwatson
64133741Sjmg
65115702Steggevoid
66115702Steggeshowtree(n)
671541Srgrimes	union node *n;
681541Srgrimes{
691541Srgrimes	trputs("showtree called\n");
70115702Stegge	shtree(n, 1, NULL, stdout);
71115702Stegge}
72126591Sbde
73115702Stegge
74115702Steggestatic void
75115702Steggeshtree(n, ind, pfx, fp)
76115702Stegge	union node *n;
77115702Stegge	int ind;
78115702Stegge	char *pfx;
79115702Stegge	FILE *fp;
80115702Stegge{
81115702Stegge	struct nodelist *lp;
82115702Stegge	char *s;
83126591Sbde
84115702Stegge	if (n == NULL)
85115702Stegge		return;
86115702Stegge
87115702Stegge	indent(ind, pfx, fp);
88115702Stegge	switch(n->type) {
891541Srgrimes	case NSEMI:
901541Srgrimes		s = "; ";
91246912Spjd		goto binop;
921541Srgrimes	case NAND:
9355205Speter		s = " && ";
9489306Salfred		goto binop;
9589306Salfred	case NOR:
96168355Srwatson		s = " || ";
97168355Srwatsonbinop:
98168355Srwatson		shtree(n->nbinary.ch1, ind, NULL, fp);
99168355Srwatson	   /*    if (ind < 0) */
100168355Srwatson			fputs(s, fp);
101168355Srwatson		shtree(n->nbinary.ch2, ind, NULL, fp);
102168355Srwatson		break;
103137804Sphk	case NCMD:
104168355Srwatson		shcmd(n, fp);
105168355Srwatson		if (ind >= 0)
106168355Srwatson			putc('\n', fp);
107168355Srwatson		break;
108237072Spjd	case NPIPE:
109137804Sphk		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
110122514Sjhb			shcmd(lp->n, fp);
111122514Sjhb			if (lp->next)
112126591Sbde				fputs(" | ", fp);
113237033Spjd		}
114237033Spjd		if (n->npipe.backgnd)
115220245Skib			fputs(" &", fp);
116219999Skib		if (ind >= 0)
117223694Sjonathan			putc('\n', fp);
118223694Sjonathan		break;
119126591Sbde	default:
12092719Salfred		fprintf(fp, "<node type %d>", n->type);
121126590Sbde		if (ind >= 0)
122137355Sphk			putc('\n', fp);
12392719Salfred		break;
124108522Salfred	}
125138832Sphk}
12692719Salfred
127108520Salfred
128108520Salfred
129115702Steggestatic void
130126591Sbdeshcmd(cmd, fp)
131126591Sbde	union node *cmd;
132224778Srwatson	FILE *fp;
133224778Srwatson{
134138835Sphk	union node *np;
135126590Sbde	int first;
136115702Stegge	char *s;
137192080Sjeff	int dftfd;
138192080Sjeff
139192080Sjeff	first = 1;
140192080Sjeff	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
14189969Salfred		if (! first)
142100072Smarkm			putchar(' ');
14389969Salfred		sharg(np, fp);
14489969Salfred		first = 0;
145237081Spjd	}
146237081Spjd	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
147237081Spjd		if (! first)
148237081Spjd			putchar(' ');
149237081Spjd		switch (np->nfile.type) {
150237081Spjd			case NTO:	s = ">";  dftfd = 1; break;
15189969Salfred			case NAPPEND:	s = ">>"; dftfd = 1; break;
15289969Salfred			case NTOFD:	s = ">&"; dftfd = 1; break;
15359774Sbde			case NFROM:	s = "<";  dftfd = 0; break;
1542165Spaul			case NFROMFD:	s = "<&"; dftfd = 0; break;
15559774Sbde			default:  	s = "*error*"; dftfd = 0; break;
156		}
157		if (np->nfile.fd != dftfd)
158			fprintf(fp, "%d", np->nfile.fd);
159		fputs(s, fp);
160		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
161			fprintf(fp, "%d", np->ndup.dupfd);
162		} else {
163			sharg(np->nfile.fname, fp);
164		}
165		first = 0;
166	}
167}
168
169
170
171static void
172sharg(arg, fp)
173	union node *arg;
174	FILE *fp;
175	{
176	char *p;
177	struct nodelist *bqlist;
178	int subtype;
179
180	if (arg->type != NARG) {
181		printf("<node type %d>\n", arg->type);
182		fflush(stdout);
183		abort();
184	}
185	bqlist = arg->narg.backquote;
186	for (p = arg->narg.text ; *p ; p++) {
187		switch (*p) {
188		case CTLESC:
189			putc(*++p, fp);
190			break;
191		case CTLVAR:
192			putc('$', fp);
193			putc('{', fp);
194			subtype = *++p;
195			if (subtype == VSLENGTH)
196				putc('#', fp);
197
198			while (*p != '=')
199				putc(*p++, fp);
200
201			if (subtype & VSNUL)
202				putc(':', fp);
203
204			switch (subtype & VSTYPE) {
205			case VSNORMAL:
206				putc('}', fp);
207				break;
208			case VSMINUS:
209				putc('-', fp);
210				break;
211			case VSPLUS:
212				putc('+', fp);
213				break;
214			case VSQUESTION:
215				putc('?', fp);
216				break;
217			case VSASSIGN:
218				putc('=', fp);
219				break;
220			case VSTRIMLEFT:
221				putc('#', fp);
222				break;
223			case VSTRIMLEFTMAX:
224				putc('#', fp);
225				putc('#', fp);
226				break;
227			case VSTRIMRIGHT:
228				putc('%', fp);
229				break;
230			case VSTRIMRIGHTMAX:
231				putc('%', fp);
232				putc('%', fp);
233				break;
234			case VSLENGTH:
235				break;
236			default:
237				printf("<subtype %d>", subtype);
238			}
239			break;
240		case CTLENDVAR:
241		     putc('}', fp);
242		     break;
243		case CTLBACKQ:
244		case CTLBACKQ|CTLQUOTE:
245			putc('$', fp);
246			putc('(', fp);
247			shtree(bqlist->n, -1, NULL, fp);
248			putc(')', fp);
249			break;
250		default:
251			putc(*p, fp);
252			break;
253		}
254	}
255}
256
257
258static void
259indent(amount, pfx, fp)
260	int amount;
261	char *pfx;
262	FILE *fp;
263{
264	int i;
265
266	for (i = 0 ; i < amount ; i++) {
267		if (pfx && i == amount - 1)
268			fputs(pfx, fp);
269		putc('\t', fp);
270	}
271}
272#endif
273
274
275
276/*
277 * Debugging stuff.
278 */
279
280
281FILE *tracefile;
282
283#if DEBUG == 2
284int debug = 1;
285#else
286int debug = 0;
287#endif
288
289
290void
291trputc(c)
292	int c;
293{
294#ifdef DEBUG
295	if (tracefile == NULL)
296		return;
297	putc(c, tracefile);
298	if (c == '\n')
299		fflush(tracefile);
300#endif
301}
302
303void
304#if __STDC__
305shtrace(const char *fmt, ...)
306#else
307shtrace(va_alist)
308	va_dcl
309#endif
310{
311#ifdef DEBUG
312	va_list va;
313#if __STDC__
314	va_start(va, fmt);
315#else
316	char *fmt;
317	va_start(va);
318	fmt = va_arg(va, char *);
319#endif
320	if (tracefile != NULL) {
321		(void) vfprintf(tracefile, fmt, va);
322		if (strchr(fmt, '\n'))
323			(void) fflush(tracefile);
324	}
325	va_end(va);
326#endif
327}
328
329
330void
331trputs(s)
332	char *s;
333{
334#ifdef DEBUG
335	if (tracefile == NULL)
336		return;
337	fputs(s, tracefile);
338	if (strchr(s, '\n'))
339		fflush(tracefile);
340#endif
341}
342
343
344#ifdef DEBUG
345static void
346trstring(s)
347	char *s;
348{
349	register char *p;
350	char c;
351
352	if (tracefile == NULL)
353		return;
354	putc('"', tracefile);
355	for (p = s ; *p ; p++) {
356		switch (*p) {
357		case '\n':  c = 'n';  goto backslash;
358		case '\t':  c = 't';  goto backslash;
359		case '\r':  c = 'r';  goto backslash;
360		case '"':  c = '"';  goto backslash;
361		case '\\':  c = '\\';  goto backslash;
362		case CTLESC:  c = 'e';  goto backslash;
363		case CTLVAR:  c = 'v';  goto backslash;
364		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
365		case CTLBACKQ:  c = 'q';  goto backslash;
366		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
367backslash:	  putc('\\', tracefile);
368			putc(c, tracefile);
369			break;
370		default:
371			if (*p >= ' ' && *p <= '~')
372				putc(*p, tracefile);
373			else {
374				putc('\\', tracefile);
375				putc(*p >> 6 & 03, tracefile);
376				putc(*p >> 3 & 07, tracefile);
377				putc(*p & 07, tracefile);
378			}
379			break;
380		}
381	}
382	putc('"', tracefile);
383}
384#endif
385
386
387void
388trargs(ap)
389	char **ap;
390{
391#ifdef DEBUG
392	if (tracefile == NULL)
393		return;
394	while (*ap) {
395		trstring(*ap++);
396		if (*ap)
397			putc(' ', tracefile);
398		else
399			putc('\n', tracefile);
400	}
401	fflush(tracefile);
402#endif
403}
404
405
406void
407opentrace() {
408#ifdef DEBUG
409	char s[100];
410	char *getenv();
411#ifdef O_APPEND
412	int flags;
413#endif
414
415	if (!debug)
416		return;
417#ifdef not_this_way
418	{
419		char *p;
420		if ((p = getenv("HOME")) == NULL) {
421			if (geteuid() == 0)
422				p = "/";
423			else
424				p = "/tmp";
425		}
426		scopy(p, s);
427		strcat(s, "/trace");
428	}
429#else
430	scopy("./trace", s);
431#endif /* not_this_way */
432	if ((tracefile = fopen(s, "a")) == NULL) {
433		fprintf(stderr, "Can't open %s\n", s);
434		return;
435	}
436#ifdef O_APPEND
437	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
438		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
439#endif
440	fputs("\nTracing started.\n", tracefile);
441	fflush(tracefile);
442#endif /* DEBUG */
443}
444