1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)tee.c 5.7 (Berkeley) 08/10/89"; 26 #endif /* not lint */ 27 28 #include <sys/types.h> 29 #include <sys/file.h> 30 #include <signal.h> 31 #include <stdio.h> 32 33 typedef struct _list { 34 struct _list *next; 35 int fd; 36 char *name; 37 } LIST; 38 LIST *head; 39 40 main(argc, argv) 41 int argc; 42 char **argv; 43 { 44 extern int errno, optind; 45 register LIST *p; 46 register int append, n, fd; 47 int ch, exitval; 48 char *buf, *malloc(), *strerror(); 49 off_t lseek(); 50 51 append = 0; 52 while ((ch = getopt(argc, argv, "ai")) != EOF) 53 switch((char)ch) { 54 case 'a': 55 append = 1; 56 break; 57 case 'i': 58 (void)signal(SIGINT, SIG_IGN); 59 break; 60 case '?': 61 default: 62 (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n"); 63 exit(1); 64 } 65 argv += optind; 66 argc -= optind; 67 68 if (!(buf = malloc((u_int)8 * 1024))) { 69 (void)fprintf(stderr, "tee: out of space.\n"); 70 exit(1); 71 } 72 add(1, "stdout"); 73 for (; *argv; ++argv) 74 if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : 75 O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) 76 (void)fprintf(stderr, "tee: %s: %s.\n", 77 *argv, strerror(errno)); 78 else 79 add(fd, *argv); 80 exitval = 0; 81 while ((n = read(0, buf, sizeof(buf))) > 0) 82 for (p = head; p; p = p->next) 83 if (write(p->fd, buf, n) != n) { 84 (void)fprintf(stderr, "tee: %s: %s.\n", 85 p->name, strerror(errno)); 86 exitval = 1; 87 } 88 if (n < 0) { 89 (void)fprintf(stderr, "tee: read: %s\n", strerror(errno)); 90 exit(1); 91 } 92 exit(exitval); 93 } 94 95 add(fd, name) 96 int fd; 97 char *name; 98 { 99 LIST *p; 100 char *malloc(), *strerror(); 101 102 /* NOSTRICT */ 103 if (!(p = (LIST *)malloc((u_int)sizeof(LIST)))) { 104 (void)fprintf(stderr, "tee: out of space.\n"); 105 exit(1); 106 } 107 p->fd = fd; 108 p->name = name; 109 p->next = head; 110 head = p; 111 } 112