xref: /csrg-svn/usr.bin/split/split.c (revision 66824)
132747Sbostic /*
2*66824Sbostic  * Copyright (c) 1987, 1993, 1994
362254Sbostic  *	The Regents of the University of California.  All rights reserved.
432747Sbostic  *
542768Sbostic  * %sccs.include.redist.c%
632747Sbostic  */
730126Sbostic 
832747Sbostic #ifndef lint
962254Sbostic static char copyright[] =
10*66824Sbostic "@(#) Copyright (c) 1987, 1993, 1994\n\
1162254Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1232747Sbostic #endif /* not lint */
1332747Sbostic 
1432747Sbostic #ifndef lint
15*66824Sbostic static char sccsid[] = "@(#)split.c	8.2 (Berkeley) 04/16/94";
1632747Sbostic #endif /* not lint */
1732747Sbostic 
1830126Sbostic #include <sys/param.h>
19*66824Sbostic 
20*66824Sbostic #include <ctype.h>
21*66824Sbostic #include <err.h>
22*66824Sbostic #include <fcntl.h>
231101Sbill #include <stdio.h>
24*66824Sbostic #include <stdlib.h>
25*66824Sbostic #include <string.h>
26*66824Sbostic #include <unistd.h>
271101Sbill 
28*66824Sbostic #define DEFLINE	1000			/* Default num lines per file. */
291101Sbill 
30*66824Sbostic long	 bytecnt;			/* Byte count to split on. */
31*66824Sbostic long	 numlines;			/* Line count to split on. */
32*66824Sbostic int	 file_open;			/* If a file open. */
33*66824Sbostic int	 ifd = -1, ofd = -1;		/* Input/output file descriptors. */
34*66824Sbostic char	 bfr[MAXBSIZE];			/* I/O buffer. */
35*66824Sbostic char	 fname[MAXPATHLEN];		/* File name prefix. */
3630126Sbostic 
37*66824Sbostic void newfile __P((void));
38*66824Sbostic void split1 __P((void));
39*66824Sbostic void split2 __P((void));
40*66824Sbostic void usage __P((void));
41*66824Sbostic 
42*66824Sbostic int
4332747Sbostic main(argc, argv)
4436598Sbostic 	int argc;
45*66824Sbostic 	char *argv[];
461101Sbill {
47*66824Sbostic 	int ch;
48*66824Sbostic 	char *ep, *p;
491101Sbill 
50*66824Sbostic 	while ((ch = getopt(argc, argv, "-0123456789b:l:")) != EOF)
51*66824Sbostic 		switch (ch) {
52*66824Sbostic 		case '0': case '1': case '2': case '3': case '4':
53*66824Sbostic 		case '5': case '6': case '7': case '8': case '9':
54*66824Sbostic 			/*
55*66824Sbostic 			 * Undocumented kludge: split was originally designed
56*66824Sbostic 			 * to take a number after a dash.
57*66824Sbostic 			 */
58*66824Sbostic 			if (numlines == 0) {
59*66824Sbostic 				p = argv[optind - 1];
60*66824Sbostic 				if (p[0] == '-' && p[1] == ch && !p[2])
61*66824Sbostic 					numlines = strtol(++p, &ep, 10);
6232747Sbostic 				else
63*66824Sbostic 					numlines =
64*66824Sbostic 					    strtol(argv[optind] + 1, &ep, 10);
65*66824Sbostic 				if (numlines <= 0 || *ep)
66*66824Sbostic 					errx(1,
67*66824Sbostic 					    "%s: illegal line count.", optarg);
681101Sbill 			}
69*66824Sbostic 			break;
70*66824Sbostic 		case '-':		/* Undocumented: historic stdin flag. */
71*66824Sbostic 			if (ifd != -1)
72*66824Sbostic 				usage();
73*66824Sbostic 			ifd = 0;
74*66824Sbostic 			break;
75*66824Sbostic 		case 'b':		/* Byte count. */
76*66824Sbostic 			if ((bytecnt = strtol(optarg, &ep, 10)) <= 0 ||
77*66824Sbostic 			    *ep != '\0' && *ep != 'k' && *ep != 'm')
78*66824Sbostic 				errx(1, "%s: illegal byte count.", optarg);
79*66824Sbostic 			if (*ep == 'k')
80*66824Sbostic 				bytecnt *= 1024;
81*66824Sbostic 			else if (*ep == 'm')
82*66824Sbostic 				bytecnt *= 1048576;
83*66824Sbostic 			break;
84*66824Sbostic 		case 'l':		/* Line count. */
85*66824Sbostic 			if (numlines != 0)
86*66824Sbostic 				usage();
87*66824Sbostic 			if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *p)
88*66824Sbostic 				errx(1, "%s: illegal line count.", optarg);
89*66824Sbostic 			break;
90*66824Sbostic 		default:
91*66824Sbostic 			usage();
921101Sbill 		}
93*66824Sbostic 	argv += optind;
94*66824Sbostic 	argc -= optind;
95*66824Sbostic 
96*66824Sbostic 	if (*argv != NULL)
97*66824Sbostic 		if (ifd == -1) {		/* Input file. */
98*66824Sbostic 			if ((ifd = open(*argv, O_RDONLY, 0)) < 0)
99*66824Sbostic 				err(1, "%s", *argv);
100*66824Sbostic 			++argv;
101*66824Sbostic 		}
102*66824Sbostic 	if (*argv != NULL)			/* File name prefix. */
103*66824Sbostic 		(void)strcpy(fname, *argv++);
104*66824Sbostic 	if (*argv != NULL)
105*66824Sbostic 		usage();
106*66824Sbostic 
107*66824Sbostic 	if (numlines == 0)
108*66824Sbostic 		numlines = DEFLINE;
109*66824Sbostic 	else if (bytecnt)
110*66824Sbostic 		usage();
111*66824Sbostic 
112*66824Sbostic 	if (ifd == -1)				/* Stdin by default. */
11330126Sbostic 		ifd = 0;
114*66824Sbostic 
115*66824Sbostic 	if (bytecnt) {
11630126Sbostic 		split1();
117*66824Sbostic 		exit (0);
118*66824Sbostic 	}
11930126Sbostic 	split2();
12036598Sbostic 	exit(0);
12130126Sbostic }
12230126Sbostic 
12330126Sbostic /*
12430126Sbostic  * split1 --
125*66824Sbostic  *	Split the input by bytes.
12630126Sbostic  */
127*66824Sbostic void
12830126Sbostic split1()
12930126Sbostic {
130*66824Sbostic 	long bcnt;
131*66824Sbostic 	int dist, len;
132*66824Sbostic 	char *C;
13330126Sbostic 
13430126Sbostic 	for (bcnt = 0;;)
135*66824Sbostic 		switch (len = read(ifd, bfr, MAXBSIZE)) {
13632747Sbostic 		case 0:
137*66824Sbostic 			exit(0);
138*66824Sbostic 		case -1:
139*66824Sbostic 			err(1, "read");
140*66824Sbostic 			/* NOTREACHED */
14132747Sbostic 		default:
14232747Sbostic 			if (!file_open) {
14332747Sbostic 				newfile();
144*66824Sbostic 				file_open = 1;
14532747Sbostic 			}
14632747Sbostic 			if (bcnt + len >= bytecnt) {
14732747Sbostic 				dist = bytecnt - bcnt;
14836598Sbostic 				if (write(ofd, bfr, dist) != dist)
149*66824Sbostic 					err(1, "write");
15032747Sbostic 				len -= dist;
151*66824Sbostic 				for (C = bfr + dist; len >= bytecnt;
152*66824Sbostic 				    len -= bytecnt, C += bytecnt) {
15330126Sbostic 					newfile();
154*66824Sbostic 					if (write(ofd,
155*66824Sbostic 					    C, (int)bytecnt) != bytecnt)
156*66824Sbostic 						err(1, "write");
15730126Sbostic 				}
15832747Sbostic 				if (len) {
15932747Sbostic 					newfile();
16036598Sbostic 					if (write(ofd, C, len) != len)
161*66824Sbostic 						err(1, "write");
162*66824Sbostic 				} else
163*66824Sbostic 					file_open = 0;
16432747Sbostic 				bcnt = len;
165*66824Sbostic 			} else {
16632747Sbostic 				bcnt += len;
16736598Sbostic 				if (write(ofd, bfr, len) != len)
168*66824Sbostic 					err(1, "write");
16932747Sbostic 			}
1701101Sbill 		}
17130126Sbostic }
1721101Sbill 
17330126Sbostic /*
17430126Sbostic  * split2 --
175*66824Sbostic  *	Split the input by lines.
17630126Sbostic  */
177*66824Sbostic void
17830126Sbostic split2()
17930126Sbostic {
180*66824Sbostic 	long lcnt;
181*66824Sbostic 	int len, bcnt;
182*66824Sbostic 	char *Ce, *Cs;
18330126Sbostic 
18430126Sbostic 	for (lcnt = 0;;)
185*66824Sbostic 		switch (len = read(ifd, bfr, MAXBSIZE)) {
18632747Sbostic 		case 0:
18732747Sbostic 			exit(0);
188*66824Sbostic 		case -1:
189*66824Sbostic 			err(1, "read");
190*66824Sbostic 			/* NOTREACHED */
19132747Sbostic 		default:
19232747Sbostic 			if (!file_open) {
19332747Sbostic 				newfile();
194*66824Sbostic 				file_open = 1;
19532747Sbostic 			}
19632747Sbostic 			for (Cs = Ce = bfr; len--; Ce++)
19732747Sbostic 				if (*Ce == '\n' && ++lcnt == numlines) {
19836598Sbostic 					bcnt = Ce - Cs + 1;
19936598Sbostic 					if (write(ofd, Cs, bcnt) != bcnt)
200*66824Sbostic 						err(1, "write");
20132747Sbostic 					lcnt = 0;
20232747Sbostic 					Cs = Ce + 1;
20332747Sbostic 					if (len)
20432747Sbostic 						newfile();
20532747Sbostic 					else
206*66824Sbostic 						file_open = 0;
20730126Sbostic 				}
20836598Sbostic 			if (Cs < Ce) {
20936598Sbostic 				bcnt = Ce - Cs;
21036598Sbostic 				if (write(ofd, Cs, bcnt) != bcnt)
211*66824Sbostic 					err(1, "write");
21236598Sbostic 			}
2131101Sbill 		}
21430126Sbostic }
21530126Sbostic 
21630126Sbostic /*
21730126Sbostic  * newfile --
218*66824Sbostic  *	Open a new output file.
21930126Sbostic  */
220*66824Sbostic void
22130126Sbostic newfile()
22230126Sbostic {
22336598Sbostic 	static long fnum;
224*66824Sbostic 	static int defname;
22536598Sbostic 	static char *fpnt;
22630126Sbostic 
227*66824Sbostic 	if (ofd == -1) {
228*66824Sbostic 		if (fname[0] == '\0') {
22930126Sbostic 			fname[0] = 'x';
23030126Sbostic 			fpnt = fname + 1;
231*66824Sbostic 			defname = 1;
232*66824Sbostic 		} else {
233*66824Sbostic 			fpnt = fname + strlen(fname);
234*66824Sbostic 			defname = 0;
23530126Sbostic 		}
23630126Sbostic 		ofd = fileno(stdout);
23730126Sbostic 	}
23830126Sbostic 	/*
239*66824Sbostic 	 * Hack to increase max files; original code wandered through
24030126Sbostic 	 * magic characters.  Maximum files is 3 * 26 * 26 == 2028
24130126Sbostic 	 */
24230126Sbostic #define MAXFILES	676
24330126Sbostic 	if (fnum == MAXFILES) {
244*66824Sbostic 		if (!defname || fname[0] == 'z')
245*66824Sbostic 			errx(1, "too many files.");
24630126Sbostic 		++fname[0];
24730126Sbostic 		fnum = 0;
24830126Sbostic 	}
24930126Sbostic 	fpnt[0] = fnum / 26 + 'a';
25030126Sbostic 	fpnt[1] = fnum % 26 + 'a';
25130126Sbostic 	++fnum;
252*66824Sbostic 	if (!freopen(fname, "w", stdout))
253*66824Sbostic 		err(1, "%s", fname);
2541101Sbill }
25530126Sbostic 
256*66824Sbostic void
25730126Sbostic usage()
25830126Sbostic {
259*66824Sbostic 	(void)fprintf(stderr,
260*66824Sbostic "usage: split [-b byte_count] [-l line_count] [file [prefix]]\n");
26136598Sbostic 	exit(1);
26230126Sbostic }
263