1 /* 2 * Copyright (c) 1987, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1987, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)split.c 8.1 (Berkeley) 06/06/93"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/file.h> 20 #include <stdio.h> 21 #include <ctype.h> 22 23 #define DEFLINE 1000 /* default num lines per file */ 24 #define ERR -1 /* general error */ 25 #define NO 0 /* no/false */ 26 #define OK 0 /* okay exit */ 27 #define YES 1 /* yes/true */ 28 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 */ 36 37 main(argc, argv) 38 int argc; 39 char **argv; 40 { 41 register int cnt; 42 long atol(); 43 char *strcpy(); 44 45 for (cnt = 1; cnt < argc; ++cnt) { 46 if (argv[cnt][0] == '-') 47 switch(argv[cnt][1]) { 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; 73 } 74 else if (ifd == ERR) { /* input file */ 75 if ((ifd = open(argv[cnt], O_RDONLY, 0)) < 0) { 76 perror(argv[cnt]); 77 exit(1); 78 } 79 } 80 else if (!*fname) /* output file prefix */ 81 strcpy(fname, argv[cnt]); 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(); 92 exit(0); 93 } 94 95 /* 96 * split1 -- 97 * split by bytes 98 */ 99 split1() 100 { 101 register long bcnt; 102 register int dist, len; 103 register char *C; 104 105 for (bcnt = 0;;) 106 switch(len = read(ifd, bfr, MAXBSIZE)) { 107 case 0: 108 exit(OK); 109 case ERR: 110 perror("read"); 111 exit(1); 112 default: 113 if (!file_open) { 114 newfile(); 115 file_open = YES; 116 } 117 if (bcnt + len >= bytecnt) { 118 dist = bytecnt - bcnt; 119 if (write(ofd, bfr, dist) != dist) 120 wrerror(); 121 len -= dist; 122 for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { 123 newfile(); 124 if (write(ofd, C, (int)bytecnt) != bytecnt) 125 wrerror(); 126 } 127 if (len) { 128 newfile(); 129 if (write(ofd, C, len) != len) 130 wrerror(); 131 } 132 else 133 file_open = NO; 134 bcnt = len; 135 } 136 else { 137 bcnt += len; 138 if (write(ofd, bfr, len) != len) 139 wrerror(); 140 } 141 } 142 } 143 144 /* 145 * split2 -- 146 * split by lines 147 */ 148 split2() 149 { 150 register char *Ce, *Cs; 151 register long lcnt; 152 register int len, bcnt; 153 154 for (lcnt = 0;;) 155 switch(len = read(ifd, bfr, MAXBSIZE)) { 156 case 0: 157 exit(0); 158 case ERR: 159 perror("read"); 160 exit(1); 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) { 168 bcnt = Ce - Cs + 1; 169 if (write(ofd, Cs, bcnt) != bcnt) 170 wrerror(); 171 lcnt = 0; 172 Cs = Ce + 1; 173 if (len) 174 newfile(); 175 else 176 file_open = NO; 177 } 178 if (Cs < Ce) { 179 bcnt = Ce - Cs; 180 if (write(ofd, Cs, bcnt) != bcnt) 181 wrerror(); 182 } 183 } 184 } 185 186 /* 187 * newfile -- 188 * open a new file 189 */ 190 newfile() 191 { 192 static long fnum; 193 static short defname; 194 static char *fpnt; 195 196 if (ofd == ERR) { 197 if (fname[0]) { 198 fpnt = fname + strlen(fname); 199 defname = NO; 200 } 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') { 215 fputs("split: too many files.\n", stderr); 216 exit(1); 217 } 218 ++fname[0]; 219 fnum = 0; 220 } 221 fpnt[0] = fnum / 26 + 'a'; 222 fpnt[1] = fnum % 26 + 'a'; 223 ++fnum; 224 if (!freopen(fname, "w", stdout)) { 225 fprintf(stderr, "split: unable to write to %s.\n", fname); 226 exit(ERR); 227 } 228 } 229 230 /* 231 * usage -- 232 * print usage message and die 233 */ 234 usage() 235 { 236 fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n", stderr); 237 exit(1); 238 } 239 240 /* 241 * wrerror -- 242 * write error 243 */ 244 wrerror() 245 { 246 perror("split: write"); 247 exit(1); 248 } 249