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)); 1761556Srgrimesmovefd: 1771556Srgrimes if (f != fd) { 178216851Sjilles if (dup2(f, fd) == -1) { 179216851Sjilles e = errno; 180216851Sjilles close(f); 181216851Sjilles error("%d: %s", fd, strerror(e)); 182216851Sjilles } 1831556Srgrimes close(f); 1841556Srgrimes } 1851556Srgrimes break; 18666612Sbrian case NFROMTO: 18766612Sbrian fname = redir->nfile.expfname; 18866612Sbrian if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) 189104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 19066612Sbrian goto movefd; 1911556Srgrimes case NTO: 192194560Sjilles if (Cflag) { 193194560Sjilles fname = redir->nfile.expfname; 194194560Sjilles if (stat(fname, &sb) == -1) { 195194560Sjilles if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) 196194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 197194560Sjilles } else if (!S_ISREG(sb.st_mode)) { 198194560Sjilles if ((f = open(fname, O_WRONLY, 0666)) < 0) 199194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 200194560Sjilles if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { 201194560Sjilles close(f); 202194560Sjilles error("cannot create %s: %s", fname, 203194560Sjilles strerror(EEXIST)); 204194560Sjilles } 205194560Sjilles } else 206194560Sjilles error("cannot create %s: %s", fname, 207194560Sjilles strerror(EEXIST)); 208194560Sjilles goto movefd; 209194560Sjilles } 210194560Sjilles /* FALLTHROUGH */ 21196922Stjr case NCLOBBER: 21296922Stjr fname = redir->nfile.expfname; 21396922Stjr if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 214104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 21596922Stjr goto movefd; 2161556Srgrimes case NAPPEND: 2171556Srgrimes fname = redir->nfile.expfname; 2181556Srgrimes if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 219104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 2201556Srgrimes goto movefd; 2211556Srgrimes case NTOFD: 2221556Srgrimes case NFROMFD: 2231556Srgrimes if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 2241556Srgrimes if (memory[redir->ndup.dupfd]) 2251556Srgrimes memory[fd] = 1; 226214290Sjilles else { 227214290Sjilles if (dup2(redir->ndup.dupfd, fd) < 0) 228214290Sjilles error("%d: %s", redir->ndup.dupfd, 229214290Sjilles strerror(errno)); 230214290Sjilles } 231124780Sdes } else { 23299645Stjr close(fd); 233124780Sdes } 2341556Srgrimes break; 2351556Srgrimes case NHERE: 2361556Srgrimes case NXHERE: 2371556Srgrimes f = openhere(redir); 2381556Srgrimes goto movefd; 2391556Srgrimes default: 2401556Srgrimes abort(); 2411556Srgrimes } 2421556Srgrimes} 2431556Srgrimes 2441556Srgrimes 2451556Srgrimes/* 2461556Srgrimes * Handle here documents. Normally we fork off a process to write the 2471556Srgrimes * data to a pipe. If the document is short, we can stuff the data in 2481556Srgrimes * the pipe without forking. 2491556Srgrimes */ 2501556Srgrimes 251213811Sobrienstatic int 25290111Simpopenhere(union node *redir) 25390111Simp{ 254264168Sjilles const char *p; 2551556Srgrimes int pip[2]; 256249034Sjilles size_t len = 0; 257249034Sjilles int flags; 258249034Sjilles ssize_t written = 0; 2591556Srgrimes 2601556Srgrimes if (pipe(pip) < 0) 26153891Scracauer error("Pipe call failed: %s", strerror(errno)); 262246288Sjilles 263246288Sjilles if (redir->type == NXHERE) 264246288Sjilles p = redir->nhere.expdoc; 265246288Sjilles else 266246288Sjilles p = redir->nhere.doc->narg.text; 267246288Sjilles len = strlen(p); 268249034Sjilles if (len == 0) 269246288Sjilles goto out; 270249034Sjilles flags = fcntl(pip[1], F_GETFL, 0); 271249034Sjilles if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) { 272249034Sjilles written = write(pip[1], p, len); 273249034Sjilles if (written < 0) 274249034Sjilles written = 0; 275249034Sjilles if ((size_t)written == len) 276249034Sjilles goto out; 277249034Sjilles fcntl(pip[1], F_SETFL, flags); 2781556Srgrimes } 279246288Sjilles 2801556Srgrimes if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 2811556Srgrimes close(pip[0]); 2821556Srgrimes signal(SIGINT, SIG_IGN); 2831556Srgrimes signal(SIGQUIT, SIG_IGN); 2841556Srgrimes signal(SIGHUP, SIG_IGN); 2851556Srgrimes signal(SIGTSTP, SIG_IGN); 2861556Srgrimes signal(SIGPIPE, SIG_DFL); 287249034Sjilles xwrite(pip[1], p + written, len - written); 2881556Srgrimes _exit(0); 2891556Srgrimes } 2901556Srgrimesout: 2911556Srgrimes close(pip[1]); 2921556Srgrimes return pip[0]; 2931556Srgrimes} 2941556Srgrimes 2951556Srgrimes 2961556Srgrimes 2971556Srgrimes/* 2981556Srgrimes * Undo the effects of the last redirection. 2991556Srgrimes */ 3001556Srgrimes 3011556Srgrimesvoid 30290111Simppopredir(void) 30390111Simp{ 30425231Ssteve struct redirtab *rp = redirlist; 3051556Srgrimes int i; 3061556Srgrimes 3071556Srgrimes for (i = 0 ; i < 10 ; i++) { 3081556Srgrimes if (rp->renamed[i] != EMPTY) { 3091556Srgrimes if (rp->renamed[i] >= 0) { 310124780Sdes dup2(rp->renamed[i], i); 3111556Srgrimes close(rp->renamed[i]); 312124780Sdes } else { 313124780Sdes close(i); 3141556Srgrimes } 3151556Srgrimes } 3161556Srgrimes } 3171556Srgrimes INTOFF; 318262951Sjmmv fd0_redirected = rp->fd0_redirected; 3191556Srgrimes redirlist = rp->next; 3201556Srgrimes ckfree(rp); 3211556Srgrimes INTON; 3221556Srgrimes} 3231556Srgrimes 3241556Srgrimes/* Return true if fd 0 has already been redirected at least once. */ 3251556Srgrimesint 32690111Simpfd0_redirected_p(void) 32790111Simp{ 3281556Srgrimes return fd0_redirected != 0; 3291556Srgrimes} 3301556Srgrimes 3311556Srgrimes/* 3321556Srgrimes * Discard all saved file descriptors. 3331556Srgrimes */ 3341556Srgrimes 3351556Srgrimesvoid 33690111Simpclearredir(void) 33790111Simp{ 33825231Ssteve struct redirtab *rp; 3391556Srgrimes int i; 3401556Srgrimes 3411556Srgrimes for (rp = redirlist ; rp ; rp = rp->next) { 3421556Srgrimes for (i = 0 ; i < 10 ; i++) { 3431556Srgrimes if (rp->renamed[i] >= 0) { 3441556Srgrimes close(rp->renamed[i]); 3451556Srgrimes } 3461556Srgrimes rp->renamed[i] = EMPTY; 3471556Srgrimes } 3481556Srgrimes } 3491556Srgrimes} 350