11123Sbill /* 235063Sbostic * Copyright (c) 1988 Regents of the University of California. 335063Sbostic * All rights reserved. 435063Sbostic * 535063Sbostic * Redistribution and use in source and binary forms are permitted 635063Sbostic * provided that the above copyright notice and this paragraph are 735063Sbostic * duplicated in all such forms and that any documentation, 835063Sbostic * advertising materials, and other materials related to such 935063Sbostic * distribution and use acknowledge that the software was developed 1035063Sbostic * by the University of California, Berkeley. The name of the 1135063Sbostic * University may not be used to endorse or promote products derived 1235063Sbostic * from this software without specific prior written permission. 1335063Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435063Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1538028Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 161123Sbill */ 171123Sbill 1835063Sbostic #ifndef lint 1935063Sbostic char copyright[] = 2035063Sbostic "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 2135063Sbostic All rights reserved.\n"; 2235063Sbostic #endif /* not lint */ 231123Sbill 2435063Sbostic #ifndef lint 25*38585Sbostic static char sccsid[] = "@(#)tee.c 5.8 (Berkeley) 08/11/89"; 2635063Sbostic #endif /* not lint */ 2725600Ssam 2835063Sbostic #include <sys/types.h> 2935063Sbostic #include <sys/file.h> 3035063Sbostic #include <signal.h> 3135063Sbostic #include <stdio.h> 3225600Ssam 3338028Sbostic typedef struct _list { 3438028Sbostic struct _list *next; 3538028Sbostic int fd; 3638028Sbostic char *name; 3738028Sbostic } LIST; 3838028Sbostic LIST *head; 3938028Sbostic 4035063Sbostic main(argc, argv) 4135063Sbostic int argc; 4235063Sbostic char **argv; 4335063Sbostic { 4438028Sbostic extern int errno, optind; 4538028Sbostic register LIST *p; 46*38585Sbostic register int n, fd, rval, wval; 47*38585Sbostic register char *bp; 48*38585Sbostic int append, ch, exitval; 4938028Sbostic char *buf, *malloc(), *strerror(); 5035063Sbostic off_t lseek(); 5125600Ssam 5235063Sbostic append = 0; 5335063Sbostic while ((ch = getopt(argc, argv, "ai")) != EOF) 5435063Sbostic switch((char)ch) { 551123Sbill case 'a': 5635063Sbostic append = 1; 571123Sbill break; 581123Sbill case 'i': 5935063Sbostic (void)signal(SIGINT, SIG_IGN); 6035063Sbostic break; 6135063Sbostic case '?': 6235063Sbostic default: 6338028Sbostic (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n"); 6438028Sbostic exit(1); 651123Sbill } 6635063Sbostic argv += optind; 6735063Sbostic argc -= optind; 6835063Sbostic 6938028Sbostic if (!(buf = malloc((u_int)8 * 1024))) { 7038028Sbostic (void)fprintf(stderr, "tee: out of space.\n"); 7138028Sbostic exit(1); 721123Sbill } 7338028Sbostic add(1, "stdout"); 7438028Sbostic for (; *argv; ++argv) 7538580Sbostic if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : 7638028Sbostic O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) 7738028Sbostic (void)fprintf(stderr, "tee: %s: %s.\n", 7838028Sbostic *argv, strerror(errno)); 7938580Sbostic else 8038028Sbostic add(fd, *argv); 8138028Sbostic exitval = 0; 82*38585Sbostic while ((rval = read(0, buf, sizeof(buf))) > 0) 83*38585Sbostic for (p = head; p; p = p->next) { 84*38585Sbostic n = rval; 85*38585Sbostic bp = buf; 86*38585Sbostic do { 87*38585Sbostic if ((wval = write(p->fd, bp, n)) == -1) { 88*38585Sbostic (void)fprintf(stderr, "tee: %s: %s.\n", 89*38585Sbostic p->name, strerror(errno)); 90*38585Sbostic exitval = 1; 91*38585Sbostic break; 92*38585Sbostic } 93*38585Sbostic bp += wval; 94*38585Sbostic } while (n -= wval); 95*38585Sbostic } 96*38585Sbostic if (rval < 0) { 9738028Sbostic (void)fprintf(stderr, "tee: read: %s\n", strerror(errno)); 9838028Sbostic exit(1); 9938028Sbostic } 10038028Sbostic exit(exitval); 1011123Sbill } 10238028Sbostic 10338028Sbostic add(fd, name) 10438028Sbostic int fd; 10538028Sbostic char *name; 10638028Sbostic { 10738028Sbostic LIST *p; 10838028Sbostic char *malloc(), *strerror(); 10938028Sbostic 11038028Sbostic /* NOSTRICT */ 11138028Sbostic if (!(p = (LIST *)malloc((u_int)sizeof(LIST)))) { 11238028Sbostic (void)fprintf(stderr, "tee: out of space.\n"); 11338028Sbostic exit(1); 11438028Sbostic } 11538028Sbostic p->fd = fd; 11638028Sbostic p->name = name; 11738028Sbostic p->next = head; 11838028Sbostic head = p; 11938028Sbostic } 120