1*916b8720SThomas Cort /* $NetBSD: tee.c,v 1.11 2013/03/06 11:44:11 yamt Exp $ */
2*916b8720SThomas Cort
3*916b8720SThomas Cort /*
4*916b8720SThomas Cort * Copyright (c) 1988, 1993
5*916b8720SThomas Cort * The Regents of the University of California. All rights reserved.
6*916b8720SThomas Cort *
7*916b8720SThomas Cort * Redistribution and use in source and binary forms, with or without
8*916b8720SThomas Cort * modification, are permitted provided that the following conditions
9*916b8720SThomas Cort * are met:
10*916b8720SThomas Cort * 1. Redistributions of source code must retain the above copyright
11*916b8720SThomas Cort * notice, this list of conditions and the following disclaimer.
12*916b8720SThomas Cort * 2. Redistributions in binary form must reproduce the above copyright
13*916b8720SThomas Cort * notice, this list of conditions and the following disclaimer in the
14*916b8720SThomas Cort * documentation and/or other materials provided with the distribution.
15*916b8720SThomas Cort * 3. Neither the name of the University nor the names of its contributors
16*916b8720SThomas Cort * may be used to endorse or promote products derived from this software
17*916b8720SThomas Cort * without specific prior written permission.
18*916b8720SThomas Cort *
19*916b8720SThomas Cort * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*916b8720SThomas Cort * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*916b8720SThomas Cort * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*916b8720SThomas Cort * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*916b8720SThomas Cort * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*916b8720SThomas Cort * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*916b8720SThomas Cort * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*916b8720SThomas Cort * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*916b8720SThomas Cort * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*916b8720SThomas Cort * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*916b8720SThomas Cort * SUCH DAMAGE.
30*916b8720SThomas Cort */
31*916b8720SThomas Cort
32*916b8720SThomas Cort #include <sys/cdefs.h>
33*916b8720SThomas Cort #ifndef lint
34*916b8720SThomas Cort __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
35*916b8720SThomas Cort The Regents of the University of California. All rights reserved.");
36*916b8720SThomas Cort #endif /* not lint */
37*916b8720SThomas Cort
38*916b8720SThomas Cort #ifndef lint
39*916b8720SThomas Cort #if 0
40*916b8720SThomas Cort static char sccsid[] = "@(#)tee.c 8.1 (Berkeley) 6/6/93";
41*916b8720SThomas Cort #endif
42*916b8720SThomas Cort __RCSID("$NetBSD: tee.c,v 1.11 2013/03/06 11:44:11 yamt Exp $");
43*916b8720SThomas Cort #endif
44*916b8720SThomas Cort
45*916b8720SThomas Cort #include <sys/types.h>
46*916b8720SThomas Cort #include <sys/stat.h>
47*916b8720SThomas Cort #include <signal.h>
48*916b8720SThomas Cort #include <errno.h>
49*916b8720SThomas Cort #include <fcntl.h>
50*916b8720SThomas Cort #include <unistd.h>
51*916b8720SThomas Cort #include <stdio.h>
52*916b8720SThomas Cort #include <stdlib.h>
53*916b8720SThomas Cort #include <string.h>
54*916b8720SThomas Cort #include <locale.h>
55*916b8720SThomas Cort #include <err.h>
56*916b8720SThomas Cort
57*916b8720SThomas Cort typedef struct _list {
58*916b8720SThomas Cort struct _list *next;
59*916b8720SThomas Cort int fd;
60*916b8720SThomas Cort const char *name;
61*916b8720SThomas Cort } LIST;
62*916b8720SThomas Cort LIST *head;
63*916b8720SThomas Cort
64*916b8720SThomas Cort void add(int, const char *);
65*916b8720SThomas Cort int main(int, char **);
66*916b8720SThomas Cort
67*916b8720SThomas Cort int
main(int argc,char * argv[])68*916b8720SThomas Cort main(int argc, char *argv[])
69*916b8720SThomas Cort {
70*916b8720SThomas Cort LIST *p;
71*916b8720SThomas Cort ssize_t rval;
72*916b8720SThomas Cort int fd;
73*916b8720SThomas Cort int append, ch, exitval;
74*916b8720SThomas Cort char *buf;
75*916b8720SThomas Cort #define BSIZE (8 * 1024)
76*916b8720SThomas Cort
77*916b8720SThomas Cort setlocale(LC_ALL, "");
78*916b8720SThomas Cort
79*916b8720SThomas Cort append = 0;
80*916b8720SThomas Cort while ((ch = getopt(argc, argv, "ai")) != -1)
81*916b8720SThomas Cort switch((char)ch) {
82*916b8720SThomas Cort case 'a':
83*916b8720SThomas Cort append = 1;
84*916b8720SThomas Cort break;
85*916b8720SThomas Cort case 'i':
86*916b8720SThomas Cort (void)signal(SIGINT, SIG_IGN);
87*916b8720SThomas Cort break;
88*916b8720SThomas Cort case '?':
89*916b8720SThomas Cort default:
90*916b8720SThomas Cort (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n");
91*916b8720SThomas Cort exit(1);
92*916b8720SThomas Cort }
93*916b8720SThomas Cort argv += optind;
94*916b8720SThomas Cort argc -= optind;
95*916b8720SThomas Cort
96*916b8720SThomas Cort if ((buf = malloc(BSIZE)) == NULL)
97*916b8720SThomas Cort err(1, "malloc");
98*916b8720SThomas Cort
99*916b8720SThomas Cort add(STDOUT_FILENO, "stdout");
100*916b8720SThomas Cort
101*916b8720SThomas Cort for (exitval = 0; *argv; ++argv)
102*916b8720SThomas Cort if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND :
103*916b8720SThomas Cort O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) {
104*916b8720SThomas Cort warn("%s", *argv);
105*916b8720SThomas Cort exitval = 1;
106*916b8720SThomas Cort } else
107*916b8720SThomas Cort add(fd, *argv);
108*916b8720SThomas Cort
109*916b8720SThomas Cort while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0)
110*916b8720SThomas Cort for (p = head; p; p = p->next) {
111*916b8720SThomas Cort const char *bp = buf;
112*916b8720SThomas Cort size_t n = rval;
113*916b8720SThomas Cort ssize_t wval;
114*916b8720SThomas Cort
115*916b8720SThomas Cort do {
116*916b8720SThomas Cort if ((wval = write(p->fd, bp, n)) == -1) {
117*916b8720SThomas Cort warn("%s", p->name);
118*916b8720SThomas Cort exitval = 1;
119*916b8720SThomas Cort break;
120*916b8720SThomas Cort }
121*916b8720SThomas Cort bp += wval;
122*916b8720SThomas Cort } while (n -= wval);
123*916b8720SThomas Cort }
124*916b8720SThomas Cort if (rval < 0) {
125*916b8720SThomas Cort warn("read");
126*916b8720SThomas Cort exitval = 1;
127*916b8720SThomas Cort }
128*916b8720SThomas Cort
129*916b8720SThomas Cort for (p = head; p; p = p->next) {
130*916b8720SThomas Cort if (close(p->fd) == -1) {
131*916b8720SThomas Cort warn("%s", p->name);
132*916b8720SThomas Cort exitval = 1;
133*916b8720SThomas Cort }
134*916b8720SThomas Cort }
135*916b8720SThomas Cort
136*916b8720SThomas Cort exit(exitval);
137*916b8720SThomas Cort }
138*916b8720SThomas Cort
139*916b8720SThomas Cort void
add(int fd,const char * name)140*916b8720SThomas Cort add(int fd, const char *name)
141*916b8720SThomas Cort {
142*916b8720SThomas Cort LIST *p;
143*916b8720SThomas Cort
144*916b8720SThomas Cort if ((p = malloc(sizeof(LIST))) == NULL)
145*916b8720SThomas Cort err(1, "malloc");
146*916b8720SThomas Cort p->fd = fd;
147*916b8720SThomas Cort p->name = name;
148*916b8720SThomas Cort p->next = head;
149*916b8720SThomas Cort head = p;
150*916b8720SThomas Cort }
151