redir.c revision 213760
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: head/bin/sh/redir.c 213760 2010-10-13 04:01:01Z obrien $"); 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#define PIPESIZE 4096 /* amount of buffering in a pipe */ 681556Srgrimes 691556Srgrimes 701556SrgrimesMKINIT 711556Srgrimesstruct redirtab { 721556Srgrimes struct redirtab *next; 73100315Stjr int renamed[10]; 741556Srgrimes}; 751556Srgrimes 761556Srgrimes 771556SrgrimesMKINIT struct redirtab *redirlist; 781556Srgrimes 798855Srgrimes/* 801556Srgrimes * We keep track of whether or not fd0 has been redirected. This is for 811556Srgrimes * background commands, where we want to redirect fd0 to /dev/null only 828855Srgrimes * if it hasn't already been redirected. 831556Srgrimes*/ 84213760Sobrienstatic int fd0_redirected = 0; 851556Srgrimes 8690111SimpSTATIC void openredirect(union node *, char[10 ]); 8790111SimpSTATIC int openhere(union node *); 881556Srgrimes 891556Srgrimes 901556Srgrimes/* 911556Srgrimes * Process a list of redirection commands. If the REDIR_PUSH flag is set, 921556Srgrimes * old file descriptors are stashed away so that the redirection can be 931556Srgrimes * undone by calling popredir. If the REDIR_BACKQ flag is set, then the 941556Srgrimes * standard output, and the standard error if it becomes a duplicate of 951556Srgrimes * stdout, is saved in memory. 961556Srgrimes */ 971556Srgrimes 981556Srgrimesvoid 9990111Simpredirect(union node *redir, int flags) 10090111Simp{ 1011556Srgrimes union node *n; 10217987Speter struct redirtab *sv = NULL; 1031556Srgrimes int i; 1041556Srgrimes int fd; 10520425Ssteve char memory[10]; /* file descriptors to write to memory */ 1061556Srgrimes 1071556Srgrimes for (i = 10 ; --i >= 0 ; ) 1081556Srgrimes memory[i] = 0; 1091556Srgrimes memory[1] = flags & REDIR_BACKQ; 1101556Srgrimes if (flags & REDIR_PUSH) { 1111556Srgrimes sv = ckmalloc(sizeof (struct redirtab)); 1121556Srgrimes for (i = 0 ; i < 10 ; i++) 1131556Srgrimes sv->renamed[i] = EMPTY; 1141556Srgrimes sv->next = redirlist; 1151556Srgrimes redirlist = sv; 1161556Srgrimes } 1171556Srgrimes for (n = redir ; n ; n = n->nfile.next) { 1181556Srgrimes fd = n->nfile.fd; 11911601Sjoerg if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && 12011601Sjoerg n->ndup.dupfd == fd) 12120425Ssteve continue; /* redirect from/to same file descriptor */ 12225231Ssteve 1231556Srgrimes if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { 1241556Srgrimes INTOFF; 12525231Ssteve if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { 12625231Ssteve switch (errno) { 12725231Ssteve case EBADF: 128199953Sjilles i = CLOSED; 129199953Sjilles break; 13025231Ssteve default: 13125231Ssteve INTON; 13225231Ssteve error("%d: %s", fd, strerror(errno)); 13325231Ssteve break; 13425231Ssteve } 135199953Sjilles } else 136199953Sjilles (void)fcntl(i, F_SETFD, FD_CLOEXEC); 137199953Sjilles sv->renamed[fd] = i; 1381556Srgrimes INTON; 1391556Srgrimes } 14025231Ssteve if (fd == 0) 14125231Ssteve fd0_redirected++; 142199953Sjilles openredirect(n, memory); 1431556Srgrimes } 1441556Srgrimes if (memory[1]) 1451556Srgrimes out1 = &memout; 1461556Srgrimes if (memory[2]) 1471556Srgrimes out2 = &memout; 1481556Srgrimes} 1491556Srgrimes 1501556Srgrimes 1511556SrgrimesSTATIC void 15290111Simpopenredirect(union node *redir, char memory[10]) 15390111Simp{ 15496922Stjr struct stat sb; 1551556Srgrimes int fd = redir->nfile.fd; 1561556Srgrimes char *fname; 1571556Srgrimes int f; 1581556Srgrimes 1591556Srgrimes /* 1601556Srgrimes * We suppress interrupts so that we won't leave open file 161199660Sjilles * descriptors around. Because the signal handler remains 162199660Sjilles * installed and we do not use system call restart, interrupts 163199660Sjilles * will still abort blocking opens such as fifos (they will fail 164199660Sjilles * with EINTR). There is, however, a race condition if an interrupt 165199660Sjilles * arrives after INTOFF and before open blocks. 1661556Srgrimes */ 1671556Srgrimes INTOFF; 1681556Srgrimes memory[fd] = 0; 1691556Srgrimes switch (redir->nfile.type) { 1701556Srgrimes case NFROM: 1711556Srgrimes fname = redir->nfile.expfname; 1721556Srgrimes if ((f = open(fname, O_RDONLY)) < 0) 173104132Stjr error("cannot open %s: %s", fname, strerror(errno)); 1741556Srgrimesmovefd: 1751556Srgrimes if (f != fd) { 176124780Sdes dup2(f, fd); 1771556Srgrimes close(f); 1781556Srgrimes } 1791556Srgrimes break; 18066612Sbrian case NFROMTO: 18166612Sbrian fname = redir->nfile.expfname; 18266612Sbrian if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) 183104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 18466612Sbrian goto movefd; 1851556Srgrimes case NTO: 186194560Sjilles if (Cflag) { 187194560Sjilles fname = redir->nfile.expfname; 188194560Sjilles if (stat(fname, &sb) == -1) { 189194560Sjilles if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) 190194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 191194560Sjilles } else if (!S_ISREG(sb.st_mode)) { 192194560Sjilles if ((f = open(fname, O_WRONLY, 0666)) < 0) 193194560Sjilles error("cannot create %s: %s", fname, strerror(errno)); 194194560Sjilles if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { 195194560Sjilles close(f); 196194560Sjilles error("cannot create %s: %s", fname, 197194560Sjilles strerror(EEXIST)); 198194560Sjilles } 199194560Sjilles } else 200194560Sjilles error("cannot create %s: %s", fname, 201194560Sjilles strerror(EEXIST)); 202194560Sjilles goto movefd; 203194560Sjilles } 204194560Sjilles /* FALLTHROUGH */ 20596922Stjr case NCLOBBER: 20696922Stjr fname = redir->nfile.expfname; 20796922Stjr if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 208104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 20996922Stjr goto movefd; 2101556Srgrimes case NAPPEND: 2111556Srgrimes fname = redir->nfile.expfname; 2121556Srgrimes if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 213104132Stjr error("cannot create %s: %s", fname, strerror(errno)); 2141556Srgrimes goto movefd; 2151556Srgrimes case NTOFD: 2161556Srgrimes case NFROMFD: 2171556Srgrimes if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 2181556Srgrimes if (memory[redir->ndup.dupfd]) 2191556Srgrimes memory[fd] = 1; 220124780Sdes else 221124780Sdes dup2(redir->ndup.dupfd, fd); 222124780Sdes } else { 22399645Stjr close(fd); 224124780Sdes } 2251556Srgrimes break; 2261556Srgrimes case NHERE: 2271556Srgrimes case NXHERE: 2281556Srgrimes f = openhere(redir); 2291556Srgrimes goto movefd; 2301556Srgrimes default: 2311556Srgrimes abort(); 2321556Srgrimes } 2331556Srgrimes INTON; 2341556Srgrimes} 2351556Srgrimes 2361556Srgrimes 2371556Srgrimes/* 2381556Srgrimes * Handle here documents. Normally we fork off a process to write the 2391556Srgrimes * data to a pipe. If the document is short, we can stuff the data in 2401556Srgrimes * the pipe without forking. 2411556Srgrimes */ 2421556Srgrimes 2431556SrgrimesSTATIC int 24490111Simpopenhere(union node *redir) 24590111Simp{ 2461556Srgrimes int pip[2]; 24717987Speter int len = 0; 2481556Srgrimes 2491556Srgrimes if (pipe(pip) < 0) 25053891Scracauer error("Pipe call failed: %s", strerror(errno)); 2511556Srgrimes if (redir->type == NHERE) { 2521556Srgrimes len = strlen(redir->nhere.doc->narg.text); 2531556Srgrimes if (len <= PIPESIZE) { 2541556Srgrimes xwrite(pip[1], redir->nhere.doc->narg.text, len); 2551556Srgrimes goto out; 2561556Srgrimes } 2571556Srgrimes } 2581556Srgrimes if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 2591556Srgrimes close(pip[0]); 2601556Srgrimes signal(SIGINT, SIG_IGN); 2611556Srgrimes signal(SIGQUIT, SIG_IGN); 2621556Srgrimes signal(SIGHUP, SIG_IGN); 2631556Srgrimes signal(SIGTSTP, SIG_IGN); 2641556Srgrimes signal(SIGPIPE, SIG_DFL); 2651556Srgrimes if (redir->type == NHERE) 2661556Srgrimes xwrite(pip[1], redir->nhere.doc->narg.text, len); 2671556Srgrimes else 2681556Srgrimes expandhere(redir->nhere.doc, pip[1]); 2691556Srgrimes _exit(0); 2701556Srgrimes } 2711556Srgrimesout: 2721556Srgrimes close(pip[1]); 2731556Srgrimes return pip[0]; 2741556Srgrimes} 2751556Srgrimes 2761556Srgrimes 2771556Srgrimes 2781556Srgrimes/* 2791556Srgrimes * Undo the effects of the last redirection. 2801556Srgrimes */ 2811556Srgrimes 2821556Srgrimesvoid 28390111Simppopredir(void) 28490111Simp{ 28525231Ssteve struct redirtab *rp = redirlist; 2861556Srgrimes int i; 2871556Srgrimes 2881556Srgrimes for (i = 0 ; i < 10 ; i++) { 2891556Srgrimes if (rp->renamed[i] != EMPTY) { 2901556Srgrimes if (i == 0) 2911556Srgrimes fd0_redirected--; 2921556Srgrimes if (rp->renamed[i] >= 0) { 293124780Sdes dup2(rp->renamed[i], i); 2941556Srgrimes close(rp->renamed[i]); 295124780Sdes } else { 296124780Sdes close(i); 2971556Srgrimes } 2981556Srgrimes } 2991556Srgrimes } 3001556Srgrimes INTOFF; 3011556Srgrimes redirlist = rp->next; 3021556Srgrimes ckfree(rp); 3031556Srgrimes INTON; 3041556Srgrimes} 3051556Srgrimes 3061556Srgrimes/* 3071556Srgrimes * Undo all redirections. Called on error or interrupt. 3081556Srgrimes */ 3091556Srgrimes 3101556Srgrimes#ifdef mkinit 3111556Srgrimes 3121556SrgrimesINCLUDE "redir.h" 3131556Srgrimes 3141556SrgrimesRESET { 3151556Srgrimes while (redirlist) 3161556Srgrimes popredir(); 3171556Srgrimes} 3181556Srgrimes 3191556SrgrimesSHELLPROC { 3201556Srgrimes clearredir(); 3211556Srgrimes} 3221556Srgrimes 3231556Srgrimes#endif 3241556Srgrimes 3251556Srgrimes/* Return true if fd 0 has already been redirected at least once. */ 3261556Srgrimesint 32790111Simpfd0_redirected_p(void) 32890111Simp{ 3291556Srgrimes return fd0_redirected != 0; 3301556Srgrimes} 3311556Srgrimes 3321556Srgrimes/* 3331556Srgrimes * Discard all saved file descriptors. 3341556Srgrimes */ 3351556Srgrimes 3361556Srgrimesvoid 33790111Simpclearredir(void) 33890111Simp{ 33925231Ssteve struct redirtab *rp; 3401556Srgrimes int i; 3411556Srgrimes 3421556Srgrimes for (rp = redirlist ; rp ; rp = rp->next) { 3431556Srgrimes for (i = 0 ; i < 10 ; i++) { 3441556Srgrimes if (rp->renamed[i] >= 0) { 3451556Srgrimes close(rp->renamed[i]); 3461556Srgrimes } 3471556Srgrimes rp->renamed[i] = EMPTY; 3481556Srgrimes } 3491556Srgrimes } 3501556Srgrimes} 351