Commit | Line | Data |
---|---|---|
a9f0b747 | 1 | /*- |
8276a8e2 KB |
2 | * Copyright (c) 1991, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
a9f0b747 KB |
4 | * |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Kenneth Almquist. | |
7 | * | |
ad787160 C |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
a9f0b747 KB |
35 | */ |
36 | ||
37 | #ifndef lint | |
ad787160 | 38 | static char sccsid[] = "@(#)show.c 8.1 (Berkeley) 5/31/93"; |
a9f0b747 KB |
39 | #endif /* not lint */ |
40 | ||
41 | #include <stdio.h> | |
42 | #include "shell.h" | |
43 | #include "parser.h" | |
44 | #include "nodes.h" | |
45 | #include "mystring.h" | |
46 | ||
47 | ||
48 | #ifdef DEBUG | |
49 | static shtree(), shcmd(), sharg(), indent(); | |
50 | ||
51 | ||
52 | showtree(n) | |
53 | union node *n; | |
54 | { | |
55 | trputs("showtree called\n"); | |
56 | shtree(n, 1, NULL, stdout); | |
57 | } | |
58 | ||
59 | ||
60 | static | |
61 | shtree(n, ind, pfx, fp) | |
62 | union node *n; | |
63 | char *pfx; | |
64 | FILE *fp; | |
65 | { | |
66 | struct nodelist *lp; | |
67 | char *s; | |
68 | ||
69 | indent(ind, pfx, fp); | |
70 | switch(n->type) { | |
71 | case NSEMI: | |
72 | s = "; "; | |
73 | goto binop; | |
74 | case NAND: | |
75 | s = " && "; | |
76 | goto binop; | |
77 | case NOR: | |
78 | s = " || "; | |
79 | binop: | |
80 | shtree(n->nbinary.ch1, ind, NULL, fp); | |
81 | /* if (ind < 0) */ | |
82 | fputs(s, fp); | |
83 | shtree(n->nbinary.ch2, ind, NULL, fp); | |
84 | break; | |
85 | case NCMD: | |
86 | shcmd(n, fp); | |
87 | if (ind >= 0) | |
88 | putc('\n', fp); | |
89 | break; | |
90 | case NPIPE: | |
91 | for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { | |
92 | shcmd(lp->n, fp); | |
93 | if (lp->next) | |
94 | fputs(" | ", fp); | |
95 | } | |
96 | if (n->npipe.backgnd) | |
97 | fputs(" &", fp); | |
98 | if (ind >= 0) | |
99 | putc('\n', fp); | |
100 | break; | |
101 | default: | |
102 | fprintf(fp, "<node type %d>", n->type); | |
103 | if (ind >= 0) | |
104 | putc('\n', fp); | |
105 | break; | |
106 | } | |
107 | } | |
108 | ||
109 | ||
110 | ||
111 | static | |
112 | shcmd(cmd, fp) | |
113 | union node *cmd; | |
114 | FILE *fp; | |
115 | { | |
116 | union node *np; | |
117 | int first; | |
118 | char *s; | |
119 | int dftfd; | |
120 | ||
121 | first = 1; | |
122 | for (np = cmd->ncmd.args ; np ; np = np->narg.next) { | |
123 | if (! first) | |
124 | putchar(' '); | |
125 | sharg(np, fp); | |
126 | first = 0; | |
127 | } | |
128 | for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { | |
129 | if (! first) | |
130 | putchar(' '); | |
131 | switch (np->nfile.type) { | |
132 | case NTO: s = ">"; dftfd = 1; break; | |
133 | case NAPPEND: s = ">>"; dftfd = 1; break; | |
134 | case NTOFD: s = ">&"; dftfd = 1; break; | |
135 | case NFROM: s = "<"; dftfd = 0; break; | |
136 | case NFROMFD: s = "<&"; dftfd = 0; break; | |
137 | } | |
138 | if (np->nfile.fd != dftfd) | |
139 | fprintf(fp, "%d", np->nfile.fd); | |
140 | fputs(s, fp); | |
141 | if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { | |
142 | fprintf(fp, "%d", np->ndup.dupfd); | |
143 | } else { | |
144 | sharg(np->nfile.fname, fp); | |
145 | } | |
146 | first = 0; | |
147 | } | |
148 | } | |
149 | ||
150 | ||
151 | ||
152 | static | |
153 | sharg(arg, fp) | |
154 | union node *arg; | |
155 | FILE *fp; | |
156 | { | |
157 | char *p; | |
158 | struct nodelist *bqlist; | |
159 | int subtype; | |
160 | ||
161 | if (arg->type != NARG) { | |
162 | printf("<node type %d>\n", arg->type); | |
163 | fflush(stdout); | |
164 | abort(); | |
165 | } | |
166 | bqlist = arg->narg.backquote; | |
167 | for (p = arg->narg.text ; *p ; p++) { | |
168 | switch (*p) { | |
169 | case CTLESC: | |
170 | putc(*++p, fp); | |
171 | break; | |
172 | case CTLVAR: | |
173 | putc('$', fp); | |
174 | putc('{', fp); | |
175 | subtype = *++p; | |
176 | while (*p != '=') | |
177 | putc(*p++, fp); | |
178 | if (subtype & VSNUL) | |
179 | putc(':', fp); | |
180 | switch (subtype & VSTYPE) { | |
181 | case VSNORMAL: | |
182 | putc('}', fp); | |
183 | break; | |
184 | case VSMINUS: | |
185 | putc('-', fp); | |
186 | break; | |
187 | case VSPLUS: | |
188 | putc('+', fp); | |
189 | break; | |
190 | case VSQUESTION: | |
191 | putc('?', fp); | |
192 | break; | |
193 | case VSASSIGN: | |
194 | putc('=', fp); | |
195 | break; | |
196 | default: | |
197 | printf("<subtype %d>", subtype); | |
198 | } | |
199 | break; | |
200 | case CTLENDVAR: | |
201 | putc('}', fp); | |
202 | break; | |
203 | case CTLBACKQ: | |
204 | case CTLBACKQ|CTLQUOTE: | |
205 | putc('$', fp); | |
206 | putc('(', fp); | |
207 | shtree(bqlist->n, -1, NULL, fp); | |
208 | putc(')', fp); | |
209 | break; | |
210 | default: | |
211 | putc(*p, fp); | |
212 | break; | |
213 | } | |
214 | } | |
215 | } | |
216 | ||
217 | ||
218 | static | |
219 | indent(amount, pfx, fp) | |
220 | char *pfx; | |
221 | FILE *fp; | |
222 | { | |
223 | int i; | |
224 | ||
225 | for (i = 0 ; i < amount ; i++) { | |
226 | if (pfx && i == amount - 1) | |
227 | fputs(pfx, fp); | |
228 | putc('\t', fp); | |
229 | } | |
230 | } | |
231 | #endif | |
232 | ||
233 | ||
234 | ||
235 | /* | |
236 | * Debugging stuff. | |
237 | */ | |
238 | ||
239 | ||
240 | FILE *tracefile; | |
241 | ||
44c32b7a MT |
242 | #if DEBUG == 2 |
243 | int debug = 1; | |
244 | #else | |
245 | int debug = 0; | |
246 | #endif | |
a9f0b747 KB |
247 | |
248 | ||
249 | trputc(c) { | |
250 | #ifdef DEBUG | |
251 | if (tracefile == NULL) | |
252 | return; | |
253 | putc(c, tracefile); | |
254 | if (c == '\n') | |
255 | fflush(tracefile); | |
256 | #endif | |
257 | } | |
258 | ||
259 | ||
260 | trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8) | |
261 | char *fmt; | |
262 | { | |
263 | #ifdef DEBUG | |
264 | if (tracefile == NULL) | |
265 | return; | |
266 | fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8); | |
267 | if (strchr(fmt, '\n')) | |
268 | fflush(tracefile); | |
269 | #endif | |
270 | } | |
271 | ||
272 | ||
273 | trputs(s) | |
274 | char *s; | |
275 | { | |
276 | #ifdef DEBUG | |
277 | if (tracefile == NULL) | |
278 | return; | |
279 | fputs(s, tracefile); | |
280 | if (strchr(s, '\n')) | |
281 | fflush(tracefile); | |
282 | #endif | |
283 | } | |
284 | ||
285 | ||
286 | trstring(s) | |
287 | char *s; | |
288 | { | |
289 | register char *p; | |
290 | char c; | |
291 | ||
292 | #ifdef DEBUG | |
293 | if (tracefile == NULL) | |
294 | return; | |
295 | putc('"', tracefile); | |
296 | for (p = s ; *p ; p++) { | |
297 | switch (*p) { | |
298 | case '\n': c = 'n'; goto backslash; | |
299 | case '\t': c = 't'; goto backslash; | |
300 | case '\r': c = 'r'; goto backslash; | |
301 | case '"': c = '"'; goto backslash; | |
302 | case '\\': c = '\\'; goto backslash; | |
303 | case CTLESC: c = 'e'; goto backslash; | |
304 | case CTLVAR: c = 'v'; goto backslash; | |
305 | case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; | |
306 | case CTLBACKQ: c = 'q'; goto backslash; | |
307 | case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; | |
308 | backslash: putc('\\', tracefile); | |
309 | putc(c, tracefile); | |
310 | break; | |
311 | default: | |
312 | if (*p >= ' ' && *p <= '~') | |
313 | putc(*p, tracefile); | |
314 | else { | |
315 | putc('\\', tracefile); | |
316 | putc(*p >> 6 & 03, tracefile); | |
317 | putc(*p >> 3 & 07, tracefile); | |
318 | putc(*p & 07, tracefile); | |
319 | } | |
320 | break; | |
321 | } | |
322 | } | |
323 | putc('"', tracefile); | |
324 | #endif | |
325 | } | |
326 | ||
327 | ||
328 | trargs(ap) | |
329 | char **ap; | |
330 | { | |
331 | #ifdef DEBUG | |
332 | if (tracefile == NULL) | |
333 | return; | |
334 | while (*ap) { | |
335 | trstring(*ap++); | |
336 | if (*ap) | |
337 | putc(' ', tracefile); | |
338 | else | |
339 | putc('\n', tracefile); | |
340 | } | |
341 | fflush(tracefile); | |
342 | #endif | |
343 | } | |
344 | ||
345 | ||
346 | opentrace() { | |
347 | char s[100]; | |
348 | char *p; | |
349 | char *getenv(); | |
350 | int flags; | |
351 | ||
352 | #ifdef DEBUG | |
44c32b7a MT |
353 | if (!debug) |
354 | return; | |
e2bf5c64 | 355 | #ifdef not_this_way |
44c32b7a | 356 | if ((p = getenv("HOME")) == NULL) { |
e2bf5c64 | 357 | if (geteuid() == 0) |
44c32b7a MT |
358 | p = "/"; |
359 | else | |
360 | p = "/tmp"; | |
361 | } | |
a9f0b747 KB |
362 | scopy(p, s); |
363 | strcat(s, "/trace"); | |
e2bf5c64 MT |
364 | #else |
365 | scopy("./trace", s); | |
366 | #endif /* not_this_way */ | |
a9f0b747 KB |
367 | if ((tracefile = fopen(s, "a")) == NULL) { |
368 | fprintf(stderr, "Can't open %s\n", s); | |
44c32b7a | 369 | return; |
a9f0b747 KB |
370 | } |
371 | #ifdef O_APPEND | |
372 | if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) | |
373 | fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); | |
374 | #endif | |
375 | fputs("\nTracing started.\n", tracefile); | |
376 | fflush(tracefile); | |
e2bf5c64 | 377 | #endif /* DEBUG */ |
a9f0b747 | 378 | } |