home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / split / split.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  6.2 KB  |  275 lines

  1. /*
  2.  * Copyright (c) 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1987 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)split.c    4.8 (Berkeley) 6/1/90";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/file.h>
  46. #include <stdio.h>
  47. #include <ctype.h>
  48.  
  49. #define DEFLINE    1000            /* default num lines per file */
  50. #define ERR    -1            /* general error */
  51. #define NO    0            /* no/false */
  52. #define OK    0            /* okay exit */
  53. #define YES    1            /* yes/true */
  54.  
  55. static long    bytecnt,        /* byte count to split on */
  56.         numlines;        /* lines in each file */
  57. static int    ifd = ERR,        /* input file descriptor */
  58.         ofd = ERR;        /* output file descriptor */
  59. static short    file_open;        /* if a file open */
  60. static char    bfr[MAXBSIZE],        /* I/O buffer */
  61.         fname[MAXPATHLEN];    /* file name */
  62.  
  63. main(argc, argv)
  64.     int argc;
  65.     char **argv;
  66. {
  67.     register int cnt;
  68.     long atol();
  69.     char *strcpy();
  70.  
  71.     for (cnt = 1; cnt < argc; ++cnt) {
  72.         if (argv[cnt][0] == '-')
  73.             switch(argv[cnt][1]) {
  74.             case 0:        /* stdin by request */
  75.                 if (ifd != ERR)
  76.                     usage();
  77.                 ifd = 0;
  78.                 break;
  79.             case 'b':    /* byte count split */
  80.                 if (numlines)
  81.                     usage();
  82.                 if (!argv[cnt][2])
  83.                     bytecnt = atol(argv[++cnt]);
  84.                 else
  85.                     bytecnt = atol(argv[cnt] + 2);
  86.                 if (bytecnt <= 0) {
  87.                     fputs("split: byte count must be greater than zero.\n", stderr);
  88.                     usage();
  89.                 }
  90.                 break;
  91.             default:
  92.                 if (!isdigit(argv[cnt][1]) || bytecnt)
  93.                     usage();
  94.                 if ((numlines = atol(argv[cnt] + 1)) <= 0) {
  95.                     fputs("split: line count must be greater than zero.\n", stderr);
  96.                     usage();
  97.                 }
  98.                 break;
  99.             }
  100.         else if (ifd == ERR) {        /* input file */
  101.             if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) {
  102.                 perror(argv[cnt]);
  103.                 exit(1);
  104.             }
  105.         }
  106.         else if (!*fname)        /* output file prefix */
  107.             strcpy(fname, argv[cnt]);
  108.         else
  109.             usage();
  110.     }
  111.     if (ifd == ERR)                /* stdin by default */
  112.         ifd = 0;
  113.     if (bytecnt)
  114.         split1();
  115.     if (!numlines)
  116.         numlines = DEFLINE;
  117.     split2();
  118.     exit(0);
  119. }
  120.  
  121. /*
  122.  * split1 --
  123.  *    split by bytes
  124.  */
  125. split1()
  126. {
  127.     register long bcnt;
  128.     register int dist, len;
  129.     register char *C;
  130.  
  131.     for (bcnt = 0;;)
  132.         switch(len = read(ifd, bfr, MAXBSIZE)) {
  133.         case 0:
  134.             exit(OK);
  135.         case ERR:
  136.             perror("read");
  137.             exit(1);
  138.         default:
  139.             if (!file_open) {
  140.                 newfile();
  141.                 file_open = YES;
  142.             }
  143.             if (bcnt + len >= bytecnt) {
  144.                 dist = bytecnt - bcnt;
  145.                 if (write(ofd, bfr, dist) != dist)
  146.                     wrerror();
  147.                 len -= dist;
  148.                 for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) {
  149.                     newfile();
  150.                     if (write(ofd, C, (int)bytecnt) != bytecnt)
  151.                         wrerror();
  152.                 }
  153.                 if (len) {
  154.                     newfile();
  155.                     if (write(ofd, C, len) != len)
  156.                         wrerror();
  157.                 }
  158.                 else
  159.                     file_open = NO;
  160.                 bcnt = len;
  161.             }
  162.             else {
  163.                 bcnt += len;
  164.                 if (write(ofd, bfr, len) != len)
  165.                     wrerror();
  166.             }
  167.         }
  168. }
  169.  
  170. /*
  171.  * split2 --
  172.  *    split by lines
  173.  */
  174. split2()
  175. {
  176.     register char *Ce, *Cs;
  177.     register long lcnt;
  178.     register int len, bcnt;
  179.  
  180.     for (lcnt = 0;;)
  181.         switch(len = read(ifd, bfr, MAXBSIZE)) {
  182.         case 0:
  183.             exit(0);
  184.         case ERR:
  185.             perror("read");
  186.             exit(1);
  187.         default:
  188.             if (!file_open) {
  189.                 newfile();
  190.                 file_open = YES;
  191.             }
  192.             for (Cs = Ce = bfr; len--; Ce++)
  193.                 if (*Ce == '\n' && ++lcnt == numlines) {
  194.                     bcnt = Ce - Cs + 1;
  195.                     if (write(ofd, Cs, bcnt) != bcnt)
  196.                         wrerror();
  197.                     lcnt = 0;
  198.                     Cs = Ce + 1;
  199.                     if (len)
  200.                         newfile();
  201.                     else
  202.                         file_open = NO;
  203.                 }
  204.             if (Cs < Ce) {
  205.                 bcnt = Ce - Cs;
  206.                 if (write(ofd, Cs, bcnt) != bcnt)
  207.                     wrerror();
  208.             }
  209.         }
  210. }
  211.  
  212. /*
  213.  * newfile --
  214.  *    open a new file
  215.  */
  216. newfile()
  217. {
  218.     static long fnum;
  219.     static short defname;
  220.     static char *fpnt;
  221.  
  222.     if (ofd == ERR) {
  223.         if (fname[0]) {
  224.             fpnt = fname + strlen(fname);
  225.             defname = NO;
  226.         }
  227.         else {
  228.             fname[0] = 'x';
  229.             fpnt = fname + 1;
  230.             defname = YES;
  231.         }
  232.         ofd = fileno(stdout);
  233.     }
  234.     /*
  235.      * hack to increase max files; original code just wandered through
  236.      * magic characters.  Maximum files is 3 * 26 * 26 == 2028
  237.      */
  238. #define MAXFILES    676
  239.     if (fnum == MAXFILES) {
  240.         if (!defname || fname[0] == 'z') {
  241.             fputs("split: too many files.\n", stderr);
  242.             exit(1);
  243.         }
  244.         ++fname[0];
  245.         fnum = 0;
  246.     }
  247.     fpnt[0] = fnum / 26 + 'a';
  248.     fpnt[1] = fnum % 26 + 'a';
  249.     ++fnum;
  250.     if (!freopen(fname, "w", stdout)) {
  251.         fprintf(stderr, "split: unable to write to %s.\n", fname);
  252.         exit(ERR);
  253.     }
  254. }
  255.  
  256. /*
  257.  * usage --
  258.  *    print usage message and die
  259.  */
  260. usage()
  261. {
  262.     fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr);
  263.     exit(1);
  264. }
  265.  
  266. /*
  267.  * wrerror --
  268.  *    write error
  269.  */
  270. wrerror()
  271. {
  272.     perror("split: write");
  273.     exit(1);
  274. }
  275.