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