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.8 (Berkeley) 08/11/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 n, fd, rval, wval; 47 register char *bp; 48 int append, ch, exitval; 49 char *buf, *malloc(), *strerror(); 50 off_t lseek(); 51 52 append = 0; 53 while ((ch = getopt(argc, argv, "ai")) != EOF) 54 switch((char)ch) { 55 case 'a': 56 append = 1; 57 break; 58 case 'i': 59 (void)signal(SIGINT, SIG_IGN); 60 break; 61 case '?': 62 default: 63 (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n"); 64 exit(1); 65 } 66 argv += optind; 67 argc -= optind; 68 69 if (!(buf = malloc((u_int)8 * 1024))) { 70 (void)fprintf(stderr, "tee: out of space.\n"); 71 exit(1); 72 } 73 add(1, "stdout"); 74 for (; *argv; ++argv) 75 if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : 76 O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) 77 (void)fprintf(stderr, "tee: %s: %s.\n", 78 *argv, strerror(errno)); 79 else 80 add(fd, *argv); 81 exitval = 0; 82 while ((rval = read(0, buf, sizeof(buf))) > 0) 83 for (p = head; p; p = p->next) { 84 n = rval; 85 bp = buf; 86 do { 87 if ((wval = write(p->fd, bp, n)) == -1) { 88 (void)fprintf(stderr, "tee: %s: %s.\n", 89 p->name, strerror(errno)); 90 exitval = 1; 91 break; 92 } 93 bp += wval; 94 } while (n -= wval); 95 } 96 if (rval < 0) { 97 (void)fprintf(stderr, "tee: read: %s\n", strerror(errno)); 98 exit(1); 99 } 100 exit(exitval); 101 } 102 103 add(fd, name) 104 int fd; 105 char *name; 106 { 107 LIST *p; 108 char *malloc(), *strerror(); 109 110 /* NOSTRICT */ 111 if (!(p = (LIST *)malloc((u_int)sizeof(LIST)))) { 112 (void)fprintf(stderr, "tee: out of space.\n"); 113 exit(1); 114 } 115 p->fd = fd; 116 p->name = name; 117 p->next = head; 118 head = p; 119 } 120