11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3436150Scharnier#if 0 3536150Scharnierstatic char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; 3636150Scharnier#endif 371556Srgrimes#endif /* not lint */ 3899110Sobrien#include <sys/cdefs.h> 3999110Sobrien__FBSDID("$FreeBSD$"); 401556Srgrimes 4117987Speter#include <sys/types.h> 4296922Stjr#include <sys/stat.h> 4317987Speter#include <signal.h> 4417987Speter#include <string.h> 4517987Speter#include <fcntl.h> 4617987Speter#include <errno.h> 4717987Speter#include <unistd.h> 4817987Speter#include <stdlib.h> 4917987Speter 501556Srgrimes/* 511556Srgrimes * Code for dealing with input/output redirection. 521556Srgrimes */ 531556Srgrimes 541556Srgrimes#include "shell.h" 551556Srgrimes#include "nodes.h" 561556Srgrimes#include "jobs.h" 571556Srgrimes#include "expand.h" 581556Srgrimes#include "redir.h" 591556Srgrimes#include "output.h" 601556Srgrimes#include "memalloc.h" 611556Srgrimes#include "error.h" 6296922Stjr#include "options.h" 631556Srgrimes 641556Srgrimes 651556Srgrimes#define EMPTY -2 /* marks an unused slot in redirtab */ 66199953Sjilles#define CLOSED -1 /* fd was not open before redir */ 671556Srgrimes 681556Srgrimes 691556Srgrimesstruct redirtab { 701556Srgrimes struct redirtab *next; 71100315Stjr int renamed[10]; 721556Srgrimes}; 731556Srgrimes 741556Srgrimes 75253658Sjillesstatic struct redirtab *redirlist; 761556Srgrimes 778855Srgrimes/* 781556Srgrimes * We keep track of whether or not fd0 has been redirected. This is for 791556Srgrimes * background commands, where we want to redirect fd0 to /dev/null only 808855Srgrimes * if it hasn't already been redirected. 811556Srgrimes*/ 82213760Sobrienstatic int fd0_redirected = 0; 831556Srgrimes 84213811Sobrienstatic void openredirect(union node *, char[10 ]); 85213811Sobrienstatic int openhere(union node *); 861556Srgrimes 871556Srgrimes 881556Srgrimes/* 891556Srgrimes * Process a list of redirection commands. If the REDIR_PUSH flag is set, 901556Srgrimes * old file descriptors are stashed away so that the redirection can be 911556Srgrimes * undone by calling popredir. If the REDIR_BACKQ flag is set, then the 921556Srgrimes * standard output, and the standard error if it becomes a duplicate of 931556Srgrimes * stdout, is saved in memory. 941556Srgrimes */ 951556Srgrimes 961556Srgrimesvoid 9790111Simpredirect(union node *redir, int flags) 9890111Simp{ 991556Srgrimes union node *n; 10017987Speter struct redirtab *sv = NULL; 1011556Srgrimes int i; 1021556Srgrimes int fd; 10320425Ssteve char memory[10]; /* file descriptors to write to memory */ 1041556Srgrimes 1051556Srgrimes for (i = 10 ; --i >= 0 ; ) 1061556Srgrimes memory[i] = 0; 1071556Srgrimes memory[1] = flags & REDIR_BACKQ; 1081556Srgrimes if (flags & REDIR_PUSH) { 1091556Srgrimes sv = ckmalloc(sizeof (struct redirtab)); 1101556Srgrimes for (i = 0 ; i < 10 ; i++) 1111556Srgrimes sv->renamed[i] = EMPTY; 1121556Srgrimes sv->next = redirlist; 1131556Srgrimes redirlist = sv; 1141556Srgrimes } 1151556Srgrimes for (n = redir ; n ; n = n->nfile.next) { 1161556Srgrimes fd = n->nfile.fd; 11711601Sjoerg if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && 11811601Sjoerg n->ndup.dupfd == fd) 11920425Ssteve continue; /* redirect from/to same file descriptor */ 12025231Ssteve 1211556Srgrimes if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { 1221556Srgrimes INTOFF; 123250267Sjilles if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) { 12425231Ssteve switch (errno) { 12525231Ssteve case EBADF: 126199953Sjilles i = CLOSED; 127199953Sjilles break; 12825231Ssteve default: 12925231Ssteve INTON; 13025231Ssteve error("%d: %s", fd, strerror(errno)); 13125231Ssteve break; 13225231Ssteve } 133250267Sjilles } 134199953Sjilles sv->renamed[fd] = i; 1351556Srgrimes INTON; 1361556Srgrimes } 13725231Ssteve if (fd == 0) 13825231Ssteve fd0_redirected++; 139199953Sjilles openredirect(n, memory); 1401556Srgrimes } 1411556Srgrimes if (memory[1]) 1421556Srgrimes out1 = &memout; 1431556Srgrimes if (memory[2]) 1441556Srgrimes out2 = &memout; 1451556Srgrimes} 1461556Srgrimes 1471556Srgrimes 148213811Sobrienstatic void 14990111Simpopenredirect(union node *redir, char memory[10]) 15090111Simp{ 15196922Stjr struct stat sb; 1521556Srgrimes int fd = redir->nfile.fd; 1531556Srgrimes char *fname; 1541556Srgrimes int f; 155216851Sjilles int e; 1561556Srgrimes 1571556Srgrimes /* 1581556Srgrimes * We suppress interrupts so that we won't leave open file 159199660Sjilles * descriptors around. Because the signal handler remains 160199660Sjilles * installed and we do not use system call restart, interrupts 161199660Sjilles * will still abort blocking opens such as fifos (they will fail 162199660Sjilles * with EINTR). There is, however, a race condition if an interrupt 163199660Sjilles * arrives after INTOFF and before open blocks. 1641556Srgrimes */ 1651556Srgrimes INTOFF; 1661556Srgrimes memory[fd] = 0; 1671556Srgrimes switch (redir->nfile.type) { 1681556Srgrimes case NFROM: 1691556Srgrimes fname = redir->nfile.expfname; 1701556Srgrimes if ((f = open(fname, O_RDONLY)) < 0) 171104132Stjr error("cannot open %s: %s", fname, strerror(errno)); 1721556Srgrimesmovefd: 1731556Srgrimes if (f != fd) { 174216851Sjilles if (dup2(f, fd) == -1) { 175216851Sjilles e = errno; 176216851Sjilles close(f); 177216851Sjilles error("%d: %s", fd, strerror(e)); 178216851Sjilles } 1791556Srgrimes close(f); 1801556Srgrimes } 1811556Srgrimes break; 18266612Sbrian case NFROMTO: 18366612Sbrian fname = redir->nfile.expfname; 18466612Sbrian if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) 185104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 18666612Sbrian goto movefd; 1871556Srgrimes case NTO: 188194560Sjilles if (Cflag) { 189194560Sjilles fname = redir->nfile.expfname; 190194560Sjilles if (stat(fname, &sb) == -1) { 191194560Sjilles if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) 192194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 193194560Sjilles } else if (!S_ISREG(sb.st_mode)) { 194194560Sjilles if ((f = open(fname, O_WRONLY, 0666)) < 0) 195194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 196194560Sjilles if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { 197194560Sjilles close(f); 198194560Sjilles error("cannot create %s: %s", fname, 199194560Sjilles strerror(EEXIST)); 200194560Sjilles } 201194560Sjilles } else 202194560Sjilles error("cannot create %s: %s", fname, 203194560Sjilles strerror(EEXIST)); 204194560Sjilles goto movefd; 205194560Sjilles } 206194560Sjilles /* FALLTHROUGH */ 20796922Stjr case NCLOBBER: 20896922Stjr fname = redir->nfile.expfname; 20996922Stjr if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 210104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 21196922Stjr goto movefd; 2121556Srgrimes case NAPPEND: 2131556Srgrimes fname = redir->nfile.expfname; 2141556Srgrimes if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 215104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 2161556Srgrimes goto movefd; 2171556Srgrimes case NTOFD: 2181556Srgrimes case NFROMFD: 2191556Srgrimes if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 2201556Srgrimes if (memory[redir->ndup.dupfd]) 2211556Srgrimes memory[fd] = 1; 222214290Sjilles else { 223214290Sjilles if (dup2(redir->ndup.dupfd, fd) < 0) 224214290Sjilles error("%d: %s", redir->ndup.dupfd, 225214290Sjilles strerror(errno)); 226214290Sjilles } 227124780Sdes } else { 22899645Stjr close(fd); 229124780Sdes } 2301556Srgrimes break; 2311556Srgrimes case NHERE: 2321556Srgrimes case NXHERE: 2331556Srgrimes f = openhere(redir); 2341556Srgrimes goto movefd; 2351556Srgrimes default: 2361556Srgrimes abort(); 2371556Srgrimes } 2381556Srgrimes INTON; 2391556Srgrimes} 2401556Srgrimes 2411556Srgrimes 2421556Srgrimes/* 2431556Srgrimes * Handle here documents. Normally we fork off a process to write the 2441556Srgrimes * data to a pipe. If the document is short, we can stuff the data in 2451556Srgrimes * the pipe without forking. 2461556Srgrimes */ 2471556Srgrimes 248213811Sobrienstatic int 24990111Simpopenhere(union node *redir) 25090111Simp{ 251246288Sjilles char *p; 2521556Srgrimes int pip[2]; 253249034Sjilles size_t len = 0; 254249034Sjilles int flags; 255249034Sjilles ssize_t written = 0; 2561556Srgrimes 2571556Srgrimes if (pipe(pip) < 0) 25853891Scracauer error("Pipe call failed: %s", strerror(errno)); 259246288Sjilles 260246288Sjilles if (redir->type == NXHERE) 261246288Sjilles p = redir->nhere.expdoc; 262246288Sjilles else 263246288Sjilles p = redir->nhere.doc->narg.text; 264246288Sjilles len = strlen(p); 265249034Sjilles if (len == 0) 266246288Sjilles goto out; 267249034Sjilles flags = fcntl(pip[1], F_GETFL, 0); 268249034Sjilles if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) { 269249034Sjilles written = write(pip[1], p, len); 270249034Sjilles if (written < 0) 271249034Sjilles written = 0; 272249034Sjilles if ((size_t)written == len) 273249034Sjilles goto out; 274249034Sjilles fcntl(pip[1], F_SETFL, flags); 2751556Srgrimes } 276246288Sjilles 2771556Srgrimes if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 2781556Srgrimes close(pip[0]); 2791556Srgrimes signal(SIGINT, SIG_IGN); 2801556Srgrimes signal(SIGQUIT, SIG_IGN); 2811556Srgrimes signal(SIGHUP, SIG_IGN); 2821556Srgrimes signal(SIGTSTP, SIG_IGN); 2831556Srgrimes signal(SIGPIPE, SIG_DFL); 284249034Sjilles xwrite(pip[1], p + written, len - written); 2851556Srgrimes _exit(0); 2861556Srgrimes } 2871556Srgrimesout: 2881556Srgrimes close(pip[1]); 2891556Srgrimes return pip[0]; 2901556Srgrimes} 2911556Srgrimes 2921556Srgrimes 2931556Srgrimes 2941556Srgrimes/* 2951556Srgrimes * Undo the effects of the last redirection. 2961556Srgrimes */ 2971556Srgrimes 2981556Srgrimesvoid 29990111Simppopredir(void) 30090111Simp{ 30125231Ssteve struct redirtab *rp = redirlist; 3021556Srgrimes int i; 3031556Srgrimes 3041556Srgrimes for (i = 0 ; i < 10 ; i++) { 3051556Srgrimes if (rp->renamed[i] != EMPTY) { 3061556Srgrimes if (i == 0) 3071556Srgrimes fd0_redirected--; 3081556Srgrimes if (rp->renamed[i] >= 0) { 309124780Sdes dup2(rp->renamed[i], i); 3101556Srgrimes close(rp->renamed[i]); 311124780Sdes } else { 312124780Sdes close(i); 3131556Srgrimes } 3141556Srgrimes } 3151556Srgrimes } 3161556Srgrimes INTOFF; 3171556Srgrimes redirlist = rp->next; 3181556Srgrimes ckfree(rp); 3191556Srgrimes INTON; 3201556Srgrimes} 3211556Srgrimes 3221556Srgrimes/* Return true if fd 0 has already been redirected at least once. */ 3231556Srgrimesint 32490111Simpfd0_redirected_p(void) 32590111Simp{ 3261556Srgrimes return fd0_redirected != 0; 3271556Srgrimes} 3281556Srgrimes 3291556Srgrimes/* 3301556Srgrimes * Discard all saved file descriptors. 3311556Srgrimes */ 3321556Srgrimes 3331556Srgrimesvoid 33490111Simpclearredir(void) 33590111Simp{ 33625231Ssteve struct redirtab *rp; 3371556Srgrimes int i; 3381556Srgrimes 3391556Srgrimes for (rp = redirlist ; rp ; rp = rp->next) { 3401556Srgrimes for (i = 0 ; i < 10 ; i++) { 3411556Srgrimes if (rp->renamed[i] >= 0) { 3421556Srgrimes close(rp->renamed[i]); 3431556Srgrimes } 3441556Srgrimes rp->renamed[i] = EMPTY; 3451556Srgrimes } 3461556Srgrimes } 3471556Srgrimes} 348