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