tee.c revision 24360
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1988, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
351590Srgrimesstatic char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1988, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
411590Srgrimesstatic char sccsid[] = "@(#)tee.c	8.1 (Berkeley) 6/6/93";
421590Srgrimes#endif /* not lint */
431590Srgrimes
441590Srgrimes#include <sys/types.h>
451590Srgrimes#include <sys/stat.h>
461590Srgrimes#include <signal.h>
471590Srgrimes#include <errno.h>
481590Srgrimes#include <fcntl.h>
491590Srgrimes#include <unistd.h>
501590Srgrimes#include <stdio.h>
511590Srgrimes#include <stdlib.h>
521590Srgrimes#include <string.h>
531590Srgrimes
541590Srgrimestypedef struct _list {
551590Srgrimes	struct _list *next;
561590Srgrimes	int fd;
571590Srgrimes	char *name;
581590Srgrimes} LIST;
591590SrgrimesLIST *head;
601590Srgrimes
611590Srgrimesvoid add __P((int, char *));
621590Srgrimesvoid err __P((int, const char *, ...));
631590Srgrimes
641590Srgrimesint
651590Srgrimesmain(argc, argv)
661590Srgrimes	int argc;
671590Srgrimes	char *argv[];
681590Srgrimes{
691590Srgrimes	register LIST *p;
701590Srgrimes	register int n, fd, rval, wval;
711590Srgrimes	register char *bp;
721590Srgrimes	int append, ch, exitval;
731590Srgrimes	char *buf;
741590Srgrimes#define	BSIZE (8 * 1024)
751590Srgrimes
761590Srgrimes	append = 0;
7724360Simp	while ((ch = getopt(argc, argv, "ai")) != -1)
781590Srgrimes		switch((char)ch) {
791590Srgrimes		case 'a':
801590Srgrimes			append = 1;
811590Srgrimes			break;
821590Srgrimes		case 'i':
831590Srgrimes			(void)signal(SIGINT, SIG_IGN);
841590Srgrimes			break;
851590Srgrimes		case '?':
861590Srgrimes		default:
871590Srgrimes			(void)fprintf(stderr, "usage: tee [-ai] [file ...]\n");
881590Srgrimes			exit(1);
891590Srgrimes		}
901590Srgrimes	argv += optind;
911590Srgrimes	argc -= optind;
921590Srgrimes
931590Srgrimes	if ((buf = malloc((u_int)BSIZE)) == NULL)
941590Srgrimes		err(1, "%s", strerror(errno));
951590Srgrimes
961590Srgrimes	add(STDOUT_FILENO, "stdout");
971590Srgrimes
981590Srgrimes	for (exitval = 0; *argv; ++argv)
991590Srgrimes		if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND :
1001590Srgrimes		    O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) {
1011590Srgrimes			err(0, "%s: %s", *argv, strerror(errno));
1021590Srgrimes			exitval = 1;
1031590Srgrimes		} else
1041590Srgrimes			add(fd, *argv);
1051590Srgrimes
1061590Srgrimes	while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0)
1071590Srgrimes		for (p = head; p; p = p->next) {
1081590Srgrimes			n = rval;
1091590Srgrimes			bp = buf;
1101590Srgrimes			do {
1111590Srgrimes				if ((wval = write(p->fd, bp, n)) == -1) {
1121590Srgrimes					err(0, "%s: %s",
1131590Srgrimes					    p->name, strerror(errno));
1141590Srgrimes					exitval = 1;
1151590Srgrimes					break;
1161590Srgrimes				}
1171590Srgrimes				bp += wval;
1181590Srgrimes			} while (n -= wval);
1191590Srgrimes		}
1201590Srgrimes	if (rval < 0)
1211590Srgrimes		err(1, "read: %s", strerror(errno));
1221590Srgrimes	exit(exitval);
1231590Srgrimes}
1241590Srgrimes
1251590Srgrimesvoid
1261590Srgrimesadd(fd, name)
1271590Srgrimes	int fd;
1281590Srgrimes	char *name;
1291590Srgrimes{
1301590Srgrimes	LIST *p;
1311590Srgrimes
1321590Srgrimes	if ((p = malloc((u_int)sizeof(LIST))) == NULL)
1331590Srgrimes		err(1, "%s", strerror(errno));
1341590Srgrimes	p->fd = fd;
1351590Srgrimes	p->name = name;
1361590Srgrimes	p->next = head;
1371590Srgrimes	head = p;
1381590Srgrimes}
1391590Srgrimes
1401590Srgrimes#if __STDC__
1411590Srgrimes#include <stdarg.h>
1421590Srgrimes#else
1431590Srgrimes#include <varargs.h>
1441590Srgrimes#endif
1451590Srgrimes
1461590Srgrimesvoid
1471590Srgrimes#if __STDC__
1481590Srgrimeserr(int doexit, const char *fmt, ...)
1491590Srgrimes#else
1501590Srgrimeserr(doexit, fmt, va_alist)
1511590Srgrimes	int doexit;
1521590Srgrimes	char *fmt;
1531590Srgrimes        va_dcl
1541590Srgrimes#endif
1551590Srgrimes{
1561590Srgrimes	va_list ap;
1571590Srgrimes#if __STDC__
1581590Srgrimes	va_start(ap, fmt);
1591590Srgrimes#else
1601590Srgrimes	va_start(ap);
1611590Srgrimes#endif
1621590Srgrimes	(void)fprintf(stderr, "tee: ");
1631590Srgrimes	(void)vfprintf(stderr, fmt, ap);
1641590Srgrimes	va_end(ap);
1651590Srgrimes	(void)fprintf(stderr, "\n");
1661590Srgrimes	if (doexit)
1671590Srgrimes		exit(1);
1681590Srgrimes}
169