split.c (c002b33b6041366aa2ed197dd154a73a00550ad6) | split.c (2fa6610f1e5e272411974f1b718dad9067dca615) |
---|---|
1/* 2 * Copyright (c) 1987, 1993, 1994 3 * The Regents of the University of California. 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 --- 30 unchanged lines hidden (view full) --- 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)split.c 8.2 (Berkeley) 4/16/94"; 43#endif 44#endif /* not lint */ 45 46#include <sys/param.h> | 1/* 2 * Copyright (c) 1987, 1993, 1994 3 * The Regents of the University of California. 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 --- 30 unchanged lines hidden (view full) --- 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)split.c 8.2 (Berkeley) 4/16/94"; 43#endif 44#endif /* not lint */ 45 46#include <sys/param.h> |
47#include <sys/types.h> |
|
47 48#include <ctype.h> 49#include <err.h> 50#include <fcntl.h> 51#include <stdio.h> 52#include <stdlib.h> 53#include <string.h> 54#include <unistd.h> | 48 49#include <ctype.h> 50#include <err.h> 51#include <fcntl.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <string.h> 55#include <unistd.h> |
56#include <regex.h> 57#include <sysexits.h> |
|
55 56#define DEFLINE 1000 /* Default num lines per file. */ 57 58long bytecnt; /* Byte count to split on. */ 59long numlines; /* Line count to split on. */ 60int file_open; /* If a file open. */ 61int ifd = -1, ofd = -1; /* Input/output file descriptors. */ 62char bfr[MAXBSIZE]; /* I/O buffer. */ 63char fname[MAXPATHLEN]; /* File name prefix. */ | 58 59#define DEFLINE 1000 /* Default num lines per file. */ 60 61long bytecnt; /* Byte count to split on. */ 62long numlines; /* Line count to split on. */ 63int file_open; /* If a file open. */ 64int ifd = -1, ofd = -1; /* Input/output file descriptors. */ 65char bfr[MAXBSIZE]; /* I/O buffer. */ 66char fname[MAXPATHLEN]; /* File name prefix. */ |
67regex_t rgx; 68int pflag; |
|
64 65void newfile __P((void)); 66void split1 __P((void)); 67void split2 __P((void)); 68static void usage __P((void)); 69 70int 71main(argc, argv) 72 int argc; 73 char *argv[]; 74{ 75 int ch; 76 char *ep, *p; 77 | 69 70void newfile __P((void)); 71void split1 __P((void)); 72void split2 __P((void)); 73static void usage __P((void)); 74 75int 76main(argc, argv) 77 int argc; 78 char *argv[]; 79{ 80 int ch; 81 char *ep, *p; 82 |
78 while ((ch = getopt(argc, argv, "-0123456789b:l:")) != -1) | 83 while ((ch = getopt(argc, argv, "-0123456789b:l:p:")) != -1) |
79 switch (ch) { 80 case '0': case '1': case '2': case '3': case '4': 81 case '5': case '6': case '7': case '8': case '9': 82 /* 83 * Undocumented kludge: split was originally designed 84 * to take a number after a dash. 85 */ 86 if (numlines == 0) { 87 p = argv[optind - 1]; 88 if (p[0] == '-' && p[1] == ch && !p[2]) 89 numlines = strtol(++p, &ep, 10); 90 else 91 numlines = 92 strtol(argv[optind] + 1, &ep, 10); 93 if (numlines <= 0 || *ep) | 84 switch (ch) { 85 case '0': case '1': case '2': case '3': case '4': 86 case '5': case '6': case '7': case '8': case '9': 87 /* 88 * Undocumented kludge: split was originally designed 89 * to take a number after a dash. 90 */ 91 if (numlines == 0) { 92 p = argv[optind - 1]; 93 if (p[0] == '-' && p[1] == ch && !p[2]) 94 numlines = strtol(++p, &ep, 10); 95 else 96 numlines = 97 strtol(argv[optind] + 1, &ep, 10); 98 if (numlines <= 0 || *ep) |
94 errx(1, "%s: illegal line count", optarg); | 99 errx(EX_USAGE, 100 "%s: illegal line count", optarg); |
95 } 96 break; 97 case '-': /* Undocumented: historic stdin flag. */ 98 if (ifd != -1) 99 usage(); 100 ifd = 0; 101 break; 102 case 'b': /* Byte count. */ 103 if ((bytecnt = strtol(optarg, &ep, 10)) <= 0 || 104 (*ep != '\0' && *ep != 'k' && *ep != 'm')) | 101 } 102 break; 103 case '-': /* Undocumented: historic stdin flag. */ 104 if (ifd != -1) 105 usage(); 106 ifd = 0; 107 break; 108 case 'b': /* Byte count. */ 109 if ((bytecnt = strtol(optarg, &ep, 10)) <= 0 || 110 (*ep != '\0' && *ep != 'k' && *ep != 'm')) |
105 errx(1, "%s: illegal byte count", optarg); | 111 errx(EX_USAGE, 112 "%s: illegal byte count", optarg); |
106 if (*ep == 'k') 107 bytecnt *= 1024; 108 else if (*ep == 'm') 109 bytecnt *= 1048576; 110 break; | 113 if (*ep == 'k') 114 bytecnt *= 1024; 115 else if (*ep == 'm') 116 bytecnt *= 1048576; 117 break; |
118 case 'p' : /* pattern matching. */ 119 if (regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB) != 0) 120 errx(EX_USAGE, "%s: illegal regexp", optarg); 121 pflag = 1; 122 break; |
|
111 case 'l': /* Line count. */ 112 if (numlines != 0) 113 usage(); 114 if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep) | 123 case 'l': /* Line count. */ 124 if (numlines != 0) 125 usage(); 126 if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep) |
115 errx(1, "%s: illegal line count", optarg); | 127 errx(EX_USAGE, 128 "%s: illegal line count", optarg); |
116 break; 117 default: 118 usage(); 119 } 120 argv += optind; 121 argc -= optind; 122 123 if (*argv != NULL) 124 if (ifd == -1) { /* Input file. */ 125 if ((ifd = open(*argv, O_RDONLY, 0)) < 0) | 129 break; 130 default: 131 usage(); 132 } 133 argv += optind; 134 argc -= optind; 135 136 if (*argv != NULL) 137 if (ifd == -1) { /* Input file. */ 138 if ((ifd = open(*argv, O_RDONLY, 0)) < 0) |
126 err(1, "%s", *argv); | 139 err(EX_NOINPUT, "%s", *argv); |
127 ++argv; 128 } 129 if (*argv != NULL) /* File name prefix. */ 130 (void)strcpy(fname, *argv++); 131 if (*argv != NULL) 132 usage(); 133 | 140 ++argv; 141 } 142 if (*argv != NULL) /* File name prefix. */ 143 (void)strcpy(fname, *argv++); 144 if (*argv != NULL) 145 usage(); 146 |
147 if (pflag && (numlines != 0 || bytecnt != 0)) 148 usage(); 149 |
|
134 if (numlines == 0) 135 numlines = DEFLINE; | 150 if (numlines == 0) 151 numlines = DEFLINE; |
136 else if (bytecnt) | 152 else if (bytecnt != 0) |
137 usage(); 138 139 if (ifd == -1) /* Stdin by default. */ 140 ifd = 0; 141 142 if (bytecnt) { 143 split1(); 144 exit (0); 145 } 146 split2(); | 153 usage(); 154 155 if (ifd == -1) /* Stdin by default. */ 156 ifd = 0; 157 158 if (bytecnt) { 159 split1(); 160 exit (0); 161 } 162 split2(); |
163 if (pflag) 164 regfree(&rgx); |
|
147 exit(0); 148} 149 150/* 151 * split1 -- 152 * Split the input by bytes. 153 */ 154void 155split1() 156{ 157 long bcnt; 158 int dist, len; 159 char *C; 160 161 for (bcnt = 0;;) | 165 exit(0); 166} 167 168/* 169 * split1 -- 170 * Split the input by bytes. 171 */ 172void 173split1() 174{ 175 long bcnt; 176 int dist, len; 177 char *C; 178 179 for (bcnt = 0;;) |
162 switch (len = read(ifd, bfr, MAXBSIZE)) { | 180 switch ((len = read(ifd, bfr, MAXBSIZE))) { |
163 case 0: 164 exit(0); 165 case -1: | 181 case 0: 182 exit(0); 183 case -1: |
166 err(1, "read"); | 184 err(EX_IOERR, "read"); |
167 /* NOTREACHED */ 168 default: | 185 /* NOTREACHED */ 186 default: |
169 if (!file_open) { | 187 if (!file_open) |
170 newfile(); | 188 newfile(); |
171 file_open = 1; 172 } | |
173 if (bcnt + len >= bytecnt) { 174 dist = bytecnt - bcnt; 175 if (write(ofd, bfr, dist) != dist) | 189 if (bcnt + len >= bytecnt) { 190 dist = bytecnt - bcnt; 191 if (write(ofd, bfr, dist) != dist) |
176 err(1, "write"); | 192 err(EX_IOERR, "write"); |
177 len -= dist; 178 for (C = bfr + dist; len >= bytecnt; 179 len -= bytecnt, C += bytecnt) { 180 newfile(); 181 if (write(ofd, 182 C, (int)bytecnt) != bytecnt) | 193 len -= dist; 194 for (C = bfr + dist; len >= bytecnt; 195 len -= bytecnt, C += bytecnt) { 196 newfile(); 197 if (write(ofd, 198 C, (int)bytecnt) != bytecnt) |
183 err(1, "write"); | 199 err(EX_IOERR, "write"); |
184 } | 200 } |
185 if (len) { | 201 if (len != 0) { |
186 newfile(); 187 if (write(ofd, C, len) != len) | 202 newfile(); 203 if (write(ofd, C, len) != len) |
188 err(1, "write"); | 204 err(EX_IOERR, "write"); |
189 } else 190 file_open = 0; 191 bcnt = len; 192 } else { 193 bcnt += len; 194 if (write(ofd, bfr, len) != len) | 205 } else 206 file_open = 0; 207 bcnt = len; 208 } else { 209 bcnt += len; 210 if (write(ofd, bfr, len) != len) |
195 err(1, "write"); | 211 err(EX_IOERR, "write"); |
196 } 197 } 198} 199 200/* 201 * split2 -- 202 * Split the input by lines. 203 */ 204void 205split2() 206{ | 212 } 213 } 214} 215 216/* 217 * split2 -- 218 * Split the input by lines. 219 */ 220void 221split2() 222{ |
207 long lcnt; 208 int len, bcnt; 209 char *Ce, *Cs; | 223 long lcnt = 0; 224 FILE *infp; |
210 | 225 |
211 for (lcnt = 0;;) 212 switch (len = read(ifd, bfr, MAXBSIZE)) { 213 case 0: 214 exit(0); 215 case -1: 216 err(1, "read"); 217 /* NOTREACHED */ 218 default: 219 if (!file_open) { | 226 /* Stick a stream on top of input file descriptor */ 227 if ((infp = fdopen(ifd, "r")) == NULL) 228 err(EX_NOINPUT, "fdopen"); 229 230 /* Process input one line at a time */ 231 while (fgets(bfr, sizeof(bfr), infp) != NULL) { 232 const int len = strlen(bfr); 233 234 /* If line is too long to deal with, just write it out */ 235 if (bfr[len - 1] != '\n') 236 goto writeit; 237 238 /* Check if we need to start a new file */ 239 if (pflag) { 240 regmatch_t pmatch; 241 242 pmatch.rm_so = 0; 243 pmatch.rm_eo = len - 1; 244 if (regexec(&rgx, bfr, 0, &pmatch, REG_STARTEND) == 0) |
220 newfile(); | 245 newfile(); |
221 file_open = 1; 222 } 223 for (Cs = Ce = bfr; len--; Ce++) 224 if (*Ce == '\n' && ++lcnt == numlines) { 225 bcnt = Ce - Cs + 1; 226 if (write(ofd, Cs, bcnt) != bcnt) 227 err(1, "write"); 228 lcnt = 0; 229 Cs = Ce + 1; 230 if (len) 231 newfile(); 232 else 233 file_open = 0; 234 } 235 if (Cs < Ce) { 236 bcnt = Ce - Cs; 237 if (write(ofd, Cs, bcnt) != bcnt) 238 err(1, "write"); 239 } | 246 } else if (lcnt++ == numlines) { 247 newfile(); 248 lcnt = 1; |
240 } | 249 } |
250 251writeit: 252 /* Open output file if needed */ 253 if (!file_open) 254 newfile(); 255 256 /* Write out line */ 257 if (write(ofd, bfr, len) != len) 258 err(EX_IOERR, "write"); 259 } 260 261 /* EOF or error? */ 262 if (ferror(infp)) 263 err(EX_IOERR, "read"); 264 else 265 exit(0); |
|
241} 242 243/* 244 * newfile -- 245 * Open a new output file. 246 */ 247void 248newfile() --- 15 unchanged lines hidden (view full) --- 264 } 265 /* 266 * Hack to increase max files; original code wandered through 267 * magic characters. Maximum files is 3 * 26 * 26 == 2028 268 */ 269#define MAXFILES 676 270 if (fnum == MAXFILES) { 271 if (!defname || fname[0] == 'z') | 266} 267 268/* 269 * newfile -- 270 * Open a new output file. 271 */ 272void 273newfile() --- 15 unchanged lines hidden (view full) --- 289 } 290 /* 291 * Hack to increase max files; original code wandered through 292 * magic characters. Maximum files is 3 * 26 * 26 == 2028 293 */ 294#define MAXFILES 676 295 if (fnum == MAXFILES) { 296 if (!defname || fname[0] == 'z') |
272 errx(1, "too many files"); | 297 errx(EX_DATAERR, "too many files"); |
273 ++fname[0]; 274 fnum = 0; 275 } 276 fpnt[0] = fnum / 26 + 'a'; 277 fpnt[1] = fnum % 26 + 'a'; 278 ++fnum; 279 if (!freopen(fname, "w", stdout)) | 298 ++fname[0]; 299 fnum = 0; 300 } 301 fpnt[0] = fnum / 26 + 'a'; 302 fpnt[1] = fnum % 26 + 'a'; 303 ++fnum; 304 if (!freopen(fname, "w", stdout)) |
280 err(1, "%s", fname); | 305 err(EX_IOERR, "%s", fname); 306 file_open = 1; |
281} 282 283static void 284usage() 285{ | 307} 308 309static void 310usage() 311{ |
286 (void)fprintf(stderr, 287"usage: split [-b byte_count] [-l line_count] [file [prefix]]\n"); 288 exit(1); | 312 errx(EX_USAGE, 313"usage: split [-b byte_count] [-l line_count] [-p pattern] [file [prefix]]"); |
289} | 314} |