Upload Tizen:Base source
[external/bash.git] / examples / loadables / tee.c
1 /* tee - duplicate standard input */
2
3 /* See Makefile for compilation details. */
4
5 /*
6    Copyright (C) 1999-2009 Free Software Foundation, Inc.
7
8    This file is part of GNU Bash.
9    Bash is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13
14    Bash is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "config.h"
24
25 #include "bashtypes.h"
26 #include "posixstat.h"
27 #include "filecntl.h"
28
29 #include <signal.h>
30
31 #if defined (HAVE_UNISTD_H)
32 #  include <unistd.h>
33 #endif
34
35 #include "bashansi.h"
36
37 #include <stdio.h>
38 #include <errno.h>
39
40 #include "builtins.h"
41 #include "shell.h"
42 #include "bashgetopt.h"
43 #include "common.h"
44
45 #if !defined (errno)
46 extern int errno;
47 #endif
48
49 typedef struct flist {
50   struct flist *next;
51   int fd;
52   char *fname;
53 } FLIST;
54
55 static FLIST *tee_flist;
56
57 #define TEE_BUFSIZE     8192
58
59 extern int interrupt_immediately;
60
61 extern char *strerror ();
62
63 tee_builtin (list)
64      WORD_LIST *list;
65 {
66   int opt, append, nointr, rval, fd, fflags;
67   int n, nr, nw;
68   FLIST *fl;
69   char *buf, *bp;
70
71   char *t;
72
73   reset_internal_getopt ();
74   append = nointr = 0;
75   tee_flist = (FLIST *)NULL;
76   while ((opt = internal_getopt (list, "ai")) != -1)
77     {
78       switch (opt)
79         {
80         case 'a':
81           append = 1;
82           break;
83         case 'i':
84           nointr = 1;
85           break;
86         default:
87           builtin_usage ();
88           return (EX_USAGE);
89         }
90     }
91   list = loptend;
92
93   if (nointr == 0)
94     interrupt_immediately++;
95
96   buf = xmalloc (TEE_BUFSIZE);
97
98   /* Initialize output file list. */
99   fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST));
100   tee_flist->fd = 1;
101   tee_flist->fname = "stdout";
102   tee_flist->next = (FLIST *)NULL;
103
104   /* Add file arguments to list of output files. */
105   fflags = append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC;
106   for (rval = EXECUTION_SUCCESS; list; list = list->next)
107     {
108       fd = open (list->word->word, fflags, 0666);
109       if (fd < 0)
110         {
111           builtin_error ("%s: cannot open: %s", list->word->word, strerror (errno));
112           rval = EXECUTION_FAILURE;
113         }
114       else
115         {
116           fl->next = (FLIST *)xmalloc (sizeof(FLIST));
117           fl->next->fd = fd;
118           fl->next->fname = list->word->word;
119           fl = fl->next;
120           fl->next = (FLIST *)NULL;
121         }
122     }
123
124   while ((nr = read(0, buf, TEE_BUFSIZE)) > 0)
125     for (fl = tee_flist; fl; fl = fl->next)
126       {
127         n = nr;
128         bp = buf;
129         do
130           {
131             if ((nw = write (fl->fd, bp, n)) == -1)
132               {
133                 builtin_error ("%s: write error: %s", fl->fname, strerror (errno));
134                 rval = EXECUTION_FAILURE;
135                 break;
136               }
137             bp += nw;
138           }
139         while (n -= nw);
140       }
141   if (nr < 0)
142     builtin_error ("read error: %s", strerror (errno));
143
144   /* Deallocate resources -- this is a builtin command. */
145   tee_flist = tee_flist->next;          /* skip bogus close of stdout */
146   while (tee_flist)
147     {
148       fl = tee_flist;
149       if (close (fl->fd) < 0)
150         {
151           builtin_error ("%s: close_error: %s", fl->fname, strerror (errno));
152           rval = EXECUTION_FAILURE;
153         }
154       tee_flist = tee_flist->next;
155       free (fl);
156     }
157   
158   return (rval);
159 }
160
161 char *tee_doc[] = {
162         "Duplicate standard output.",
163         "",
164         "Copy standard input to standard output, making a copy in each",
165         "filename argument.  If the `-a' option is gived, the specified",
166         "files are appended to, otherwise they are overwritten.  If the",
167         "`-i' option is supplied, tee ignores interrupts.",
168         (char *)NULL
169 };
170
171 struct builtin tee_struct = {
172         "tee",                  /* builtin name */
173         tee_builtin,            /* function implementing the builtin */
174         BUILTIN_ENABLED,        /* initial flags for builtin */
175         tee_doc,                /* array of long documentation strings. */
176         "tee [-ai] [file ...]", /* usage synopsis; becomes short_doc */
177         0                       /* reserved for internal use */
178 };