document distributed with 4.2BSD
[unix-history] / usr / src / bin / cat / cat.c
index 24db983..0b9e5ef 100644 (file)
@@ -1,6 +1,12 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)cat.c       4.7 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)cat.c      5.2 (Berkeley) %G%";
+#endif not lint
 
 /*
  * Concatenate files.
 
 /*
  * Concatenate files.
@@ -10,8 +16,10 @@ static       char *sccsid = "@(#)cat.c       4.7 (Berkeley) %G%";
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
-int    bflg, eflg, nflg, sflg, tflg, vflg;
-int    spaced, col, lno, inline;
+/* #define OPTSIZE BUFSIZ      /* define this only if not 4.2 BSD or beyond */
+
+int    bflg, eflg, nflg, sflg, tflg, uflg, vflg;
+int    spaced, col, lno, inline, ibsize, obsize;
 
 main(argc, argv)
 char **argv;
 
 main(argc, argv)
 char **argv;
@@ -21,6 +29,7 @@ char **argv;
        register c;
        int dev, ino = -1;
        struct stat statb;
        register c;
        int dev, ino = -1;
        struct stat statb;
+       int retval = 0;
 
        lno = 1;
        for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
 
        lno = 1;
        for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
@@ -29,6 +38,7 @@ char **argv;
                        break;
                case 'u':
                        setbuf(stdout, (char *)NULL);
                        break;
                case 'u':
                        setbuf(stdout, (char *)NULL);
+                       uflg++;
                        continue;
                case 'n':
                        nflg++;
                        continue;
                case 'n':
                        nflg++;
@@ -60,7 +70,12 @@ char **argv;
                        dev = statb.st_dev;
                        ino = statb.st_ino;
                }
                        dev = statb.st_dev;
                        ino = statb.st_ino;
                }
+#ifndef        OPTSIZE
+               obsize = statb.st_blksize;
+#endif
        }
        }
+       else
+               obsize = 0;
        if (argc < 2) {
                argc = 2;
                fflg++;
        if (argc < 2) {
                argc = 2;
                fflg++;
@@ -71,6 +86,7 @@ char **argv;
                else {
                        if ((fi = fopen(*argv, "r")) == NULL) {
                                perror(*argv);
                else {
                        if ((fi = fopen(*argv, "r")) == NULL) {
                                perror(*argv);
+                               retval = 1;
                                continue;
                        }
                }
                                continue;
                        }
                }
@@ -80,21 +96,33 @@ char **argv;
                                fprintf(stderr, "cat: input %s is output\n",
                                   fflg?"-": *argv);
                                fclose(fi);
                                fprintf(stderr, "cat: input %s is output\n",
                                   fflg?"-": *argv);
                                fclose(fi);
+                               retval = 1;
                                continue;
                        }
                                continue;
                        }
+#ifndef        OPTSIZE
+                       ibsize = statb.st_blksize;
+#endif
                }
                }
+               else
+                       ibsize = 0;
                if (nflg||sflg||vflg)
                        copyopt(fi);
                if (nflg||sflg||vflg)
                        copyopt(fi);
-               else {
+               else if (uflg) {
                        while ((c = getc(fi)) != EOF)
                                putchar(c);
                        while ((c = getc(fi)) != EOF)
                                putchar(c);
-               }
+               } else
+                       retval |= fastcat(fileno(fi));  /* no flags specified */
                if (fi!=stdin)
                        fclose(fi);
                if (fi!=stdin)
                        fclose(fi);
+               else
+                       clearerr(fi);           /* reset sticky eof */
+               if (ferror(stdout)) {
+                       fprintf(stderr, "cat: output write error\n");
+                       retval = 1;
+                       break;
+               }
        }
        }
-       if (ferror(stdout))
-               fprintf(stderr, "cat: output write error\n");
-       return(0);
+       exit(retval);
 }
 
 copyopt(f)
 }
 
 copyopt(f)
@@ -143,3 +171,52 @@ top:
        spaced = 0;
        goto top;
 }
        spaced = 0;
        goto top;
 }
+
+fastcat(fd)
+register int fd;
+{
+       register int    buffsize, n, nwritten, offset;
+       register char   *buff;
+       struct stat     statbuff;
+       char            *malloc();
+
+#ifndef        OPTSIZE
+       if (obsize)
+               buffsize = obsize;      /* common case, use output blksize */
+       else if (ibsize)
+               buffsize = ibsize;
+       else
+               buffsize = BUFSIZ;
+#else
+       buffsize = OPTSIZE;
+#endif
+
+       if ((buff = malloc(buffsize)) == NULL) {
+               perror("cat: no memory");
+               return (1);
+       }
+
+       /*
+        * Note that on some systems (V7), very large writes to a pipe
+        * return less than the requested size of the write.
+        * In this case, multiple writes are required.
+        */
+       while ((n = read(fd, buff, buffsize)) > 0) {
+               offset = 0;
+               do {
+                       nwritten = write(fileno(stdout), &buff[offset], n);
+                       if (nwritten <= 0) {
+                               perror("cat: write error");
+                               exit(2);
+                       }
+                       offset += nwritten;
+               } while ((n -= nwritten) > 0);
+       }
+
+       free(buff);
+       if (n < 0) {
+               perror("cat: read error");
+               return (1);
+       }
+       return (0);
+}