show.c revision 90111
174667Sjedgar/*- 290781Sjedgar * Copyright (c) 1991, 1993 374667Sjedgar * The Regents of the University of California. All rights reserved. 474667Sjedgar * 574667Sjedgar * This code is derived from software contributed to Berkeley by 674667Sjedgar * Kenneth Almquist. 774667Sjedgar * 874667Sjedgar * Redistribution and use in source and binary forms, with or without 974667Sjedgar * modification, are permitted provided that the following conditions 1074667Sjedgar * are met: 1174667Sjedgar * 1. Redistributions of source code must retain the above copyright 1274667Sjedgar * notice, this list of conditions and the following disclaimer. 1374667Sjedgar * 2. Redistributions in binary form must reproduce the above copyright 1474667Sjedgar * notice, this list of conditions and the following disclaimer in the 1574667Sjedgar * documentation and/or other materials provided with the distribution. 1674667Sjedgar * 3. All advertising materials mentioning features or use of this software 17184607Simp * must display the following acknowledgement: 18184607Simp * This product includes software developed by the University of 19184607Simp * California, Berkeley and its contributors. 20184607Simp * 4. Neither the name of the University nor the names of its contributors 21184607Simp * may be used to endorse or promote products derived from this software 22184607Simp * without specific prior written permission. 23184607Simp * 24184607Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2574667Sjedgar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2674667Sjedgar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2792986Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2892986Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2992986Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3074667Sjedgar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3175185Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3274667Sjedgar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3375185Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3474667Sjedgar * SUCH DAMAGE. 3574667Sjedgar */ 3674667Sjedgar 3774667Sjedgar#ifndef lint 3874667Sjedgar#if 0 3975928Sjedgarstatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 4074667Sjedgar#endif 4174667Sjedgarstatic const char rcsid[] = 4274667Sjedgar "$FreeBSD: head/bin/sh/show.c 90111 2002-02-02 06:50:57Z imp $"; 4374667Sjedgar#endif /* not lint */ 4474667Sjedgar 4574667Sjedgar#include <stdio.h> 4690781Sjedgar#include <stdarg.h> 4774667Sjedgar#include <errno.h> 4890781Sjedgar 4974667Sjedgar#include "shell.h" 5074667Sjedgar#include "parser.h" 5174667Sjedgar#include "nodes.h" 5274667Sjedgar#include "mystring.h" 5374667Sjedgar#include "show.h" 5474667Sjedgar 5590781Sjedgar 5674667Sjedgar#ifdef DEBUG 5774667Sjedgarstatic void shtree(union node *, int, char *, FILE*); 5874667Sjedgarstatic void shcmd(union node *, FILE *); 5974667Sjedgarstatic void sharg(union node *, FILE *); 6074667Sjedgarstatic void indent(int, char *, FILE *); 6174667Sjedgarstatic void trstring(char *); 6274667Sjedgar 6390781Sjedgar 6474667Sjedgarvoid 6574667Sjedgarshowtree(union node *n) 6674667Sjedgar{ 6774667Sjedgar trputs("showtree called\n"); 6874667Sjedgar shtree(n, 1, NULL, stdout); 6974667Sjedgar} 7074667Sjedgar 7190781Sjedgar 7274667Sjedgarstatic void 73shtree(union node *n, int ind, char *pfx, FILE *fp) 74{ 75 struct nodelist *lp; 76 char *s; 77 78 if (n == NULL) 79 return; 80 81 indent(ind, pfx, fp); 82 switch(n->type) { 83 case NSEMI: 84 s = "; "; 85 goto binop; 86 case NAND: 87 s = " && "; 88 goto binop; 89 case NOR: 90 s = " || "; 91binop: 92 shtree(n->nbinary.ch1, ind, NULL, fp); 93 /* if (ind < 0) */ 94 fputs(s, fp); 95 shtree(n->nbinary.ch2, ind, NULL, fp); 96 break; 97 case NCMD: 98 shcmd(n, fp); 99 if (ind >= 0) 100 putc('\n', fp); 101 break; 102 case NPIPE: 103 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 104 shcmd(lp->n, fp); 105 if (lp->next) 106 fputs(" | ", fp); 107 } 108 if (n->npipe.backgnd) 109 fputs(" &", fp); 110 if (ind >= 0) 111 putc('\n', fp); 112 break; 113 default: 114 fprintf(fp, "<node type %d>", n->type); 115 if (ind >= 0) 116 putc('\n', fp); 117 break; 118 } 119} 120 121 122 123static void 124shcmd(union node *cmd, FILE *fp) 125{ 126 union node *np; 127 int first; 128 char *s; 129 int dftfd; 130 131 first = 1; 132 for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 133 if (! first) 134 putchar(' '); 135 sharg(np, fp); 136 first = 0; 137 } 138 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 139 if (! first) 140 putchar(' '); 141 switch (np->nfile.type) { 142 case NTO: s = ">"; dftfd = 1; break; 143 case NAPPEND: s = ">>"; dftfd = 1; break; 144 case NTOFD: s = ">&"; dftfd = 1; break; 145 case NFROM: s = "<"; dftfd = 0; break; 146 case NFROMTO: s = "<>"; dftfd = 0; break; 147 case NFROMFD: s = "<&"; dftfd = 0; break; 148 default: s = "*error*"; dftfd = 0; break; 149 } 150 if (np->nfile.fd != dftfd) 151 fprintf(fp, "%d", np->nfile.fd); 152 fputs(s, fp); 153 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 154 fprintf(fp, "%d", np->ndup.dupfd); 155 } else { 156 sharg(np->nfile.fname, fp); 157 } 158 first = 0; 159 } 160} 161 162 163 164static void 165sharg(union node *arg, FILE *fp) 166{ 167 char *p; 168 struct nodelist *bqlist; 169 int subtype; 170 171 if (arg->type != NARG) { 172 printf("<node type %d>\n", arg->type); 173 fflush(stdout); 174 abort(); 175 } 176 bqlist = arg->narg.backquote; 177 for (p = arg->narg.text ; *p ; p++) { 178 switch (*p) { 179 case CTLESC: 180 putc(*++p, fp); 181 break; 182 case CTLVAR: 183 putc('$', fp); 184 putc('{', fp); 185 subtype = *++p; 186 if (subtype == VSLENGTH) 187 putc('#', fp); 188 189 while (*p != '=') 190 putc(*p++, fp); 191 192 if (subtype & VSNUL) 193 putc(':', fp); 194 195 switch (subtype & VSTYPE) { 196 case VSNORMAL: 197 putc('}', fp); 198 break; 199 case VSMINUS: 200 putc('-', fp); 201 break; 202 case VSPLUS: 203 putc('+', fp); 204 break; 205 case VSQUESTION: 206 putc('?', fp); 207 break; 208 case VSASSIGN: 209 putc('=', fp); 210 break; 211 case VSTRIMLEFT: 212 putc('#', fp); 213 break; 214 case VSTRIMLEFTMAX: 215 putc('#', fp); 216 putc('#', fp); 217 break; 218 case VSTRIMRIGHT: 219 putc('%', fp); 220 break; 221 case VSTRIMRIGHTMAX: 222 putc('%', fp); 223 putc('%', fp); 224 break; 225 case VSLENGTH: 226 break; 227 default: 228 printf("<subtype %d>", subtype); 229 } 230 break; 231 case CTLENDVAR: 232 putc('}', fp); 233 break; 234 case CTLBACKQ: 235 case CTLBACKQ|CTLQUOTE: 236 putc('$', fp); 237 putc('(', fp); 238 shtree(bqlist->n, -1, NULL, fp); 239 putc(')', fp); 240 break; 241 default: 242 putc(*p, fp); 243 break; 244 } 245 } 246} 247 248 249static void 250indent(int amount, char *pfx, FILE *fp) 251{ 252 int i; 253 254 for (i = 0 ; i < amount ; i++) { 255 if (pfx && i == amount - 1) 256 fputs(pfx, fp); 257 putc('\t', fp); 258 } 259} 260 261 262/* 263 * Debugging stuff. 264 */ 265 266 267FILE *tracefile; 268 269#if DEBUG == 2 270int debug = 1; 271#else 272int debug = 0; 273#endif 274 275 276void 277trputc(int c) 278{ 279 if (tracefile == NULL) 280 return; 281 putc(c, tracefile); 282 if (c == '\n') 283 fflush(tracefile); 284} 285 286 287void 288sh_trace(const char *fmt, ...) 289{ 290 va_list va; 291 va_start(va, fmt); 292 if (tracefile != NULL) { 293 (void) vfprintf(tracefile, fmt, va); 294 if (strchr(fmt, '\n')) 295 (void) fflush(tracefile); 296 } 297 va_end(va); 298} 299 300 301void 302trputs(char *s) 303{ 304 if (tracefile == NULL) 305 return; 306 fputs(s, tracefile); 307 if (strchr(s, '\n')) 308 fflush(tracefile); 309} 310 311 312static void 313trstring(char *s) 314{ 315 char *p; 316 char c; 317 318 if (tracefile == NULL) 319 return; 320 putc('"', tracefile); 321 for (p = s ; *p ; p++) { 322 switch (*p) { 323 case '\n': c = 'n'; goto backslash; 324 case '\t': c = 't'; goto backslash; 325 case '\r': c = 'r'; goto backslash; 326 case '"': c = '"'; goto backslash; 327 case '\\': c = '\\'; goto backslash; 328 case CTLESC: c = 'e'; goto backslash; 329 case CTLVAR: c = 'v'; goto backslash; 330 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 331 case CTLBACKQ: c = 'q'; goto backslash; 332 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 333backslash: putc('\\', tracefile); 334 putc(c, tracefile); 335 break; 336 default: 337 if (*p >= ' ' && *p <= '~') 338 putc(*p, tracefile); 339 else { 340 putc('\\', tracefile); 341 putc(*p >> 6 & 03, tracefile); 342 putc(*p >> 3 & 07, tracefile); 343 putc(*p & 07, tracefile); 344 } 345 break; 346 } 347 } 348 putc('"', tracefile); 349} 350 351 352void 353trargs(char **ap) 354{ 355 if (tracefile == NULL) 356 return; 357 while (*ap) { 358 trstring(*ap++); 359 if (*ap) 360 putc(' ', tracefile); 361 else 362 putc('\n', tracefile); 363 } 364 fflush(tracefile); 365} 366 367 368void 369opentrace(void) 370{ 371 char s[100]; 372 char *getenv(); 373#ifdef O_APPEND 374 int flags; 375#endif 376 377 if (!debug) 378 return; 379#ifdef not_this_way 380 { 381 char *p; 382 if ((p = getenv("HOME")) == NULL) { 383 if (geteuid() == 0) 384 p = "/"; 385 else 386 p = "/tmp"; 387 } 388 scopy(p, s); 389 strcat(s, "/trace"); 390 } 391#else 392 scopy("./trace", s); 393#endif /* not_this_way */ 394 if ((tracefile = fopen(s, "a")) == NULL) { 395 fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 396 return; 397 } 398#ifdef O_APPEND 399 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 400 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 401#endif 402 fputs("\nTracing started.\n", tracefile); 403 fflush(tracefile); 404} 405#endif /* DEBUG */ 406