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