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