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