Commit | Line | Data |
---|---|---|
86bcea21 KB |
1 | /* |
2 | * Copyright (c) 1987 Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
cb956e54 | 5 | * %sccs.include.redist.c% |
86bcea21 KB |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
10 | "@(#) Copyright (c) 1987 Regents of the University of California.\n\ | |
11 | All rights reserved.\n"; | |
12 | #endif /* not lint */ | |
13 | ||
14 | #ifndef lint | |
cb956e54 | 15 | static char sccsid[] = "@(#)split.c 4.8 (Berkeley) %G%"; |
86bcea21 | 16 | #endif /* not lint */ |
460f3462 KB |
17 | |
18 | #include <sys/param.h> | |
19 | #include <sys/file.h> | |
f37d3151 | 20 | #include <stdio.h> |
460f3462 KB |
21 | #include <ctype.h> |
22 | ||
23 | #define DEFLINE 1000 /* default num lines per file */ | |
24 | #define ERR -1 /* general error */ | |
460f3462 KB |
25 | #define NO 0 /* no/false */ |
26 | #define OK 0 /* okay exit */ | |
27 | #define YES 1 /* yes/true */ | |
f37d3151 | 28 | |
460f3462 KB |
29 | static long bytecnt, /* byte count to split on */ |
30 | numlines; /* lines in each file */ | |
31 | static int ifd = ERR, /* input file descriptor */ | |
32 | ofd = ERR; /* output file descriptor */ | |
33 | static short file_open; /* if a file open */ | |
34 | static char bfr[MAXBSIZE], /* I/O buffer */ | |
35 | fname[MAXPATHLEN]; /* file name */ | |
f37d3151 | 36 | |
86bcea21 | 37 | main(argc, argv) |
4bf5591e KB |
38 | int argc; |
39 | char **argv; | |
f37d3151 | 40 | { |
4bf5591e KB |
41 | register int cnt; |
42 | long atol(); | |
43 | char *strcpy(); | |
f37d3151 | 44 | |
86bcea21 | 45 | for (cnt = 1; cnt < argc; ++cnt) { |
460f3462 KB |
46 | if (argv[cnt][0] == '-') |
47 | switch(argv[cnt][1]) { | |
86bcea21 KB |
48 | case 0: /* stdin by request */ |
49 | if (ifd != ERR) | |
50 | usage(); | |
51 | ifd = 0; | |
52 | break; | |
53 | case 'b': /* byte count split */ | |
54 | if (numlines) | |
55 | usage(); | |
56 | if (!argv[cnt][2]) | |
57 | bytecnt = atol(argv[++cnt]); | |
58 | else | |
59 | bytecnt = atol(argv[cnt] + 2); | |
60 | if (bytecnt <= 0) { | |
61 | fputs("split: byte count must be greater than zero.\n", stderr); | |
62 | usage(); | |
63 | } | |
64 | break; | |
65 | default: | |
66 | if (!isdigit(argv[cnt][1]) || bytecnt) | |
67 | usage(); | |
68 | if ((numlines = atol(argv[cnt] + 1)) <= 0) { | |
69 | fputs("split: line count must be greater than zero.\n", stderr); | |
70 | usage(); | |
71 | } | |
72 | break; | |
460f3462 KB |
73 | } |
74 | else if (ifd == ERR) { /* input file */ | |
86bcea21 | 75 | if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { |
460f3462 | 76 | perror(argv[cnt]); |
4bf5591e | 77 | exit(1); |
f37d3151 | 78 | } |
f37d3151 | 79 | } |
460f3462 | 80 | else if (!*fname) /* output file prefix */ |
86bcea21 | 81 | strcpy(fname, argv[cnt]); |
460f3462 KB |
82 | else |
83 | usage(); | |
84 | } | |
85 | if (ifd == ERR) /* stdin by default */ | |
86 | ifd = 0; | |
87 | if (bytecnt) | |
88 | split1(); | |
89 | if (!numlines) | |
90 | numlines = DEFLINE; | |
91 | split2(); | |
4bf5591e | 92 | exit(0); |
460f3462 KB |
93 | } |
94 | ||
95 | /* | |
96 | * split1 -- | |
97 | * split by bytes | |
98 | */ | |
460f3462 KB |
99 | split1() |
100 | { | |
4bf5591e KB |
101 | register long bcnt; |
102 | register int dist, len; | |
103 | register char *C; | |
460f3462 KB |
104 | |
105 | for (bcnt = 0;;) | |
86bcea21 KB |
106 | switch(len = read(ifd, bfr, MAXBSIZE)) { |
107 | case 0: | |
108 | exit(OK); | |
109 | case ERR: | |
110 | perror("read"); | |
4bf5591e | 111 | exit(1); |
86bcea21 KB |
112 | default: |
113 | if (!file_open) { | |
114 | newfile(); | |
115 | file_open = YES; | |
116 | } | |
117 | if (bcnt + len >= bytecnt) { | |
118 | dist = bytecnt - bcnt; | |
4bf5591e KB |
119 | if (write(ofd, bfr, dist) != dist) |
120 | wrerror(); | |
86bcea21 KB |
121 | len -= dist; |
122 | for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { | |
460f3462 | 123 | newfile(); |
4bf5591e KB |
124 | if (write(ofd, C, (int)bytecnt) != bytecnt) |
125 | wrerror(); | |
460f3462 | 126 | } |
86bcea21 KB |
127 | if (len) { |
128 | newfile(); | |
4bf5591e KB |
129 | if (write(ofd, C, len) != len) |
130 | wrerror(); | |
460f3462 | 131 | } |
86bcea21 KB |
132 | else |
133 | file_open = NO; | |
134 | bcnt = len; | |
135 | } | |
136 | else { | |
137 | bcnt += len; | |
4bf5591e KB |
138 | if (write(ofd, bfr, len) != len) |
139 | wrerror(); | |
86bcea21 | 140 | } |
460f3462 KB |
141 | } |
142 | } | |
143 | ||
144 | /* | |
145 | * split2 -- | |
146 | * split by lines | |
147 | */ | |
460f3462 KB |
148 | split2() |
149 | { | |
4bf5591e KB |
150 | register char *Ce, *Cs; |
151 | register long lcnt; | |
152 | register int len, bcnt; | |
460f3462 KB |
153 | |
154 | for (lcnt = 0;;) | |
86bcea21 KB |
155 | switch(len = read(ifd, bfr, MAXBSIZE)) { |
156 | case 0: | |
157 | exit(0); | |
158 | case ERR: | |
159 | perror("read"); | |
4bf5591e | 160 | exit(1); |
86bcea21 KB |
161 | default: |
162 | if (!file_open) { | |
163 | newfile(); | |
164 | file_open = YES; | |
165 | } | |
166 | for (Cs = Ce = bfr; len--; Ce++) | |
167 | if (*Ce == '\n' && ++lcnt == numlines) { | |
4bf5591e KB |
168 | bcnt = Ce - Cs + 1; |
169 | if (write(ofd, Cs, bcnt) != bcnt) | |
170 | wrerror(); | |
86bcea21 KB |
171 | lcnt = 0; |
172 | Cs = Ce + 1; | |
173 | if (len) | |
174 | newfile(); | |
175 | else | |
176 | file_open = NO; | |
460f3462 | 177 | } |
4bf5591e KB |
178 | if (Cs < Ce) { |
179 | bcnt = Ce - Cs; | |
180 | if (write(ofd, Cs, bcnt) != bcnt) | |
181 | wrerror(); | |
182 | } | |
f37d3151 | 183 | } |
460f3462 | 184 | } |
f37d3151 | 185 | |
460f3462 KB |
186 | /* |
187 | * newfile -- | |
188 | * open a new file | |
189 | */ | |
460f3462 KB |
190 | newfile() |
191 | { | |
4bf5591e KB |
192 | static long fnum; |
193 | static short defname; | |
194 | static char *fpnt; | |
460f3462 KB |
195 | |
196 | if (ofd == ERR) { | |
197 | if (fname[0]) { | |
198 | fpnt = fname + strlen(fname); | |
199 | defname = NO; | |
f37d3151 | 200 | } |
460f3462 KB |
201 | else { |
202 | fname[0] = 'x'; | |
203 | fpnt = fname + 1; | |
204 | defname = YES; | |
205 | } | |
206 | ofd = fileno(stdout); | |
207 | } | |
208 | /* | |
209 | * hack to increase max files; original code just wandered through | |
210 | * magic characters. Maximum files is 3 * 26 * 26 == 2028 | |
211 | */ | |
212 | #define MAXFILES 676 | |
213 | if (fnum == MAXFILES) { | |
214 | if (!defname || fname[0] == 'z') { | |
86bcea21 | 215 | fputs("split: too many files.\n", stderr); |
4bf5591e | 216 | exit(1); |
f37d3151 | 217 | } |
460f3462 KB |
218 | ++fname[0]; |
219 | fnum = 0; | |
220 | } | |
221 | fpnt[0] = fnum / 26 + 'a'; | |
222 | fpnt[1] = fnum % 26 + 'a'; | |
223 | ++fnum; | |
86bcea21 KB |
224 | if (!freopen(fname, "w", stdout)) { |
225 | fprintf(stderr, "split: unable to write to %s.\n", fname); | |
460f3462 KB |
226 | exit(ERR); |
227 | } | |
228 | } | |
229 | ||
230 | /* | |
231 | * usage -- | |
232 | * print usage message and die | |
233 | */ | |
460f3462 KB |
234 | usage() |
235 | { | |
86bcea21 | 236 | fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); |
4bf5591e KB |
237 | exit(1); |
238 | } | |
239 | ||
240 | /* | |
241 | * wrerror -- | |
242 | * write error | |
243 | */ | |
244 | wrerror() | |
245 | { | |
246 | perror("split: write"); | |
247 | exit(1); | |
f37d3151 | 248 | } |