1138593Ssam/*
2138593Ssam * Copyright (c) 1988, 1993
3138593Ssam *	The Regents of the University of California.  All rights reserved.
4138593Ssam *
5138593Ssam * Redistribution and use in source and binary forms, with or without
6138593Ssam * modification, are permitted provided that the following conditions
7138593Ssam * are met:
8138593Ssam * 1. Redistributions of source code must retain the above copyright
9138593Ssam *    notice, this list of conditions and the following disclaimer.
10138593Ssam * 2. Redistributions in binary form must reproduce the above copyright
11138593Ssam *    notice, this list of conditions and the following disclaimer in the
12138593Ssam *    documentation and/or other materials provided with the distribution.
13138593Ssam * 4. Neither the name of the University nor the names of its contributors
14138593Ssam *    may be used to endorse or promote products derived from this software
15138593Ssam *    without specific prior written permission.
16138593Ssam *
17138593Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18138593Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19138593Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20138593Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21138593Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22138593Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23138593Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24138593Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25138593Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26138593Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27138593Ssam * SUCH DAMAGE.
28138593Ssam */
29138593Ssam
30138593Ssam#ifndef lint
31138593Ssamstatic const char copyright[] =
32138593Ssam"@(#) Copyright (c) 1988, 1993\n\
33138593Ssam	The Regents of the University of California.  All rights reserved.\n";
34138593Ssam#endif /* not lint */
35138593Ssam
36138593Ssam#ifndef lint
37138593Ssam#if 0
38138593Ssamstatic char sccsid[] = "@(#)tee.c	8.1 (Berkeley) 6/6/93";
39138593Ssam#endif
40138593Ssamstatic const char rcsid[] =
41138593Ssam  "$FreeBSD$";
42138593Ssam#endif /* not lint */
43138593Ssam
44138593Ssam#include <sys/types.h>
45166956Ssam#include <sys/stat.h>
46138593Ssam#include <err.h>
47138593Ssam#include <fcntl.h>
48138593Ssam#include <signal.h>
49138593Ssam#include <stdio.h>
50138593Ssam#include <stdlib.h>
51138593Ssam#include <string.h>
52138593Ssam#include <unistd.h>
53138593Ssam
54138593Ssamtypedef struct _list {
55191121Sbrooks	struct _list *next;
56138593Ssam	int fd;
57138593Ssam	const char *name;
58138593Ssam} LIST;
59166956SsamLIST *head;
60138593Ssam
61138593Ssamvoid add(int, const char *);
62138593Ssamstatic void usage(void);
63138593Ssam
64138593Ssamint
65166956Ssammain(int argc, char *argv[])
66138593Ssam{
67138593Ssam	LIST *p;
68138593Ssam	int n, fd, rval, wval;
69138593Ssam	char *bp;
70138593Ssam	int append, ch, exitval;
71166956Ssam	char *buf;
72166956Ssam#define	BSIZE (8 * 1024)
73166956Ssam
74138593Ssam	append = 0;
75138593Ssam	while ((ch = getopt(argc, argv, "ai")) != -1)
76138593Ssam		switch((char)ch) {
77138593Ssam		case 'a':
78166956Ssam			append = 1;
79166956Ssam			break;
80138593Ssam		case 'i':
81138593Ssam			(void)signal(SIGINT, SIG_IGN);
82138593Ssam			break;
83166956Ssam		case '?':
84166956Ssam		default:
85166956Ssam			usage();
86138593Ssam		}
87138593Ssam	argv += optind;
88138593Ssam	argc -= optind;
89138593Ssam
90138593Ssam	if ((buf = malloc(BSIZE)) == NULL)
91138593Ssam		err(1, "malloc");
92138593Ssam
93138593Ssam	add(STDOUT_FILENO, "stdout");
94138593Ssam
95138593Ssam	for (exitval = 0; *argv; ++argv)
96138593Ssam		if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND :
97138593Ssam		    O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) {
98138593Ssam			warn("%s", *argv);
99138593Ssam			exitval = 1;
100138593Ssam		} else
101138593Ssam			add(fd, *argv);
102138593Ssam
103138593Ssam	while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0)
104138593Ssam		for (p = head; p; p = p->next) {
105138593Ssam			n = rval;
106138593Ssam			bp = buf;
107138593Ssam			do {
108138593Ssam				if ((wval = write(p->fd, bp, n)) == -1) {
109138593Ssam					warn("%s", p->name);
110138593Ssam					exitval = 1;
111138593Ssam					break;
112138593Ssam				}
113138593Ssam				bp += wval;
114138593Ssam			} while (n -= wval);
115138593Ssam		}
116138593Ssam	if (rval < 0)
117138593Ssam		err(1, "read");
118138593Ssam	exit(exitval);
119138593Ssam}
120138593Ssam
121138593Ssamstatic void
122138593Ssamusage(void)
123138593Ssam{
124138593Ssam	(void)fprintf(stderr, "usage: tee [-ai] [file ...]\n");
125138593Ssam	exit(1);
126138593Ssam}
127138593Ssam
128138593Ssamvoid
129138593Ssamadd(int fd, const char *name)
130138593Ssam{
131138593Ssam	LIST *p;
132138593Ssam
133138593Ssam	if ((p = malloc(sizeof(LIST))) == NULL)
134138593Ssam		err(1, "malloc");
135138593Ssam	p->fd = fd;
136138593Ssam	p->name = name;
137138593Ssam	p->next = head;
138138593Ssam	head = p;
139138593Ssam}
140138593Ssam