1*32747Sbostic /* 2*32747Sbostic * Copyright (c) 1987 Regents of the University of California. 3*32747Sbostic * All rights reserved. 4*32747Sbostic * 5*32747Sbostic * Redistribution and use in source and binary forms are permitted 6*32747Sbostic * provided that this notice is preserved and that due credit is given 7*32747Sbostic * to the University of California at Berkeley. The name of the University 8*32747Sbostic * may not be used to endorse or promote products derived from this 9*32747Sbostic * software without specific written prior permission. This software 10*32747Sbostic * is provided ``as is'' without express or implied warranty. 11*32747Sbostic */ 1230126Sbostic 13*32747Sbostic #ifndef lint 14*32747Sbostic char copyright[] = 15*32747Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 16*32747Sbostic All rights reserved.\n"; 17*32747Sbostic #endif /* not lint */ 18*32747Sbostic 19*32747Sbostic #ifndef lint 20*32747Sbostic static char sccsid[] = "@(#)split.c 4.5 (Berkeley) 12/02/87"; 21*32747Sbostic #endif /* not lint */ 22*32747Sbostic 2330126Sbostic #include <sys/param.h> 2430126Sbostic #include <sys/file.h> 251101Sbill #include <stdio.h> 2630126Sbostic #include <ctype.h> 271101Sbill 2830126Sbostic #define DEFLINE 1000 /* default num lines per file */ 2930126Sbostic #define ERR -1 /* general error */ 3030126Sbostic #define ERREXIT 0 /* error exit */ 3130126Sbostic #define NO 0 /* no/false */ 3230126Sbostic #define OK 0 /* okay exit */ 3330126Sbostic #define YES 1 /* yes/true */ 341101Sbill 3530126Sbostic static long bytecnt, /* byte count to split on */ 3630126Sbostic numlines; /* lines in each file */ 3730126Sbostic static int ifd = ERR, /* input file descriptor */ 3830126Sbostic ofd = ERR; /* output file descriptor */ 3930126Sbostic static short file_open; /* if a file open */ 4030126Sbostic static char bfr[MAXBSIZE], /* I/O buffer */ 4130126Sbostic fname[MAXPATHLEN]; /* file name */ 4230126Sbostic 43*32747Sbostic main(argc, argv) 44*32747Sbostic int argc; 45*32747Sbostic char **argv; 461101Sbill { 4730126Sbostic register int cnt; /* general counter */ 4830126Sbostic long atol(); 4930126Sbostic char *strcpy(); 501101Sbill 51*32747Sbostic for (cnt = 1; cnt < argc; ++cnt) { 5230126Sbostic if (argv[cnt][0] == '-') 5330126Sbostic switch(argv[cnt][1]) { 54*32747Sbostic case 0: /* stdin by request */ 55*32747Sbostic if (ifd != ERR) 56*32747Sbostic usage(); 57*32747Sbostic ifd = 0; 58*32747Sbostic break; 59*32747Sbostic case 'b': /* byte count split */ 60*32747Sbostic if (numlines) 61*32747Sbostic usage(); 62*32747Sbostic if (!argv[cnt][2]) 63*32747Sbostic bytecnt = atol(argv[++cnt]); 64*32747Sbostic else 65*32747Sbostic bytecnt = atol(argv[cnt] + 2); 66*32747Sbostic if (bytecnt <= 0) { 67*32747Sbostic fputs("split: byte count must be greater than zero.\n", stderr); 68*32747Sbostic usage(); 69*32747Sbostic } 70*32747Sbostic break; 71*32747Sbostic default: 72*32747Sbostic if (!isdigit(argv[cnt][1]) || bytecnt) 73*32747Sbostic usage(); 74*32747Sbostic if ((numlines = atol(argv[cnt] + 1)) <= 0) { 75*32747Sbostic fputs("split: line count must be greater than zero.\n", stderr); 76*32747Sbostic usage(); 77*32747Sbostic } 78*32747Sbostic break; 791101Sbill } 8030126Sbostic else if (ifd == ERR) { /* input file */ 81*32747Sbostic if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { 8230126Sbostic perror(argv[cnt]); 8330126Sbostic exit(ERREXIT); 8430126Sbostic } 851101Sbill } 8630126Sbostic else if (!*fname) /* output file prefix */ 87*32747Sbostic strcpy(fname, argv[cnt]); 8830126Sbostic else 8930126Sbostic usage(); 9030126Sbostic } 9130126Sbostic if (ifd == ERR) /* stdin by default */ 9230126Sbostic ifd = 0; 9330126Sbostic if (bytecnt) 9430126Sbostic split1(); 9530126Sbostic if (!numlines) 9630126Sbostic numlines = DEFLINE; 9730126Sbostic split2(); 9830126Sbostic } 9930126Sbostic 10030126Sbostic /* 10130126Sbostic * split1 -- 10230126Sbostic * split by bytes 10330126Sbostic */ 10430126Sbostic static 10530126Sbostic split1() 10630126Sbostic { 10730126Sbostic register long bcnt; /* byte counter */ 10830126Sbostic register int dist, /* buffer offset */ 10930126Sbostic len; /* read length */ 11030126Sbostic register char *C; /* tmp pointer into buffer */ 11130126Sbostic 11230126Sbostic for (bcnt = 0;;) 113*32747Sbostic switch(len = read(ifd, bfr, MAXBSIZE)) { 114*32747Sbostic case 0: 115*32747Sbostic exit(OK); 116*32747Sbostic case ERR: 117*32747Sbostic perror("read"); 118*32747Sbostic exit(ERREXIT); 119*32747Sbostic default: 120*32747Sbostic if (!file_open) { 121*32747Sbostic newfile(); 122*32747Sbostic file_open = YES; 123*32747Sbostic } 124*32747Sbostic if (bcnt + len >= bytecnt) { 125*32747Sbostic dist = bytecnt - bcnt; 126*32747Sbostic write(ofd, bfr, dist); 127*32747Sbostic len -= dist; 128*32747Sbostic for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { 12930126Sbostic newfile(); 130*32747Sbostic write(ofd, C, (int)bytecnt); 13130126Sbostic } 132*32747Sbostic if (len) { 133*32747Sbostic newfile(); 134*32747Sbostic write(ofd, C, len); 13530126Sbostic } 136*32747Sbostic else 137*32747Sbostic file_open = NO; 138*32747Sbostic bcnt = len; 139*32747Sbostic } 140*32747Sbostic else { 141*32747Sbostic bcnt += len; 142*32747Sbostic write(ofd, bfr, len); 143*32747Sbostic } 1441101Sbill } 14530126Sbostic } 1461101Sbill 14730126Sbostic /* 14830126Sbostic * split2 -- 14930126Sbostic * split by lines 15030126Sbostic */ 15130126Sbostic static 15230126Sbostic split2() 15330126Sbostic { 15430126Sbostic register char *Ce, /* start/end pointers */ 15530126Sbostic *Cs; 15630126Sbostic register long lcnt; /* line counter */ 15730126Sbostic register int len; /* read length */ 15830126Sbostic 15930126Sbostic for (lcnt = 0;;) 160*32747Sbostic switch(len = read(ifd, bfr, MAXBSIZE)) { 161*32747Sbostic case 0: 162*32747Sbostic exit(0); 163*32747Sbostic case ERR: 164*32747Sbostic perror("read"); 165*32747Sbostic break; 166*32747Sbostic default: 167*32747Sbostic if (!file_open) { 168*32747Sbostic newfile(); 169*32747Sbostic file_open = YES; 170*32747Sbostic } 171*32747Sbostic for (Cs = Ce = bfr; len--; Ce++) 172*32747Sbostic if (*Ce == '\n' && ++lcnt == numlines) { 173*32747Sbostic write(ofd, Cs, (int)(Ce - Cs) + 1); 174*32747Sbostic lcnt = 0; 175*32747Sbostic Cs = Ce + 1; 176*32747Sbostic if (len) 177*32747Sbostic newfile(); 178*32747Sbostic else 179*32747Sbostic file_open = NO; 18030126Sbostic } 181*32747Sbostic if (Cs < Ce) 182*32747Sbostic write(ofd, Cs, (int)(Ce - Cs)); 1831101Sbill } 18430126Sbostic } 18530126Sbostic 18630126Sbostic /* 18730126Sbostic * newfile -- 18830126Sbostic * open a new file 18930126Sbostic */ 19030126Sbostic static 19130126Sbostic newfile() 19230126Sbostic { 19330126Sbostic static long fnum; /* file name counter */ 19430126Sbostic static short defname; /* using default name, "x" */ 19530126Sbostic static char *fpnt; /* output file name pointer */ 19630126Sbostic 19730126Sbostic if (ofd == ERR) { 19830126Sbostic if (fname[0]) { 19930126Sbostic fpnt = fname + strlen(fname); 20030126Sbostic defname = NO; 2011101Sbill } 20230126Sbostic else { 20330126Sbostic fname[0] = 'x'; 20430126Sbostic fpnt = fname + 1; 20530126Sbostic defname = YES; 20630126Sbostic } 20730126Sbostic ofd = fileno(stdout); 20830126Sbostic } 20930126Sbostic /* 21030126Sbostic * hack to increase max files; original code just wandered through 21130126Sbostic * magic characters. Maximum files is 3 * 26 * 26 == 2028 21230126Sbostic */ 21330126Sbostic #define MAXFILES 676 21430126Sbostic if (fnum == MAXFILES) { 21530126Sbostic if (!defname || fname[0] == 'z') { 216*32747Sbostic fputs("split: too many files.\n", stderr); 21730126Sbostic exit(ERREXIT); 21830126Sbostic } 21930126Sbostic ++fname[0]; 22030126Sbostic fnum = 0; 22130126Sbostic } 22230126Sbostic fpnt[0] = fnum / 26 + 'a'; 22330126Sbostic fpnt[1] = fnum % 26 + 'a'; 22430126Sbostic ++fnum; 225*32747Sbostic if (!freopen(fname, "w", stdout)) { 226*32747Sbostic fprintf(stderr, "split: unable to write to %s.\n", fname); 22730126Sbostic exit(ERR); 22830126Sbostic } 2291101Sbill } 23030126Sbostic 23130126Sbostic /* 23230126Sbostic * usage -- 23330126Sbostic * print usage message and die 23430126Sbostic */ 23530126Sbostic static 23630126Sbostic usage() 23730126Sbostic { 238*32747Sbostic fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); 23930126Sbostic exit(ERREXIT); 24030126Sbostic } 241