tee.c revision 200420
19663SMark.Logan@Sun.COM/*
29663SMark.Logan@Sun.COM * Copyright (c) 1988, 1993
39663SMark.Logan@Sun.COM *	The Regents of the University of California.  All rights reserved.
49663SMark.Logan@Sun.COM *
59663SMark.Logan@Sun.COM * Redistribution and use in source and binary forms, with or without
69663SMark.Logan@Sun.COM * modification, are permitted provided that the following conditions
79663SMark.Logan@Sun.COM * are met:
89663SMark.Logan@Sun.COM * 1. Redistributions of source code must retain the above copyright
99663SMark.Logan@Sun.COM *    notice, this list of conditions and the following disclaimer.
109663SMark.Logan@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright
119663SMark.Logan@Sun.COM *    notice, this list of conditions and the following disclaimer in the
129663SMark.Logan@Sun.COM *    documentation and/or other materials provided with the distribution.
139663SMark.Logan@Sun.COM * 3. All advertising materials mentioning features or use of this software
149663SMark.Logan@Sun.COM *    must display the following acknowledgement:
159663SMark.Logan@Sun.COM *	This product includes software developed by the University of
169663SMark.Logan@Sun.COM *	California, Berkeley and its contributors.
179663SMark.Logan@Sun.COM * 4. Neither the name of the University nor the names of its contributors
189663SMark.Logan@Sun.COM *    may be used to endorse or promote products derived from this software
199663SMark.Logan@Sun.COM *    without specific prior written permission.
209663SMark.Logan@Sun.COM *
219663SMark.Logan@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
229663SMark.Logan@Sun.COM * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239663SMark.Logan@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249663SMark.Logan@Sun.COM * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259663SMark.Logan@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269663SMark.Logan@Sun.COM * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279663SMark.Logan@Sun.COM * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289663SMark.Logan@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299663SMark.Logan@Sun.COM * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309663SMark.Logan@Sun.COM * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319663SMark.Logan@Sun.COM * SUCH DAMAGE.
329663SMark.Logan@Sun.COM */
339663SMark.Logan@Sun.COM
349663SMark.Logan@Sun.COM#ifndef lint
359663SMark.Logan@Sun.COMstatic const char copyright[] =
369663SMark.Logan@Sun.COM"@(#) Copyright (c) 1988, 1993\n\
379663SMark.Logan@Sun.COM	The Regents of the University of California.  All rights reserved.\n";
389663SMark.Logan@Sun.COM#endif /* not lint */
399663SMark.Logan@Sun.COM
409663SMark.Logan@Sun.COM#ifndef lint
419663SMark.Logan@Sun.COM#if 0
429663SMark.Logan@Sun.COMstatic char sccsid[] = "@(#)tee.c	8.1 (Berkeley) 6/6/93";
439663SMark.Logan@Sun.COM#endif
449663SMark.Logan@Sun.COMstatic const char rcsid[] =
459663SMark.Logan@Sun.COM  "$FreeBSD: head/usr.bin/tee/tee.c 200420 2009-12-11 23:35:38Z delphij $";
469663SMark.Logan@Sun.COM#endif /* not lint */
479663SMark.Logan@Sun.COM
489663SMark.Logan@Sun.COM#include <sys/types.h>
499663SMark.Logan@Sun.COM#include <sys/stat.h>
509663SMark.Logan@Sun.COM#include <err.h>
519663SMark.Logan@Sun.COM#include <fcntl.h>
529663SMark.Logan@Sun.COM#include <signal.h>
539663SMark.Logan@Sun.COM#include <stdio.h>
549663SMark.Logan@Sun.COM#include <stdlib.h>
559663SMark.Logan@Sun.COM#include <unistd.h>
569663SMark.Logan@Sun.COM
579663SMark.Logan@Sun.COMtypedef struct _list {
589663SMark.Logan@Sun.COM	struct _list *next;
599663SMark.Logan@Sun.COM	int fd;
609663SMark.Logan@Sun.COM	const char *name;
619663SMark.Logan@Sun.COM} LIST;
629663SMark.Logan@Sun.COMLIST *head;
639663SMark.Logan@Sun.COM
649663SMark.Logan@Sun.COMvoid add(int, const char *);
659663SMark.Logan@Sun.COMstatic void usage(void);
669663SMark.Logan@Sun.COM
679663SMark.Logan@Sun.COMint
689663SMark.Logan@Sun.COMmain(int argc, char *argv[])
699663SMark.Logan@Sun.COM{
709663SMark.Logan@Sun.COM	LIST *p;
719663SMark.Logan@Sun.COM	int n, fd, rval, wval;
729663SMark.Logan@Sun.COM	char *bp;
739663SMark.Logan@Sun.COM	int append, ch, exitval;
749663SMark.Logan@Sun.COM	char *buf;
759663SMark.Logan@Sun.COM#define	BSIZE (8 * 1024)
769663SMark.Logan@Sun.COM
779663SMark.Logan@Sun.COM	append = 0;
789663SMark.Logan@Sun.COM	while ((ch = getopt(argc, argv, "ai")) != -1)
799663SMark.Logan@Sun.COM		switch((char)ch) {
809663SMark.Logan@Sun.COM		case 'a':
819663SMark.Logan@Sun.COM			append = 1;
829663SMark.Logan@Sun.COM			break;
839663SMark.Logan@Sun.COM		case 'i':
849663SMark.Logan@Sun.COM			(void)signal(SIGINT, SIG_IGN);
859663SMark.Logan@Sun.COM			break;
869663SMark.Logan@Sun.COM		case '?':
879663SMark.Logan@Sun.COM		default:
889663SMark.Logan@Sun.COM			usage();
899663SMark.Logan@Sun.COM		}
909663SMark.Logan@Sun.COM	argv += optind;
919663SMark.Logan@Sun.COM	argc -= optind;
929663SMark.Logan@Sun.COM
939663SMark.Logan@Sun.COM	if ((buf = malloc(BSIZE)) == NULL)
949663SMark.Logan@Sun.COM		err(1, "malloc");
959663SMark.Logan@Sun.COM
969663SMark.Logan@Sun.COM	add(STDOUT_FILENO, "stdout");
979663SMark.Logan@Sun.COM
989663SMark.Logan@Sun.COM	for (exitval = 0; *argv; ++argv)
999663SMark.Logan@Sun.COM		if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND :
1009663SMark.Logan@Sun.COM		    O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) {
1019663SMark.Logan@Sun.COM			warn("%s", *argv);
1029663SMark.Logan@Sun.COM			exitval = 1;
1039663SMark.Logan@Sun.COM		} else
1049663SMark.Logan@Sun.COM			add(fd, *argv);
1059663SMark.Logan@Sun.COM
1069663SMark.Logan@Sun.COM	while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0)
1079663SMark.Logan@Sun.COM		for (p = head; p; p = p->next) {
1089663SMark.Logan@Sun.COM			n = rval;
1099663SMark.Logan@Sun.COM			bp = buf;
1109663SMark.Logan@Sun.COM			do {
1119663SMark.Logan@Sun.COM				if ((wval = write(p->fd, bp, n)) == -1) {
1129663SMark.Logan@Sun.COM					warn("%s", p->name);
1139663SMark.Logan@Sun.COM					exitval = 1;
1149663SMark.Logan@Sun.COM					break;
1159663SMark.Logan@Sun.COM				}
1169663SMark.Logan@Sun.COM				bp += wval;
1179663SMark.Logan@Sun.COM			} while (n -= wval);
1189663SMark.Logan@Sun.COM		}
1199663SMark.Logan@Sun.COM	if (rval < 0)
1209663SMark.Logan@Sun.COM		err(1, "read");
1219663SMark.Logan@Sun.COM	exit(exitval);
1229663SMark.Logan@Sun.COM}
1239663SMark.Logan@Sun.COM
1249663SMark.Logan@Sun.COMstatic void
1259663SMark.Logan@Sun.COMusage(void)
1269663SMark.Logan@Sun.COM{
1279663SMark.Logan@Sun.COM	(void)fprintf(stderr, "usage: tee [-ai] [file ...]\n");
1289663SMark.Logan@Sun.COM	exit(1);
1299663SMark.Logan@Sun.COM}
1309663SMark.Logan@Sun.COM
1319663SMark.Logan@Sun.COMvoid
1329663SMark.Logan@Sun.COMadd(int fd, const char *name)
1339663SMark.Logan@Sun.COM{
1349663SMark.Logan@Sun.COM	LIST *p;
1359663SMark.Logan@Sun.COM
1369663SMark.Logan@Sun.COM	if ((p = malloc(sizeof(LIST))) == NULL)
1379663SMark.Logan@Sun.COM		err(1, "malloc");
1389663SMark.Logan@Sun.COM	p->fd = fd;
1399663SMark.Logan@Sun.COM	p->name = name;
1409663SMark.Logan@Sun.COM	p->next = head;
1419663SMark.Logan@Sun.COM	head = p;
1429663SMark.Logan@Sun.COM}
1439663SMark.Logan@Sun.COM