xref: /csrg-svn/usr.bin/split/split.c (revision 36598)
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