00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
00039 #endif
00040
00041
00042
00043
00044
00045 #include "shell.h"
00046 #include "nodes.h"
00047 #include "jobs.h"
00048 #include "expand.h"
00049 #include "redir.h"
00050 #include "eval.h"
00051 #include "output.h"
00052 #include "memalloc.h"
00053 #include "error.h"
00054 #include <sys/types.h>
00055 #include <signal.h>
00056 #include <fcntl.h>
00057 #include <errno.h>
00058 #include <limits.h>
00059
00060
00061 #define EMPTY -2
00062 #define PIPESIZE 4096
00063
00064
00065 MKINIT
00066 struct redirtab {
00067 struct redirtab *next;
00068 short renamed[10];
00069 };
00070
00071
00072 MKINIT struct redirtab *redirlist;
00073
00074
00075
00076
00077 int fd0_redirected = 0;
00078
00079 #ifdef __STDC__
00080 STATIC void openredirect(union node *, char *);
00081 STATIC int openhere(union node *);
00082 #else
00083 STATIC void openredirect();
00084 STATIC int openhere();
00085 #endif
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 void
00098 redirect(redir, flags)
00099 union node *redir;
00100 int flags;
00101 {
00102 union node *n;
00103 struct redirtab *sv;
00104 int i;
00105 int fd;
00106 char memory[10];
00107
00108 for (i = 10 ; --i >= 0 ; )
00109 memory[i] = 0;
00110 memory[1] = flags & REDIR_BACKQ;
00111 if (flags & REDIR_PUSH) {
00112 sv = ckmalloc(sizeof (struct redirtab));
00113 for (i = 0 ; i < 10 ; i++)
00114 sv->renamed[i] = EMPTY;
00115 sv->next = redirlist;
00116 redirlist = sv;
00117 }
00118 for (n = redir ; n ; n = n->nfile.next) {
00119 fd = n->nfile.fd;
00120 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
00121 INTOFF;
00122 if ((i = copyfd(fd, 10)) != EMPTY) {
00123 sv->renamed[fd] = i;
00124 close(fd);
00125 }
00126 INTON;
00127 if (i == EMPTY)
00128 error("Out of file descriptors");
00129 } else {
00130 close(fd);
00131 }
00132 if (fd == 0)
00133 fd0_redirected++;
00134 openredirect(n, memory);
00135 }
00136 if (memory[1])
00137 out1 = &memout;
00138 if (memory[2])
00139 out2 = &memout;
00140 }
00141
00142
00143 STATIC void
00144 openredirect(redir, memory)
00145 union node *redir;
00146 char memory[10];
00147 {
00148 int fd = redir->nfile.fd;
00149 char *fname;
00150 int f;
00151
00152
00153 exitstatus = 0;
00154
00155
00156
00157
00158
00159
00160 INTOFF;
00161 memory[fd] = 0;
00162 switch (redir->nfile.type) {
00163 case NFROM:
00164 fname = redir->nfile.expfname;
00165 if ((f = open(fname, O_RDONLY)) < 0)
00166 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
00167 movefd:
00168 if (f != fd) {
00169 copyfd(f, fd);
00170 close(f);
00171 }
00172 break;
00173 case NTO:
00174 fname = redir->nfile.expfname;
00175 #ifdef O_CREAT
00176 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
00177 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
00178 #else
00179 if ((f = creat(fname, 0666)) < 0)
00180 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
00181 #endif
00182 goto movefd;
00183 case NAPPEND:
00184 fname = redir->nfile.expfname;
00185 #ifdef O_APPEND
00186 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
00187 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
00188 #else
00189 if ((f = open(fname, O_WRONLY)) < 0
00190 && (f = creat(fname, 0666)) < 0)
00191 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
00192 lseek(f, 0L, 2);
00193 #endif
00194 goto movefd;
00195 case NTOFD:
00196 case NFROMFD:
00197 if (redir->ndup.dupfd >= 0) {
00198 if (memory[redir->ndup.dupfd])
00199 memory[fd] = 1;
00200 else
00201 copyfd(redir->ndup.dupfd, fd);
00202 }
00203 break;
00204 case NHERE:
00205 case NXHERE:
00206 f = openhere(redir);
00207 goto movefd;
00208 default:
00209 abort();
00210 }
00211 INTON;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221 STATIC int
00222 openhere(redir)
00223 union node *redir;
00224 {
00225 int pip[2];
00226 int len;
00227
00228 if (pipe(pip) < 0)
00229 error("Pipe call failed");
00230 if (redir->type == NHERE) {
00231 len = strlen(redir->nhere.doc->narg.text);
00232 if (len <= PIPESIZE) {
00233 xwrite(pip[1], redir->nhere.doc->narg.text, len);
00234 goto out;
00235 }
00236 }
00237 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
00238 close(pip[0]);
00239 signal(SIGINT, SIG_IGN);
00240 signal(SIGQUIT, SIG_IGN);
00241 signal(SIGHUP, SIG_IGN);
00242 #ifdef SIGTSTP
00243 signal(SIGTSTP, SIG_IGN);
00244 #endif
00245 signal(SIGPIPE, SIG_DFL);
00246 if (redir->type == NHERE)
00247 xwrite(pip[1], redir->nhere.doc->narg.text, len);
00248 else
00249 expandhere(redir->nhere.doc, pip[1]);
00250 _exit(0);
00251 }
00252 out:
00253 close(pip[1]);
00254 return pip[0];
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 void
00264 popredir() {
00265 register struct redirtab *rp = redirlist;
00266 int i;
00267
00268 for (i = 0 ; i < 10 ; i++) {
00269 if (rp->renamed[i] != EMPTY) {
00270 if (i == 0)
00271 fd0_redirected--;
00272 close(i);
00273 if (rp->renamed[i] >= 0) {
00274 copyfd(rp->renamed[i], i);
00275 close(rp->renamed[i]);
00276 }
00277 }
00278 }
00279 INTOFF;
00280 redirlist = rp->next;
00281 ckfree(rp);
00282 INTON;
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 #ifdef mkinit
00292
00293 INCLUDE "redir.h"
00294
00295 RESET {
00296 while (redirlist)
00297 popredir();
00298 }
00299
00300 SHELLPROC {
00301 clearredir();
00302 }
00303
00304 #endif
00305
00306
00307
00308
00309
00310
00311 void
00312 clearredir() {
00313 register struct redirtab *rp;
00314 int i;
00315
00316 for (rp = redirlist ; rp ; rp = rp->next) {
00317 for (i = 0 ; i < 10 ; i++) {
00318 if (rp->renamed[i] >= 0) {
00319 close(rp->renamed[i]);
00320 }
00321 rp->renamed[i] = EMPTY;
00322 }
00323 }
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 int
00335 copyfd(from, to) {
00336 #ifdef F_DUPFD
00337 int newfd;
00338
00339 newfd = fcntl(from, F_DUPFD, to);
00340 if (newfd < 0 && errno == EMFILE)
00341 return EMPTY;
00342 return newfd;
00343 #else
00344 char toclose[32];
00345 int i;
00346 int newfd;
00347 int e;
00348
00349 for (i = 0 ; i < to ; i++)
00350 toclose[i] = 0;
00351 INTOFF;
00352 while ((newfd = dup(from)) >= 0 && newfd < to)
00353 toclose[newfd] = 1;
00354 e = errno;
00355 for (i = 0 ; i < to ; i++) {
00356 if (toclose[i])
00357 close(i);
00358 }
00359 INTON;
00360 if (newfd < 0 && e == EMFILE)
00361 return EMPTY;
00362 return newfd;
00363 #endif
00364 }
00365
00366
00367 int
00368 fd0_redirected_p () {
00369 return fd0_redirected != 0;
00370 }