1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef lint 36 #endif /* not lint */ 37 #include <sys/cdefs.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <signal.h> 41 #include <string.h> 42 #include <fcntl.h> 43 #include <errno.h> 44 #include <unistd.h> 45 #include <stdlib.h> 46 47 /* 48 * Code for dealing with input/output redirection. 49 */ 50 51 #include "shell.h" 52 #include "nodes.h" 53 #include "jobs.h" 54 #include "expand.h" 55 #include "redir.h" 56 #include "output.h" 57 #include "memalloc.h" 58 #include "error.h" 59 #include "options.h" 60 61 62 #define EMPTY -2 /* marks an unused slot in redirtab */ 63 #define CLOSED -1 /* fd was not open before redir */ 64 65 66 struct redirtab { 67 struct redirtab *next; 68 int renamed[10]; 69 int fd0_redirected; 70 unsigned int empty_redirs; 71 }; 72 73 74 static struct redirtab *redirlist; 75 76 /* 77 * We keep track of whether or not fd0 has been redirected. This is for 78 * background commands, where we want to redirect fd0 to /dev/null only 79 * if it hasn't already been redirected. 80 */ 81 static int fd0_redirected = 0; 82 83 /* Number of redirtabs that have not been allocated. */ 84 static unsigned int empty_redirs = 0; 85 86 static void openredirect(union node *, char[10 ]); 87 static int openhere(union node *); 88 89 90 /* 91 * Process a list of redirection commands. If the REDIR_PUSH flag is set, 92 * old file descriptors are stashed away so that the redirection can be 93 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the 94 * standard output, and the standard error if it becomes a duplicate of 95 * stdout, is saved in memory. 96 * 97 * We suppress interrupts so that we won't leave open file 98 * descriptors around. Because the signal handler remains 99 * installed and we do not use system call restart, interrupts 100 * will still abort blocking opens such as fifos (they will fail 101 * with EINTR). There is, however, a race condition if an interrupt 102 * arrives after INTOFF and before open blocks. 103 */ 104 105 void 106 redirect(union node *redir, int flags) 107 { 108 union node *n; 109 struct redirtab *sv = NULL; 110 int i; 111 int fd; 112 char memory[10]; /* file descriptors to write to memory */ 113 114 INTOFF; 115 for (i = 10 ; --i >= 0 ; ) 116 memory[i] = 0; 117 memory[1] = flags & REDIR_BACKQ; 118 if (flags & REDIR_PUSH) { 119 empty_redirs++; 120 if (redir != NULL) { 121 sv = ckmalloc(sizeof (struct redirtab)); 122 for (i = 0 ; i < 10 ; i++) 123 sv->renamed[i] = EMPTY; 124 sv->fd0_redirected = fd0_redirected; 125 sv->empty_redirs = empty_redirs - 1; 126 sv->next = redirlist; 127 redirlist = sv; 128 empty_redirs = 0; 129 } 130 } 131 for (n = redir ; n ; n = n->nfile.next) { 132 fd = n->nfile.fd; 133 if (fd == 0) 134 fd0_redirected = 1; 135 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && 136 n->ndup.dupfd == fd) 137 continue; /* redirect from/to same file descriptor */ 138 139 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { 140 INTOFF; 141 if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) { 142 switch (errno) { 143 case EBADF: 144 i = CLOSED; 145 break; 146 default: 147 INTON; 148 error("%d: %s", fd, strerror(errno)); 149 break; 150 } 151 } 152 sv->renamed[fd] = i; 153 INTON; 154 } 155 openredirect(n, memory); 156 INTON; 157 INTOFF; 158 } 159 if (memory[1]) 160 out1 = &memout; 161 if (memory[2]) 162 out2 = &memout; 163 INTON; 164 } 165 166 167 static void 168 openredirect(union node *redir, char memory[10]) 169 { 170 struct stat sb; 171 int fd = redir->nfile.fd; 172 const char *fname; 173 int f; 174 int e; 175 176 memory[fd] = 0; 177 switch (redir->nfile.type) { 178 case NFROM: 179 fname = redir->nfile.expfname; 180 if ((f = open(fname, O_RDONLY)) < 0) 181 error("cannot open %s: %s", fname, strerror(errno)); 182 break; 183 case NFROMTO: 184 fname = redir->nfile.expfname; 185 if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) 186 error("cannot create %s: %s", fname, strerror(errno)); 187 break; 188 case NTO: 189 if (Cflag) { 190 fname = redir->nfile.expfname; 191 if (stat(fname, &sb) == -1) { 192 if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) 193 error("cannot create %s: %s", fname, strerror(errno)); 194 } else if (!S_ISREG(sb.st_mode)) { 195 if ((f = open(fname, O_WRONLY, 0666)) < 0) 196 error("cannot create %s: %s", fname, strerror(errno)); 197 if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { 198 close(f); 199 error("cannot create %s: %s", fname, 200 strerror(EEXIST)); 201 } 202 } else 203 error("cannot create %s: %s", fname, 204 strerror(EEXIST)); 205 break; 206 } 207 /* FALLTHROUGH */ 208 case NCLOBBER: 209 fname = redir->nfile.expfname; 210 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 211 error("cannot create %s: %s", fname, strerror(errno)); 212 break; 213 case NAPPEND: 214 fname = redir->nfile.expfname; 215 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 216 error("cannot create %s: %s", fname, strerror(errno)); 217 break; 218 case NTOFD: 219 case NFROMFD: 220 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 221 if (memory[redir->ndup.dupfd]) 222 memory[fd] = 1; 223 else { 224 if (dup2(redir->ndup.dupfd, fd) < 0) 225 error("%d: %s", redir->ndup.dupfd, 226 strerror(errno)); 227 } 228 } else { 229 close(fd); 230 } 231 return; 232 case NHERE: 233 case NXHERE: 234 f = openhere(redir); 235 break; 236 default: 237 abort(); 238 } 239 if (f != fd) { 240 if (dup2(f, fd) == -1) { 241 e = errno; 242 close(f); 243 error("%d: %s", fd, strerror(e)); 244 } 245 close(f); 246 } 247 } 248 249 250 /* 251 * Handle here documents. Normally we fork off a process to write the 252 * data to a pipe. If the document is short, we can stuff the data in 253 * the pipe without forking. 254 */ 255 256 static int 257 openhere(union node *redir) 258 { 259 const char *p; 260 int pip[2]; 261 size_t len = 0; 262 int flags; 263 ssize_t written = 0; 264 265 if (pipe(pip) < 0) 266 error("Pipe call failed: %s", strerror(errno)); 267 268 if (redir->type == NXHERE) 269 p = redir->nhere.expdoc; 270 else 271 p = redir->nhere.doc->narg.text; 272 len = strlen(p); 273 if (len == 0) 274 goto out; 275 flags = fcntl(pip[1], F_GETFL, 0); 276 if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) { 277 written = write(pip[1], p, len); 278 if (written < 0) 279 written = 0; 280 if ((size_t)written == len) 281 goto out; 282 fcntl(pip[1], F_SETFL, flags); 283 } 284 285 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 286 close(pip[0]); 287 signal(SIGINT, SIG_IGN); 288 signal(SIGQUIT, SIG_IGN); 289 signal(SIGHUP, SIG_IGN); 290 signal(SIGTSTP, SIG_IGN); 291 signal(SIGPIPE, SIG_DFL); 292 xwrite(pip[1], p + written, len - written); 293 _exit(0); 294 } 295 out: 296 close(pip[1]); 297 return pip[0]; 298 } 299 300 301 302 /* 303 * Undo the effects of the last redirection. 304 */ 305 306 void 307 popredir(void) 308 { 309 struct redirtab *rp = redirlist; 310 int i; 311 312 INTOFF; 313 if (empty_redirs > 0) { 314 empty_redirs--; 315 INTON; 316 return; 317 } 318 for (i = 0 ; i < 10 ; i++) { 319 if (rp->renamed[i] != EMPTY) { 320 if (rp->renamed[i] >= 0) { 321 dup2(rp->renamed[i], i); 322 close(rp->renamed[i]); 323 } else { 324 close(i); 325 } 326 } 327 } 328 fd0_redirected = rp->fd0_redirected; 329 empty_redirs = rp->empty_redirs; 330 redirlist = rp->next; 331 ckfree(rp); 332 INTON; 333 } 334 335 /* Return true if fd 0 has already been redirected at least once. */ 336 int 337 fd0_redirected_p(void) 338 { 339 return fd0_redirected != 0; 340 } 341 342 /* 343 * Discard all saved file descriptors. 344 */ 345 346 void 347 clearredir(void) 348 { 349 struct redirtab *rp; 350 int i; 351 352 for (rp = redirlist ; rp ; rp = rp->next) { 353 for (i = 0 ; i < 10 ; i++) { 354 if (rp->renamed[i] >= 0) { 355 close(rp->renamed[i]); 356 } 357 rp->renamed[i] = EMPTY; 358 } 359 } 360 } 361