0,0 → 1,447 |
/* $NetBSD: show.c,v 1.18 1999/10/08 21:10:44 pk Exp $ */ |
|
/*- |
* Copyright (c) 1991, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Kenneth Almquist. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
* must display the following acknowledgement: |
* This product includes software developed by the University of |
* California, Berkeley and its contributors. |
* 4. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
*/ |
|
#include <sys/cdefs.h> |
#ifndef lint |
#if 0 |
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; |
#else |
__RCSID("$NetBSD: show.c,v 1.18 1999/10/08 21:10:44 pk Exp $"); |
#endif |
#endif /* not lint */ |
|
#include <stdio.h> |
#ifdef __STDC__ |
#include <stdarg.h> |
#else |
#include <varargs.h> |
#endif |
|
#include "shell.h" |
#include "parser.h" |
#include "nodes.h" |
#include "mystring.h" |
#include "show.h" |
|
|
#ifdef DEBUG |
static void shtree (union node *, int, char *, FILE*); |
static void shcmd (union node *, FILE *); |
static void sharg (union node *, FILE *); |
static void indent (int, char *, FILE *); |
static void trstring (char *); |
|
|
void |
showtree(n) |
union node *n; |
{ |
trputs("showtree called\n"); |
shtree(n, 1, NULL, stdout); |
} |
|
|
static void |
shtree(n, ind, pfx, fp) |
union node *n; |
int ind; |
char *pfx; |
FILE *fp; |
{ |
struct nodelist *lp; |
const char *s; |
|
if (n == NULL) |
return; |
|
indent(ind, pfx, fp); |
switch(n->type) { |
case NSEMI: |
s = "; "; |
goto binop; |
case NAND: |
s = " && "; |
goto binop; |
case NOR: |
s = " || "; |
binop: |
shtree(n->nbinary.ch1, ind, NULL, fp); |
/* if (ind < 0) */ |
fputs(s, fp); |
shtree(n->nbinary.ch2, ind, NULL, fp); |
break; |
case NCMD: |
shcmd(n, fp); |
if (ind >= 0) |
putc('\n', fp); |
break; |
case NPIPE: |
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { |
shcmd(lp->n, fp); |
if (lp->next) |
fputs(" | ", fp); |
} |
if (n->npipe.backgnd) |
fputs(" &", fp); |
if (ind >= 0) |
putc('\n', fp); |
break; |
default: |
fprintf(fp, "<node type %d>", n->type); |
if (ind >= 0) |
putc('\n', fp); |
break; |
} |
} |
|
|
|
static void |
shcmd(cmd, fp) |
union node *cmd; |
FILE *fp; |
{ |
union node *np; |
int first; |
const char *s; |
int dftfd; |
|
first = 1; |
for (np = cmd->ncmd.args ; np ; np = np->narg.next) { |
if (! first) |
putchar(' '); |
sharg(np, fp); |
first = 0; |
} |
for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { |
if (! first) |
putchar(' '); |
switch (np->nfile.type) { |
case NTO: s = ">"; dftfd = 1; break; |
case NAPPEND: s = ">>"; dftfd = 1; break; |
case NTOFD: s = ">&"; dftfd = 1; break; |
case NTOOV: s = ">|"; dftfd = 1; break; |
case NFROM: s = "<"; dftfd = 0; break; |
case NFROMFD: s = "<&"; dftfd = 0; break; |
case NFROMTO: s = "<>"; dftfd = 0; break; |
default: s = "*error*"; dftfd = 0; break; |
} |
if (np->nfile.fd != dftfd) |
fprintf(fp, "%d", np->nfile.fd); |
fputs(s, fp); |
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { |
fprintf(fp, "%d", np->ndup.dupfd); |
} else { |
sharg(np->nfile.fname, fp); |
} |
first = 0; |
} |
} |
|
|
|
static void |
sharg(arg, fp) |
union node *arg; |
FILE *fp; |
{ |
char *p; |
struct nodelist *bqlist; |
int subtype; |
|
if (arg->type != NARG) { |
printf("<node type %d>\n", arg->type); |
fflush(stdout); |
abort(); |
} |
bqlist = arg->narg.backquote; |
for (p = arg->narg.text ; *p ; p++) { |
switch (*p) { |
case CTLESC: |
putc(*++p, fp); |
break; |
case CTLVAR: |
putc('$', fp); |
putc('{', fp); |
subtype = *++p; |
if (subtype == VSLENGTH) |
putc('#', fp); |
|
while (*p != '=') |
putc(*p++, fp); |
|
if (subtype & VSNUL) |
putc(':', fp); |
|
switch (subtype & VSTYPE) { |
case VSNORMAL: |
putc('}', fp); |
break; |
case VSMINUS: |
putc('-', fp); |
break; |
case VSPLUS: |
putc('+', fp); |
break; |
case VSQUESTION: |
putc('?', fp); |
break; |
case VSASSIGN: |
putc('=', fp); |
break; |
case VSTRIMLEFT: |
putc('#', fp); |
break; |
case VSTRIMLEFTMAX: |
putc('#', fp); |
putc('#', fp); |
break; |
case VSTRIMRIGHT: |
putc('%', fp); |
break; |
case VSTRIMRIGHTMAX: |
putc('%', fp); |
putc('%', fp); |
break; |
case VSLENGTH: |
break; |
default: |
printf("<subtype %d>", subtype); |
} |
break; |
case CTLENDVAR: |
putc('}', fp); |
break; |
case CTLBACKQ: |
case CTLBACKQ|CTLQUOTE: |
putc('$', fp); |
putc('(', fp); |
shtree(bqlist->n, -1, NULL, fp); |
putc(')', fp); |
break; |
default: |
putc(*p, fp); |
break; |
} |
} |
} |
|
|
static void |
indent(amount, pfx, fp) |
int amount; |
char *pfx; |
FILE *fp; |
{ |
int i; |
|
for (i = 0 ; i < amount ; i++) { |
if (pfx && i == amount - 1) |
fputs(pfx, fp); |
putc('\t', fp); |
} |
} |
#endif |
|
|
|
/* |
* Debugging stuff. |
*/ |
|
|
FILE *tracefile; |
|
#if DEBUG == 2 |
int debug = 1; |
#else |
int debug = 0; |
#endif |
|
|
#ifdef DEBUG |
void |
trputc(c) |
int c; |
{ |
if (tracefile == NULL) |
return; |
putc(c, tracefile); |
if (c == '\n') |
fflush(tracefile); |
} |
#endif |
|
void |
#ifdef __STDC__ |
trace(const char *fmt, ...) |
#else |
trace(va_alist) |
va_dcl |
#endif |
{ |
#ifdef DEBUG |
va_list va; |
#ifdef __STDC__ |
va_start(va, fmt); |
#else |
char *fmt; |
va_start(va); |
fmt = va_arg(va, char *); |
#endif |
if (tracefile != NULL) { |
(void) vfprintf(tracefile, fmt, va); |
if (strchr(fmt, '\n')) |
(void) fflush(tracefile); |
} |
va_end(va); |
#endif |
} |
|
|
#ifdef DEBUG |
void |
trputs(s) |
const char *s; |
{ |
if (tracefile == NULL) |
return; |
fputs(s, tracefile); |
if (strchr(s, '\n')) |
fflush(tracefile); |
} |
|
|
static void |
trstring(s) |
char *s; |
{ |
char *p; |
char c; |
|
if (tracefile == NULL) |
return; |
putc('"', tracefile); |
for (p = s ; *p ; p++) { |
switch (*p) { |
case '\n': c = 'n'; goto backslash; |
case '\t': c = 't'; goto backslash; |
case '\r': c = 'r'; goto backslash; |
case '"': c = '"'; goto backslash; |
case '\\': c = '\\'; goto backslash; |
case CTLESC: c = 'e'; goto backslash; |
case CTLVAR: c = 'v'; goto backslash; |
case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; |
case CTLBACKQ: c = 'q'; goto backslash; |
case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; |
backslash: putc('\\', tracefile); |
putc(c, tracefile); |
break; |
default: |
if (*p >= ' ' && *p <= '~') |
putc(*p, tracefile); |
else { |
putc('\\', tracefile); |
putc(*p >> 6 & 03, tracefile); |
putc(*p >> 3 & 07, tracefile); |
putc(*p & 07, tracefile); |
} |
break; |
} |
} |
putc('"', tracefile); |
} |
#endif |
|
|
void |
trargs(ap) |
char **ap; |
{ |
#ifdef DEBUG |
if (tracefile == NULL) |
return; |
while (*ap) { |
trstring(*ap++); |
if (*ap) |
putc(' ', tracefile); |
else |
putc('\n', tracefile); |
} |
fflush(tracefile); |
#endif |
} |
|
|
#ifdef DEBUG |
void |
opentrace() { |
char s[100]; |
#ifdef O_APPEND |
int flags; |
#endif |
|
if (!debug) |
return; |
#ifdef not_this_way |
{ |
char *p; |
if ((p = getenv("HOME")) == NULL) { |
if (geteuid() == 0) |
p = "/"; |
else |
p = "/tmp"; |
} |
scopy(p, s); |
strcat(s, "/trace"); |
} |
#else |
scopy("./trace", s); |
#endif /* not_this_way */ |
if ((tracefile = fopen(s, "a")) == NULL) { |
fprintf(stderr, "Can't open %s\n", s); |
return; |
} |
#ifdef O_APPEND |
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) |
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); |
#endif |
fputs("\nTracing started.\n", tracefile); |
fflush(tracefile); |
} |
#endif /* DEBUG */ |