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]; 72262951Sjmmv int fd0_redirected; 731556Srgrimes}; 741556Srgrimes 751556Srgrimes 76253658Sjillesstatic struct redirtab *redirlist; 771556Srgrimes 788855Srgrimes/* 791556Srgrimes * We keep track of whether or not fd0 has been redirected. This is for 801556Srgrimes * background commands, where we want to redirect fd0 to /dev/null only 818855Srgrimes * if it hasn't already been redirected. 821556Srgrimes*/ 83213760Sobrienstatic int fd0_redirected = 0; 841556Srgrimes 85213811Sobrienstatic void openredirect(union node *, char[10 ]); 86213811Sobrienstatic int openhere(union node *); 871556Srgrimes 881556Srgrimes 891556Srgrimes/* 901556Srgrimes * Process a list of redirection commands. If the REDIR_PUSH flag is set, 911556Srgrimes * old file descriptors are stashed away so that the redirection can be 921556Srgrimes * undone by calling popredir. If the REDIR_BACKQ flag is set, then the 931556Srgrimes * standard output, and the standard error if it becomes a duplicate of 941556Srgrimes * stdout, is saved in memory. 95264478Sjilles* 96264478Sjilles * We suppress interrupts so that we won't leave open file 97264478Sjilles * descriptors around. Because the signal handler remains 98264478Sjilles * installed and we do not use system call restart, interrupts 99264478Sjilles * will still abort blocking opens such as fifos (they will fail 100264478Sjilles * with EINTR). There is, however, a race condition if an interrupt 101264478Sjilles * arrives after INTOFF and before open blocks. 1021556Srgrimes */ 1031556Srgrimes 1041556Srgrimesvoid 10590111Simpredirect(union node *redir, int flags) 10690111Simp{ 1071556Srgrimes union node *n; 10817987Speter struct redirtab *sv = NULL; 1091556Srgrimes int i; 1101556Srgrimes int fd; 11120425Ssteve char memory[10]; /* file descriptors to write to memory */ 1121556Srgrimes 113264478Sjilles INTOFF; 1141556Srgrimes for (i = 10 ; --i >= 0 ; ) 1151556Srgrimes memory[i] = 0; 1161556Srgrimes memory[1] = flags & REDIR_BACKQ; 1171556Srgrimes if (flags & REDIR_PUSH) { 1181556Srgrimes sv = ckmalloc(sizeof (struct redirtab)); 1191556Srgrimes for (i = 0 ; i < 10 ; i++) 1201556Srgrimes sv->renamed[i] = EMPTY; 121262951Sjmmv sv->fd0_redirected = fd0_redirected; 1221556Srgrimes sv->next = redirlist; 1231556Srgrimes redirlist = sv; 1241556Srgrimes } 1251556Srgrimes for (n = redir ; n ; n = n->nfile.next) { 1261556Srgrimes fd = n->nfile.fd; 127262951Sjmmv if (fd == 0) 128262951Sjmmv fd0_redirected = 1; 12911601Sjoerg if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && 13011601Sjoerg n->ndup.dupfd == fd) 13120425Ssteve continue; /* redirect from/to same file descriptor */ 13225231Ssteve 1331556Srgrimes if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { 1341556Srgrimes INTOFF; 135250267Sjilles if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) { 13625231Ssteve switch (errno) { 13725231Ssteve case EBADF: 138199953Sjilles i = CLOSED; 139199953Sjilles break; 14025231Ssteve default: 14125231Ssteve INTON; 14225231Ssteve error("%d: %s", fd, strerror(errno)); 14325231Ssteve break; 14425231Ssteve } 145250267Sjilles } 146199953Sjilles sv->renamed[fd] = i; 1471556Srgrimes INTON; 1481556Srgrimes } 149199953Sjilles openredirect(n, memory); 150264478Sjilles INTON; 151264478Sjilles INTOFF; 1521556Srgrimes } 1531556Srgrimes if (memory[1]) 1541556Srgrimes out1 = &memout; 1551556Srgrimes if (memory[2]) 1561556Srgrimes out2 = &memout; 157264478Sjilles INTON; 1581556Srgrimes} 1591556Srgrimes 1601556Srgrimes 161213811Sobrienstatic void 16290111Simpopenredirect(union node *redir, char memory[10]) 16390111Simp{ 16496922Stjr struct stat sb; 1651556Srgrimes int fd = redir->nfile.fd; 166264168Sjilles const char *fname; 1671556Srgrimes int f; 168216851Sjilles int e; 1691556Srgrimes 1701556Srgrimes memory[fd] = 0; 1711556Srgrimes switch (redir->nfile.type) { 1721556Srgrimes case NFROM: 1731556Srgrimes fname = redir->nfile.expfname; 1741556Srgrimes if ((f = open(fname, O_RDONLY)) < 0) 175104132Stjr error("cannot open %s: %s", fname, strerror(errno)); 1761556Srgrimes break; 17766612Sbrian case NFROMTO: 17866612Sbrian fname = redir->nfile.expfname; 17966612Sbrian if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) 180104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 181287750Sjilles break; 1821556Srgrimes case NTO: 183194560Sjilles if (Cflag) { 184194560Sjilles fname = redir->nfile.expfname; 185194560Sjilles if (stat(fname, &sb) == -1) { 186194560Sjilles if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) 187194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 188194560Sjilles } else if (!S_ISREG(sb.st_mode)) { 189194560Sjilles if ((f = open(fname, O_WRONLY, 0666)) < 0) 190194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 191194560Sjilles if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { 192194560Sjilles close(f); 193194560Sjilles error("cannot create %s: %s", fname, 194194560Sjilles strerror(EEXIST)); 195194560Sjilles } 196194560Sjilles } else 197194560Sjilles error("cannot create %s: %s", fname, 198194560Sjilles strerror(EEXIST)); 199287750Sjilles break; 200194560Sjilles } 201194560Sjilles /* FALLTHROUGH */ 20296922Stjr case NCLOBBER: 20396922Stjr fname = redir->nfile.expfname; 20496922Stjr if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 205104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 206287750Sjilles break; 2071556Srgrimes case NAPPEND: 2081556Srgrimes fname = redir->nfile.expfname; 2091556Srgrimes if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 210104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 211287750Sjilles break; 2121556Srgrimes case NTOFD: 2131556Srgrimes case NFROMFD: 2141556Srgrimes if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 2151556Srgrimes if (memory[redir->ndup.dupfd]) 2161556Srgrimes memory[fd] = 1; 217214290Sjilles else { 218214290Sjilles if (dup2(redir->ndup.dupfd, fd) < 0) 219214290Sjilles error("%d: %s", redir->ndup.dupfd, 220214290Sjilles strerror(errno)); 221214290Sjilles } 222124780Sdes } else { 22399645Stjr close(fd); 224124780Sdes } 225287750Sjilles return; 2261556Srgrimes case NHERE: 2271556Srgrimes case NXHERE: 2281556Srgrimes f = openhere(redir); 229287750Sjilles break; 2301556Srgrimes default: 2311556Srgrimes abort(); 2321556Srgrimes } 233287750Sjilles if (f != fd) { 234287750Sjilles if (dup2(f, fd) == -1) { 235287750Sjilles e = errno; 236287750Sjilles close(f); 237287750Sjilles error("%d: %s", fd, strerror(e)); 238287750Sjilles } 239287750Sjilles close(f); 240287750Sjilles } 2411556Srgrimes} 2421556Srgrimes 2431556Srgrimes 2441556Srgrimes/* 2451556Srgrimes * Handle here documents. Normally we fork off a process to write the 2461556Srgrimes * data to a pipe. If the document is short, we can stuff the data in 2471556Srgrimes * the pipe without forking. 2481556Srgrimes */ 2491556Srgrimes 250213811Sobrienstatic int 25190111Simpopenhere(union node *redir) 25290111Simp{ 253264168Sjilles const char *p; 2541556Srgrimes int pip[2]; 255249034Sjilles size_t len = 0; 256249034Sjilles int flags; 257249034Sjilles ssize_t written = 0; 2581556Srgrimes 2591556Srgrimes if (pipe(pip) < 0) 26053891Scracauer error("Pipe call failed: %s", strerror(errno)); 261246288Sjilles 262246288Sjilles if (redir->type == NXHERE) 263246288Sjilles p = redir->nhere.expdoc; 264246288Sjilles else 265246288Sjilles p = redir->nhere.doc->narg.text; 266246288Sjilles len = strlen(p); 267249034Sjilles if (len == 0) 268246288Sjilles goto out; 269249034Sjilles flags = fcntl(pip[1], F_GETFL, 0); 270249034Sjilles if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) { 271249034Sjilles written = write(pip[1], p, len); 272249034Sjilles if (written < 0) 273249034Sjilles written = 0; 274249034Sjilles if ((size_t)written == len) 275249034Sjilles goto out; 276249034Sjilles fcntl(pip[1], F_SETFL, flags); 2771556Srgrimes } 278246288Sjilles 2791556Srgrimes if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 2801556Srgrimes close(pip[0]); 2811556Srgrimes signal(SIGINT, SIG_IGN); 2821556Srgrimes signal(SIGQUIT, SIG_IGN); 2831556Srgrimes signal(SIGHUP, SIG_IGN); 2841556Srgrimes signal(SIGTSTP, SIG_IGN); 2851556Srgrimes signal(SIGPIPE, SIG_DFL); 286249034Sjilles xwrite(pip[1], p + written, len - written); 2871556Srgrimes _exit(0); 2881556Srgrimes } 2891556Srgrimesout: 2901556Srgrimes close(pip[1]); 2911556Srgrimes return pip[0]; 2921556Srgrimes} 2931556Srgrimes 2941556Srgrimes 2951556Srgrimes 2961556Srgrimes/* 2971556Srgrimes * Undo the effects of the last redirection. 2981556Srgrimes */ 2991556Srgrimes 3001556Srgrimesvoid 30190111Simppopredir(void) 30290111Simp{ 30325231Ssteve struct redirtab *rp = redirlist; 3041556Srgrimes int i; 3051556Srgrimes 3061556Srgrimes for (i = 0 ; i < 10 ; i++) { 3071556Srgrimes if (rp->renamed[i] != EMPTY) { 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; 317262951Sjmmv fd0_redirected = rp->fd0_redirected; 3181556Srgrimes redirlist = rp->next; 3191556Srgrimes ckfree(rp); 3201556Srgrimes INTON; 3211556Srgrimes} 3221556Srgrimes 3231556Srgrimes/* Return true if fd 0 has already been redirected at least once. */ 3241556Srgrimesint 32590111Simpfd0_redirected_p(void) 32690111Simp{ 3271556Srgrimes return fd0_redirected != 0; 3281556Srgrimes} 3291556Srgrimes 3301556Srgrimes/* 3311556Srgrimes * Discard all saved file descriptors. 3321556Srgrimes */ 3331556Srgrimes 3341556Srgrimesvoid 33590111Simpclearredir(void) 33690111Simp{ 33725231Ssteve struct redirtab *rp; 3381556Srgrimes int i; 3391556Srgrimes 3401556Srgrimes for (rp = redirlist ; rp ; rp = rp->next) { 3411556Srgrimes for (i = 0 ; i < 10 ; i++) { 3421556Srgrimes if (rp->renamed[i] >= 0) { 3431556Srgrimes close(rp->renamed[i]); 3441556Srgrimes } 3451556Srgrimes rp->renamed[i] = EMPTY; 3461556Srgrimes } 3471556Srgrimes } 3481556Srgrimes} 349