merge with 1.8.1d
[coreutils.git] / src / tee.c
blob0099d5c703c1659aef4017f02b05ee7c4d1a0be8
1 /* tee - read from standard input and write to standard output and files.
2 Copyright (C) 1985, 1990, 1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Mike Parker, Richard M. Stallman, and David MacKenzie */
20 #ifdef HAVE_CONFIG_H
21 #if defined (CONFIG_BROKETS)
22 /* We use <config.h> instead of "config.h" so that a compilation
23 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
24 (which it would do because it found this file in $srcdir). */
25 #include <config.h>
26 #else
27 #include "config.h"
28 #endif
29 #endif
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <signal.h>
34 #include <getopt.h>
36 #include "system.h"
37 #include "version.h"
39 char *xmalloc ();
40 void error ();
41 void xwrite ();
43 static int tee ();
45 /* If nonzero, append to output files rather than truncating them. */
46 static int append;
48 /* If nonzero, ignore interrupts. */
49 static int ignore_interrupts;
51 /* The name that this program was run with. */
52 char *program_name;
54 /* If non-zero, display usage information and exit. */
55 static int show_help;
57 /* If non-zero, print the version on standard output and exit. */
58 static int show_version;
60 static struct option const long_options[] =
62 {"append", no_argument, NULL, 'a'},
63 {"help", no_argument, &show_help, 1},
64 {"ignore-interrupts", no_argument, NULL, 'i'},
65 {"version", no_argument, &show_version, 1},
66 {NULL, 0, NULL, 0}
69 static void
70 usage ()
72 fprintf (stderr, "\
73 Usage: %s [{--help,--version}] [-ai] [--append]\n\
74 [--ignore-interrupts] [file...]\n",
75 program_name);
76 exit (1);
79 void
80 main (argc, argv)
81 int argc;
82 char **argv;
84 int errs;
85 int optc;
87 program_name = argv[0];
88 append = 0;
89 ignore_interrupts = 0;
91 while ((optc = getopt_long (argc, argv, "ai", long_options, (int *) 0))
92 != EOF)
94 switch (optc)
96 case 0:
97 break;
99 case 'a':
100 append = 1;
101 break;
103 case 'i':
104 ignore_interrupts = 1;
105 break;
107 default:
108 usage ();
112 if (show_version)
114 printf ("%s\n", version_string);
115 exit (0);
118 if (show_help)
119 usage ();
121 if (ignore_interrupts)
123 #ifdef _POSIX_VERSION
124 struct sigaction sigact;
126 sigact.sa_handler = SIG_IGN;
127 sigemptyset (&sigact.sa_mask);
128 sigact.sa_flags = 0;
129 sigaction (SIGINT, &sigact, NULL);
130 #else /* !_POSIX_VERSION */
131 signal (SIGINT, SIG_IGN);
132 #endif /* _POSIX_VERSION */
135 errs = tee (argc - optind, &argv[optind]);
136 if (close (0) != 0)
137 error (1, errno, "standard input");
138 if (close (1) != 0)
139 error (1, errno, "standard output");
140 exit (errs);
143 /* Copy the standard input into each of the NFILES files in FILES
144 and into the standard output.
145 Return 0 if successful, 1 if any errors occur. */
147 static int
148 tee (nfiles, files)
149 int nfiles;
150 char **files;
152 int *descriptors;
153 char buffer[BUFSIZ];
154 register int bytes_read, i, ret = 0, mode;
156 if (nfiles)
157 descriptors = (int *) xmalloc (nfiles * sizeof (int));
158 mode = O_WRONLY | O_CREAT;
159 if (append)
160 mode |= O_APPEND;
161 else
162 mode |= O_TRUNC;
164 for (i = 0; i < nfiles; i++)
166 descriptors[i] = open (files[i], mode, 0666);
167 if (descriptors[i] == -1)
169 error (0, errno, "%s", files[i]);
170 ret = 1;
174 while ((bytes_read = read (0, buffer, sizeof buffer)) > 0)
176 xwrite (1, buffer, bytes_read);
177 for (i = 0; i < nfiles; i++)
178 if (descriptors[i] != -1)
179 xwrite (descriptors[i], buffer, bytes_read);
181 if (bytes_read == -1)
183 error (0, errno, "read error");
184 ret = 1;
187 for (i = 0; i < nfiles; i++)
188 if (descriptors[i] != -1 && close (descriptors[i]) != 0)
190 error (0, errno, "%s", files[i]);
191 ret = 1;
194 if (nfiles)
195 free (descriptors);
197 return ret;