132747Sbostic /* 232747Sbostic * Copyright (c) 1987 Regents of the University of California. 332747Sbostic * All rights reserved. 432747Sbostic * 532747Sbostic * Redistribution and use in source and binary forms are permitted 634912Sbostic * provided that the above copyright notice and this paragraph are 734912Sbostic * duplicated in all such forms and that any documentation, 834912Sbostic * advertising materials, and other materials related to such 934912Sbostic * distribution and use acknowledge that the software was developed 1034912Sbostic * by the University of California, Berkeley. The name of the 1134912Sbostic * University may not be used to endorse or promote products derived 1234912Sbostic * from this software without specific prior written permission. 1334912Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434912Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534912Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1632747Sbostic */ 1730126Sbostic 1832747Sbostic #ifndef lint 1932747Sbostic char copyright[] = 2032747Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 2132747Sbostic All rights reserved.\n"; 2232747Sbostic #endif /* not lint */ 2332747Sbostic 2432747Sbostic #ifndef lint 25*36598Sbostic static char sccsid[] = "@(#)split.c 4.7 (Berkeley) 01/23/89"; 2632747Sbostic #endif /* not lint */ 2732747Sbostic 2830126Sbostic #include <sys/param.h> 2930126Sbostic #include <sys/file.h> 301101Sbill #include <stdio.h> 3130126Sbostic #include <ctype.h> 321101Sbill 3330126Sbostic #define DEFLINE 1000 /* default num lines per file */ 3430126Sbostic #define ERR -1 /* general error */ 3530126Sbostic #define NO 0 /* no/false */ 3630126Sbostic #define OK 0 /* okay exit */ 3730126Sbostic #define YES 1 /* yes/true */ 381101Sbill 3930126Sbostic static long bytecnt, /* byte count to split on */ 4030126Sbostic numlines; /* lines in each file */ 4130126Sbostic static int ifd = ERR, /* input file descriptor */ 4230126Sbostic ofd = ERR; /* output file descriptor */ 4330126Sbostic static short file_open; /* if a file open */ 4430126Sbostic static char bfr[MAXBSIZE], /* I/O buffer */ 4530126Sbostic fname[MAXPATHLEN]; /* file name */ 4630126Sbostic 4732747Sbostic main(argc, argv) 48*36598Sbostic int argc; 49*36598Sbostic char **argv; 501101Sbill { 51*36598Sbostic register int cnt; 52*36598Sbostic long atol(); 53*36598Sbostic char *strcpy(); 541101Sbill 5532747Sbostic for (cnt = 1; cnt < argc; ++cnt) { 5630126Sbostic if (argv[cnt][0] == '-') 5730126Sbostic switch(argv[cnt][1]) { 5832747Sbostic case 0: /* stdin by request */ 5932747Sbostic if (ifd != ERR) 6032747Sbostic usage(); 6132747Sbostic ifd = 0; 6232747Sbostic break; 6332747Sbostic case 'b': /* byte count split */ 6432747Sbostic if (numlines) 6532747Sbostic usage(); 6632747Sbostic if (!argv[cnt][2]) 6732747Sbostic bytecnt = atol(argv[++cnt]); 6832747Sbostic else 6932747Sbostic bytecnt = atol(argv[cnt] + 2); 7032747Sbostic if (bytecnt <= 0) { 7132747Sbostic fputs("split: byte count must be greater than zero.\n", stderr); 7232747Sbostic usage(); 7332747Sbostic } 7432747Sbostic break; 7532747Sbostic default: 7632747Sbostic if (!isdigit(argv[cnt][1]) || bytecnt) 7732747Sbostic usage(); 7832747Sbostic if ((numlines = atol(argv[cnt] + 1)) <= 0) { 7932747Sbostic fputs("split: line count must be greater than zero.\n", stderr); 8032747Sbostic usage(); 8132747Sbostic } 8232747Sbostic break; 831101Sbill } 8430126Sbostic else if (ifd == ERR) { /* input file */ 8532747Sbostic if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { 8630126Sbostic perror(argv[cnt]); 87*36598Sbostic exit(1); 8830126Sbostic } 891101Sbill } 9030126Sbostic else if (!*fname) /* output file prefix */ 9132747Sbostic strcpy(fname, argv[cnt]); 9230126Sbostic else 9330126Sbostic usage(); 9430126Sbostic } 9530126Sbostic if (ifd == ERR) /* stdin by default */ 9630126Sbostic ifd = 0; 9730126Sbostic if (bytecnt) 9830126Sbostic split1(); 9930126Sbostic if (!numlines) 10030126Sbostic numlines = DEFLINE; 10130126Sbostic split2(); 102*36598Sbostic exit(0); 10330126Sbostic } 10430126Sbostic 10530126Sbostic /* 10630126Sbostic * split1 -- 10730126Sbostic * split by bytes 10830126Sbostic */ 10930126Sbostic split1() 11030126Sbostic { 111*36598Sbostic register long bcnt; 112*36598Sbostic register int dist, len; 113*36598Sbostic register char *C; 11430126Sbostic 11530126Sbostic for (bcnt = 0;;) 11632747Sbostic switch(len = read(ifd, bfr, MAXBSIZE)) { 11732747Sbostic case 0: 11832747Sbostic exit(OK); 11932747Sbostic case ERR: 12032747Sbostic perror("read"); 121*36598Sbostic exit(1); 12232747Sbostic default: 12332747Sbostic if (!file_open) { 12432747Sbostic newfile(); 12532747Sbostic file_open = YES; 12632747Sbostic } 12732747Sbostic if (bcnt + len >= bytecnt) { 12832747Sbostic dist = bytecnt - bcnt; 129*36598Sbostic if (write(ofd, bfr, dist) != dist) 130*36598Sbostic wrerror(); 13132747Sbostic len -= dist; 13232747Sbostic for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { 13330126Sbostic newfile(); 134*36598Sbostic if (write(ofd, C, (int)bytecnt) != bytecnt) 135*36598Sbostic wrerror(); 13630126Sbostic } 13732747Sbostic if (len) { 13832747Sbostic newfile(); 139*36598Sbostic if (write(ofd, C, len) != len) 140*36598Sbostic wrerror(); 14130126Sbostic } 14232747Sbostic else 14332747Sbostic file_open = NO; 14432747Sbostic bcnt = len; 14532747Sbostic } 14632747Sbostic else { 14732747Sbostic bcnt += len; 148*36598Sbostic if (write(ofd, bfr, len) != len) 149*36598Sbostic wrerror(); 15032747Sbostic } 1511101Sbill } 15230126Sbostic } 1531101Sbill 15430126Sbostic /* 15530126Sbostic * split2 -- 15630126Sbostic * split by lines 15730126Sbostic */ 15830126Sbostic split2() 15930126Sbostic { 160*36598Sbostic register char *Ce, *Cs; 161*36598Sbostic register long lcnt; 162*36598Sbostic register int len, bcnt; 16330126Sbostic 16430126Sbostic for (lcnt = 0;;) 16532747Sbostic switch(len = read(ifd, bfr, MAXBSIZE)) { 16632747Sbostic case 0: 16732747Sbostic exit(0); 16832747Sbostic case ERR: 16932747Sbostic perror("read"); 170*36598Sbostic exit(1); 17132747Sbostic default: 17232747Sbostic if (!file_open) { 17332747Sbostic newfile(); 17432747Sbostic file_open = YES; 17532747Sbostic } 17632747Sbostic for (Cs = Ce = bfr; len--; Ce++) 17732747Sbostic if (*Ce == '\n' && ++lcnt == numlines) { 178*36598Sbostic bcnt = Ce - Cs + 1; 179*36598Sbostic if (write(ofd, Cs, bcnt) != bcnt) 180*36598Sbostic wrerror(); 18132747Sbostic lcnt = 0; 18232747Sbostic Cs = Ce + 1; 18332747Sbostic if (len) 18432747Sbostic newfile(); 18532747Sbostic else 18632747Sbostic file_open = NO; 18730126Sbostic } 188*36598Sbostic if (Cs < Ce) { 189*36598Sbostic bcnt = Ce - Cs; 190*36598Sbostic if (write(ofd, Cs, bcnt) != bcnt) 191*36598Sbostic wrerror(); 192*36598Sbostic } 1931101Sbill } 19430126Sbostic } 19530126Sbostic 19630126Sbostic /* 19730126Sbostic * newfile -- 19830126Sbostic * open a new file 19930126Sbostic */ 20030126Sbostic newfile() 20130126Sbostic { 202*36598Sbostic static long fnum; 203*36598Sbostic static short defname; 204*36598Sbostic static char *fpnt; 20530126Sbostic 20630126Sbostic if (ofd == ERR) { 20730126Sbostic if (fname[0]) { 20830126Sbostic fpnt = fname + strlen(fname); 20930126Sbostic defname = NO; 2101101Sbill } 21130126Sbostic else { 21230126Sbostic fname[0] = 'x'; 21330126Sbostic fpnt = fname + 1; 21430126Sbostic defname = YES; 21530126Sbostic } 21630126Sbostic ofd = fileno(stdout); 21730126Sbostic } 21830126Sbostic /* 21930126Sbostic * hack to increase max files; original code just wandered through 22030126Sbostic * magic characters. Maximum files is 3 * 26 * 26 == 2028 22130126Sbostic */ 22230126Sbostic #define MAXFILES 676 22330126Sbostic if (fnum == MAXFILES) { 22430126Sbostic if (!defname || fname[0] == 'z') { 22532747Sbostic fputs("split: too many files.\n", stderr); 226*36598Sbostic exit(1); 22730126Sbostic } 22830126Sbostic ++fname[0]; 22930126Sbostic fnum = 0; 23030126Sbostic } 23130126Sbostic fpnt[0] = fnum / 26 + 'a'; 23230126Sbostic fpnt[1] = fnum % 26 + 'a'; 23330126Sbostic ++fnum; 23432747Sbostic if (!freopen(fname, "w", stdout)) { 23532747Sbostic fprintf(stderr, "split: unable to write to %s.\n", fname); 23630126Sbostic exit(ERR); 23730126Sbostic } 2381101Sbill } 23930126Sbostic 24030126Sbostic /* 24130126Sbostic * usage -- 24230126Sbostic * print usage message and die 24330126Sbostic */ 24430126Sbostic usage() 24530126Sbostic { 24632747Sbostic fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); 247*36598Sbostic exit(1); 24830126Sbostic } 249*36598Sbostic 250*36598Sbostic /* 251*36598Sbostic * wrerror -- 252*36598Sbostic * write error 253*36598Sbostic */ 254*36598Sbostic wrerror() 255*36598Sbostic { 256*36598Sbostic perror("split: write"); 257*36598Sbostic exit(1); 258*36598Sbostic } 259