xref: /csrg-svn/usr.bin/split/split.c (revision 30126)
1*30126Sbostic static char *sccsid = "@(#)split.c	4.3 (Berkeley) 11/20/86";
2*30126Sbostic 
3*30126Sbostic #include <sys/param.h>
4*30126Sbostic #include <sys/file.h>
51101Sbill #include <stdio.h>
6*30126Sbostic #include <ctype.h>
71101Sbill 
8*30126Sbostic #define DEFLINE	1000			/* default num lines per file */
9*30126Sbostic #define ERR	-1			/* general error */
10*30126Sbostic #define ERREXIT	0			/* error exit */
11*30126Sbostic #define NO	0			/* no/false */
12*30126Sbostic #define OK	0			/* okay exit */
13*30126Sbostic #define YES	1			/* yes/true */
141101Sbill 
15*30126Sbostic static long	bytecnt,		/* byte count to split on */
16*30126Sbostic 		numlines;		/* lines in each file */
17*30126Sbostic static int	ifd = ERR,		/* input file descriptor */
18*30126Sbostic 		ofd = ERR;		/* output file descriptor */
19*30126Sbostic static short	file_open;		/* if a file open */
20*30126Sbostic static char	bfr[MAXBSIZE],		/* I/O buffer */
21*30126Sbostic 		fname[MAXPATHLEN];	/* file name */
22*30126Sbostic 
23*30126Sbostic main(argc,argv)
24*30126Sbostic int	argc;
25*30126Sbostic char	**argv;
261101Sbill {
27*30126Sbostic 	register int	cnt;		/* general counter */
28*30126Sbostic 	long	atol();
29*30126Sbostic 	char	*strcpy();
301101Sbill 
31*30126Sbostic 	for (cnt = 1;cnt < argc;++cnt) {
32*30126Sbostic 		if (argv[cnt][0] == '-')
33*30126Sbostic 			switch(argv[cnt][1]) {
34*30126Sbostic 				case 0:		/* stdin by request */
35*30126Sbostic 					if (ifd != ERR)
36*30126Sbostic 						usage();
37*30126Sbostic 					ifd = 0;
38*30126Sbostic 					break;
39*30126Sbostic 				case 'b':	/* byte count split */
40*30126Sbostic 					if (numlines)
41*30126Sbostic 						usage();
42*30126Sbostic 					if (!argv[cnt][2])
43*30126Sbostic 						bytecnt = atol(argv[++cnt]);
44*30126Sbostic 					else
45*30126Sbostic 						bytecnt = atol(argv[cnt] + 2);
46*30126Sbostic 					if (bytecnt <= 0) {
47*30126Sbostic 						fputs("split: byte count must be greater than zero.\n",stderr);
48*30126Sbostic 						usage();
49*30126Sbostic 					}
50*30126Sbostic 					break;
51*30126Sbostic 				default:
52*30126Sbostic 					if (!isdigit(argv[cnt][1]) || bytecnt)
53*30126Sbostic 						usage();
54*30126Sbostic 					if ((numlines = atol(argv[cnt] + 2)) <= 0) {
55*30126Sbostic 						fputs("split: line count must be greater than zero.\n",stderr);
56*30126Sbostic 						usage();
57*30126Sbostic 					}
58*30126Sbostic 					break;
591101Sbill 			}
60*30126Sbostic 		else if (ifd == ERR) {		/* input file */
61*30126Sbostic 			if ((ifd = open(argv[cnt],O_RDONLY,0)) < 0) {
62*30126Sbostic 				perror(argv[cnt]);
63*30126Sbostic 				exit(ERREXIT);
64*30126Sbostic 			}
651101Sbill 		}
66*30126Sbostic 		else if (!*fname)		/* output file prefix */
67*30126Sbostic 			strcpy(fname,argv[cnt]);
68*30126Sbostic 		else
69*30126Sbostic 			usage();
70*30126Sbostic 	}
71*30126Sbostic 	if (ifd == ERR)				/* stdin by default */
72*30126Sbostic 		ifd = 0;
73*30126Sbostic 	if (bytecnt)
74*30126Sbostic 		split1();
75*30126Sbostic 	if (!numlines)
76*30126Sbostic 		numlines = DEFLINE;
77*30126Sbostic 	split2();
78*30126Sbostic }
79*30126Sbostic 
80*30126Sbostic /*
81*30126Sbostic  * split1 --
82*30126Sbostic  *	split by bytes
83*30126Sbostic  */
84*30126Sbostic static
85*30126Sbostic split1()
86*30126Sbostic {
87*30126Sbostic 	register long	bcnt;		/* byte counter */
88*30126Sbostic 	register int	dist,		/* buffer offset */
89*30126Sbostic 			len;		/* read length */
90*30126Sbostic 	register char	*C;		/* tmp pointer into buffer */
91*30126Sbostic 
92*30126Sbostic 	for (bcnt = 0;;)
93*30126Sbostic 		switch(len = read(ifd,bfr,MAXBSIZE)) {
94*30126Sbostic 			case 0:
95*30126Sbostic 				exit(OK);
96*30126Sbostic 			case ERR:
97*30126Sbostic 				perror("read");
98*30126Sbostic 				exit(ERREXIT);
99*30126Sbostic 			default:
100*30126Sbostic 				if (!file_open) {
101*30126Sbostic 					newfile();
102*30126Sbostic 					file_open = YES;
103*30126Sbostic 				}
104*30126Sbostic 				if (bcnt + len >= bytecnt) {
105*30126Sbostic 					dist = bytecnt - bcnt;
106*30126Sbostic 					write(ofd,bfr,dist);
107*30126Sbostic 					len -= dist;
108*30126Sbostic 					for (C = bfr + dist;len >= bytecnt;len -= bytecnt,C += bytecnt) {
109*30126Sbostic 						newfile();
110*30126Sbostic 						write(ofd,C,(int)bytecnt);
111*30126Sbostic 					}
112*30126Sbostic 					if (len) {
113*30126Sbostic 						newfile();
114*30126Sbostic 						write(ofd,C,len);
115*30126Sbostic 					}
116*30126Sbostic 					else
117*30126Sbostic 						file_open = NO;
118*30126Sbostic 					bcnt = len;
119*30126Sbostic 				}
120*30126Sbostic 				else {
121*30126Sbostic 					bcnt += len;
122*30126Sbostic 					write(ofd,bfr,len);
123*30126Sbostic 				}
1241101Sbill 		}
125*30126Sbostic }
1261101Sbill 
127*30126Sbostic /*
128*30126Sbostic  * split2 --
129*30126Sbostic  *	split by lines
130*30126Sbostic  */
131*30126Sbostic static
132*30126Sbostic split2()
133*30126Sbostic {
134*30126Sbostic 	register char	*Ce,			/* start/end pointers */
135*30126Sbostic 			*Cs;
136*30126Sbostic 	register long	lcnt;			/* line counter */
137*30126Sbostic 	register int	len;			/* read length */
138*30126Sbostic 
139*30126Sbostic 	for (lcnt = 0;;)
140*30126Sbostic 		switch(len = read(ifd,bfr,MAXBSIZE)) {
141*30126Sbostic 			case 0:
142*30126Sbostic 				exit(0);
143*30126Sbostic 			case ERR:
144*30126Sbostic 				perror("read");
145*30126Sbostic 				break;
146*30126Sbostic 			default:
147*30126Sbostic 				if (!file_open) {
148*30126Sbostic 					newfile();
149*30126Sbostic 					file_open = YES;
150*30126Sbostic 				}
151*30126Sbostic 				for (Cs = Ce = bfr;len--;Ce++)
152*30126Sbostic 					if (*Ce == '\n' && ++lcnt == numlines) {
153*30126Sbostic 						write(ofd,Cs,(int)(Ce - Cs) + 1);
154*30126Sbostic 						lcnt = 0;
155*30126Sbostic 						Cs = Ce + 1;
156*30126Sbostic 						if (len)
157*30126Sbostic 							newfile();
158*30126Sbostic 						else
159*30126Sbostic 							file_open = NO;
160*30126Sbostic 					}
161*30126Sbostic 				if (Cs < Ce)
162*30126Sbostic 					write(ofd,Cs,(int)(Ce - Cs));
1631101Sbill 		}
164*30126Sbostic }
165*30126Sbostic 
166*30126Sbostic /*
167*30126Sbostic  * newfile --
168*30126Sbostic  *	open a new file
169*30126Sbostic  */
170*30126Sbostic static
171*30126Sbostic newfile()
172*30126Sbostic {
173*30126Sbostic 	static long	fnum;		/* file name counter */
174*30126Sbostic 	static short	defname;	/* using default name, "x" */
175*30126Sbostic 	static char	*fpnt;		/* output file name pointer */
176*30126Sbostic 
177*30126Sbostic 	if (ofd == ERR) {
178*30126Sbostic 		if (fname[0]) {
179*30126Sbostic 			fpnt = fname + strlen(fname);
180*30126Sbostic 			defname = NO;
1811101Sbill 		}
182*30126Sbostic 		else {
183*30126Sbostic 			fname[0] = 'x';
184*30126Sbostic 			fpnt = fname + 1;
185*30126Sbostic 			defname = YES;
186*30126Sbostic 		}
187*30126Sbostic 		ofd = fileno(stdout);
188*30126Sbostic 	}
189*30126Sbostic 	/*
190*30126Sbostic 	 * hack to increase max files; original code just wandered through
191*30126Sbostic 	 * magic characters.  Maximum files is 3 * 26 * 26 == 2028
192*30126Sbostic 	 */
193*30126Sbostic #define MAXFILES	676
194*30126Sbostic 	if (fnum == MAXFILES) {
195*30126Sbostic 		if (!defname || fname[0] == 'z') {
196*30126Sbostic 			fputs("split: too many files.\n",stderr);
197*30126Sbostic 			exit(ERREXIT);
198*30126Sbostic 		}
199*30126Sbostic 		++fname[0];
200*30126Sbostic 		fnum = 0;
201*30126Sbostic 	}
202*30126Sbostic 	fpnt[0] = fnum / 26 + 'a';
203*30126Sbostic 	fpnt[1] = fnum % 26 + 'a';
204*30126Sbostic 	++fnum;
205*30126Sbostic 	if (!freopen(fname,"w",stdout)) {
206*30126Sbostic 		fprintf(stderr,"split: unable to write to %s.\n",fname);
207*30126Sbostic 		exit(ERR);
208*30126Sbostic 	}
2091101Sbill }
210*30126Sbostic 
211*30126Sbostic /*
212*30126Sbostic  * usage --
213*30126Sbostic  *	print usage message and die
214*30126Sbostic  */
215*30126Sbostic static
216*30126Sbostic usage()
217*30126Sbostic {
218*30126Sbostic 	fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n",stderr);
219*30126Sbostic 	exit(ERREXIT);
220*30126Sbostic }
221