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