xref: /csrg-svn/usr.bin/split/split.c (revision 67068)
132747Sbostic /*
266824Sbostic  * 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[] =
1066824Sbostic "@(#) 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*67068Sbostic static char sccsid[] = "@(#)split.c	8.3 (Berkeley) 04/25/94";
1632747Sbostic #endif /* not lint */
1732747Sbostic 
1830126Sbostic #include <sys/param.h>
1966824Sbostic 
2066824Sbostic #include <ctype.h>
2166824Sbostic #include <err.h>
2266824Sbostic #include <fcntl.h>
231101Sbill #include <stdio.h>
2466824Sbostic #include <stdlib.h>
2566824Sbostic #include <string.h>
2666824Sbostic #include <unistd.h>
271101Sbill 
2866824Sbostic #define DEFLINE	1000			/* Default num lines per file. */
291101Sbill 
3066824Sbostic long	 bytecnt;			/* Byte count to split on. */
3166824Sbostic long	 numlines;			/* Line count to split on. */
3266824Sbostic int	 file_open;			/* If a file open. */
3366824Sbostic int	 ifd = -1, ofd = -1;		/* Input/output file descriptors. */
3466824Sbostic char	 bfr[MAXBSIZE];			/* I/O buffer. */
3566824Sbostic char	 fname[MAXPATHLEN];		/* File name prefix. */
3630126Sbostic 
3766824Sbostic void newfile __P((void));
3866824Sbostic void split1 __P((void));
3966824Sbostic void split2 __P((void));
4066824Sbostic void usage __P((void));
4166824Sbostic 
4266824Sbostic int
main(argc,argv)4332747Sbostic main(argc, argv)
4436598Sbostic 	int argc;
4566824Sbostic 	char *argv[];
461101Sbill {
4766824Sbostic 	int ch;
4866824Sbostic 	char *ep, *p;
491101Sbill 
5066824Sbostic 	while ((ch = getopt(argc, argv, "-0123456789b:l:")) != EOF)
5166824Sbostic 		switch (ch) {
5266824Sbostic 		case '0': case '1': case '2': case '3': case '4':
5366824Sbostic 		case '5': case '6': case '7': case '8': case '9':
5466824Sbostic 			/*
5566824Sbostic 			 * Undocumented kludge: split was originally designed
5666824Sbostic 			 * to take a number after a dash.
5766824Sbostic 			 */
5866824Sbostic 			if (numlines == 0) {
5966824Sbostic 				p = argv[optind - 1];
6066824Sbostic 				if (p[0] == '-' && p[1] == ch && !p[2])
6166824Sbostic 					numlines = strtol(++p, &ep, 10);
6232747Sbostic 				else
6366824Sbostic 					numlines =
6466824Sbostic 					    strtol(argv[optind] + 1, &ep, 10);
6566824Sbostic 				if (numlines <= 0 || *ep)
6666824Sbostic 					errx(1,
6766824Sbostic 					    "%s: illegal line count.", optarg);
681101Sbill 			}
6966824Sbostic 			break;
7066824Sbostic 		case '-':		/* Undocumented: historic stdin flag. */
7166824Sbostic 			if (ifd != -1)
7266824Sbostic 				usage();
7366824Sbostic 			ifd = 0;
7466824Sbostic 			break;
7566824Sbostic 		case 'b':		/* Byte count. */
7666824Sbostic 			if ((bytecnt = strtol(optarg, &ep, 10)) <= 0 ||
7766824Sbostic 			    *ep != '\0' && *ep != 'k' && *ep != 'm')
7866824Sbostic 				errx(1, "%s: illegal byte count.", optarg);
7966824Sbostic 			if (*ep == 'k')
8066824Sbostic 				bytecnt *= 1024;
8166824Sbostic 			else if (*ep == 'm')
8266824Sbostic 				bytecnt *= 1048576;
8366824Sbostic 			break;
8466824Sbostic 		case 'l':		/* Line count. */
8566824Sbostic 			if (numlines != 0)
8666824Sbostic 				usage();
87*67068Sbostic 			if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep)
8866824Sbostic 				errx(1, "%s: illegal line count.", optarg);
8966824Sbostic 			break;
9066824Sbostic 		default:
9166824Sbostic 			usage();
921101Sbill 		}
9366824Sbostic 	argv += optind;
9466824Sbostic 	argc -= optind;
9566824Sbostic 
9666824Sbostic 	if (*argv != NULL)
9766824Sbostic 		if (ifd == -1) {		/* Input file. */
9866824Sbostic 			if ((ifd = open(*argv, O_RDONLY, 0)) < 0)
9966824Sbostic 				err(1, "%s", *argv);
10066824Sbostic 			++argv;
10166824Sbostic 		}
10266824Sbostic 	if (*argv != NULL)			/* File name prefix. */
10366824Sbostic 		(void)strcpy(fname, *argv++);
10466824Sbostic 	if (*argv != NULL)
10566824Sbostic 		usage();
10666824Sbostic 
10766824Sbostic 	if (numlines == 0)
10866824Sbostic 		numlines = DEFLINE;
10966824Sbostic 	else if (bytecnt)
11066824Sbostic 		usage();
11166824Sbostic 
11266824Sbostic 	if (ifd == -1)				/* Stdin by default. */
11330126Sbostic 		ifd = 0;
11466824Sbostic 
11566824Sbostic 	if (bytecnt) {
11630126Sbostic 		split1();
11766824Sbostic 		exit (0);
11866824Sbostic 	}
11930126Sbostic 	split2();
12036598Sbostic 	exit(0);
12130126Sbostic }
12230126Sbostic 
12330126Sbostic /*
12430126Sbostic  * split1 --
12566824Sbostic  *	Split the input by bytes.
12630126Sbostic  */
12766824Sbostic void
split1()12830126Sbostic split1()
12930126Sbostic {
13066824Sbostic 	long bcnt;
13166824Sbostic 	int dist, len;
13266824Sbostic 	char *C;
13330126Sbostic 
13430126Sbostic 	for (bcnt = 0;;)
13566824Sbostic 		switch (len = read(ifd, bfr, MAXBSIZE)) {
13632747Sbostic 		case 0:
13766824Sbostic 			exit(0);
13866824Sbostic 		case -1:
13966824Sbostic 			err(1, "read");
14066824Sbostic 			/* NOTREACHED */
14132747Sbostic 		default:
14232747Sbostic 			if (!file_open) {
14332747Sbostic 				newfile();
14466824Sbostic 				file_open = 1;
14532747Sbostic 			}
14632747Sbostic 			if (bcnt + len >= bytecnt) {
14732747Sbostic 				dist = bytecnt - bcnt;
14836598Sbostic 				if (write(ofd, bfr, dist) != dist)
14966824Sbostic 					err(1, "write");
15032747Sbostic 				len -= dist;
15166824Sbostic 				for (C = bfr + dist; len >= bytecnt;
15266824Sbostic 				    len -= bytecnt, C += bytecnt) {
15330126Sbostic 					newfile();
15466824Sbostic 					if (write(ofd,
15566824Sbostic 					    C, (int)bytecnt) != bytecnt)
15666824Sbostic 						err(1, "write");
15730126Sbostic 				}
15832747Sbostic 				if (len) {
15932747Sbostic 					newfile();
16036598Sbostic 					if (write(ofd, C, len) != len)
16166824Sbostic 						err(1, "write");
16266824Sbostic 				} else
16366824Sbostic 					file_open = 0;
16432747Sbostic 				bcnt = len;
16566824Sbostic 			} else {
16632747Sbostic 				bcnt += len;
16736598Sbostic 				if (write(ofd, bfr, len) != len)
16866824Sbostic 					err(1, "write");
16932747Sbostic 			}
1701101Sbill 		}
17130126Sbostic }
1721101Sbill 
17330126Sbostic /*
17430126Sbostic  * split2 --
17566824Sbostic  *	Split the input by lines.
17630126Sbostic  */
17766824Sbostic void
split2()17830126Sbostic split2()
17930126Sbostic {
18066824Sbostic 	long lcnt;
18166824Sbostic 	int len, bcnt;
18266824Sbostic 	char *Ce, *Cs;
18330126Sbostic 
18430126Sbostic 	for (lcnt = 0;;)
18566824Sbostic 		switch (len = read(ifd, bfr, MAXBSIZE)) {
18632747Sbostic 		case 0:
18732747Sbostic 			exit(0);
18866824Sbostic 		case -1:
18966824Sbostic 			err(1, "read");
19066824Sbostic 			/* NOTREACHED */
19132747Sbostic 		default:
19232747Sbostic 			if (!file_open) {
19332747Sbostic 				newfile();
19466824Sbostic 				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)
20066824Sbostic 						err(1, "write");
20132747Sbostic 					lcnt = 0;
20232747Sbostic 					Cs = Ce + 1;
20332747Sbostic 					if (len)
20432747Sbostic 						newfile();
20532747Sbostic 					else
20666824Sbostic 						file_open = 0;
20730126Sbostic 				}
20836598Sbostic 			if (Cs < Ce) {
20936598Sbostic 				bcnt = Ce - Cs;
21036598Sbostic 				if (write(ofd, Cs, bcnt) != bcnt)
21166824Sbostic 					err(1, "write");
21236598Sbostic 			}
2131101Sbill 		}
21430126Sbostic }
21530126Sbostic 
21630126Sbostic /*
21730126Sbostic  * newfile --
21866824Sbostic  *	Open a new output file.
21930126Sbostic  */
22066824Sbostic void
newfile()22130126Sbostic newfile()
22230126Sbostic {
22336598Sbostic 	static long fnum;
22466824Sbostic 	static int defname;
22536598Sbostic 	static char *fpnt;
22630126Sbostic 
22766824Sbostic 	if (ofd == -1) {
22866824Sbostic 		if (fname[0] == '\0') {
22930126Sbostic 			fname[0] = 'x';
23030126Sbostic 			fpnt = fname + 1;
23166824Sbostic 			defname = 1;
23266824Sbostic 		} else {
23366824Sbostic 			fpnt = fname + strlen(fname);
23466824Sbostic 			defname = 0;
23530126Sbostic 		}
23630126Sbostic 		ofd = fileno(stdout);
23730126Sbostic 	}
23830126Sbostic 	/*
23966824Sbostic 	 * 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) {
24466824Sbostic 		if (!defname || fname[0] == 'z')
24566824Sbostic 			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;
25266824Sbostic 	if (!freopen(fname, "w", stdout))
25366824Sbostic 		err(1, "%s", fname);
2541101Sbill }
25530126Sbostic 
25666824Sbostic void
usage()25730126Sbostic usage()
25830126Sbostic {
25966824Sbostic 	(void)fprintf(stderr,
26066824Sbostic "usage: split [-b byte_count] [-l line_count] [file [prefix]]\n");
26136598Sbostic 	exit(1);
26230126Sbostic }
263