summaryrefslogtreecommitdiff
path: root/examples/loadables/tee.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/loadables/tee.c')
-rw-r--r--examples/loadables/tee.c157
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 */
+};