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