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