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