xref: /original-bsd/bin/sh/show.c (revision 01e8f48f)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)show.c	8.2 (Berkeley) 04/28/95";
13 #endif /* not lint */
14 
15 #include <stdio.h>
16 #include "shell.h"
17 #include "parser.h"
18 #include "nodes.h"
19 #include "mystring.h"
20 
21 
22 #ifdef DEBUG
23 static shtree(), shcmd(), sharg(), indent();
24 
25 
26 showtree(n)
27 	union node *n;
28 	{
29 	trputs("showtree called\n");
30 	shtree(n, 1, NULL, stdout);
31 }
32 
33 
34 static
35 shtree(n, ind, pfx, fp)
36 	union node *n;
37 	char *pfx;
38 	FILE *fp;
39 	{
40 	struct nodelist *lp;
41 	char *s;
42 
43 	if (n == NULL)
44 		return;
45 
46 	indent(ind, pfx, fp);
47 	switch(n->type) {
48 	case NSEMI:
49 		s = "; ";
50 		goto binop;
51 	case NAND:
52 		s = " && ";
53 		goto binop;
54 	case NOR:
55 		s = " || ";
56 binop:
57 		shtree(n->nbinary.ch1, ind, NULL, fp);
58 	   /*    if (ind < 0) */
59 			fputs(s, fp);
60 		shtree(n->nbinary.ch2, ind, NULL, fp);
61 		break;
62 	case NCMD:
63 		shcmd(n, fp);
64 		if (ind >= 0)
65 			putc('\n', fp);
66 		break;
67 	case NPIPE:
68 		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
69 			shcmd(lp->n, fp);
70 			if (lp->next)
71 				fputs(" | ", fp);
72 		}
73 		if (n->npipe.backgnd)
74 			fputs(" &", fp);
75 		if (ind >= 0)
76 			putc('\n', fp);
77 		break;
78 	default:
79 		fprintf(fp, "<node type %d>", n->type);
80 		if (ind >= 0)
81 			putc('\n', fp);
82 		break;
83 	}
84 }
85 
86 
87 
88 static
89 shcmd(cmd, fp)
90 	union node *cmd;
91 	FILE *fp;
92 	{
93 	union node *np;
94 	int first;
95 	char *s;
96 	int dftfd;
97 
98 	first = 1;
99 	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
100 		if (! first)
101 			putchar(' ');
102 		sharg(np, fp);
103 		first = 0;
104 	}
105 	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
106 		if (! first)
107 			putchar(' ');
108 		switch (np->nfile.type) {
109 			case NTO:	s = ">";  dftfd = 1; break;
110 			case NAPPEND:	s = ">>"; dftfd = 1; break;
111 			case NTOFD:	s = ">&"; dftfd = 1; break;
112 			case NFROM:	s = "<";  dftfd = 0; break;
113 			case NFROMFD:	s = "<&"; dftfd = 0; break;
114 		}
115 		if (np->nfile.fd != dftfd)
116 			fprintf(fp, "%d", np->nfile.fd);
117 		fputs(s, fp);
118 		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
119 			fprintf(fp, "%d", np->ndup.dupfd);
120 		} else {
121 			sharg(np->nfile.fname, fp);
122 		}
123 		first = 0;
124 	}
125 }
126 
127 
128 
129 static
130 sharg(arg, fp)
131 	union node *arg;
132 	FILE *fp;
133 	{
134 	char *p;
135 	struct nodelist *bqlist;
136 	int subtype;
137 
138 	if (arg->type != NARG) {
139 		printf("<node type %d>\n", arg->type);
140 		fflush(stdout);
141 		abort();
142 	}
143 	bqlist = arg->narg.backquote;
144 	for (p = arg->narg.text ; *p ; p++) {
145 		switch (*p) {
146 		case CTLESC:
147 			putc(*++p, fp);
148 			break;
149 		case CTLVAR:
150 			putc('$', fp);
151 			putc('{', fp);
152 			subtype = *++p;
153 			if (subtype == VSLENGTH)
154 				putc('#', fp);
155 
156 			while (*p != '=')
157 				putc(*p++, fp);
158 
159 			if (subtype & VSNUL)
160 				putc(':', fp);
161 
162 			switch (subtype & VSTYPE) {
163 			case VSNORMAL:
164 				putc('}', fp);
165 				break;
166 			case VSMINUS:
167 				putc('-', fp);
168 				break;
169 			case VSPLUS:
170 				putc('+', fp);
171 				break;
172 			case VSQUESTION:
173 				putc('?', fp);
174 				break;
175 			case VSASSIGN:
176 				putc('=', fp);
177 				break;
178 			case VSTRIMLEFT:
179 				putc('#', fp);
180 				break;
181 			case VSTRIMLEFTMAX:
182 				putc('#', fp);
183 				putc('#', fp);
184 				break;
185 			case VSTRIMRIGHT:
186 				putc('%', fp);
187 				break;
188 			case VSTRIMRIGHTMAX:
189 				putc('%', fp);
190 				putc('%', fp);
191 				break;
192 			case VSLENGTH:
193 				break;
194 			default:
195 				printf("<subtype %d>", subtype);
196 			}
197 			break;
198 		case CTLENDVAR:
199 		     putc('}', fp);
200 		     break;
201 		case CTLBACKQ:
202 		case CTLBACKQ|CTLQUOTE:
203 			putc('$', fp);
204 			putc('(', fp);
205 			shtree(bqlist->n, -1, NULL, fp);
206 			putc(')', fp);
207 			break;
208 		default:
209 			putc(*p, fp);
210 			break;
211 		}
212 	}
213 }
214 
215 
216 static
217 indent(amount, pfx, fp)
218 	char *pfx;
219 	FILE *fp;
220 	{
221 	int i;
222 
223 	for (i = 0 ; i < amount ; i++) {
224 		if (pfx && i == amount - 1)
225 			fputs(pfx, fp);
226 		putc('\t', fp);
227 	}
228 }
229 #endif
230 
231 
232 
233 /*
234  * Debugging stuff.
235  */
236 
237 
238 FILE *tracefile;
239 
240 #if DEBUG == 2
241 int debug = 1;
242 #else
243 int debug = 0;
244 #endif
245 
246 
247 trputc(c) {
248 #ifdef DEBUG
249 	if (tracefile == NULL)
250 		return;
251 	putc(c, tracefile);
252 	if (c == '\n')
253 		fflush(tracefile);
254 #endif
255 }
256 
257 
258 trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
259 	char *fmt;
260 	{
261 #ifdef DEBUG
262 	if (tracefile == NULL)
263 		return;
264 	fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
265 	if (strchr(fmt, '\n'))
266 		fflush(tracefile);
267 #endif
268 }
269 
270 
271 trputs(s)
272 	char *s;
273 	{
274 #ifdef DEBUG
275 	if (tracefile == NULL)
276 		return;
277 	fputs(s, tracefile);
278 	if (strchr(s, '\n'))
279 		fflush(tracefile);
280 #endif
281 }
282 
283 
284 trstring(s)
285 	char *s;
286 	{
287 	register char *p;
288 	char c;
289 
290 #ifdef DEBUG
291 	if (tracefile == NULL)
292 		return;
293 	putc('"', tracefile);
294 	for (p = s ; *p ; p++) {
295 		switch (*p) {
296 		case '\n':  c = 'n';  goto backslash;
297 		case '\t':  c = 't';  goto backslash;
298 		case '\r':  c = 'r';  goto backslash;
299 		case '"':  c = '"';  goto backslash;
300 		case '\\':  c = '\\';  goto backslash;
301 		case CTLESC:  c = 'e';  goto backslash;
302 		case CTLVAR:  c = 'v';  goto backslash;
303 		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
304 		case CTLBACKQ:  c = 'q';  goto backslash;
305 		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
306 backslash:	  putc('\\', tracefile);
307 			putc(c, tracefile);
308 			break;
309 		default:
310 			if (*p >= ' ' && *p <= '~')
311 				putc(*p, tracefile);
312 			else {
313 				putc('\\', tracefile);
314 				putc(*p >> 6 & 03, tracefile);
315 				putc(*p >> 3 & 07, tracefile);
316 				putc(*p & 07, tracefile);
317 			}
318 			break;
319 		}
320 	}
321 	putc('"', tracefile);
322 #endif
323 }
324 
325 
326 trargs(ap)
327 	char **ap;
328 	{
329 #ifdef DEBUG
330 	if (tracefile == NULL)
331 		return;
332 	while (*ap) {
333 		trstring(*ap++);
334 		if (*ap)
335 			putc(' ', tracefile);
336 		else
337 			putc('\n', tracefile);
338 	}
339 	fflush(tracefile);
340 #endif
341 }
342 
343 
344 opentrace() {
345 	char s[100];
346 	char *p;
347 	char *getenv();
348 	int flags;
349 
350 #ifdef DEBUG
351 	if (!debug)
352 		return;
353 #ifdef not_this_way
354 	if ((p = getenv("HOME")) == NULL) {
355 		if (geteuid() == 0)
356 			p = "/";
357 		else
358 			p = "/tmp";
359 	}
360 	scopy(p, s);
361 	strcat(s, "/trace");
362 #else
363 	scopy("./trace", s);
364 #endif /* not_this_way */
365 	if ((tracefile = fopen(s, "a")) == NULL) {
366 		fprintf(stderr, "Can't open %s\n", s);
367 		return;
368 	}
369 #ifdef O_APPEND
370 	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
371 		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
372 #endif
373 	fputs("\nTracing started.\n", tracefile);
374 	fflush(tracefile);
375 #endif /* DEBUG */
376 }
377