147144Sbostic /*-
260712Sbostic * Copyright (c) 1991, 1993
360712Sbostic * The Regents of the University of California. All rights reserved.
447144Sbostic *
547144Sbostic * This code is derived from software contributed to Berkeley by
647144Sbostic * Kenneth Almquist.
747144Sbostic *
860711Sbostic * %sccs.include.redist.c%
947144Sbostic */
1047144Sbostic
1147144Sbostic #ifndef lint
12*69272Schristos static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 05/04/95";
1347144Sbostic #endif /* not lint */
1447144Sbostic
1547144Sbostic #include <stdio.h>
16*69272Schristos #if __STDC__
17*69272Schristos #include <stdarg.h>
18*69272Schristos #else
19*69272Schristos #include <varargs.h>
20*69272Schristos #endif
21*69272Schristos
2247144Sbostic #include "shell.h"
2347144Sbostic #include "parser.h"
2447144Sbostic #include "nodes.h"
2547144Sbostic #include "mystring.h"
26*69272Schristos #include "show.h"
2747144Sbostic
2847144Sbostic
2947144Sbostic #ifdef DEBUG
30*69272Schristos static void shtree __P((union node *, int, char *, FILE*));
31*69272Schristos static void shcmd __P((union node *, FILE *));
32*69272Schristos static void sharg __P((union node *, FILE *));
33*69272Schristos static void indent __P((int, char *, FILE *));
34*69272Schristos static void trstring __P((char *));
3547144Sbostic
3647144Sbostic
37*69272Schristos void
showtree(n)3847144Sbostic showtree(n)
3947144Sbostic union node *n;
40*69272Schristos {
4147144Sbostic trputs("showtree called\n");
4247144Sbostic shtree(n, 1, NULL, stdout);
4347144Sbostic }
4447144Sbostic
4547144Sbostic
46*69272Schristos static void
shtree(n,ind,pfx,fp)4747144Sbostic shtree(n, ind, pfx, fp)
4847144Sbostic union node *n;
49*69272Schristos int ind;
5047144Sbostic char *pfx;
5147144Sbostic FILE *fp;
52*69272Schristos {
5347144Sbostic struct nodelist *lp;
5447144Sbostic char *s;
5547144Sbostic
5669090Sbostic if (n == NULL)
5769090Sbostic return;
5869090Sbostic
5947144Sbostic indent(ind, pfx, fp);
6047144Sbostic switch(n->type) {
6147144Sbostic case NSEMI:
6247144Sbostic s = "; ";
6347144Sbostic goto binop;
6447144Sbostic case NAND:
6547144Sbostic s = " && ";
6647144Sbostic goto binop;
6747144Sbostic case NOR:
6847144Sbostic s = " || ";
6947144Sbostic binop:
7047144Sbostic shtree(n->nbinary.ch1, ind, NULL, fp);
7147144Sbostic /* if (ind < 0) */
7247144Sbostic fputs(s, fp);
7347144Sbostic shtree(n->nbinary.ch2, ind, NULL, fp);
7447144Sbostic break;
7547144Sbostic case NCMD:
7647144Sbostic shcmd(n, fp);
7747144Sbostic if (ind >= 0)
7847144Sbostic putc('\n', fp);
7947144Sbostic break;
8047144Sbostic case NPIPE:
8147144Sbostic for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
8247144Sbostic shcmd(lp->n, fp);
8347144Sbostic if (lp->next)
8447144Sbostic fputs(" | ", fp);
8547144Sbostic }
8647144Sbostic if (n->npipe.backgnd)
8747144Sbostic fputs(" &", fp);
8847144Sbostic if (ind >= 0)
8947144Sbostic putc('\n', fp);
9047144Sbostic break;
9147144Sbostic default:
9247144Sbostic fprintf(fp, "<node type %d>", n->type);
9347144Sbostic if (ind >= 0)
9447144Sbostic putc('\n', fp);
9547144Sbostic break;
9647144Sbostic }
9747144Sbostic }
9847144Sbostic
9947144Sbostic
10047144Sbostic
101*69272Schristos static void
shcmd(cmd,fp)10247144Sbostic shcmd(cmd, fp)
10347144Sbostic union node *cmd;
10447144Sbostic FILE *fp;
105*69272Schristos {
10647144Sbostic union node *np;
10747144Sbostic int first;
10847144Sbostic char *s;
10947144Sbostic int dftfd;
11047144Sbostic
11147144Sbostic first = 1;
11247144Sbostic for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11347144Sbostic if (! first)
11447144Sbostic putchar(' ');
11547144Sbostic sharg(np, fp);
11647144Sbostic first = 0;
11747144Sbostic }
11847144Sbostic for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11947144Sbostic if (! first)
12047144Sbostic putchar(' ');
12147144Sbostic switch (np->nfile.type) {
12247144Sbostic case NTO: s = ">"; dftfd = 1; break;
12347144Sbostic case NAPPEND: s = ">>"; dftfd = 1; break;
12447144Sbostic case NTOFD: s = ">&"; dftfd = 1; break;
12547144Sbostic case NFROM: s = "<"; dftfd = 0; break;
12647144Sbostic case NFROMFD: s = "<&"; dftfd = 0; break;
127*69272Schristos default: s = "*error*"; dftfd = 0; break;
12847144Sbostic }
12947144Sbostic if (np->nfile.fd != dftfd)
13047144Sbostic fprintf(fp, "%d", np->nfile.fd);
13147144Sbostic fputs(s, fp);
13247144Sbostic if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
13347144Sbostic fprintf(fp, "%d", np->ndup.dupfd);
13447144Sbostic } else {
13547144Sbostic sharg(np->nfile.fname, fp);
13647144Sbostic }
13747144Sbostic first = 0;
13847144Sbostic }
13947144Sbostic }
14047144Sbostic
14147144Sbostic
14247144Sbostic
143*69272Schristos static void
sharg(arg,fp)14447144Sbostic sharg(arg, fp)
14547144Sbostic union node *arg;
14647144Sbostic FILE *fp;
14747144Sbostic {
14847144Sbostic char *p;
14947144Sbostic struct nodelist *bqlist;
15047144Sbostic int subtype;
15147144Sbostic
15247144Sbostic if (arg->type != NARG) {
15347144Sbostic printf("<node type %d>\n", arg->type);
15447144Sbostic fflush(stdout);
15547144Sbostic abort();
15647144Sbostic }
15747144Sbostic bqlist = arg->narg.backquote;
15847144Sbostic for (p = arg->narg.text ; *p ; p++) {
15947144Sbostic switch (*p) {
16047144Sbostic case CTLESC:
16147144Sbostic putc(*++p, fp);
16247144Sbostic break;
16347144Sbostic case CTLVAR:
16447144Sbostic putc('$', fp);
16547144Sbostic putc('{', fp);
16647144Sbostic subtype = *++p;
16769090Sbostic if (subtype == VSLENGTH)
16869090Sbostic putc('#', fp);
16969090Sbostic
17047144Sbostic while (*p != '=')
17147144Sbostic putc(*p++, fp);
17269090Sbostic
17347144Sbostic if (subtype & VSNUL)
17447144Sbostic putc(':', fp);
17569090Sbostic
17647144Sbostic switch (subtype & VSTYPE) {
17747144Sbostic case VSNORMAL:
17847144Sbostic putc('}', fp);
17947144Sbostic break;
18047144Sbostic case VSMINUS:
18147144Sbostic putc('-', fp);
18247144Sbostic break;
18347144Sbostic case VSPLUS:
18447144Sbostic putc('+', fp);
18547144Sbostic break;
18647144Sbostic case VSQUESTION:
18747144Sbostic putc('?', fp);
18847144Sbostic break;
18947144Sbostic case VSASSIGN:
19047144Sbostic putc('=', fp);
19147144Sbostic break;
19269090Sbostic case VSTRIMLEFT:
19369090Sbostic putc('#', fp);
19469090Sbostic break;
19569090Sbostic case VSTRIMLEFTMAX:
19669090Sbostic putc('#', fp);
19769090Sbostic putc('#', fp);
19869090Sbostic break;
19969090Sbostic case VSTRIMRIGHT:
20069090Sbostic putc('%', fp);
20169090Sbostic break;
20269090Sbostic case VSTRIMRIGHTMAX:
20369090Sbostic putc('%', fp);
20469090Sbostic putc('%', fp);
20569090Sbostic break;
20669090Sbostic case VSLENGTH:
20769090Sbostic break;
20847144Sbostic default:
20947144Sbostic printf("<subtype %d>", subtype);
21047144Sbostic }
21147144Sbostic break;
21247144Sbostic case CTLENDVAR:
21347144Sbostic putc('}', fp);
21447144Sbostic break;
21547144Sbostic case CTLBACKQ:
21647144Sbostic case CTLBACKQ|CTLQUOTE:
21747144Sbostic putc('$', fp);
21847144Sbostic putc('(', fp);
21947144Sbostic shtree(bqlist->n, -1, NULL, fp);
22047144Sbostic putc(')', fp);
22147144Sbostic break;
22247144Sbostic default:
22347144Sbostic putc(*p, fp);
22447144Sbostic break;
22547144Sbostic }
22647144Sbostic }
22747144Sbostic }
22847144Sbostic
22947144Sbostic
230*69272Schristos static void
indent(amount,pfx,fp)23147144Sbostic indent(amount, pfx, fp)
232*69272Schristos int amount;
23347144Sbostic char *pfx;
23447144Sbostic FILE *fp;
235*69272Schristos {
23647144Sbostic int i;
23747144Sbostic
23847144Sbostic for (i = 0 ; i < amount ; i++) {
23947144Sbostic if (pfx && i == amount - 1)
24047144Sbostic fputs(pfx, fp);
24147144Sbostic putc('\t', fp);
24247144Sbostic }
24347144Sbostic }
24447144Sbostic #endif
24547144Sbostic
24647144Sbostic
24747144Sbostic
24847144Sbostic /*
24947144Sbostic * Debugging stuff.
25047144Sbostic */
25147144Sbostic
25247144Sbostic
25347144Sbostic FILE *tracefile;
25447144Sbostic
25547983Smarc #if DEBUG == 2
25647983Smarc int debug = 1;
25747983Smarc #else
25847983Smarc int debug = 0;
25947983Smarc #endif
26047144Sbostic
26147144Sbostic
262*69272Schristos void
trputc(c)263*69272Schristos trputc(c)
264*69272Schristos int c;
265*69272Schristos {
26647144Sbostic #ifdef DEBUG
26747144Sbostic if (tracefile == NULL)
26847144Sbostic return;
26947144Sbostic putc(c, tracefile);
27047144Sbostic if (c == '\n')
27147144Sbostic fflush(tracefile);
27247144Sbostic #endif
27347144Sbostic }
27447144Sbostic
275*69272Schristos void
276*69272Schristos #if __STDC__
trace(const char * fmt,...)277*69272Schristos trace(const char *fmt, ...)
278*69272Schristos #else
279*69272Schristos trace(va_alist)
280*69272Schristos va_dcl
281*69272Schristos #endif
282*69272Schristos {
283*69272Schristos #ifdef DEBUG
284*69272Schristos va_list va;
285*69272Schristos #if __STDC__
286*69272Schristos va_start(va, fmt);
287*69272Schristos #else
28847144Sbostic char *fmt;
289*69272Schristos va_start(va);
290*69272Schristos fmt = va_arg(va, char *);
29147144Sbostic #endif
292*69272Schristos if (tracefile != NULL) {
293*69272Schristos (void) vfprintf(tracefile, fmt, va);
294*69272Schristos if (strchr(fmt, '\n'))
295*69272Schristos (void) fflush(tracefile);
296*69272Schristos }
297*69272Schristos va_end(va);
298*69272Schristos #endif
29947144Sbostic }
30047144Sbostic
30147144Sbostic
302*69272Schristos void
trputs(s)30347144Sbostic trputs(s)
30447144Sbostic char *s;
305*69272Schristos {
30647144Sbostic #ifdef DEBUG
30747144Sbostic if (tracefile == NULL)
30847144Sbostic return;
30947144Sbostic fputs(s, tracefile);
31047144Sbostic if (strchr(s, '\n'))
31147144Sbostic fflush(tracefile);
31247144Sbostic #endif
31347144Sbostic }
31447144Sbostic
31547144Sbostic
316*69272Schristos static void
trstring(s)31747144Sbostic trstring(s)
31847144Sbostic char *s;
319*69272Schristos {
32047144Sbostic register char *p;
32147144Sbostic char c;
32247144Sbostic
32347144Sbostic #ifdef DEBUG
32447144Sbostic if (tracefile == NULL)
32547144Sbostic return;
32647144Sbostic putc('"', tracefile);
32747144Sbostic for (p = s ; *p ; p++) {
32847144Sbostic switch (*p) {
32947144Sbostic case '\n': c = 'n'; goto backslash;
33047144Sbostic case '\t': c = 't'; goto backslash;
33147144Sbostic case '\r': c = 'r'; goto backslash;
33247144Sbostic case '"': c = '"'; goto backslash;
33347144Sbostic case '\\': c = '\\'; goto backslash;
33447144Sbostic case CTLESC: c = 'e'; goto backslash;
33547144Sbostic case CTLVAR: c = 'v'; goto backslash;
33647144Sbostic case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
33747144Sbostic case CTLBACKQ: c = 'q'; goto backslash;
33847144Sbostic case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
33947144Sbostic backslash: putc('\\', tracefile);
34047144Sbostic putc(c, tracefile);
34147144Sbostic break;
34247144Sbostic default:
34347144Sbostic if (*p >= ' ' && *p <= '~')
34447144Sbostic putc(*p, tracefile);
34547144Sbostic else {
34647144Sbostic putc('\\', tracefile);
34747144Sbostic putc(*p >> 6 & 03, tracefile);
34847144Sbostic putc(*p >> 3 & 07, tracefile);
34947144Sbostic putc(*p & 07, tracefile);
35047144Sbostic }
35147144Sbostic break;
35247144Sbostic }
35347144Sbostic }
35447144Sbostic putc('"', tracefile);
35547144Sbostic #endif
35647144Sbostic }
35747144Sbostic
35847144Sbostic
359*69272Schristos void
trargs(ap)36047144Sbostic trargs(ap)
36147144Sbostic char **ap;
362*69272Schristos {
36347144Sbostic #ifdef DEBUG
36447144Sbostic if (tracefile == NULL)
36547144Sbostic return;
36647144Sbostic while (*ap) {
36747144Sbostic trstring(*ap++);
36847144Sbostic if (*ap)
36947144Sbostic putc(' ', tracefile);
37047144Sbostic else
37147144Sbostic putc('\n', tracefile);
37247144Sbostic }
37347144Sbostic fflush(tracefile);
37447144Sbostic #endif
37547144Sbostic }
37647144Sbostic
37747144Sbostic
378*69272Schristos void
opentrace()37947144Sbostic opentrace() {
38047144Sbostic char s[100];
38147144Sbostic char *getenv();
382*69272Schristos #ifdef O_APPEND
38347144Sbostic int flags;
384*69272Schristos #endif
38547144Sbostic
38647144Sbostic #ifdef DEBUG
38747983Smarc if (!debug)
38847983Smarc return;
38955226Smarc #ifdef not_this_way
390*69272Schristos {
391*69272Schristos char *p;
392*69272Schristos if ((p = getenv("HOME")) == NULL) {
393*69272Schristos if (geteuid() == 0)
394*69272Schristos p = "/";
395*69272Schristos else
396*69272Schristos p = "/tmp";
397*69272Schristos }
398*69272Schristos scopy(p, s);
399*69272Schristos strcat(s, "/trace");
40047983Smarc }
40155226Smarc #else
40255226Smarc scopy("./trace", s);
40355226Smarc #endif /* not_this_way */
40447144Sbostic if ((tracefile = fopen(s, "a")) == NULL) {
40547144Sbostic fprintf(stderr, "Can't open %s\n", s);
40647983Smarc return;
40747144Sbostic }
40847144Sbostic #ifdef O_APPEND
40947144Sbostic if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
41047144Sbostic fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
41147144Sbostic #endif
41247144Sbostic fputs("\nTracing started.\n", tracefile);
41347144Sbostic fflush(tracefile);
41455226Smarc #endif /* DEBUG */
41547144Sbostic }
416