cat.c

Go to the documentation of this file.
00001 /* cat - concatenates files             Author: Andy Tanenbaum */
00002 
00003 /* 30 March 1990 - Slightly modified for efficiency by Norbert Schlenker. */
00004 /* 23 March 2002 - Proper error messages by Kees J. Bot. */
00005 
00006 
00007 #include <errno.h>
00008 #include <sys/types.h>
00009 #include <fcntl.h>
00010 #include <string.h>
00011 #include <unistd.h>
00012 #include <stdlib.h>
00013 #include <minix/minlib.h>
00014 #include <stdio.h>
00015 
00016 #define CHUNK_SIZE      (2048 * sizeof(char *))
00017 
00018 static int unbuffered;
00019 static char ibuf[CHUNK_SIZE];
00020 static char obuf[CHUNK_SIZE];
00021 static char *op = obuf;
00022 
00023 int main(int argc, char **argv);
00024 static void copyout(char *file, int fd);
00025 static void output(char *buf, size_t count);
00026 static void report(char *label);
00027 static void fatal(char *label);
00028 
00029 static char STDIN[] = "standard input";
00030 static char STDOUT[] = "standard output";
00031 
00032 static int excode = 0;
00033 
00034 int main(int argc, char *argv[])
00035 {
00036   int i, fd;
00037 
00038   i = 1;
00039   while (i < argc && argv[i][0] == '-') {
00040         char *opt = argv[i] + 1;
00041 
00042         if (opt[0] == 0) break;                         /* - */
00043         i++;
00044         if (opt[0] == '-' && opt[1] == 0) break;        /* -- */
00045 
00046         while (*opt != 0) switch (*opt++) {
00047         case 'u':
00048                 unbuffered = 1;
00049                 break;
00050         default:
00051                 std_err("Usage: cat [-u] [file ...]\n");
00052                 exit(1);
00053         }
00054   }
00055 
00056   if (i >= argc) {
00057         copyout(STDIN, STDIN_FILENO);
00058   } else {
00059         while (i < argc) {
00060                 char *file = argv[i++];
00061 
00062                 if (file[0] == '-' && file[1] == 0) {
00063                         copyout(STDIN, STDIN_FILENO);
00064                 } else {
00065                         fd = open(file, O_RDONLY);
00066                         if (fd < 0) {
00067                                 report(file);
00068                         } else {
00069                                 copyout(file, fd);
00070                                 close(fd);
00071                         }
00072                 }
00073         }
00074   }
00075   output(obuf, (op - obuf));
00076   return(excode);
00077 }
00078 
00079 static void copyout(char *file, int fd)
00080 {
00081   int n;
00082 
00083   while (1) {
00084         n = read(fd, ibuf, CHUNK_SIZE);
00085         if (n < 0) fatal(file);
00086         if (n == 0) return;
00087         if (unbuffered || (op == obuf && n == CHUNK_SIZE)) {
00088                 output(ibuf, n);
00089         } else {
00090                 int bytes_left;
00091 
00092                 bytes_left = &obuf[CHUNK_SIZE] - op;
00093                 if (n <= bytes_left) {
00094                         memcpy(op, ibuf, (size_t)n);
00095                         op += n;
00096                 } else {
00097                         memcpy(op, ibuf, (size_t)bytes_left);
00098                         output(obuf, CHUNK_SIZE);
00099                         n -= bytes_left;
00100                         memcpy(obuf, ibuf + bytes_left, (size_t)n);
00101                         op = obuf + n;
00102                 }
00103         }
00104   }
00105 }
00106 
00107 static void output(char *buf, size_t count)
00108 {
00109   ssize_t n;
00110 
00111   while (count > 0) {
00112         n = write(STDOUT_FILENO, buf, count);
00113         if (n <= 0) {
00114                 if (n < 0) fatal(STDOUT);
00115                 std_err("cat: standard output: EOF\n");
00116                 exit(1);
00117         }
00118         buf += n;
00119         count -= n;
00120   }
00121 }
00122 
00123 static void report(char *label)
00124 {
00125   int e = errno;
00126   std_err("cat: ");
00127   std_err(label);
00128   std_err(": ");
00129   std_err(strerror(e));
00130   std_err("\n");
00131   excode = 1;
00132 }
00133 
00134 static void fatal(char *label)
00135 {
00136   report(label);
00137   exit(1);
00138 }

Generated on Fri Apr 14 22:57:04 2006 for minix by  doxygen 1.4.6