Annotation of src/usr.bin/split/split.c, Revision 1.1.1.1
1.1 deraadt 1: /* $NetBSD: split.c,v 1.5 1995/08/31 22:22:05 jtc Exp $ */
2:
3: /*
4: * Copyright (c) 1987, 1993, 1994
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: static char copyright[] =
38: "@(#) Copyright (c) 1987, 1993, 1994\n\
39: The Regents of the University of California. All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: #if 0
44: static char sccsid[] = "@(#)split.c 8.3 (Berkeley) 4/25/94";
45: #endif
46: static char rcsid[] = "$NetBSD: split.c,v 1.5 1995/08/31 22:22:05 jtc Exp $";
47: #endif /* not lint */
48:
49: #include <sys/param.h>
50:
51: #include <ctype.h>
52: #include <err.h>
53: #include <fcntl.h>
54: #include <stdio.h>
55: #include <stdlib.h>
56: #include <string.h>
57: #include <unistd.h>
58:
59: #define DEFLINE 1000 /* Default num lines per file. */
60:
61: long bytecnt; /* Byte count to split on. */
62: long numlines; /* Line count to split on. */
63: int file_open; /* If a file open. */
64: int ifd = -1, ofd = -1; /* Input/output file descriptors. */
65: char bfr[MAXBSIZE]; /* I/O buffer. */
66: char fname[MAXPATHLEN]; /* File name prefix. */
67:
68: void newfile __P((void));
69: void split1 __P((void));
70: void split2 __P((void));
71: void usage __P((void));
72:
73: int
74: main(argc, argv)
75: int argc;
76: char *argv[];
77: {
78: int ch;
79: char *ep, *p;
80:
81: while ((ch = getopt(argc, argv, "-0123456789b:l:")) != EOF)
82: switch (ch) {
83: case '0': case '1': case '2': case '3': case '4':
84: case '5': case '6': case '7': case '8': case '9':
85: /*
86: * Undocumented kludge: split was originally designed
87: * to take a number after a dash.
88: */
89: if (numlines == 0) {
90: p = argv[optind - 1];
91: if (p[0] == '-' && p[1] == ch && !p[2])
92: numlines = strtol(++p, &ep, 10);
93: else
94: numlines =
95: strtol(argv[optind] + 1, &ep, 10);
96: if (numlines <= 0 || *ep)
97: errx(1,
98: "%s: illegal line count.", optarg);
99: }
100: break;
101: case '-': /* Undocumented: historic stdin flag. */
102: if (ifd != -1)
103: usage();
104: ifd = 0;
105: break;
106: case 'b': /* Byte count. */
107: if ((bytecnt = strtol(optarg, &ep, 10)) <= 0 ||
108: *ep != '\0' && *ep != 'k' && *ep != 'm')
109: errx(1, "%s: illegal byte count.", optarg);
110: if (*ep == 'k')
111: bytecnt *= 1024;
112: else if (*ep == 'm')
113: bytecnt *= 1048576;
114: break;
115: case 'l': /* Line count. */
116: if (numlines != 0)
117: usage();
118: if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep)
119: errx(1, "%s: illegal line count.", optarg);
120: break;
121: default:
122: usage();
123: }
124: argv += optind;
125: argc -= optind;
126:
127: if (*argv != NULL)
128: if (ifd == -1) { /* Input file. */
129: if ((ifd = open(*argv, O_RDONLY, 0)) < 0)
130: err(1, "%s", *argv);
131: ++argv;
132: }
133: if (*argv != NULL) /* File name prefix. */
134: (void)strcpy(fname, *argv++);
135: if (*argv != NULL)
136: usage();
137:
138: if (numlines == 0)
139: numlines = DEFLINE;
140: else if (bytecnt)
141: usage();
142:
143: if (ifd == -1) /* Stdin by default. */
144: ifd = 0;
145:
146: if (bytecnt) {
147: split1();
148: exit (0);
149: }
150: split2();
151: exit(0);
152: }
153:
154: /*
155: * split1 --
156: * Split the input by bytes.
157: */
158: void
159: split1()
160: {
161: long bcnt;
162: int dist, len;
163: char *C;
164:
165: for (bcnt = 0;;)
166: switch (len = read(ifd, bfr, MAXBSIZE)) {
167: case 0:
168: exit(0);
169: case -1:
170: err(1, "read");
171: /* NOTREACHED */
172: default:
173: if (!file_open) {
174: newfile();
175: file_open = 1;
176: }
177: if (bcnt + len >= bytecnt) {
178: dist = bytecnt - bcnt;
179: if (write(ofd, bfr, dist) != dist)
180: err(1, "write");
181: len -= dist;
182: for (C = bfr + dist; len >= bytecnt;
183: len -= bytecnt, C += bytecnt) {
184: newfile();
185: if (write(ofd,
186: C, (int)bytecnt) != bytecnt)
187: err(1, "write");
188: }
189: if (len) {
190: newfile();
191: if (write(ofd, C, len) != len)
192: err(1, "write");
193: } else
194: file_open = 0;
195: bcnt = len;
196: } else {
197: bcnt += len;
198: if (write(ofd, bfr, len) != len)
199: err(1, "write");
200: }
201: }
202: }
203:
204: /*
205: * split2 --
206: * Split the input by lines.
207: */
208: void
209: split2()
210: {
211: long lcnt;
212: int len, bcnt;
213: char *Ce, *Cs;
214:
215: for (lcnt = 0;;)
216: switch (len = read(ifd, bfr, MAXBSIZE)) {
217: case 0:
218: exit(0);
219: case -1:
220: err(1, "read");
221: /* NOTREACHED */
222: default:
223: if (!file_open) {
224: newfile();
225: file_open = 1;
226: }
227: for (Cs = Ce = bfr; len--; Ce++)
228: if (*Ce == '\n' && ++lcnt == numlines) {
229: bcnt = Ce - Cs + 1;
230: if (write(ofd, Cs, bcnt) != bcnt)
231: err(1, "write");
232: lcnt = 0;
233: Cs = Ce + 1;
234: if (len)
235: newfile();
236: else
237: file_open = 0;
238: }
239: if (Cs < Ce) {
240: bcnt = Ce - Cs;
241: if (write(ofd, Cs, bcnt) != bcnt)
242: err(1, "write");
243: }
244: }
245: }
246:
247: /*
248: * newfile --
249: * Open a new output file.
250: */
251: void
252: newfile()
253: {
254: static long fnum;
255: static int defname;
256: static char *fpnt;
257:
258: if (ofd == -1) {
259: if (fname[0] == '\0') {
260: fname[0] = 'x';
261: fpnt = fname + 1;
262: defname = 1;
263: } else {
264: fpnt = fname + strlen(fname);
265: defname = 0;
266: }
267: ofd = fileno(stdout);
268: }
269: /*
270: * Hack to increase max files; original code wandered through
271: * magic characters. Maximum files is 3 * 26 * 26 == 2028
272: */
273: #define MAXFILES 676
274: if (fnum == MAXFILES) {
275: if (!defname || fname[0] == 'z')
276: errx(1, "too many files.");
277: ++fname[0];
278: fnum = 0;
279: }
280: fpnt[0] = fnum / 26 + 'a';
281: fpnt[1] = fnum % 26 + 'a';
282: ++fnum;
283: if (!freopen(fname, "w", stdout))
284: err(1, "%s", fname);
285: }
286:
287: void
288: usage()
289: {
290: (void)fprintf(stderr,
291: "usage: split [-b byte_count] [-l line_count] [file [prefix]]\n");
292: exit(1);
293: }