* Copyright (c) 1991 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)redir.c 5.1 (Berkeley) %G%";
* Code for dealing with input/output redirection.
#define EMPTY -2 /* marks an unused slot in redirtab */
#define PIPESIZE 4096 /* amount of buffering in a pipe */
MKINIT
struct redirtab
*redirlist
;
STATIC
void openredirect(union node
*, char *);
STATIC
int openhere(union node
*);
STATIC
void openredirect();
* Process a list of redirection commands. If the REDIR_PUSH flag is set,
* old file descriptors are stashed away so that the redirection can be
* undone by calling popredir. If the REDIR_BACKQ flag is set, then the
* standard output, and the standard error if it becomes a duplicate of
* stdout, is saved in memory.
char memory
[10]; /* file descriptors to write to memory */
for (i
= 10 ; --i
>= 0 ; )
memory
[1] = flags
& REDIR_BACKQ
;
if (flags
& REDIR_PUSH
) {
sv
= ckmalloc(sizeof (struct redirtab
));
for (i
= 0 ; i
< 10 ; i
++)
for (n
= redir
; n
; n
= n
->nfile
.next
) {
if ((flags
& REDIR_PUSH
) && sv
->renamed
[fd
] == EMPTY
) {
if ((i
= copyfd(fd
, 10)) != EMPTY
) {
error("Out of file descriptors");
openredirect(redir
, memory
)
int fd
= redir
->nfile
.fd
;
* We suppress interrupts so that we won't leave open file
* descriptors around. This may not be such a good idea because
* an open of a device or a fifo can block indefinitely.
switch (redir
->nfile
.type
) {
fname
= redir
->nfile
.expfname
;
if ((f
= open(fname
, O_RDONLY
)) < 0)
error("cannot open %s: %s", fname
, errmsg(errno
, E_OPEN
));
fname
= redir
->nfile
.expfname
;
if ((f
= open(fname
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
error("cannot create %s: %s", fname
, errmsg(errno
, E_CREAT
));
if ((f
= creat(fname
, 0666)) < 0)
error("cannot create %s: %s", fname
, errmsg(errno
, E_CREAT
));
fname
= redir
->nfile
.expfname
;
if ((f
= open(fname
, O_WRONLY
|O_CREAT
|O_APPEND
, 0666)) < 0)
error("cannot create %s: %s", fname
, errmsg(errno
, E_CREAT
));
if ((f
= open(fname
, O_WRONLY
)) < 0
&& (f
= creat(fname
, 0666)) < 0)
error("cannot create %s: %s", fname
, errmsg(errno
, E_CREAT
));
if (redir
->ndup
.dupfd
>= 0) { /* if not ">&-" */
if (memory
[redir
->ndup
.dupfd
])
copyfd(redir
->ndup
.dupfd
, fd
);
* Handle here documents. Normally we fork off a process to write the
* data to a pipe. If the document is short, we can stuff the data in
* the pipe without forking.
error("Pipe call failed");
if (redir
->type
== NHERE
) {
len
= strlen(redir
->nhere
.doc
->narg
.text
);
xwrite(pip
[1], redir
->nhere
.doc
->narg
.text
, len
);
if (forkshell((struct job
*)NULL
, (union node
*)NULL
, FORK_NOJOB
) == 0) {
signal(SIGQUIT
, SIG_IGN
);
signal(SIGTSTP
, SIG_IGN
);
signal(SIGPIPE
, SIG_DFL
);
if (redir
->type
== NHERE
)
xwrite(pip
[1], redir
->nhere
.doc
->narg
.text
, len
);
expandhere(redir
->nhere
.doc
, pip
[1]);
* Undo the effects of the last redirection.
register struct redirtab
*rp
= redirlist
;
for (i
= 0 ; i
< 10 ; i
++) {
if (rp
->renamed
[i
] != EMPTY
) {
if (rp
->renamed
[i
] >= 0) {
copyfd(rp
->renamed
[i
], i
);
* Undo all redirections. Called on error or interrupt.
* Discard all saved file descriptors.
register struct redirtab
*rp
;
for (rp
= redirlist
; rp
; rp
= rp
->next
) {
for (i
= 0 ; i
< 10 ; i
++) {
if (rp
->renamed
[i
] >= 0) {
* Copy a file descriptor, like the F_DUPFD option of fcntl. Returns -1
* if the source file descriptor is closed, EMPTY if there are no unused
newfd
= fcntl(from
, F_DUPFD
, to
);
if (newfd
< 0 && errno
== EMFILE
)
for (i
= 0 ; i
< to
; i
++)
while ((newfd
= dup(from
)) >= 0 && newfd
< to
)
for (i
= 0 ; i
< to
; i
++) {
if (newfd
< 0 && e
== EMFILE
)