xref: /csrg-svn/usr.bin/tee/tee.c (revision 38585)
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