xref: /minix3/usr.bin/tee/tee.c (revision 916b8720337ab8bb96db43eb3e7131da276278e9)
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