POSIX 1003.2 is not going to allow write errors to be ignored; let's
[unix-history] / usr / src / usr.bin / tee / tee.c
index 43c9438..0fc0d8a 100644 (file)
-static char *sccsid = "@(#)tee.c       4.1 (Berkeley) %G%";
 /*
 /*
- * tee-- pipe fitting
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  */
 
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <pagsiz.h>
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1988 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
 
 
-#define        BUFSIZ  BSIZE
-int openf[20] = { 1 };
-int n = 1;
-int t = 0;
-int aflag;
+#ifndef lint
+static char sccsid[] = "@(#)tee.c      5.6 (Berkeley) %G%";
+#endif /* not lint */
 
 
-char in[BUFSIZ];
-
-char out[BUFSIZ];
+#include <sys/types.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <stdio.h>
 
 
-extern errno;
-long   lseek();
+typedef struct _list {
+       struct _list *next;
+       int fd;
+       char *name;
+} LIST;
+LIST *head;
 
 
-main(argc,argv)
-char **argv;
+main(argc, argv)
+       int argc;
+       char **argv;
 {
 {
-       int register r,w,p;
-       struct stat buf;
-       while(argc>1&&argv[1][0]=='-') {
-               switch(argv[1][1]) {
+       extern int errno, optind;
+       register LIST *p;
+       register int append, n, fd;
+       int ch, exitval;
+       char *buf, *malloc(), *strerror();
+       off_t lseek();
+
+       append = 0;
+       while ((ch = getopt(argc, argv, "ai")) != EOF)
+               switch((char)ch) {
                case 'a':
                case 'a':
-                       aflag++;
+                       append = 1;
                        break;
                case 'i':
                        break;
                case 'i':
-               case 0:
-                       signal(SIGINT, SIG_IGN);
+                       (void)signal(SIGINT, SIG_IGN);
+                       break;
+               case '?':
+               default:
+                       (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n");
+                       exit(1);
                }
                }
-               argv++;
-               argc--;
+       argv += optind;
+       argc -= optind;
+
+       if (!(buf = malloc((u_int)8 * 1024))) {
+               (void)fprintf(stderr, "tee: out of space.\n");
+               exit(1);
        }
        }
-       fstat(1,&buf);
-       t = (buf.st_mode&S_IFMT)==S_IFCHR;
-       if(lseek(1,0L,1)==-1&&errno==ESPIPE)
-               t++;
-       while(argc-->1) {
-               if(aflag) {
-                       openf[n] = open(argv[1],1);
-                       if(openf[n] < 0)
-                               openf[n] = creat(argv[1],0666);
-                       lseek(openf[n++],0L,2);
-               } else
-                       openf[n++] = creat(argv[1],0666);
-               if(stat(argv[1],&buf)>=0) {
-                       if((buf.st_mode&S_IFMT)==S_IFCHR)
-                               t++;
-               } else {
-                       puts("tee: cannot open ");
-                       puts(argv[1]);
-                       puts("\n");
-                       n--;
+       add(1, "stdout");
+       for (; *argv; ++argv)
+               if ((fd = open(*argv, append ? O_WRONLY|O_CREAT :
+                   O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0)
+                       (void)fprintf(stderr, "tee: %s: %s.\n",
+                           *argv, strerror(errno));
+               else {
+                       if (append)
+                               (void)lseek(fd, 0L, L_XTND);
+                       add(fd, *argv);
                }
                }
-               argv++;
-       }
-       r = w = 0;
-       for(;;) {
-               for(p=0;p<BUFSIZ;) {
-                       if(r>=w) {
-                               if(t>0&&p>0) break;
-                               w = read(0,in,BUFSIZ);
-                               r = 0;
-                               if(w<=0) {
-                                       stash(p);
-                                       return;
-                               }
+       exitval = 0;
+       while ((n = read(0, buf, sizeof(buf))) > 0)
+               for (p = head; p; p = p->next)
+                       if (write(p->fd, buf, n) != n) {
+                               (void)fprintf(stderr, "tee: %s: %s.\n",
+                                   p->name, strerror(errno));
+                               exitval = 1;
                        }
                        }
-                       out[p++] = in[r++];
-               }
-               stash(p);
+       if (n < 0) {
+               (void)fprintf(stderr, "tee: read: %s\n", strerror(errno));
+               exit(1);
        }
        }
+       exit(exitval);
 }
 
 }
 
-stash(p)
+add(fd, name)
+       int fd;
+       char *name;
 {
 {
-       int k;
-       int i;
-       int d;
-       d = t ? 16 : p;
-       for(i=0; i<p; i+=d)
-               for(k=0;k<n;k++)
-                       write(openf[k], out+i, d<p-i?d:p-i);
-}
+       LIST *p;
+       char *malloc(), *strerror();
 
 
-puts(s)
-char *s;
-{
-       while(*s)
-               write(2,s++,1);
+       /* NOSTRICT */
+       if (!(p = (LIST *)malloc((u_int)sizeof(LIST)))) {
+               (void)fprintf(stderr, "tee: out of space.\n");
+               exit(1);
+       }
+       p->fd = fd;
+       p->name = name;
+       p->next = head;
+       head = p;
 }
 }