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