diff options
Diffstat (limited to 'examples/loadables/tee.c')
-rw-r--r-- | examples/loadables/tee.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/examples/loadables/tee.c b/examples/loadables/tee.c new file mode 100644 index 0000000..934abda --- /dev/null +++ b/examples/loadables/tee.c @@ -0,0 +1,157 @@ +/* tee - duplicate standard input */ + +/* See Makefile for compilation details. */ + +#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); + + /* Initialize output file list. */ + fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST)); + tee_flist->fd = 1; + tee_flist->fname = "stdout"; + tee_flist->next = (FLIST *)NULL; + + /* Add file arguments to list of output files. */ + 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)); + + /* Deallocate resources -- this is a builtin command. */ + tee_flist = tee_flist->next; /* skip bogus close of stdout */ + 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", /* builtin name */ + tee_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + tee_doc, /* array of long documentation strings. */ + "tee [-ai] [file ...]", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; |