1127664Sbms/*- 2127664Sbms * SPDX-License-Identifier: BSD-3-Clause 3127664Sbms * 4127664Sbms * Copyright (c) 1991, 1993 5127664Sbms * The Regents of the University of California. All rights reserved. 6127664Sbms * 7127664Sbms * This code is derived from software contributed to Berkeley by 8127664Sbms * Kenneth Almquist. 9127664Sbms * 10127664Sbms * Redistribution and use in source and binary forms, with or without 11127664Sbms * modification, are permitted provided that the following conditions 12146768Ssam * are met: 13162012Ssam * 1. Redistributions of source code must retain the above copyright 14162012Ssam * notice, this list of conditions and the following disclaimer. 15162012Ssam * 2. Redistributions in binary form must reproduce the above copyright 16127664Sbms * notice, this list of conditions and the following disclaimer in the 17127664Sbms * documentation and/or other materials provided with the distribution. 18127664Sbms * 3. Neither the name of the University nor the names of its contributors 19127664Sbms * may be used to endorse or promote products derived from this software 20190225Srpaulo * without specific prior written permission. 21127664Sbms * 22127664Sbms * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23127664Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24127664Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25127664Sbms * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26127664Sbms * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27127664Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28127664Sbms * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29127664Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30127664Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31127664Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32127664Sbms * SUCH DAMAGE. 33127664Sbms */ 34127664Sbms 35127664Sbms#include <fcntl.h> 36127664Sbms#include <stdio.h> 37127664Sbms#include <stdlib.h> 38127664Sbms#include <stdarg.h> 39127664Sbms#include <errno.h> 40127664Sbms 41127664Sbms#include "shell.h" 42127664Sbms#include "parser.h" 43127664Sbms#include "nodes.h" 44127664Sbms#include "mystring.h" 45127664Sbms#include "show.h" 46146768Ssam 47146768Ssam 48127664Sbms#ifdef DEBUG 49190225Srpaulostatic void shtree(union node *, int, char *, FILE*); 50190225Srpaulostatic void shcmd(union node *, FILE *); 51146768Ssamstatic void sharg(union node *, FILE *); 52146768Ssamstatic void indent(int, char *, FILE *); 53127664Sbmsstatic void trstring(char *); 54172677Smlaier 55172677Smlaier 56172677Smlaiervoid 57172677Smlaiershowtree(union node *n) 58172677Smlaier{ 59172677Smlaier trputs("showtree called\n"); 60172677Smlaier shtree(n, 1, NULL, stdout); 61172677Smlaier} 62172677Smlaier 63172677Smlaier 64172677Smlaierstatic void 65172677Smlaiershtree(union node *n, int ind, char *pfx, FILE *fp) 66146768Ssam{ 67146768Ssam struct nodelist *lp; 68146768Ssam const char *s; 69146768Ssam 70146768Ssam if (n == NULL) 71146768Ssam return; 72146768Ssam 73127664Sbms indent(ind, pfx, fp); 74146768Ssam switch(n->type) { 75146768Ssam case NSEMI: 76146768Ssam s = "; "; 77127664Sbms goto binop; 78127664Sbms case NAND: 79127664Sbms s = " && "; 80127664Sbms goto binop; 81127664Sbms case NOR: 82127664Sbms s = " || "; 83127664Sbmsbinop: 84127664Sbms shtree(n->nbinary.ch1, ind, NULL, fp); 85127664Sbms /* if (ind < 0) */ 86127664Sbms fputs(s, fp); 87127664Sbms shtree(n->nbinary.ch2, ind, NULL, fp); 88127664Sbms break; 89127664Sbms case NCMD: 90190225Srpaulo shcmd(n, fp); 91127664Sbms if (ind >= 0) 92127664Sbms putc('\n', fp); 93127664Sbms break; 94172677Smlaier case NPIPE: 95172677Smlaier for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 96172677Smlaier shcmd(lp->n, fp); 97172677Smlaier if (lp->next) 98127664Sbms fputs(" | ", fp); 99127664Sbms } 100127664Sbms if (n->npipe.backgnd) 101127664Sbms fputs(" &", fp); 102127664Sbms if (ind >= 0) 103127664Sbms putc('\n', fp); 104146768Ssam break; 105146768Ssam default: 106146768Ssam fprintf(fp, "<node type %d>", n->type); 107146768Ssam if (ind >= 0) 108127664Sbms putc('\n', fp); 109146768Ssam break; 110146768Ssam } 111146768Ssam} 112127664Sbms 113146768Ssam 114146768Ssam 115146768Ssamstatic void 116146768Ssamshcmd(union node *cmd, FILE *fp) 117146768Ssam{ 118146768Ssam union node *np; 119146768Ssam int first; 120127664Sbms const char *s; 121127664Sbms int dftfd; 122127664Sbms 123127664Sbms first = 1; 124127664Sbms for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 125127664Sbms if (! first) 126127664Sbms putchar(' '); 127146768Ssam sharg(np, fp); 128190225Srpaulo first = 0; 129146768Ssam } 130162012Ssam for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 131162012Ssam if (! first) 132162012Ssam putchar(' '); 133162012Ssam switch (np->nfile.type) { 134162012Ssam case NTO: s = ">"; dftfd = 1; break; 135146768Ssam case NAPPEND: s = ">>"; dftfd = 1; break; 136162012Ssam case NTOFD: s = ">&"; dftfd = 1; break; 137162012Ssam case NCLOBBER: s = ">|"; dftfd = 1; break; 138127664Sbms case NFROM: s = "<"; dftfd = 0; break; 139146768Ssam case NFROMTO: s = "<>"; dftfd = 0; break; 140146768Ssam case NFROMFD: s = "<&"; dftfd = 0; break; 141162012Ssam case NHERE: s = "<<"; dftfd = 0; break; 142190225Srpaulo case NXHERE: s = "<<"; dftfd = 0; break; 143190225Srpaulo default: s = "*error*"; dftfd = 0; break; 144190225Srpaulo } 145190225Srpaulo if (np->nfile.fd != dftfd) 146190225Srpaulo fprintf(fp, "%d", np->nfile.fd); 147190225Srpaulo fputs(s, fp); 148190225Srpaulo if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 149146768Ssam if (np->ndup.dupfd >= 0) 150146768Ssam fprintf(fp, "%d", np->ndup.dupfd); 151127664Sbms else 152127664Sbms fprintf(fp, "-"); 153146768Ssam } else if (np->nfile.type == NHERE) { 154146768Ssam fprintf(fp, "HERE"); 155146768Ssam } else if (np->nfile.type == NXHERE) { 156146768Ssam fprintf(fp, "XHERE"); 157146768Ssam } else { 158190225Srpaulo sharg(np->nfile.fname, fp); 159146768Ssam } 160146768Ssam first = 0; 161146768Ssam } 162146768Ssam} 163127664Sbms 164127664Sbms 165146768Ssam 166146768Ssamstatic void 167146768Ssamsharg(union node *arg, FILE *fp) 168146768Ssam{ 169127664Sbms char *p; 170146768Ssam struct nodelist *bqlist; 171146768Ssam int subtype; 172146768Ssam 173127664Sbms if (arg->type != NARG) { 174146768Ssam printf("<node type %d>\n", arg->type); 175146768Ssam fflush(stdout); 176146768Ssam abort(); 177146768Ssam } 178127664Sbms bqlist = arg->narg.backquote; 179146768Ssam for (p = arg->narg.text ; *p ; p++) { 180146768Ssam switch (*p) { 181146768Ssam case CTLESC: 182127664Sbms putc(*++p, fp); 183146768Ssam break; 184127664Sbms case CTLVAR: 185146768Ssam putc('$', fp); 186127664Sbms putc('{', fp); 187127664Sbms subtype = *++p; 188190225Srpaulo if (subtype == VSLENGTH) 189190225Srpaulo putc('#', fp); 190190225Srpaulo 191190225Srpaulo while (*p != '=') 192190225Srpaulo putc(*p++, fp); 193190225Srpaulo 194190225Srpaulo if (subtype & VSNUL) 195190225Srpaulo putc(':', fp); 196190225Srpaulo 197190225Srpaulo switch (subtype & VSTYPE) { 198190225Srpaulo case VSNORMAL: 199190225Srpaulo putc('}', fp); 200190225Srpaulo break; 201190225Srpaulo case VSMINUS: 202190225Srpaulo putc('-', fp); 203190225Srpaulo break; 204190225Srpaulo case VSPLUS: 205190225Srpaulo putc('+', fp); 206190225Srpaulo break; 207190225Srpaulo case VSQUESTION: 208190225Srpaulo putc('?', fp); 209190225Srpaulo break; 210190225Srpaulo case VSASSIGN: 211190225Srpaulo putc('=', fp); 212190225Srpaulo break; 213190225Srpaulo case VSTRIMLEFT: 214190225Srpaulo putc('#', fp); 215190225Srpaulo break; 216190225Srpaulo case VSTRIMLEFTMAX: 217190225Srpaulo putc('#', fp); 218190225Srpaulo putc('#', fp); 219190225Srpaulo break; 220127664Sbms case VSTRIMRIGHT: 221127664Sbms putc('%', fp); 222127664Sbms break; 223127664Sbms case VSTRIMRIGHTMAX: 224127664Sbms putc('%', fp); 225146768Ssam putc('%', fp); 226146768Ssam break; 227146768Ssam case VSLENGTH: 228127664Sbms break; 229127664Sbms default: 230127664Sbms printf("<subtype %d>", subtype); 231190225Srpaulo } 232127664Sbms break; 233162012Ssam case CTLENDVAR: 234162012Ssam putc('}', fp); 235127664Sbms break; 236162012Ssam case CTLBACKQ: 237162012Ssam case CTLBACKQ|CTLQUOTE: 238162012Ssam putc('$', fp); 239162012Ssam putc('(', fp); 240127664Sbms shtree(bqlist->n, -1, NULL, fp); 241162012Ssam putc(')', fp); 242162012Ssam break; 243162012Ssam default: 244127664Sbms putc(*p, fp); 245162012Ssam break; 246162012Ssam } 247162012Ssam } 248127664Sbms} 249162012Ssam 250162012Ssam 251162012Ssamstatic void 252162012Ssamindent(int amount, char *pfx, FILE *fp) 253162012Ssam{ 254162012Ssam int i; 255162012Ssam 256162012Ssam for (i = 0 ; i < amount ; i++) { 257162012Ssam if (pfx && i == amount - 1) 258162012Ssam fputs(pfx, fp); 259162012Ssam putc('\t', fp); 260162012Ssam } 261190225Srpaulo} 262190225Srpaulo 263190225Srpaulo 264162012Ssam/* 265162012Ssam * Debugging stuff. 266162012Ssam */ 267162012Ssam 268162012Ssam 269162012Ssamstatic FILE *tracefile; 270162012Ssam#if DEBUG >= 2 271162012Ssamint debug = 1; 272162012Ssam#else 273127664Sbmsint debug = 0; 274162012Ssam#endif 275162012Ssam 276162012Ssam 277162012Ssamvoid 278162012Ssamtrputc(int c) 279162012Ssam{ 280162012Ssam if (tracefile == NULL) 281162012Ssam return; 282162012Ssam putc(c, tracefile); 283162012Ssam if (c == '\n') 284146768Ssam fflush(tracefile); 285162012Ssam} 286162012Ssam 287190225Srpaulo 288162012Ssamvoid 289162012Ssamsh_trace(const char *fmt, ...) 290162012Ssam{ 291190225Srpaulo va_list va; 292162012Ssam va_start(va, fmt); 293162012Ssam if (tracefile != NULL) { 294162012Ssam (void) vfprintf(tracefile, fmt, va); 295162012Ssam if (strchr(fmt, '\n')) 296162012Ssam (void) fflush(tracefile); 297162012Ssam } 298190225Srpaulo va_end(va); 299162012Ssam} 300127664Sbms 301162012Ssam 302162012Ssamvoid 303162012Ssamtrputs(const char *s) 304162012Ssam{ 305127664Sbms if (tracefile == NULL) 306162012Ssam return; 307162012Ssam fputs(s, tracefile); 308162012Ssam if (strchr(s, '\n')) 309127664Sbms fflush(tracefile); 310162012Ssam} 311162012Ssam 312162012Ssam 313127664Sbmsstatic void 314162012Ssamtrstring(char *s) 315162012Ssam{ 316162012Ssam char *p; 317162012Ssam char c; 318162012Ssam 319162012Ssam if (tracefile == NULL) 320162012Ssam return; 321162012Ssam putc('"', tracefile); 322162012Ssam for (p = s ; *p ; p++) { 323190225Srpaulo switch (*p) { 324190225Srpaulo case '\n': c = 'n'; goto backslash; 325162012Ssam case '\t': c = 't'; goto backslash; 326162012Ssam case '\r': c = 'r'; goto backslash; 327172677Smlaier case '"': c = '"'; goto backslash; 328172677Smlaier case '\\': c = '\\'; goto backslash; 329172677Smlaier case CTLESC: c = 'e'; goto backslash; 330190225Srpaulo case CTLVAR: c = 'v'; goto backslash; 331190225Srpaulo case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 332172677Smlaier case CTLBACKQ: c = 'q'; goto backslash; 333172677Smlaier case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 334162012Ssambackslash: putc('\\', tracefile); 335127664Sbms putc(c, tracefile); 336146768Ssam break; 337127664Sbms default: 338127664Sbms if (*p >= ' ' && *p <= '~') 339146768Ssam putc(*p, tracefile); 340127664Sbms else { 341127664Sbms putc('\\', tracefile); 342162012Ssam putc(*p >> 6 & 03, tracefile); 343190225Srpaulo putc(*p >> 3 & 07, tracefile); 344190225Srpaulo putc(*p & 07, tracefile); 345190225Srpaulo } 346190225Srpaulo break; 347127664Sbms } 348190225Srpaulo } 349190225Srpaulo putc('"', tracefile); 350190225Srpaulo} 351190225Srpaulo 352190225Srpaulo 353190225Srpaulovoid 354190225Srpaulotrargs(char **ap) 355190225Srpaulo{ 356190225Srpaulo if (tracefile == NULL) 357190225Srpaulo return; 358190225Srpaulo while (*ap) { 359190225Srpaulo trstring(*ap++); 360190225Srpaulo if (*ap) 361190225Srpaulo putc(' ', tracefile); 362190225Srpaulo else 363190225Srpaulo putc('\n', tracefile); 364190225Srpaulo } 365190225Srpaulo fflush(tracefile); 366190225Srpaulo} 367190225Srpaulo 368190225Srpaulo 369190225Srpaulovoid 370190225Srpauloopentrace(void) 371190225Srpaulo{ 372190225Srpaulo char s[100]; 373190225Srpaulo int flags; 374190225Srpaulo 375190225Srpaulo if (!debug) 376190225Srpaulo return; 377190225Srpaulo#ifdef not_this_way 378190225Srpaulo { 379190225Srpaulo char *p; 380190225Srpaulo if ((p = getenv("HOME")) == NULL) { 381190225Srpaulo if (geteuid() == 0) 382190225Srpaulo p = "/"; 383190225Srpaulo else 384190225Srpaulo p = "/tmp"; 385190225Srpaulo } 386190225Srpaulo strcpy(s, p); 387190225Srpaulo strcat(s, "/trace"); 388190225Srpaulo } 389190225Srpaulo#else 390190225Srpaulo strcpy(s, "./trace"); 391190225Srpaulo#endif /* not_this_way */ 392190225Srpaulo if ((tracefile = fopen(s, "a")) == NULL) { 393190225Srpaulo fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 394190225Srpaulo return; 395190225Srpaulo } 396190225Srpaulo if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 397190225Srpaulo fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 398190225Srpaulo fputs("\nTracing started.\n", tracefile); 399190225Srpaulo fflush(tracefile); 400190225Srpaulo} 401190225Srpaulo#endif /* DEBUG */ 402190225Srpaulo