BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / split / split.c
index 08ac19d..318db8b 100644 (file)
-static char *sccsid = "@(#)split.c     4.2 (Berkeley) %G%";
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may 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.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1987 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)split.c    4.8 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <ctype.h>
 
 
-unsigned count = 1000;
-int    fnumber;
-char   fname[100];
-char   *ifil;
-char   *ofil;
-FILE   *is;
-FILE   *os;
+#define DEFLINE        1000                    /* default num lines per file */
+#define ERR    -1                      /* general error */
+#define NO     0                       /* no/false */
+#define OK     0                       /* okay exit */
+#define YES    1                       /* yes/true */
+
+static long    bytecnt,                /* byte count to split on */
+               numlines;               /* lines in each file */
+static int     ifd = ERR,              /* input file descriptor */
+               ofd = ERR;              /* output file descriptor */
+static short   file_open;              /* if a file open */
+static char    bfr[MAXBSIZE],          /* I/O buffer */
+               fname[MAXPATHLEN];      /* file name */
 
 main(argc, argv)
 
 main(argc, argv)
-char *argv[];
+       int argc;
+       char **argv;
 {
 {
-       register i, c, f;
-       int iflg = 0;
+       register int cnt;
+       long atol();
+       char *strcpy();
 
 
-       for(i=1; i<argc; i++)
-               if(argv[i][0] == '-')
-                       switch(argv[i][1]) {
-               
-                       case '\0':
-                               iflg = 1;
-                               continue;
-               
-                       case '0':
-                       case '1':
-                       case '2':
-                       case '3':
-                       case '4':
-                       case '5':
-                       case '6':
-                       case '7':
-                       case '8':
-                       case '9':
-                               count = atoi(argv[i]+1);
-                               continue;
+       for (cnt = 1; cnt < argc; ++cnt) {
+               if (argv[cnt][0] == '-')
+                       switch(argv[cnt][1]) {
+                       case 0:         /* stdin by request */
+                               if (ifd != ERR)
+                                       usage();
+                               ifd = 0;
+                               break;
+                       case 'b':       /* byte count split */
+                               if (numlines)
+                                       usage();
+                               if (!argv[cnt][2])
+                                       bytecnt = atol(argv[++cnt]);
+                               else
+                                       bytecnt = atol(argv[cnt] + 2);
+                               if (bytecnt <= 0) {
+                                       fputs("split: byte count must be greater than zero.\n", stderr);
+                                       usage();
+                               }
+                               break;
+                       default:
+                               if (!isdigit(argv[cnt][1]) || bytecnt)
+                                       usage();
+                               if ((numlines = atol(argv[cnt] + 1)) <= 0) {
+                                       fputs("split: line count must be greater than zero.\n", stderr);
+                                       usage();
+                               }
+                               break;
+                       }
+               else if (ifd == ERR) {          /* input file */
+                       if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) {
+                               perror(argv[cnt]);
+                               exit(1);
                        }
                        }
-               else if(iflg)
-                       ofil = argv[i];
-               else {
-                       ifil = argv[i];
-                       iflg = 2;
                }
                }
-       if(iflg != 2)
-               is = stdin;
-       else
-               if((is=fopen(ifil,"r")) == NULL) {
-                       perror(ifil);
+               else if (!*fname)               /* output file prefix */
+                       strcpy(fname, argv[cnt]);
+               else
+                       usage();
+       }
+       if (ifd == ERR)                         /* stdin by default */
+               ifd = 0;
+       if (bytecnt)
+               split1();
+       if (!numlines)
+               numlines = DEFLINE;
+       split2();
+       exit(0);
+}
+
+/*
+ * split1 --
+ *     split by bytes
+ */
+split1()
+{
+       register long bcnt;
+       register int dist, len;
+       register char *C;
+
+       for (bcnt = 0;;)
+               switch(len = read(ifd, bfr, MAXBSIZE)) {
+               case 0:
+                       exit(OK);
+               case ERR:
+                       perror("read");
                        exit(1);
                        exit(1);
+               default:
+                       if (!file_open) {
+                               newfile();
+                               file_open = YES;
+                       }
+                       if (bcnt + len >= bytecnt) {
+                               dist = bytecnt - bcnt;
+                               if (write(ofd, bfr, dist) != dist)
+                                       wrerror();
+                               len -= dist;
+                               for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) {
+                                       newfile();
+                                       if (write(ofd, C, (int)bytecnt) != bytecnt)
+                                               wrerror();
+                               }
+                               if (len) {
+                                       newfile();
+                                       if (write(ofd, C, len) != len)
+                                               wrerror();
+                               }
+                               else
+                                       file_open = NO;
+                               bcnt = len;
+                       }
+                       else {
+                               bcnt += len;
+                               if (write(ofd, bfr, len) != len)
+                                       wrerror();
+                       }
                }
                }
-       if(ofil == 0)
-               ofil = "x";
+}
+
+/*
+ * split2 --
+ *     split by lines
+ */
+split2()
+{
+       register char *Ce, *Cs;
+       register long lcnt;
+       register int len, bcnt;
 
 
-loop:
-       f = 1;
-       for(i=0; i<count; i++)
-       do {
-               c = getc(is);
-               if(c == EOF) {
-                       if(f == 0)
-                               fclose(os);
+       for (lcnt = 0;;)
+               switch(len = read(ifd, bfr, MAXBSIZE)) {
+               case 0:
                        exit(0);
                        exit(0);
-               }
-               if(f) {
-                       for(f=0; ofil[f]; f++)
-                               fname[f] = ofil[f];
-                       fname[f++] = fnumber/26 + 'a';
-                       fname[f++] = fnumber%26 + 'a';
-                       fname[f] = '\0';
-                       fnumber++;
-                       if((os=fopen(fname,"w")) == NULL) {
-                               fprintf(stderr,"Cannot create output\n");
-                               exit(1);
+               case ERR:
+                       perror("read");
+                       exit(1);
+               default:
+                       if (!file_open) {
+                               newfile();
+                               file_open = YES;
+                       }
+                       for (Cs = Ce = bfr; len--; Ce++)
+                               if (*Ce == '\n' && ++lcnt == numlines) {
+                                       bcnt = Ce - Cs + 1;
+                                       if (write(ofd, Cs, bcnt) != bcnt)
+                                               wrerror();
+                                       lcnt = 0;
+                                       Cs = Ce + 1;
+                                       if (len)
+                                               newfile();
+                                       else
+                                               file_open = NO;
+                               }
+                       if (Cs < Ce) {
+                               bcnt = Ce - Cs;
+                               if (write(ofd, Cs, bcnt) != bcnt)
+                                       wrerror();
                        }
                        }
-                       f = 0;
                }
                }
-               putc(c, os);
-       } while(c != '\n');
-       fclose(os);
-       goto loop;
+}
+
+/*
+ * newfile --
+ *     open a new file
+ */
+newfile()
+{
+       static long fnum;
+       static short defname;
+       static char *fpnt;
+
+       if (ofd == ERR) {
+               if (fname[0]) {
+                       fpnt = fname + strlen(fname);
+                       defname = NO;
+               }
+               else {
+                       fname[0] = 'x';
+                       fpnt = fname + 1;
+                       defname = YES;
+               }
+               ofd = fileno(stdout);
+       }
+       /*
+        * hack to increase max files; original code just wandered through
+        * magic characters.  Maximum files is 3 * 26 * 26 == 2028
+        */
+#define MAXFILES       676
+       if (fnum == MAXFILES) {
+               if (!defname || fname[0] == 'z') {
+                       fputs("split: too many files.\n", stderr);
+                       exit(1);
+               }
+               ++fname[0];
+               fnum = 0;
+       }
+       fpnt[0] = fnum / 26 + 'a';
+       fpnt[1] = fnum % 26 + 'a';
+       ++fnum;
+       if (!freopen(fname, "w", stdout)) {
+               fprintf(stderr, "split: unable to write to %s.\n", fname);
+               exit(ERR);
+       }
+}
+
+/*
+ * usage --
+ *     print usage message and die
+ */
+usage()
+{
+       fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr);
+       exit(1);
+}
+
+/*
+ * wrerror --
+ *     write error
+ */
+wrerror()
+{
+       perror("split: write");
+       exit(1);
 }
 }