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*39688Sbostic static char sccsid[] = "@(#)tee.c 5.9 (Berkeley) 12/06/89"; 2635063Sbostic #endif /* not lint */ 2725600Ssam 2835063Sbostic #include <sys/types.h> 2935063Sbostic #include <sys/file.h> 3035063Sbostic #include <signal.h> 3135063Sbostic #include <stdio.h> 32*39688Sbostic #include <unistd.h> 3325600Ssam 3438028Sbostic typedef struct _list { 3538028Sbostic struct _list *next; 3638028Sbostic int fd; 3738028Sbostic char *name; 3838028Sbostic } LIST; 3938028Sbostic LIST *head; 4038028Sbostic 4135063Sbostic main(argc, argv) 4235063Sbostic int argc; 4335063Sbostic char **argv; 4435063Sbostic { 4538028Sbostic extern int errno, optind; 4638028Sbostic register LIST *p; 4738585Sbostic register int n, fd, rval, wval; 4838585Sbostic register char *bp; 4938585Sbostic int append, ch, exitval; 5038028Sbostic char *buf, *malloc(), *strerror(); 5135063Sbostic off_t lseek(); 5225600Ssam 5335063Sbostic append = 0; 5435063Sbostic while ((ch = getopt(argc, argv, "ai")) != EOF) 5535063Sbostic switch((char)ch) { 561123Sbill case 'a': 5735063Sbostic append = 1; 581123Sbill break; 591123Sbill case 'i': 6035063Sbostic (void)signal(SIGINT, SIG_IGN); 6135063Sbostic break; 6235063Sbostic case '?': 6335063Sbostic default: 6438028Sbostic (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n"); 6538028Sbostic exit(1); 661123Sbill } 6735063Sbostic argv += optind; 6835063Sbostic argc -= optind; 6935063Sbostic 7038028Sbostic if (!(buf = malloc((u_int)8 * 1024))) { 7138028Sbostic (void)fprintf(stderr, "tee: out of space.\n"); 7238028Sbostic exit(1); 731123Sbill } 74*39688Sbostic add(STDOUT_FILENO, "stdout"); 7538028Sbostic for (; *argv; ++argv) 7638580Sbostic if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : 7738028Sbostic O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) 7838028Sbostic (void)fprintf(stderr, "tee: %s: %s.\n", 7938028Sbostic *argv, strerror(errno)); 8038580Sbostic else 8138028Sbostic add(fd, *argv); 8238028Sbostic exitval = 0; 83*39688Sbostic while ((rval = read(STDIN_FILENO, buf, sizeof(buf))) > 0) 8438585Sbostic for (p = head; p; p = p->next) { 8538585Sbostic n = rval; 8638585Sbostic bp = buf; 8738585Sbostic do { 8838585Sbostic if ((wval = write(p->fd, bp, n)) == -1) { 8938585Sbostic (void)fprintf(stderr, "tee: %s: %s.\n", 9038585Sbostic p->name, strerror(errno)); 9138585Sbostic exitval = 1; 9238585Sbostic break; 9338585Sbostic } 9438585Sbostic bp += wval; 9538585Sbostic } while (n -= wval); 9638585Sbostic } 9738585Sbostic if (rval < 0) { 9838028Sbostic (void)fprintf(stderr, "tee: read: %s\n", strerror(errno)); 9938028Sbostic exit(1); 10038028Sbostic } 10138028Sbostic exit(exitval); 1021123Sbill } 10338028Sbostic 10438028Sbostic add(fd, name) 10538028Sbostic int fd; 10638028Sbostic char *name; 10738028Sbostic { 10838028Sbostic LIST *p; 10938028Sbostic char *malloc(), *strerror(); 11038028Sbostic 11138028Sbostic /* NOSTRICT */ 11238028Sbostic if (!(p = (LIST *)malloc((u_int)sizeof(LIST)))) { 11338028Sbostic (void)fprintf(stderr, "tee: out of space.\n"); 11438028Sbostic exit(1); 11538028Sbostic } 11638028Sbostic p->fd = fd; 11738028Sbostic p->name = name; 11838028Sbostic p->next = head; 11938028Sbostic head = p; 12038028Sbostic } 121