redir.c revision 199953
1121572Sume/*- 262583Sitojun * Copyright (c) 1991, 1993 355505Sshin * The Regents of the University of California. All rights reserved. 455505Sshin * 555505Sshin * This code is derived from software contributed to Berkeley by 655505Sshin * Kenneth Almquist. 755505Sshin * 855505Sshin * Redistribution and use in source and binary forms, with or without 955505Sshin * modification, are permitted provided that the following conditions 1055505Sshin * are met: 1155505Sshin * 1. Redistributions of source code must retain the above copyright 1255505Sshin * notice, this list of conditions and the following disclaimer. 1355505Sshin * 2. Redistributions in binary form must reproduce the above copyright 1455505Sshin * notice, this list of conditions and the following disclaimer in the 1555505Sshin * documentation and/or other materials provided with the distribution. 1655505Sshin * 4. Neither the name of the University nor the names of its contributors 1755505Sshin * may be used to endorse or promote products derived from this software 1855505Sshin * without specific prior written permission. 1955505Sshin * 2055505Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2155505Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2255505Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2355505Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2455505Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2555505Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2655505Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2755505Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2855505Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2955505Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3055505Sshin * SUCH DAMAGE. 3155505Sshin */ 3284208Sdillon 3384208Sdillon#ifndef lint 3484208Sdillon#if 0 3555505Sshinstatic char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; 3655505Sshin#endif 3755505Sshin#endif /* not lint */ 3855505Sshin#include <sys/cdefs.h> 39171135Sgnn__FBSDID("$FreeBSD: head/bin/sh/redir.c 199953 2009-11-29 22:33:59Z jilles $"); 4055505Sshin 41171135Sgnn#include <sys/types.h> 4255505Sshin#include <sys/stat.h> 4355505Sshin#include <signal.h> 4455505Sshin#include <string.h> 4562583Sitojun#include <fcntl.h> 4655505Sshin#include <errno.h> 4755505Sshin#include <unistd.h> 4855505Sshin#include <stdlib.h> 4955505Sshin 5055505Sshin/* 5155505Sshin * Code for dealing with input/output redirection. 5255505Sshin */ 5355505Sshin 5455505Sshin#include "shell.h" 5555505Sshin#include "nodes.h" 5655505Sshin#include "jobs.h" 5755505Sshin#include "expand.h" 5855505Sshin#include "redir.h" 5955505Sshin#include "output.h" 6092941Sobrien#include "memalloc.h" 6192941Sobrien#include "error.h" 6292941Sobrien#include "options.h" 6392917Sobrien 6455505Sshin 6555505Sshin#define EMPTY -2 /* marks an unused slot in redirtab */ 6655505Sshin#define CLOSED -1 /* fd was not open before redir */ 6755505Sshin#define PIPESIZE 4096 /* amount of buffering in a pipe */ 6855505Sshin 6955505Sshin 7055505SshinMKINIT 7155505Sshinstruct redirtab { 7255505Sshin struct redirtab *next; 7355505Sshin int renamed[10]; 7455505Sshin}; 7555505Sshin 7655505Sshin 7762583SitojunMKINIT struct redirtab *redirlist; 7855505Sshin 7962583Sitojun/* 8062583Sitojun * We keep track of whether or not fd0 has been redirected. This is for 8155505Sshin * background commands, where we want to redirect fd0 to /dev/null only 8255505Sshin * if it hasn't already been redirected. 8355505Sshin*/ 8455505SshinSTATIC int fd0_redirected = 0; 8555505Sshin 8662583SitojunSTATIC void openredirect(union node *, char[10 ]); 8755505SshinSTATIC int openhere(union node *); 8855505Sshin 8955505Sshin 9055505Sshin/* 9155505Sshin * Process a list of redirection commands. If the REDIR_PUSH flag is set, 9255505Sshin * old file descriptors are stashed away so that the redirection can be 9355505Sshin * undone by calling popredir. If the REDIR_BACKQ flag is set, then the 9455505Sshin * standard output, and the standard error if it becomes a duplicate of 9555505Sshin * stdout, is saved in memory. 9655505Sshin */ 9755505Sshin 9855505Sshinvoid 9955505Sshinredirect(union node *redir, int flags) 10062583Sitojun{ 10155505Sshin union node *n; 10255505Sshin struct redirtab *sv = NULL; 10355505Sshin int i; 10455505Sshin int fd; 10555505Sshin char memory[10]; /* file descriptors to write to memory */ 10655505Sshin 10755505Sshin for (i = 10 ; --i >= 0 ; ) 10855505Sshin memory[i] = 0; 10955505Sshin memory[1] = flags & REDIR_BACKQ; 11055505Sshin if (flags & REDIR_PUSH) { 11155505Sshin sv = ckmalloc(sizeof (struct redirtab)); 11262583Sitojun for (i = 0 ; i < 10 ; i++) 11355505Sshin sv->renamed[i] = EMPTY; 11455505Sshin sv->next = redirlist; 11555505Sshin redirlist = sv; 11655505Sshin } 11755505Sshin for (n = redir ; n ; n = n->nfile.next) { 11855505Sshin fd = n->nfile.fd; 11955505Sshin if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && 12055505Sshin n->ndup.dupfd == fd) 12155505Sshin continue; /* redirect from/to same file descriptor */ 12262583Sitojun 12355505Sshin if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { 12455505Sshin INTOFF; 12562583Sitojun if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { 12662583Sitojun switch (errno) { 12755505Sshin case EBADF: 12855505Sshin i = CLOSED; 12962583Sitojun break; 13055505Sshin default: 13155505Sshin INTON; 13255505Sshin error("%d: %s", fd, strerror(errno)); 13355505Sshin break; 13462583Sitojun } 13562583Sitojun } else 13662583Sitojun (void)fcntl(i, F_SETFD, FD_CLOEXEC); 13762583Sitojun sv->renamed[fd] = i; 13855505Sshin INTON; 13955505Sshin } 14055505Sshin if (fd == 0) 14162583Sitojun fd0_redirected++; 14262583Sitojun openredirect(n, memory); 14355505Sshin } 14455505Sshin if (memory[1]) 14555505Sshin out1 = &memout; 14655505Sshin if (memory[2]) 14762583Sitojun out2 = &memout; 14862583Sitojun} 14962583Sitojun 15055505Sshin 15162583SitojunSTATIC void 15262583Sitojunopenredirect(union node *redir, char memory[10]) 15355505Sshin{ 15455505Sshin struct stat sb; 15555505Sshin int fd = redir->nfile.fd; 15655505Sshin char *fname; 15762583Sitojun int f; 15862583Sitojun 15962583Sitojun /* 16062583Sitojun * We suppress interrupts so that we won't leave open file 16155505Sshin * descriptors around. Because the signal handler remains 16255505Sshin * installed and we do not use system call restart, interrupts 16355505Sshin * will still abort blocking opens such as fifos (they will fail 16462583Sitojun * with EINTR). There is, however, a race condition if an interrupt 165216369Skevlo * arrives after INTOFF and before open blocks. 166216369Skevlo */ 16755505Sshin INTOFF; 16862583Sitojun memory[fd] = 0; 16962583Sitojun switch (redir->nfile.type) { 17055505Sshin case NFROM: 17162583Sitojun fname = redir->nfile.expfname; 17262583Sitojun if ((f = open(fname, O_RDONLY)) < 0) 17362583Sitojun error("cannot open %s: %s", fname, strerror(errno)); 17455505Sshinmovefd: 17562583Sitojun if (f != fd) { 17662583Sitojun dup2(f, fd); 17762583Sitojun close(f); 17862583Sitojun } 17962583Sitojun break; 18062583Sitojun case NFROMTO: 18162583Sitojun fname = redir->nfile.expfname; 18262583Sitojun if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) 18362583Sitojun error("cannot create %s: %s", fname, strerror(errno)); 18462583Sitojun goto movefd; 18562583Sitojun case NTO: 18662583Sitojun if (Cflag) { 18762583Sitojun fname = redir->nfile.expfname; 18862583Sitojun if (stat(fname, &sb) == -1) { 18962583Sitojun if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) 19062583Sitojun error("cannot create %s: %s", fname, strerror(errno)); 19162583Sitojun } else if (!S_ISREG(sb.st_mode)) { 19262583Sitojun if ((f = open(fname, O_WRONLY, 0666)) < 0) 19362583Sitojun error("cannot create %s: %s", fname, strerror(errno)); 19462583Sitojun if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { 19562583Sitojun close(f); 19662583Sitojun error("cannot create %s: %s", fname, 19762583Sitojun strerror(EEXIST)); 19862583Sitojun } 19962583Sitojun } else 200125681Sbms error("cannot create %s: %s", fname, 201125681Sbms strerror(EEXIST)); 202264870Sbrueffer goto movefd; 20362583Sitojun } 20462583Sitojun /* FALLTHROUGH */ 20562583Sitojun case NCLOBBER: 20662583Sitojun fname = redir->nfile.expfname; 20762583Sitojun if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 20862583Sitojun error("cannot create %s: %s", fname, strerror(errno)); 20962583Sitojun goto movefd; 21062583Sitojun case NAPPEND: 21162583Sitojun fname = redir->nfile.expfname; 21262583Sitojun if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 21362583Sitojun error("cannot create %s: %s", fname, strerror(errno)); 21462583Sitojun goto movefd; 21562583Sitojun case NTOFD: 21662583Sitojun case NFROMFD: 21762583Sitojun if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 21862583Sitojun if (memory[redir->ndup.dupfd]) 21962583Sitojun memory[fd] = 1; 22062583Sitojun else 22162583Sitojun dup2(redir->ndup.dupfd, fd); 22262583Sitojun } else { 22362583Sitojun close(fd); 22462583Sitojun } 22562583Sitojun break; 22662583Sitojun case NHERE: 22762583Sitojun case NXHERE: 22862583Sitojun f = openhere(redir); 22962583Sitojun goto movefd; 23062583Sitojun default: 23162583Sitojun abort(); 23262583Sitojun } 23362583Sitojun INTON; 23455505Sshin} 23555505Sshin 23662583Sitojun 23762583Sitojun/* 23862583Sitojun * Handle here documents. Normally we fork off a process to write the 23962583Sitojun * data to a pipe. If the document is short, we can stuff the data in 24062583Sitojun * the pipe without forking. 24155505Sshin */ 24262583Sitojun 24362583SitojunSTATIC int 24462583Sitojunopenhere(union node *redir) 24562583Sitojun{ 24662583Sitojun int pip[2]; 24762583Sitojun int len = 0; 24862583Sitojun 24962583Sitojun if (pipe(pip) < 0) 25062583Sitojun error("Pipe call failed: %s", strerror(errno)); 25162583Sitojun if (redir->type == NHERE) { 25262583Sitojun len = strlen(redir->nhere.doc->narg.text); 25362583Sitojun if (len <= PIPESIZE) { 25462583Sitojun xwrite(pip[1], redir->nhere.doc->narg.text, len); 25562583Sitojun goto out; 25662583Sitojun } 25762583Sitojun } 25855505Sshin if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 25955505Sshin close(pip[0]); 26062583Sitojun signal(SIGINT, SIG_IGN); 26162583Sitojun signal(SIGQUIT, SIG_IGN); 26262583Sitojun signal(SIGHUP, SIG_IGN); 26362583Sitojun signal(SIGTSTP, SIG_IGN); 26462583Sitojun signal(SIGPIPE, SIG_DFL); 26562583Sitojun if (redir->type == NHERE) 26662583Sitojun xwrite(pip[1], redir->nhere.doc->narg.text, len); 26762583Sitojun else 26862583Sitojun expandhere(redir->nhere.doc, pip[1]); 269121572Sume _exit(0); 27062583Sitojun } 27162583Sitojunout: 27262583Sitojun close(pip[1]); 27355505Sshin return pip[0]; 27455505Sshin} 27555505Sshin 27655505Sshin 27762583Sitojun 27855505Sshin/* 27962583Sitojun * Undo the effects of the last redirection. 28062583Sitojun */ 28162583Sitojun 28255505Sshinvoid 28362583Sitojunpopredir(void) 28455505Sshin{ 28562583Sitojun struct redirtab *rp = redirlist; 28662583Sitojun int i; 28762583Sitojun 28862583Sitojun for (i = 0 ; i < 10 ; i++) { 28962583Sitojun if (rp->renamed[i] != EMPTY) { 29062583Sitojun if (i == 0) 29162583Sitojun fd0_redirected--; 29262583Sitojun if (rp->renamed[i] >= 0) { 29355505Sshin dup2(rp->renamed[i], i); 29462583Sitojun close(rp->renamed[i]); 29562583Sitojun } else { 29662583Sitojun close(i); 29762583Sitojun } 29862583Sitojun } 29962583Sitojun } 30062583Sitojun INTOFF; 30155505Sshin redirlist = rp->next; 30262583Sitojun ckfree(rp); 30362583Sitojun INTON; 30462583Sitojun} 30562583Sitojun 30662583Sitojun/* 30762583Sitojun * Undo all redirections. Called on error or interrupt. 30855505Sshin */ 309 310#ifdef mkinit 311 312INCLUDE "redir.h" 313 314RESET { 315 while (redirlist) 316 popredir(); 317} 318 319SHELLPROC { 320 clearredir(); 321} 322 323#endif 324 325/* Return true if fd 0 has already been redirected at least once. */ 326int 327fd0_redirected_p(void) 328{ 329 return fd0_redirected != 0; 330} 331 332/* 333 * Discard all saved file descriptors. 334 */ 335 336void 337clearredir(void) 338{ 339 struct redirtab *rp; 340 int i; 341 342 for (rp = redirlist ; rp ; rp = rp->next) { 343 for (i = 0 ; i < 10 ; i++) { 344 if (rp->renamed[i] >= 0) { 345 close(rp->renamed[i]); 346 } 347 rp->renamed[i] = EMPTY; 348 } 349 } 350} 351