132747Sbostic /* 2*66824Sbostic * Copyright (c) 1987, 1993, 1994 362254Sbostic * The Regents of the University of California. All rights reserved. 432747Sbostic * 542768Sbostic * %sccs.include.redist.c% 632747Sbostic */ 730126Sbostic 832747Sbostic #ifndef lint 962254Sbostic static char copyright[] = 10*66824Sbostic "@(#) Copyright (c) 1987, 1993, 1994\n\ 1162254Sbostic The Regents of the University of California. All rights reserved.\n"; 1232747Sbostic #endif /* not lint */ 1332747Sbostic 1432747Sbostic #ifndef lint 15*66824Sbostic static char sccsid[] = "@(#)split.c 8.2 (Berkeley) 04/16/94"; 1632747Sbostic #endif /* not lint */ 1732747Sbostic 1830126Sbostic #include <sys/param.h> 19*66824Sbostic 20*66824Sbostic #include <ctype.h> 21*66824Sbostic #include <err.h> 22*66824Sbostic #include <fcntl.h> 231101Sbill #include <stdio.h> 24*66824Sbostic #include <stdlib.h> 25*66824Sbostic #include <string.h> 26*66824Sbostic #include <unistd.h> 271101Sbill 28*66824Sbostic #define DEFLINE 1000 /* Default num lines per file. */ 291101Sbill 30*66824Sbostic long bytecnt; /* Byte count to split on. */ 31*66824Sbostic long numlines; /* Line count to split on. */ 32*66824Sbostic int file_open; /* If a file open. */ 33*66824Sbostic int ifd = -1, ofd = -1; /* Input/output file descriptors. */ 34*66824Sbostic char bfr[MAXBSIZE]; /* I/O buffer. */ 35*66824Sbostic char fname[MAXPATHLEN]; /* File name prefix. */ 3630126Sbostic 37*66824Sbostic void newfile __P((void)); 38*66824Sbostic void split1 __P((void)); 39*66824Sbostic void split2 __P((void)); 40*66824Sbostic void usage __P((void)); 41*66824Sbostic 42*66824Sbostic int 4332747Sbostic main(argc, argv) 4436598Sbostic int argc; 45*66824Sbostic char *argv[]; 461101Sbill { 47*66824Sbostic int ch; 48*66824Sbostic char *ep, *p; 491101Sbill 50*66824Sbostic while ((ch = getopt(argc, argv, "-0123456789b:l:")) != EOF) 51*66824Sbostic switch (ch) { 52*66824Sbostic case '0': case '1': case '2': case '3': case '4': 53*66824Sbostic case '5': case '6': case '7': case '8': case '9': 54*66824Sbostic /* 55*66824Sbostic * Undocumented kludge: split was originally designed 56*66824Sbostic * to take a number after a dash. 57*66824Sbostic */ 58*66824Sbostic if (numlines == 0) { 59*66824Sbostic p = argv[optind - 1]; 60*66824Sbostic if (p[0] == '-' && p[1] == ch && !p[2]) 61*66824Sbostic numlines = strtol(++p, &ep, 10); 6232747Sbostic else 63*66824Sbostic numlines = 64*66824Sbostic strtol(argv[optind] + 1, &ep, 10); 65*66824Sbostic if (numlines <= 0 || *ep) 66*66824Sbostic errx(1, 67*66824Sbostic "%s: illegal line count.", optarg); 681101Sbill } 69*66824Sbostic break; 70*66824Sbostic case '-': /* Undocumented: historic stdin flag. */ 71*66824Sbostic if (ifd != -1) 72*66824Sbostic usage(); 73*66824Sbostic ifd = 0; 74*66824Sbostic break; 75*66824Sbostic case 'b': /* Byte count. */ 76*66824Sbostic if ((bytecnt = strtol(optarg, &ep, 10)) <= 0 || 77*66824Sbostic *ep != '\0' && *ep != 'k' && *ep != 'm') 78*66824Sbostic errx(1, "%s: illegal byte count.", optarg); 79*66824Sbostic if (*ep == 'k') 80*66824Sbostic bytecnt *= 1024; 81*66824Sbostic else if (*ep == 'm') 82*66824Sbostic bytecnt *= 1048576; 83*66824Sbostic break; 84*66824Sbostic case 'l': /* Line count. */ 85*66824Sbostic if (numlines != 0) 86*66824Sbostic usage(); 87*66824Sbostic if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *p) 88*66824Sbostic errx(1, "%s: illegal line count.", optarg); 89*66824Sbostic break; 90*66824Sbostic default: 91*66824Sbostic usage(); 921101Sbill } 93*66824Sbostic argv += optind; 94*66824Sbostic argc -= optind; 95*66824Sbostic 96*66824Sbostic if (*argv != NULL) 97*66824Sbostic if (ifd == -1) { /* Input file. */ 98*66824Sbostic if ((ifd = open(*argv, O_RDONLY, 0)) < 0) 99*66824Sbostic err(1, "%s", *argv); 100*66824Sbostic ++argv; 101*66824Sbostic } 102*66824Sbostic if (*argv != NULL) /* File name prefix. */ 103*66824Sbostic (void)strcpy(fname, *argv++); 104*66824Sbostic if (*argv != NULL) 105*66824Sbostic usage(); 106*66824Sbostic 107*66824Sbostic if (numlines == 0) 108*66824Sbostic numlines = DEFLINE; 109*66824Sbostic else if (bytecnt) 110*66824Sbostic usage(); 111*66824Sbostic 112*66824Sbostic if (ifd == -1) /* Stdin by default. */ 11330126Sbostic ifd = 0; 114*66824Sbostic 115*66824Sbostic if (bytecnt) { 11630126Sbostic split1(); 117*66824Sbostic exit (0); 118*66824Sbostic } 11930126Sbostic split2(); 12036598Sbostic exit(0); 12130126Sbostic } 12230126Sbostic 12330126Sbostic /* 12430126Sbostic * split1 -- 125*66824Sbostic * Split the input by bytes. 12630126Sbostic */ 127*66824Sbostic void 12830126Sbostic split1() 12930126Sbostic { 130*66824Sbostic long bcnt; 131*66824Sbostic int dist, len; 132*66824Sbostic char *C; 13330126Sbostic 13430126Sbostic for (bcnt = 0;;) 135*66824Sbostic switch (len = read(ifd, bfr, MAXBSIZE)) { 13632747Sbostic case 0: 137*66824Sbostic exit(0); 138*66824Sbostic case -1: 139*66824Sbostic err(1, "read"); 140*66824Sbostic /* NOTREACHED */ 14132747Sbostic default: 14232747Sbostic if (!file_open) { 14332747Sbostic newfile(); 144*66824Sbostic file_open = 1; 14532747Sbostic } 14632747Sbostic if (bcnt + len >= bytecnt) { 14732747Sbostic dist = bytecnt - bcnt; 14836598Sbostic if (write(ofd, bfr, dist) != dist) 149*66824Sbostic err(1, "write"); 15032747Sbostic len -= dist; 151*66824Sbostic for (C = bfr + dist; len >= bytecnt; 152*66824Sbostic len -= bytecnt, C += bytecnt) { 15330126Sbostic newfile(); 154*66824Sbostic if (write(ofd, 155*66824Sbostic C, (int)bytecnt) != bytecnt) 156*66824Sbostic err(1, "write"); 15730126Sbostic } 15832747Sbostic if (len) { 15932747Sbostic newfile(); 16036598Sbostic if (write(ofd, C, len) != len) 161*66824Sbostic err(1, "write"); 162*66824Sbostic } else 163*66824Sbostic file_open = 0; 16432747Sbostic bcnt = len; 165*66824Sbostic } else { 16632747Sbostic bcnt += len; 16736598Sbostic if (write(ofd, bfr, len) != len) 168*66824Sbostic err(1, "write"); 16932747Sbostic } 1701101Sbill } 17130126Sbostic } 1721101Sbill 17330126Sbostic /* 17430126Sbostic * split2 -- 175*66824Sbostic * Split the input by lines. 17630126Sbostic */ 177*66824Sbostic void 17830126Sbostic split2() 17930126Sbostic { 180*66824Sbostic long lcnt; 181*66824Sbostic int len, bcnt; 182*66824Sbostic char *Ce, *Cs; 18330126Sbostic 18430126Sbostic for (lcnt = 0;;) 185*66824Sbostic switch (len = read(ifd, bfr, MAXBSIZE)) { 18632747Sbostic case 0: 18732747Sbostic exit(0); 188*66824Sbostic case -1: 189*66824Sbostic err(1, "read"); 190*66824Sbostic /* NOTREACHED */ 19132747Sbostic default: 19232747Sbostic if (!file_open) { 19332747Sbostic newfile(); 194*66824Sbostic file_open = 1; 19532747Sbostic } 19632747Sbostic for (Cs = Ce = bfr; len--; Ce++) 19732747Sbostic if (*Ce == '\n' && ++lcnt == numlines) { 19836598Sbostic bcnt = Ce - Cs + 1; 19936598Sbostic if (write(ofd, Cs, bcnt) != bcnt) 200*66824Sbostic err(1, "write"); 20132747Sbostic lcnt = 0; 20232747Sbostic Cs = Ce + 1; 20332747Sbostic if (len) 20432747Sbostic newfile(); 20532747Sbostic else 206*66824Sbostic file_open = 0; 20730126Sbostic } 20836598Sbostic if (Cs < Ce) { 20936598Sbostic bcnt = Ce - Cs; 21036598Sbostic if (write(ofd, Cs, bcnt) != bcnt) 211*66824Sbostic err(1, "write"); 21236598Sbostic } 2131101Sbill } 21430126Sbostic } 21530126Sbostic 21630126Sbostic /* 21730126Sbostic * newfile -- 218*66824Sbostic * Open a new output file. 21930126Sbostic */ 220*66824Sbostic void 22130126Sbostic newfile() 22230126Sbostic { 22336598Sbostic static long fnum; 224*66824Sbostic static int defname; 22536598Sbostic static char *fpnt; 22630126Sbostic 227*66824Sbostic if (ofd == -1) { 228*66824Sbostic if (fname[0] == '\0') { 22930126Sbostic fname[0] = 'x'; 23030126Sbostic fpnt = fname + 1; 231*66824Sbostic defname = 1; 232*66824Sbostic } else { 233*66824Sbostic fpnt = fname + strlen(fname); 234*66824Sbostic defname = 0; 23530126Sbostic } 23630126Sbostic ofd = fileno(stdout); 23730126Sbostic } 23830126Sbostic /* 239*66824Sbostic * Hack to increase max files; original code wandered through 24030126Sbostic * magic characters. Maximum files is 3 * 26 * 26 == 2028 24130126Sbostic */ 24230126Sbostic #define MAXFILES 676 24330126Sbostic if (fnum == MAXFILES) { 244*66824Sbostic if (!defname || fname[0] == 'z') 245*66824Sbostic errx(1, "too many files."); 24630126Sbostic ++fname[0]; 24730126Sbostic fnum = 0; 24830126Sbostic } 24930126Sbostic fpnt[0] = fnum / 26 + 'a'; 25030126Sbostic fpnt[1] = fnum % 26 + 'a'; 25130126Sbostic ++fnum; 252*66824Sbostic if (!freopen(fname, "w", stdout)) 253*66824Sbostic err(1, "%s", fname); 2541101Sbill } 25530126Sbostic 256*66824Sbostic void 25730126Sbostic usage() 25830126Sbostic { 259*66824Sbostic (void)fprintf(stderr, 260*66824Sbostic "usage: split [-b byte_count] [-l line_count] [file [prefix]]\n"); 26136598Sbostic exit(1); 26230126Sbostic } 263