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, 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. 32 */ 33 34 #ifndef lint 35 char 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 41 /*static char sccsid[] = "from: @(#)split.c 4.8 (Berkeley) 6/1/90";*/ 42 static char rcsid[] = "$Id: split.c,v 1.3 1994/04/06 00:04:09 cgd Exp $"; 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/file.h> 47 #include <stdio.h> 48 #include <ctype.h> 49 50 #define DEFLINE 1000 /* default num lines per file */ 51 #define ERR -1 /* general error */ 52 #define NO 0 /* no/false */ 53 #define OK 0 /* okay exit */ 54 #define YES 1 /* yes/true */ 55 56 static long bytecnt, /* byte count to split on */ 57 numlines; /* lines in each file */ 58 static int ifd = ERR, /* input file descriptor */ 59 ofd = ERR; /* output file descriptor */ 60 static short file_open; /* if a file open */ 61 static char bfr[MAXBSIZE], /* I/O buffer */ 62 fname[MAXPATHLEN]; /* file name */ 63 64 main(argc, argv) 65 int argc; 66 char **argv; 67 { 68 register int cnt; 69 long atol(); 70 char *strcpy(); 71 72 for (cnt = 1; cnt < argc; ++cnt) { 73 if (argv[cnt][0] == '-') 74 switch(argv[cnt][1]) { 75 case 0: /* stdin by request */ 76 if (ifd != ERR) 77 usage(); 78 ifd = 0; 79 break; 80 case 'b': /* byte count split */ 81 if (numlines) 82 usage(); 83 if (!argv[cnt][2]) { 84 if (++cnt >= argc) 85 usage(); 86 bytecnt = atol(argv[cnt]); 87 } else 88 bytecnt = atol(argv[cnt] + 2); 89 if (bytecnt <= 0) { 90 fputs("split: byte count must be greater than zero.\n", stderr); 91 usage(); 92 } 93 break; 94 default: 95 if (!isdigit(argv[cnt][1]) || bytecnt) 96 usage(); 97 if ((numlines = atol(argv[cnt] + 1)) <= 0) { 98 fputs("split: line count must be greater than zero.\n", stderr); 99 usage(); 100 } 101 break; 102 } 103 else if (ifd == ERR) { /* input file */ 104 if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { 105 perror(argv[cnt]); 106 exit(1); 107 } 108 } 109 else if (!*fname) /* output file prefix */ 110 strcpy(fname, argv[cnt]); 111 else 112 usage(); 113 } 114 if (ifd == ERR) /* stdin by default */ 115 ifd = 0; 116 if (bytecnt) 117 split1(); 118 if (!numlines) 119 numlines = DEFLINE; 120 split2(); 121 exit(0); 122 } 123 124 /* 125 * split1 -- 126 * split by bytes 127 */ 128 split1() 129 { 130 register long bcnt; 131 register int dist, len; 132 register char *C; 133 134 for (bcnt = 0;;) 135 switch(len = read(ifd, bfr, MAXBSIZE)) { 136 case 0: 137 exit(OK); 138 case ERR: 139 perror("read"); 140 exit(1); 141 default: 142 if (!file_open) { 143 newfile(); 144 file_open = YES; 145 } 146 if (bcnt + len >= bytecnt) { 147 dist = bytecnt - bcnt; 148 if (write(ofd, bfr, dist) != dist) 149 wrerror(); 150 len -= dist; 151 for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { 152 newfile(); 153 if (write(ofd, C, (int)bytecnt) != bytecnt) 154 wrerror(); 155 } 156 if (len) { 157 newfile(); 158 if (write(ofd, C, len) != len) 159 wrerror(); 160 } 161 else 162 file_open = NO; 163 bcnt = len; 164 } 165 else { 166 bcnt += len; 167 if (write(ofd, bfr, len) != len) 168 wrerror(); 169 } 170 } 171 } 172 173 /* 174 * split2 -- 175 * split by lines 176 */ 177 split2() 178 { 179 register char *Ce, *Cs; 180 register long lcnt; 181 register int len, bcnt; 182 183 for (lcnt = 0;;) 184 switch(len = read(ifd, bfr, MAXBSIZE)) { 185 case 0: 186 exit(0); 187 case ERR: 188 perror("read"); 189 exit(1); 190 default: 191 if (!file_open) { 192 newfile(); 193 file_open = YES; 194 } 195 for (Cs = Ce = bfr; len--; Ce++) 196 if (*Ce == '\n' && ++lcnt == numlines) { 197 bcnt = Ce - Cs + 1; 198 if (write(ofd, Cs, bcnt) != bcnt) 199 wrerror(); 200 lcnt = 0; 201 Cs = Ce + 1; 202 if (len) 203 newfile(); 204 else 205 file_open = NO; 206 } 207 if (Cs < Ce) { 208 bcnt = Ce - Cs; 209 if (write(ofd, Cs, bcnt) != bcnt) 210 wrerror(); 211 } 212 } 213 } 214 215 /* 216 * newfile -- 217 * open a new file 218 */ 219 newfile() 220 { 221 static long fnum; 222 static short defname; 223 static char *fpnt; 224 225 if (ofd == ERR) { 226 if (fname[0]) { 227 fpnt = fname + strlen(fname); 228 defname = NO; 229 } 230 else { 231 fname[0] = 'x'; 232 fpnt = fname + 1; 233 defname = YES; 234 } 235 ofd = fileno(stdout); 236 } 237 /* 238 * hack to increase max files; original code just wandered through 239 * magic characters. Maximum files is 3 * 26 * 26 == 2028 240 */ 241 #define MAXFILES 676 242 if (fnum == MAXFILES) { 243 if (!defname || fname[0] == 'z') { 244 fputs("split: too many files.\n", stderr); 245 exit(1); 246 } 247 ++fname[0]; 248 fnum = 0; 249 } 250 fpnt[0] = fnum / 26 + 'a'; 251 fpnt[1] = fnum % 26 + 'a'; 252 ++fnum; 253 if (!freopen(fname, "w", stdout)) { 254 fprintf(stderr, "split: unable to write to %s.\n", fname); 255 exit(ERR); 256 } 257 } 258 259 /* 260 * usage -- 261 * print usage message and die 262 */ 263 usage() 264 { 265 fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); 266 exit(1); 267 } 268 269 /* 270 * wrerror -- 271 * write error 272 */ 273 wrerror() 274 { 275 perror("split: write"); 276 exit(1); 277 } 278