show.c revision 59437
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 * 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. 35 */ 36 37#ifndef lint 38#if 0 39static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 40#endif 41static const char rcsid[] = 42 "$FreeBSD: head/bin/sh/show.c 59437 2000-04-20 09:55:57Z cracauer $"; 43#endif /* not lint */ 44 45#include <stdio.h> 46#ifdef __STDC__ 47#include <stdarg.h> 48#else 49#include <varargs.h> 50#endif 51#if DEBUG == 2 52#include <errno.h> 53#endif 54 55#include "shell.h" 56#include "parser.h" 57#include "nodes.h" 58#include "mystring.h" 59#include "show.h" 60 61 62#ifdef DEBUG 63static void shtree __P((union node *, int, char *, FILE*)); 64static void shcmd __P((union node *, FILE *)); 65static void sharg __P((union node *, FILE *)); 66static void indent __P((int, char *, FILE *)); 67static void trstring __P((char *)); 68 69 70void 71showtree(n) 72 union node *n; 73{ 74 trputs("showtree called\n"); 75 shtree(n, 1, NULL, stdout); 76} 77 78 79static void 80shtree(n, ind, pfx, fp) 81 union node *n; 82 int ind; 83 char *pfx; 84 FILE *fp; 85{ 86 struct nodelist *lp; 87 char *s; 88 89 if (n == NULL) 90 return; 91 92 indent(ind, pfx, fp); 93 switch(n->type) { 94 case NSEMI: 95 s = "; "; 96 goto binop; 97 case NAND: 98 s = " && "; 99 goto binop; 100 case NOR: 101 s = " || "; 102binop: 103 shtree(n->nbinary.ch1, ind, NULL, fp); 104 /* if (ind < 0) */ 105 fputs(s, fp); 106 shtree(n->nbinary.ch2, ind, NULL, fp); 107 break; 108 case NCMD: 109 shcmd(n, fp); 110 if (ind >= 0) 111 putc('\n', fp); 112 break; 113 case NPIPE: 114 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 115 shcmd(lp->n, fp); 116 if (lp->next) 117 fputs(" | ", fp); 118 } 119 if (n->npipe.backgnd) 120 fputs(" &", fp); 121 if (ind >= 0) 122 putc('\n', fp); 123 break; 124 default: 125 fprintf(fp, "<node type %d>", n->type); 126 if (ind >= 0) 127 putc('\n', fp); 128 break; 129 } 130} 131 132 133 134static void 135shcmd(cmd, fp) 136 union node *cmd; 137 FILE *fp; 138{ 139 union node *np; 140 int first; 141 char *s; 142 int dftfd; 143 144 first = 1; 145 for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 146 if (! first) 147 putchar(' '); 148 sharg(np, fp); 149 first = 0; 150 } 151 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 152 if (! first) 153 putchar(' '); 154 switch (np->nfile.type) { 155 case NTO: s = ">"; dftfd = 1; break; 156 case NAPPEND: s = ">>"; dftfd = 1; break; 157 case NTOFD: s = ">&"; dftfd = 1; break; 158 case NFROM: s = "<"; dftfd = 0; break; 159 case NFROMFD: s = "<&"; dftfd = 0; break; 160 default: s = "*error*"; dftfd = 0; break; 161 } 162 if (np->nfile.fd != dftfd) 163 fprintf(fp, "%d", np->nfile.fd); 164 fputs(s, fp); 165 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 166 fprintf(fp, "%d", np->ndup.dupfd); 167 } else { 168 sharg(np->nfile.fname, fp); 169 } 170 first = 0; 171 } 172} 173 174 175 176static void 177sharg(arg, fp) 178 union node *arg; 179 FILE *fp; 180 { 181 char *p; 182 struct nodelist *bqlist; 183 int subtype; 184 185 if (arg->type != NARG) { 186 printf("<node type %d>\n", arg->type); 187 fflush(stdout); 188 abort(); 189 } 190 bqlist = arg->narg.backquote; 191 for (p = arg->narg.text ; *p ; p++) { 192 switch (*p) { 193 case CTLESC: 194 putc(*++p, fp); 195 break; 196 case CTLVAR: 197 putc('$', fp); 198 putc('{', fp); 199 subtype = *++p; 200 if (subtype == VSLENGTH) 201 putc('#', fp); 202 203 while (*p != '=') 204 putc(*p++, fp); 205 206 if (subtype & VSNUL) 207 putc(':', fp); 208 209 switch (subtype & VSTYPE) { 210 case VSNORMAL: 211 putc('}', fp); 212 break; 213 case VSMINUS: 214 putc('-', fp); 215 break; 216 case VSPLUS: 217 putc('+', fp); 218 break; 219 case VSQUESTION: 220 putc('?', fp); 221 break; 222 case VSASSIGN: 223 putc('=', fp); 224 break; 225 case VSTRIMLEFT: 226 putc('#', fp); 227 break; 228 case VSTRIMLEFTMAX: 229 putc('#', fp); 230 putc('#', fp); 231 break; 232 case VSTRIMRIGHT: 233 putc('%', fp); 234 break; 235 case VSTRIMRIGHTMAX: 236 putc('%', fp); 237 putc('%', fp); 238 break; 239 case VSLENGTH: 240 break; 241 default: 242 printf("<subtype %d>", subtype); 243 } 244 break; 245 case CTLENDVAR: 246 putc('}', fp); 247 break; 248 case CTLBACKQ: 249 case CTLBACKQ|CTLQUOTE: 250 putc('$', fp); 251 putc('(', fp); 252 shtree(bqlist->n, -1, NULL, fp); 253 putc(')', fp); 254 break; 255 default: 256 putc(*p, fp); 257 break; 258 } 259 } 260} 261 262 263static void 264indent(amount, pfx, fp) 265 int amount; 266 char *pfx; 267 FILE *fp; 268{ 269 int i; 270 271 for (i = 0 ; i < amount ; i++) { 272 if (pfx && i == amount - 1) 273 fputs(pfx, fp); 274 putc('\t', fp); 275 } 276} 277 278 279/* 280 * Debugging stuff. 281 */ 282 283 284FILE *tracefile; 285 286#if DEBUG == 2 287int debug = 1; 288#else 289int debug = 0; 290#endif 291 292 293void 294trputc(c) 295 int c; 296{ 297 if (tracefile == NULL) 298 return; 299 putc(c, tracefile); 300 if (c == '\n') 301 fflush(tracefile); 302} 303 304 305void 306#ifdef __STDC__ 307trace(const char *fmt, ...) 308#else 309trace(va_alist) 310 va_dcl 311#endif 312{ 313 va_list va; 314#ifdef __STDC__ 315 va_start(va, fmt); 316#else 317 char *fmt; 318 va_start(va); 319 fmt = va_arg(va, char *); 320#endif 321 if (tracefile != NULL) { 322 (void) vfprintf(tracefile, fmt, va); 323 if (strchr(fmt, '\n')) 324 (void) fflush(tracefile); 325 } 326 va_end(va); 327} 328 329 330void 331trputs(s) 332 char *s; 333{ 334 if (tracefile == NULL) 335 return; 336 fputs(s, tracefile); 337 if (strchr(s, '\n')) 338 fflush(tracefile); 339} 340 341 342static void 343trstring(s) 344 char *s; 345{ 346 char *p; 347 char c; 348 349 if (tracefile == NULL) 350 return; 351 putc('"', tracefile); 352 for (p = s ; *p ; p++) { 353 switch (*p) { 354 case '\n': c = 'n'; goto backslash; 355 case '\t': c = 't'; goto backslash; 356 case '\r': c = 'r'; goto backslash; 357 case '"': c = '"'; goto backslash; 358 case '\\': c = '\\'; goto backslash; 359 case CTLESC: c = 'e'; goto backslash; 360 case CTLVAR: c = 'v'; goto backslash; 361 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 362 case CTLBACKQ: c = 'q'; goto backslash; 363 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 364backslash: putc('\\', tracefile); 365 putc(c, tracefile); 366 break; 367 default: 368 if (*p >= ' ' && *p <= '~') 369 putc(*p, tracefile); 370 else { 371 putc('\\', tracefile); 372 putc(*p >> 6 & 03, tracefile); 373 putc(*p >> 3 & 07, tracefile); 374 putc(*p & 07, tracefile); 375 } 376 break; 377 } 378 } 379 putc('"', tracefile); 380} 381 382 383void 384trargs(ap) 385 char **ap; 386{ 387 if (tracefile == NULL) 388 return; 389 while (*ap) { 390 trstring(*ap++); 391 if (*ap) 392 putc(' ', tracefile); 393 else 394 putc('\n', tracefile); 395 } 396 fflush(tracefile); 397} 398 399 400void 401opentrace() { 402 char s[100]; 403 char *getenv(); 404#ifdef O_APPEND 405 int flags; 406#endif 407 408 if (!debug) 409 return; 410#ifdef not_this_way 411 { 412 char *p; 413 if ((p = getenv("HOME")) == NULL) { 414 if (geteuid() == 0) 415 p = "/"; 416 else 417 p = "/tmp"; 418 } 419 scopy(p, s); 420 strcat(s, "/trace"); 421 } 422#else 423 scopy("./trace", s); 424#endif /* not_this_way */ 425 if ((tracefile = fopen(s, "a")) == NULL) { 426 fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 427 return; 428 } 429#ifdef O_APPEND 430 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 431 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 432#endif 433 fputs("\nTracing started.\n", tracefile); 434 fflush(tracefile); 435} 436#endif /* DEBUG */ 437