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 6*34912Sbostic * provided that the above copyright notice and this paragraph are 7*34912Sbostic * duplicated in all such forms and that any documentation, 8*34912Sbostic * advertising materials, and other materials related to such 9*34912Sbostic * distribution and use acknowledge that the software was developed 10*34912Sbostic * by the University of California, Berkeley. The name of the 11*34912Sbostic * University may not be used to endorse or promote products derived 12*34912Sbostic * from this software without specific prior written permission. 13*34912Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34912Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34912Sbostic * 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*34912Sbostic static char sccsid[] = "@(#)split.c 4.6 (Berkeley) 06/29/88"; 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 ERREXIT 0 /* error exit */ 3630126Sbostic #define NO 0 /* no/false */ 3730126Sbostic #define OK 0 /* okay exit */ 3830126Sbostic #define YES 1 /* yes/true */ 391101Sbill 4030126Sbostic static long bytecnt, /* byte count to split on */ 4130126Sbostic numlines; /* lines in each file */ 4230126Sbostic static int ifd = ERR, /* input file descriptor */ 4330126Sbostic ofd = ERR; /* output file descriptor */ 4430126Sbostic static short file_open; /* if a file open */ 4530126Sbostic static char bfr[MAXBSIZE], /* I/O buffer */ 4630126Sbostic fname[MAXPATHLEN]; /* file name */ 4730126Sbostic 4832747Sbostic main(argc, argv) 4932747Sbostic int argc; 5032747Sbostic char **argv; 511101Sbill { 5230126Sbostic register int cnt; /* general counter */ 5330126Sbostic long atol(); 5430126Sbostic char *strcpy(); 551101Sbill 5632747Sbostic for (cnt = 1; cnt < argc; ++cnt) { 5730126Sbostic if (argv[cnt][0] == '-') 5830126Sbostic switch(argv[cnt][1]) { 5932747Sbostic case 0: /* stdin by request */ 6032747Sbostic if (ifd != ERR) 6132747Sbostic usage(); 6232747Sbostic ifd = 0; 6332747Sbostic break; 6432747Sbostic case 'b': /* byte count split */ 6532747Sbostic if (numlines) 6632747Sbostic usage(); 6732747Sbostic if (!argv[cnt][2]) 6832747Sbostic bytecnt = atol(argv[++cnt]); 6932747Sbostic else 7032747Sbostic bytecnt = atol(argv[cnt] + 2); 7132747Sbostic if (bytecnt <= 0) { 7232747Sbostic fputs("split: byte count must be greater than zero.\n", stderr); 7332747Sbostic usage(); 7432747Sbostic } 7532747Sbostic break; 7632747Sbostic default: 7732747Sbostic if (!isdigit(argv[cnt][1]) || bytecnt) 7832747Sbostic usage(); 7932747Sbostic if ((numlines = atol(argv[cnt] + 1)) <= 0) { 8032747Sbostic fputs("split: line count must be greater than zero.\n", stderr); 8132747Sbostic usage(); 8232747Sbostic } 8332747Sbostic break; 841101Sbill } 8530126Sbostic else if (ifd == ERR) { /* input file */ 8632747Sbostic if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { 8730126Sbostic perror(argv[cnt]); 8830126Sbostic exit(ERREXIT); 8930126Sbostic } 901101Sbill } 9130126Sbostic else if (!*fname) /* output file prefix */ 9232747Sbostic strcpy(fname, argv[cnt]); 9330126Sbostic else 9430126Sbostic usage(); 9530126Sbostic } 9630126Sbostic if (ifd == ERR) /* stdin by default */ 9730126Sbostic ifd = 0; 9830126Sbostic if (bytecnt) 9930126Sbostic split1(); 10030126Sbostic if (!numlines) 10130126Sbostic numlines = DEFLINE; 10230126Sbostic split2(); 10330126Sbostic } 10430126Sbostic 10530126Sbostic /* 10630126Sbostic * split1 -- 10730126Sbostic * split by bytes 10830126Sbostic */ 10930126Sbostic static 11030126Sbostic split1() 11130126Sbostic { 11230126Sbostic register long bcnt; /* byte counter */ 11330126Sbostic register int dist, /* buffer offset */ 11430126Sbostic len; /* read length */ 11530126Sbostic register char *C; /* tmp pointer into buffer */ 11630126Sbostic 11730126Sbostic for (bcnt = 0;;) 11832747Sbostic switch(len = read(ifd, bfr, MAXBSIZE)) { 11932747Sbostic case 0: 12032747Sbostic exit(OK); 12132747Sbostic case ERR: 12232747Sbostic perror("read"); 12332747Sbostic exit(ERREXIT); 12432747Sbostic default: 12532747Sbostic if (!file_open) { 12632747Sbostic newfile(); 12732747Sbostic file_open = YES; 12832747Sbostic } 12932747Sbostic if (bcnt + len >= bytecnt) { 13032747Sbostic dist = bytecnt - bcnt; 13132747Sbostic write(ofd, bfr, dist); 13232747Sbostic len -= dist; 13332747Sbostic for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { 13430126Sbostic newfile(); 13532747Sbostic write(ofd, C, (int)bytecnt); 13630126Sbostic } 13732747Sbostic if (len) { 13832747Sbostic newfile(); 13932747Sbostic write(ofd, C, len); 14030126Sbostic } 14132747Sbostic else 14232747Sbostic file_open = NO; 14332747Sbostic bcnt = len; 14432747Sbostic } 14532747Sbostic else { 14632747Sbostic bcnt += len; 14732747Sbostic write(ofd, bfr, len); 14832747Sbostic } 1491101Sbill } 15030126Sbostic } 1511101Sbill 15230126Sbostic /* 15330126Sbostic * split2 -- 15430126Sbostic * split by lines 15530126Sbostic */ 15630126Sbostic static 15730126Sbostic split2() 15830126Sbostic { 15930126Sbostic register char *Ce, /* start/end pointers */ 16030126Sbostic *Cs; 16130126Sbostic register long lcnt; /* line counter */ 16230126Sbostic register int len; /* read length */ 16330126Sbostic 16430126Sbostic for (lcnt = 0;;) 16532747Sbostic switch(len = read(ifd, bfr, MAXBSIZE)) { 16632747Sbostic case 0: 16732747Sbostic exit(0); 16832747Sbostic case ERR: 16932747Sbostic perror("read"); 17032747Sbostic break; 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) { 17832747Sbostic write(ofd, Cs, (int)(Ce - Cs) + 1); 17932747Sbostic lcnt = 0; 18032747Sbostic Cs = Ce + 1; 18132747Sbostic if (len) 18232747Sbostic newfile(); 18332747Sbostic else 18432747Sbostic file_open = NO; 18530126Sbostic } 18632747Sbostic if (Cs < Ce) 18732747Sbostic write(ofd, Cs, (int)(Ce - Cs)); 1881101Sbill } 18930126Sbostic } 19030126Sbostic 19130126Sbostic /* 19230126Sbostic * newfile -- 19330126Sbostic * open a new file 19430126Sbostic */ 19530126Sbostic static 19630126Sbostic newfile() 19730126Sbostic { 19830126Sbostic static long fnum; /* file name counter */ 19930126Sbostic static short defname; /* using default name, "x" */ 20030126Sbostic static char *fpnt; /* output file name pointer */ 20130126Sbostic 20230126Sbostic if (ofd == ERR) { 20330126Sbostic if (fname[0]) { 20430126Sbostic fpnt = fname + strlen(fname); 20530126Sbostic defname = NO; 2061101Sbill } 20730126Sbostic else { 20830126Sbostic fname[0] = 'x'; 20930126Sbostic fpnt = fname + 1; 21030126Sbostic defname = YES; 21130126Sbostic } 21230126Sbostic ofd = fileno(stdout); 21330126Sbostic } 21430126Sbostic /* 21530126Sbostic * hack to increase max files; original code just wandered through 21630126Sbostic * magic characters. Maximum files is 3 * 26 * 26 == 2028 21730126Sbostic */ 21830126Sbostic #define MAXFILES 676 21930126Sbostic if (fnum == MAXFILES) { 22030126Sbostic if (!defname || fname[0] == 'z') { 22132747Sbostic fputs("split: too many files.\n", stderr); 22230126Sbostic exit(ERREXIT); 22330126Sbostic } 22430126Sbostic ++fname[0]; 22530126Sbostic fnum = 0; 22630126Sbostic } 22730126Sbostic fpnt[0] = fnum / 26 + 'a'; 22830126Sbostic fpnt[1] = fnum % 26 + 'a'; 22930126Sbostic ++fnum; 23032747Sbostic if (!freopen(fname, "w", stdout)) { 23132747Sbostic fprintf(stderr, "split: unable to write to %s.\n", fname); 23230126Sbostic exit(ERR); 23330126Sbostic } 2341101Sbill } 23530126Sbostic 23630126Sbostic /* 23730126Sbostic * usage -- 23830126Sbostic * print usage message and die 23930126Sbostic */ 24030126Sbostic static 24130126Sbostic usage() 24230126Sbostic { 24332747Sbostic fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); 24430126Sbostic exit(ERREXIT); 24530126Sbostic } 246