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.2 1993/08/01 18:08:21 mycroft 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 bytecnt = atol(argv[++cnt]); 85 else 86 bytecnt = atol(argv[cnt] + 2); 87 if (bytecnt <= 0) { 88 fputs("split: byte count must be greater than zero.\n", stderr); 89 usage(); 90 } 91 break; 92 default: 93 if (!isdigit(argv[cnt][1]) || bytecnt) 94 usage(); 95 if ((numlines = atol(argv[cnt] + 1)) <= 0) { 96 fputs("split: line count must be greater than zero.\n", stderr); 97 usage(); 98 } 99 break; 100 } 101 else if (ifd == ERR) { /* input file */ 102 if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { 103 perror(argv[cnt]); 104 exit(1); 105 } 106 } 107 else if (!*fname) /* output file prefix */ 108 strcpy(fname, argv[cnt]); 109 else 110 usage(); 111 } 112 if (ifd == ERR) /* stdin by default */ 113 ifd = 0; 114 if (bytecnt) 115 split1(); 116 if (!numlines) 117 numlines = DEFLINE; 118 split2(); 119 exit(0); 120 } 121 122 /* 123 * split1 -- 124 * split by bytes 125 */ 126 split1() 127 { 128 register long bcnt; 129 register int dist, len; 130 register char *C; 131 132 for (bcnt = 0;;) 133 switch(len = read(ifd, bfr, MAXBSIZE)) { 134 case 0: 135 exit(OK); 136 case ERR: 137 perror("read"); 138 exit(1); 139 default: 140 if (!file_open) { 141 newfile(); 142 file_open = YES; 143 } 144 if (bcnt + len >= bytecnt) { 145 dist = bytecnt - bcnt; 146 if (write(ofd, bfr, dist) != dist) 147 wrerror(); 148 len -= dist; 149 for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { 150 newfile(); 151 if (write(ofd, C, (int)bytecnt) != bytecnt) 152 wrerror(); 153 } 154 if (len) { 155 newfile(); 156 if (write(ofd, C, len) != len) 157 wrerror(); 158 } 159 else 160 file_open = NO; 161 bcnt = len; 162 } 163 else { 164 bcnt += len; 165 if (write(ofd, bfr, len) != len) 166 wrerror(); 167 } 168 } 169 } 170 171 /* 172 * split2 -- 173 * split by lines 174 */ 175 split2() 176 { 177 register char *Ce, *Cs; 178 register long lcnt; 179 register int len, bcnt; 180 181 for (lcnt = 0;;) 182 switch(len = read(ifd, bfr, MAXBSIZE)) { 183 case 0: 184 exit(0); 185 case ERR: 186 perror("read"); 187 exit(1); 188 default: 189 if (!file_open) { 190 newfile(); 191 file_open = YES; 192 } 193 for (Cs = Ce = bfr; len--; Ce++) 194 if (*Ce == '\n' && ++lcnt == numlines) { 195 bcnt = Ce - Cs + 1; 196 if (write(ofd, Cs, bcnt) != bcnt) 197 wrerror(); 198 lcnt = 0; 199 Cs = Ce + 1; 200 if (len) 201 newfile(); 202 else 203 file_open = NO; 204 } 205 if (Cs < Ce) { 206 bcnt = Ce - Cs; 207 if (write(ofd, Cs, bcnt) != bcnt) 208 wrerror(); 209 } 210 } 211 } 212 213 /* 214 * newfile -- 215 * open a new file 216 */ 217 newfile() 218 { 219 static long fnum; 220 static short defname; 221 static char *fpnt; 222 223 if (ofd == ERR) { 224 if (fname[0]) { 225 fpnt = fname + strlen(fname); 226 defname = NO; 227 } 228 else { 229 fname[0] = 'x'; 230 fpnt = fname + 1; 231 defname = YES; 232 } 233 ofd = fileno(stdout); 234 } 235 /* 236 * hack to increase max files; original code just wandered through 237 * magic characters. Maximum files is 3 * 26 * 26 == 2028 238 */ 239 #define MAXFILES 676 240 if (fnum == MAXFILES) { 241 if (!defname || fname[0] == 'z') { 242 fputs("split: too many files.\n", stderr); 243 exit(1); 244 } 245 ++fname[0]; 246 fnum = 0; 247 } 248 fpnt[0] = fnum / 26 + 'a'; 249 fpnt[1] = fnum % 26 + 'a'; 250 ++fnum; 251 if (!freopen(fname, "w", stdout)) { 252 fprintf(stderr, "split: unable to write to %s.\n", fname); 253 exit(ERR); 254 } 255 } 256 257 /* 258 * usage -- 259 * print usage message and die 260 */ 261 usage() 262 { 263 fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); 264 exit(1); 265 } 266 267 /* 268 * wrerror -- 269 * write error 270 */ 271 wrerror() 272 { 273 perror("split: write"); 274 exit(1); 275 } 276