xref: /csrg-svn/usr.bin/split/split.c (revision 42768)
132747Sbostic /*
232747Sbostic  * Copyright (c) 1987 Regents of the University of California.
332747Sbostic  * All rights reserved.
432747Sbostic  *
5*42768Sbostic  * %sccs.include.redist.c%
632747Sbostic  */
730126Sbostic 
832747Sbostic #ifndef lint
932747Sbostic char copyright[] =
1032747Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\
1132747Sbostic  All rights reserved.\n";
1232747Sbostic #endif /* not lint */
1332747Sbostic 
1432747Sbostic #ifndef lint
15*42768Sbostic static char sccsid[] = "@(#)split.c	4.8 (Berkeley) 06/01/90";
1632747Sbostic #endif /* not lint */
1732747Sbostic 
1830126Sbostic #include <sys/param.h>
1930126Sbostic #include <sys/file.h>
201101Sbill #include <stdio.h>
2130126Sbostic #include <ctype.h>
221101Sbill 
2330126Sbostic #define DEFLINE	1000			/* default num lines per file */
2430126Sbostic #define ERR	-1			/* general error */
2530126Sbostic #define NO	0			/* no/false */
2630126Sbostic #define OK	0			/* okay exit */
2730126Sbostic #define YES	1			/* yes/true */
281101Sbill 
2930126Sbostic static long	bytecnt,		/* byte count to split on */
3030126Sbostic 		numlines;		/* lines in each file */
3130126Sbostic static int	ifd = ERR,		/* input file descriptor */
3230126Sbostic 		ofd = ERR;		/* output file descriptor */
3330126Sbostic static short	file_open;		/* if a file open */
3430126Sbostic static char	bfr[MAXBSIZE],		/* I/O buffer */
3530126Sbostic 		fname[MAXPATHLEN];	/* file name */
3630126Sbostic 
3732747Sbostic main(argc, argv)
3836598Sbostic 	int argc;
3936598Sbostic 	char **argv;
401101Sbill {
4136598Sbostic 	register int cnt;
4236598Sbostic 	long atol();
4336598Sbostic 	char *strcpy();
441101Sbill 
4532747Sbostic 	for (cnt = 1; cnt < argc; ++cnt) {
4630126Sbostic 		if (argv[cnt][0] == '-')
4730126Sbostic 			switch(argv[cnt][1]) {
4832747Sbostic 			case 0:		/* stdin by request */
4932747Sbostic 				if (ifd != ERR)
5032747Sbostic 					usage();
5132747Sbostic 				ifd = 0;
5232747Sbostic 				break;
5332747Sbostic 			case 'b':	/* byte count split */
5432747Sbostic 				if (numlines)
5532747Sbostic 					usage();
5632747Sbostic 				if (!argv[cnt][2])
5732747Sbostic 					bytecnt = atol(argv[++cnt]);
5832747Sbostic 				else
5932747Sbostic 					bytecnt = atol(argv[cnt] + 2);
6032747Sbostic 				if (bytecnt <= 0) {
6132747Sbostic 					fputs("split: byte count must be greater than zero.\n", stderr);
6232747Sbostic 					usage();
6332747Sbostic 				}
6432747Sbostic 				break;
6532747Sbostic 			default:
6632747Sbostic 				if (!isdigit(argv[cnt][1]) || bytecnt)
6732747Sbostic 					usage();
6832747Sbostic 				if ((numlines = atol(argv[cnt] + 1)) <= 0) {
6932747Sbostic 					fputs("split: line count must be greater than zero.\n", stderr);
7032747Sbostic 					usage();
7132747Sbostic 				}
7232747Sbostic 				break;
731101Sbill 			}
7430126Sbostic 		else if (ifd == ERR) {		/* input file */
7532747Sbostic 			if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) {
7630126Sbostic 				perror(argv[cnt]);
7736598Sbostic 				exit(1);
7830126Sbostic 			}
791101Sbill 		}
8030126Sbostic 		else if (!*fname)		/* output file prefix */
8132747Sbostic 			strcpy(fname, argv[cnt]);
8230126Sbostic 		else
8330126Sbostic 			usage();
8430126Sbostic 	}
8530126Sbostic 	if (ifd == ERR)				/* stdin by default */
8630126Sbostic 		ifd = 0;
8730126Sbostic 	if (bytecnt)
8830126Sbostic 		split1();
8930126Sbostic 	if (!numlines)
9030126Sbostic 		numlines = DEFLINE;
9130126Sbostic 	split2();
9236598Sbostic 	exit(0);
9330126Sbostic }
9430126Sbostic 
9530126Sbostic /*
9630126Sbostic  * split1 --
9730126Sbostic  *	split by bytes
9830126Sbostic  */
9930126Sbostic split1()
10030126Sbostic {
10136598Sbostic 	register long bcnt;
10236598Sbostic 	register int dist, len;
10336598Sbostic 	register char *C;
10430126Sbostic 
10530126Sbostic 	for (bcnt = 0;;)
10632747Sbostic 		switch(len = read(ifd, bfr, MAXBSIZE)) {
10732747Sbostic 		case 0:
10832747Sbostic 			exit(OK);
10932747Sbostic 		case ERR:
11032747Sbostic 			perror("read");
11136598Sbostic 			exit(1);
11232747Sbostic 		default:
11332747Sbostic 			if (!file_open) {
11432747Sbostic 				newfile();
11532747Sbostic 				file_open = YES;
11632747Sbostic 			}
11732747Sbostic 			if (bcnt + len >= bytecnt) {
11832747Sbostic 				dist = bytecnt - bcnt;
11936598Sbostic 				if (write(ofd, bfr, dist) != dist)
12036598Sbostic 					wrerror();
12132747Sbostic 				len -= dist;
12232747Sbostic 				for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) {
12330126Sbostic 					newfile();
12436598Sbostic 					if (write(ofd, C, (int)bytecnt) != bytecnt)
12536598Sbostic 						wrerror();
12630126Sbostic 				}
12732747Sbostic 				if (len) {
12832747Sbostic 					newfile();
12936598Sbostic 					if (write(ofd, C, len) != len)
13036598Sbostic 						wrerror();
13130126Sbostic 				}
13232747Sbostic 				else
13332747Sbostic 					file_open = NO;
13432747Sbostic 				bcnt = len;
13532747Sbostic 			}
13632747Sbostic 			else {
13732747Sbostic 				bcnt += len;
13836598Sbostic 				if (write(ofd, bfr, len) != len)
13936598Sbostic 					wrerror();
14032747Sbostic 			}
1411101Sbill 		}
14230126Sbostic }
1431101Sbill 
14430126Sbostic /*
14530126Sbostic  * split2 --
14630126Sbostic  *	split by lines
14730126Sbostic  */
14830126Sbostic split2()
14930126Sbostic {
15036598Sbostic 	register char *Ce, *Cs;
15136598Sbostic 	register long lcnt;
15236598Sbostic 	register int len, bcnt;
15330126Sbostic 
15430126Sbostic 	for (lcnt = 0;;)
15532747Sbostic 		switch(len = read(ifd, bfr, MAXBSIZE)) {
15632747Sbostic 		case 0:
15732747Sbostic 			exit(0);
15832747Sbostic 		case ERR:
15932747Sbostic 			perror("read");
16036598Sbostic 			exit(1);
16132747Sbostic 		default:
16232747Sbostic 			if (!file_open) {
16332747Sbostic 				newfile();
16432747Sbostic 				file_open = YES;
16532747Sbostic 			}
16632747Sbostic 			for (Cs = Ce = bfr; len--; Ce++)
16732747Sbostic 				if (*Ce == '\n' && ++lcnt == numlines) {
16836598Sbostic 					bcnt = Ce - Cs + 1;
16936598Sbostic 					if (write(ofd, Cs, bcnt) != bcnt)
17036598Sbostic 						wrerror();
17132747Sbostic 					lcnt = 0;
17232747Sbostic 					Cs = Ce + 1;
17332747Sbostic 					if (len)
17432747Sbostic 						newfile();
17532747Sbostic 					else
17632747Sbostic 						file_open = NO;
17730126Sbostic 				}
17836598Sbostic 			if (Cs < Ce) {
17936598Sbostic 				bcnt = Ce - Cs;
18036598Sbostic 				if (write(ofd, Cs, bcnt) != bcnt)
18136598Sbostic 					wrerror();
18236598Sbostic 			}
1831101Sbill 		}
18430126Sbostic }
18530126Sbostic 
18630126Sbostic /*
18730126Sbostic  * newfile --
18830126Sbostic  *	open a new file
18930126Sbostic  */
19030126Sbostic newfile()
19130126Sbostic {
19236598Sbostic 	static long fnum;
19336598Sbostic 	static short defname;
19436598Sbostic 	static char *fpnt;
19530126Sbostic 
19630126Sbostic 	if (ofd == ERR) {
19730126Sbostic 		if (fname[0]) {
19830126Sbostic 			fpnt = fname + strlen(fname);
19930126Sbostic 			defname = NO;
2001101Sbill 		}
20130126Sbostic 		else {
20230126Sbostic 			fname[0] = 'x';
20330126Sbostic 			fpnt = fname + 1;
20430126Sbostic 			defname = YES;
20530126Sbostic 		}
20630126Sbostic 		ofd = fileno(stdout);
20730126Sbostic 	}
20830126Sbostic 	/*
20930126Sbostic 	 * hack to increase max files; original code just wandered through
21030126Sbostic 	 * magic characters.  Maximum files is 3 * 26 * 26 == 2028
21130126Sbostic 	 */
21230126Sbostic #define MAXFILES	676
21330126Sbostic 	if (fnum == MAXFILES) {
21430126Sbostic 		if (!defname || fname[0] == 'z') {
21532747Sbostic 			fputs("split: too many files.\n", stderr);
21636598Sbostic 			exit(1);
21730126Sbostic 		}
21830126Sbostic 		++fname[0];
21930126Sbostic 		fnum = 0;
22030126Sbostic 	}
22130126Sbostic 	fpnt[0] = fnum / 26 + 'a';
22230126Sbostic 	fpnt[1] = fnum % 26 + 'a';
22330126Sbostic 	++fnum;
22432747Sbostic 	if (!freopen(fname, "w", stdout)) {
22532747Sbostic 		fprintf(stderr, "split: unable to write to %s.\n", fname);
22630126Sbostic 		exit(ERR);
22730126Sbostic 	}
2281101Sbill }
22930126Sbostic 
23030126Sbostic /*
23130126Sbostic  * usage --
23230126Sbostic  *	print usage message and die
23330126Sbostic  */
23430126Sbostic usage()
23530126Sbostic {
23632747Sbostic 	fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr);
23736598Sbostic 	exit(1);
23830126Sbostic }
23936598Sbostic 
24036598Sbostic /*
24136598Sbostic  * wrerror --
24236598Sbostic  *	write error
24336598Sbostic  */
24436598Sbostic wrerror()
24536598Sbostic {
24636598Sbostic 	perror("split: write");
24736598Sbostic 	exit(1);
24836598Sbostic }
249