#include "config.h"
#include "bashtypes.h"
#include "posixstat.h"
#include "filecntl.h"
#include <signal.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include <errno.h>
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
typedef struct flist {
struct flist *next;
int fd;
char *fname;
} FLIST;
static FLIST *tee_flist;
#define TEE_BUFSIZE 8192
extern int interrupt_immediately;
extern char *strerror ();
tee_builtin (list)
WORD_LIST *list;
{
int opt, append, nointr, rval, fd, fflags;
int n, nr, nw;
FLIST *fl;
char *buf, *bp;
char *t;
reset_internal_getopt ();
append = nointr = 0;
tee_flist = (FLIST *)NULL;
while ((opt = internal_getopt (list, "ai")) != -1)
{
switch (opt)
{
case 'a':
append = 1;
break;
case 'i':
nointr = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (nointr == 0)
interrupt_immediately++;
buf = xmalloc (TEE_BUFSIZE);
fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST));
tee_flist->fd = 1;
tee_flist->fname = "stdout";
tee_flist->next = (FLIST *)NULL;
fflags = append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC;
for (rval = EXECUTION_SUCCESS; list; list = list->next)
{
fd = open (list->word->word, fflags, 0666);
if (fd < 0)
{
builtin_error ("%s: cannot open: %s", list->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
}
else
{
fl->next = (FLIST *)xmalloc (sizeof(FLIST));
fl->next->fd = fd;
fl->next->fname = list->word->word;
fl = fl->next;
fl->next = (FLIST *)NULL;
}
}
while ((nr = read(0, buf, TEE_BUFSIZE)) > 0)
for (fl = tee_flist; fl; fl = fl->next)
{
n = nr;
bp = buf;
do
{
if ((nw = write (fl->fd, bp, n)) == -1)
{
builtin_error ("%s: write error: %s", fl->fname, strerror (errno));
rval = EXECUTION_FAILURE;
break;
}
bp += nw;
}
while (n -= nw);
}
if (nr < 0)
builtin_error ("read error: %s", strerror (errno));
tee_flist = tee_flist->next;
while (tee_flist)
{
fl = tee_flist;
if (close (fl->fd) < 0)
{
builtin_error ("%s: close_error: %s", fl->fname, strerror (errno));
rval = EXECUTION_FAILURE;
}
tee_flist = tee_flist->next;
free (fl);
}
return (rval);
}
char *tee_doc[] = {
"Copy standard input to standard output, making a copy in each",
"filename argument. If the `-a' option is gived, the specified",
"files are appended to, otherwise they are overwritten. If the",
"`-i' option is supplied, tee ignores interrupts.",
(char *)NULL
};
struct builtin tee_struct = {
"tee",
tee_builtin,
BUILTIN_ENABLED,
tee_doc,
"tee [-ai] [file ...]",
0
};