72}; 73 74/* Flags passed to regcomp() and regexec() */ 75int cflags = 0; 76int eflags = REG_STARTEND; 77 78/* Shortcut for matching all cases like empty regex */ 79bool matchall; 80 81/* Searching patterns */ 82unsigned int patterns, pattern_sz; 83char **pattern; 84regex_t *r_pattern; 85fastgrep_t *fg_pattern; 86 87/* Filename exclusion/inclusion patterns */ 88unsigned int fpatterns, fpattern_sz; 89unsigned int dpatterns, dpattern_sz; 90struct epat *dpattern, *fpattern; 91 92/* For regex errors */ 93char re_error[RE_ERROR_BUF + 1]; 94 95/* Command-line flags */ 96unsigned long long Aflag; /* -A x: print x lines trailing each match */ 97unsigned long long Bflag; /* -B x: print x lines leading each match */ 98bool Hflag; /* -H: always print file name */ 99bool Lflag; /* -L: only show names of files with no matches */ 100bool bflag; /* -b: show block numbers for each match */ 101bool cflag; /* -c: only show a count of matching lines */ 102bool hflag; /* -h: don't print filename headers */ 103bool iflag; /* -i: ignore case */ 104bool lflag; /* -l: only show names of files with matches */ 105bool mflag; /* -m x: stop reading the files after x matches */ 106unsigned long long mcount; /* count for -m */ 107bool nflag; /* -n: show line numbers in front of matching lines */ 108bool oflag; /* -o: print only matching part */ 109bool qflag; /* -q: quiet mode (don't output anything) */ 110bool sflag; /* -s: silent mode (ignore errors) */ 111bool vflag; /* -v: only show non-matching lines */ 112bool wflag; /* -w: pattern must start and end on word boundaries */ 113bool xflag; /* -x: pattern must match entire line */ 114bool lbflag; /* --line-buffered */ 115bool nullflag; /* --null */ 116char *label; /* --label */ 117const char *color; /* --color */ 118int grepbehave = GREP_BASIC; /* -EFGP: type of the regex */ 119int binbehave = BINFILE_BIN; /* -aIU: handling of binary files */ 120int filebehave = FILE_STDIO; /* -JZ: normal, gzip or bzip2 file */ 121int devbehave = DEV_READ; /* -D: handling of devices */ 122int dirbehave = DIR_READ; /* -dRr: handling of directories */ 123int linkbehave = LINK_READ; /* -OpS: handling of symlinks */ 124 125bool dexclude, dinclude; /* --exclude amd --include */ 126bool fexclude, finclude; /* --exclude-dir and --include-dir */ 127 128enum { 129 BIN_OPT = CHAR_MAX + 1, 130 COLOR_OPT, 131 HELP_OPT, 132 MMAP_OPT, 133 LINEBUF_OPT, 134 LABEL_OPT, 135 NULL_OPT, 136 R_EXCLUDE_OPT, 137 R_INCLUDE_OPT, 138 R_DEXCLUDE_OPT, 139 R_DINCLUDE_OPT 140}; 141 142static inline const char *init_color(const char *); 143 144/* Housekeeping */ 145bool first = true; /* flag whether we are processing the first match */ 146bool prev; /* flag whether or not the previous line matched */ 147int tail; /* lines left to print */ 148bool notfound; /* file not found */ 149 150extern char *__progname; 151 152/* 153 * Prints usage information and returns 2. 154 */ 155static void 156usage(void) 157{ 158 fprintf(stderr, getstr(4), __progname); 159 fprintf(stderr, "%s", getstr(5)); 160 fprintf(stderr, "%s", getstr(5)); 161 fprintf(stderr, "%s", getstr(6)); 162 fprintf(stderr, "%s", getstr(7)); 163 exit(2); 164} 165 166static const char *optstr = "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxy"; 167 168struct option long_options[] = 169{ 170 {"binary-files", required_argument, NULL, BIN_OPT}, 171 {"help", no_argument, NULL, HELP_OPT}, 172 {"mmap", no_argument, NULL, MMAP_OPT}, 173 {"line-buffered", no_argument, NULL, LINEBUF_OPT}, 174 {"label", required_argument, NULL, LABEL_OPT}, 175 {"null", no_argument, NULL, NULL_OPT}, 176 {"color", optional_argument, NULL, COLOR_OPT}, 177 {"colour", optional_argument, NULL, COLOR_OPT}, 178 {"exclude", required_argument, NULL, R_EXCLUDE_OPT}, 179 {"include", required_argument, NULL, R_INCLUDE_OPT}, 180 {"exclude-dir", required_argument, NULL, R_DEXCLUDE_OPT}, 181 {"include-dir", required_argument, NULL, R_DINCLUDE_OPT}, 182 {"after-context", required_argument, NULL, 'A'}, 183 {"text", no_argument, NULL, 'a'}, 184 {"before-context", required_argument, NULL, 'B'}, 185 {"byte-offset", no_argument, NULL, 'b'}, 186 {"context", optional_argument, NULL, 'C'}, 187 {"count", no_argument, NULL, 'c'}, 188 {"devices", required_argument, NULL, 'D'}, 189 {"directories", required_argument, NULL, 'd'}, 190 {"extended-regexp", no_argument, NULL, 'E'}, 191 {"regexp", required_argument, NULL, 'e'}, 192 {"fixed-strings", no_argument, NULL, 'F'}, 193 {"file", required_argument, NULL, 'f'}, 194 {"basic-regexp", no_argument, NULL, 'G'}, 195 {"no-filename", no_argument, NULL, 'h'}, 196 {"with-filename", no_argument, NULL, 'H'}, 197 {"ignore-case", no_argument, NULL, 'i'}, 198 {"bz2decompress", no_argument, NULL, 'J'}, 199 {"files-with-matches", no_argument, NULL, 'l'}, 200 {"files-without-match", no_argument, NULL, 'L'}, 201 {"max-count", required_argument, NULL, 'm'}, 202 {"line-number", no_argument, NULL, 'n'}, 203 {"only-matching", no_argument, NULL, 'o'}, 204 {"quiet", no_argument, NULL, 'q'}, 205 {"silent", no_argument, NULL, 'q'}, 206 {"recursive", no_argument, NULL, 'r'}, 207 {"no-messages", no_argument, NULL, 's'}, 208 {"binary", no_argument, NULL, 'U'}, 209 {"unix-byte-offsets", no_argument, NULL, 'u'}, 210 {"invert-match", no_argument, NULL, 'v'}, 211 {"version", no_argument, NULL, 'V'}, 212 {"word-regexp", no_argument, NULL, 'w'}, 213 {"line-regexp", no_argument, NULL, 'x'}, 214 {"decompress", no_argument, NULL, 'Z'}, 215 {NULL, no_argument, NULL, 0} 216}; 217 218/* 219 * Adds a searching pattern to the internal array. 220 */ 221static void 222add_pattern(char *pat, size_t len) 223{ 224 225 /* Check if we can do a shortcut */ 226 if (len == 0 || matchall) { 227 matchall = true; 228 return; 229 } 230 /* Increase size if necessary */ 231 if (patterns == pattern_sz) { 232 pattern_sz *= 2; 233 pattern = grep_realloc(pattern, ++pattern_sz * 234 sizeof(*pattern)); 235 } 236 if (len > 0 && pat[len - 1] == '\n') 237 --len; 238 /* pat may not be NUL-terminated */ 239 pattern[patterns] = grep_malloc(len + 1); 240 strlcpy(pattern[patterns], pat, len + 1); 241 ++patterns; 242} 243 244/* 245 * Adds a file include/exclude pattern to the internal array. 246 */ 247static void 248add_fpattern(const char *pat, int mode) 249{ 250 251 /* Increase size if necessary */ 252 if (fpatterns == fpattern_sz) { 253 fpattern_sz *= 2; 254 fpattern = grep_realloc(fpattern, ++fpattern_sz * 255 sizeof(struct epat)); 256 } 257 fpattern[fpatterns].pat = grep_strdup(pat); 258 fpattern[fpatterns].mode = mode; 259 ++fpatterns; 260} 261 262/* 263 * Adds a directory include/exclude pattern to the internal array. 264 */ 265static void 266add_dpattern(const char *pat, int mode) 267{ 268 269 /* Increase size if necessary */ 270 if (dpatterns == dpattern_sz) { 271 dpattern_sz *= 2; 272 dpattern = grep_realloc(dpattern, ++dpattern_sz * 273 sizeof(struct epat)); 274 } 275 dpattern[dpatterns].pat = grep_strdup(pat); 276 dpattern[dpatterns].mode = mode; 277 ++dpatterns; 278} 279 280/* 281 * Reads searching patterns from a file and adds them with add_pattern(). 282 */ 283static void 284read_patterns(const char *fn) 285{ 286 FILE *f; 287 char *line; 288 size_t len; 289 290 if ((f = fopen(fn, "r")) == NULL) 291 err(2, "%s", fn); 292 while ((line = fgetln(f, &len)) != NULL) 293 add_pattern(line, *line == '\n' ? 0 : len); 294 if (ferror(f)) 295 err(2, "%s", fn); 296 fclose(f); 297} 298 299static inline const char * 300init_color(const char *d) 301{ 302 char *c; 303 304 c = getenv("GREP_COLOR"); 305 return (c != NULL ? c : d); 306} 307 308int 309main(int argc, char *argv[]) 310{ 311 char **aargv, **eargv, *eopts; 312 char *ep; 313 unsigned long long l; 314 unsigned int aargc, eargc, i; 315 int c, lastc, needpattern, newarg, prevoptind; 316 317 setlocale(LC_ALL, ""); 318 319#ifndef WITHOUT_NLS 320 catalog = catopen("grep", NL_CAT_LOCALE); 321#endif 322 323 /* Check what is the program name of the binary. In this 324 way we can have all the funcionalities in one binary 325 without the need of scripting and using ugly hacks. */ 326 switch (__progname[0]) { 327 case 'e': 328 grepbehave = GREP_EXTENDED; 329 break; 330 case 'f': 331 grepbehave = GREP_FIXED; 332 break; 333 case 'g': 334 grepbehave = GREP_BASIC; 335 break; 336 case 'z': 337 filebehave = FILE_GZIP; 338 switch(__progname[1]) { 339 case 'e': 340 grepbehave = GREP_EXTENDED; 341 break; 342 case 'f': 343 grepbehave = GREP_FIXED; 344 break; 345 case 'g': 346 grepbehave = GREP_BASIC; 347 break; 348 } 349 break; 350 } 351 352 lastc = '\0'; 353 newarg = 1; 354 prevoptind = 1; 355 needpattern = 1; 356 357 eopts = getenv("GREP_OPTIONS"); 358 359 eargc = 1; 360 if (eopts != NULL) { 361 char *str; 362 363 for(i = 0; i < strlen(eopts); i++) 364 if (eopts[i] == ' ') 365 eargc++; 366 367 eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1)); 368 369 str = strtok(eopts, " "); 370 eargc = 0; 371 372 while(str != NULL) { 373 eargv[++eargc] = (char *)grep_malloc(sizeof(char) * 374 (strlen(str) + 1)); 375 strlcpy(eargv[eargc], str, strlen(str) + 1); 376 str = strtok(NULL, " "); 377 } 378 eargv[++eargc] = NULL; 379 380 aargv = (char **)grep_calloc(eargc + argc + 1, 381 sizeof(char *)); 382 aargv[0] = argv[0]; 383 384 for(i = 1; i < eargc; i++) 385 aargv[i] = eargv[i]; 386 for(int j = 1; j < argc; j++) 387 aargv[i++] = argv[j]; 388 389 aargc = eargc + argc - 1; 390 391 } else { 392 aargv = argv; 393 aargc = argc; 394 } 395 396 while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) != 397 -1)) { 398 switch (c) { 399 case '0': case '1': case '2': case '3': case '4': 400 case '5': case '6': case '7': case '8': case '9': 401 if (newarg || !isdigit(lastc)) 402 Aflag = 0; 403 else if (Aflag > LLONG_MAX / 10) { 404 errno = ERANGE; 405 err(2, NULL); 406 } 407 Aflag = Bflag = (Aflag * 10) + (c - '0'); 408 break; 409 case 'C': 410 if (optarg == NULL) { 411 Aflag = Bflag = 2; 412 break; 413 } 414 /* FALLTHROUGH */ 415 case 'A': 416 /* FALLTHROUGH */ 417 case 'B': 418 errno = 0; 419 l = strtoull(optarg, &ep, 10); 420 if (((errno == ERANGE) && (l == ULLONG_MAX)) || 421 ((errno == EINVAL) && (l == 0))) 422 err(2, NULL); 423 else if (ep[0] != '\0') { 424 errno = EINVAL; 425 err(2, NULL); 426 } 427 if (c == 'A') 428 Aflag = l; 429 else if (c == 'B') 430 Bflag = l; 431 else 432 Aflag = Bflag = l; 433 break; 434 case 'a': 435 binbehave = BINFILE_TEXT; 436 break; 437 case 'b': 438 bflag = true; 439 break; 440 case 'c': 441 cflag = true; 442 break; 443 case 'D': 444 if (strcasecmp(optarg, "skip") == 0) 445 devbehave = DEV_SKIP; 446 else if (strcasecmp(optarg, "read") == 0) 447 devbehave = DEV_READ;
| 71}; 72 73/* Flags passed to regcomp() and regexec() */ 74int cflags = 0; 75int eflags = REG_STARTEND; 76 77/* Shortcut for matching all cases like empty regex */ 78bool matchall; 79 80/* Searching patterns */ 81unsigned int patterns, pattern_sz; 82char **pattern; 83regex_t *r_pattern; 84fastgrep_t *fg_pattern; 85 86/* Filename exclusion/inclusion patterns */ 87unsigned int fpatterns, fpattern_sz; 88unsigned int dpatterns, dpattern_sz; 89struct epat *dpattern, *fpattern; 90 91/* For regex errors */ 92char re_error[RE_ERROR_BUF + 1]; 93 94/* Command-line flags */ 95unsigned long long Aflag; /* -A x: print x lines trailing each match */ 96unsigned long long Bflag; /* -B x: print x lines leading each match */ 97bool Hflag; /* -H: always print file name */ 98bool Lflag; /* -L: only show names of files with no matches */ 99bool bflag; /* -b: show block numbers for each match */ 100bool cflag; /* -c: only show a count of matching lines */ 101bool hflag; /* -h: don't print filename headers */ 102bool iflag; /* -i: ignore case */ 103bool lflag; /* -l: only show names of files with matches */ 104bool mflag; /* -m x: stop reading the files after x matches */ 105unsigned long long mcount; /* count for -m */ 106bool nflag; /* -n: show line numbers in front of matching lines */ 107bool oflag; /* -o: print only matching part */ 108bool qflag; /* -q: quiet mode (don't output anything) */ 109bool sflag; /* -s: silent mode (ignore errors) */ 110bool vflag; /* -v: only show non-matching lines */ 111bool wflag; /* -w: pattern must start and end on word boundaries */ 112bool xflag; /* -x: pattern must match entire line */ 113bool lbflag; /* --line-buffered */ 114bool nullflag; /* --null */ 115char *label; /* --label */ 116const char *color; /* --color */ 117int grepbehave = GREP_BASIC; /* -EFGP: type of the regex */ 118int binbehave = BINFILE_BIN; /* -aIU: handling of binary files */ 119int filebehave = FILE_STDIO; /* -JZ: normal, gzip or bzip2 file */ 120int devbehave = DEV_READ; /* -D: handling of devices */ 121int dirbehave = DIR_READ; /* -dRr: handling of directories */ 122int linkbehave = LINK_READ; /* -OpS: handling of symlinks */ 123 124bool dexclude, dinclude; /* --exclude amd --include */ 125bool fexclude, finclude; /* --exclude-dir and --include-dir */ 126 127enum { 128 BIN_OPT = CHAR_MAX + 1, 129 COLOR_OPT, 130 HELP_OPT, 131 MMAP_OPT, 132 LINEBUF_OPT, 133 LABEL_OPT, 134 NULL_OPT, 135 R_EXCLUDE_OPT, 136 R_INCLUDE_OPT, 137 R_DEXCLUDE_OPT, 138 R_DINCLUDE_OPT 139}; 140 141static inline const char *init_color(const char *); 142 143/* Housekeeping */ 144bool first = true; /* flag whether we are processing the first match */ 145bool prev; /* flag whether or not the previous line matched */ 146int tail; /* lines left to print */ 147bool notfound; /* file not found */ 148 149extern char *__progname; 150 151/* 152 * Prints usage information and returns 2. 153 */ 154static void 155usage(void) 156{ 157 fprintf(stderr, getstr(4), __progname); 158 fprintf(stderr, "%s", getstr(5)); 159 fprintf(stderr, "%s", getstr(5)); 160 fprintf(stderr, "%s", getstr(6)); 161 fprintf(stderr, "%s", getstr(7)); 162 exit(2); 163} 164 165static const char *optstr = "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxy"; 166 167struct option long_options[] = 168{ 169 {"binary-files", required_argument, NULL, BIN_OPT}, 170 {"help", no_argument, NULL, HELP_OPT}, 171 {"mmap", no_argument, NULL, MMAP_OPT}, 172 {"line-buffered", no_argument, NULL, LINEBUF_OPT}, 173 {"label", required_argument, NULL, LABEL_OPT}, 174 {"null", no_argument, NULL, NULL_OPT}, 175 {"color", optional_argument, NULL, COLOR_OPT}, 176 {"colour", optional_argument, NULL, COLOR_OPT}, 177 {"exclude", required_argument, NULL, R_EXCLUDE_OPT}, 178 {"include", required_argument, NULL, R_INCLUDE_OPT}, 179 {"exclude-dir", required_argument, NULL, R_DEXCLUDE_OPT}, 180 {"include-dir", required_argument, NULL, R_DINCLUDE_OPT}, 181 {"after-context", required_argument, NULL, 'A'}, 182 {"text", no_argument, NULL, 'a'}, 183 {"before-context", required_argument, NULL, 'B'}, 184 {"byte-offset", no_argument, NULL, 'b'}, 185 {"context", optional_argument, NULL, 'C'}, 186 {"count", no_argument, NULL, 'c'}, 187 {"devices", required_argument, NULL, 'D'}, 188 {"directories", required_argument, NULL, 'd'}, 189 {"extended-regexp", no_argument, NULL, 'E'}, 190 {"regexp", required_argument, NULL, 'e'}, 191 {"fixed-strings", no_argument, NULL, 'F'}, 192 {"file", required_argument, NULL, 'f'}, 193 {"basic-regexp", no_argument, NULL, 'G'}, 194 {"no-filename", no_argument, NULL, 'h'}, 195 {"with-filename", no_argument, NULL, 'H'}, 196 {"ignore-case", no_argument, NULL, 'i'}, 197 {"bz2decompress", no_argument, NULL, 'J'}, 198 {"files-with-matches", no_argument, NULL, 'l'}, 199 {"files-without-match", no_argument, NULL, 'L'}, 200 {"max-count", required_argument, NULL, 'm'}, 201 {"line-number", no_argument, NULL, 'n'}, 202 {"only-matching", no_argument, NULL, 'o'}, 203 {"quiet", no_argument, NULL, 'q'}, 204 {"silent", no_argument, NULL, 'q'}, 205 {"recursive", no_argument, NULL, 'r'}, 206 {"no-messages", no_argument, NULL, 's'}, 207 {"binary", no_argument, NULL, 'U'}, 208 {"unix-byte-offsets", no_argument, NULL, 'u'}, 209 {"invert-match", no_argument, NULL, 'v'}, 210 {"version", no_argument, NULL, 'V'}, 211 {"word-regexp", no_argument, NULL, 'w'}, 212 {"line-regexp", no_argument, NULL, 'x'}, 213 {"decompress", no_argument, NULL, 'Z'}, 214 {NULL, no_argument, NULL, 0} 215}; 216 217/* 218 * Adds a searching pattern to the internal array. 219 */ 220static void 221add_pattern(char *pat, size_t len) 222{ 223 224 /* Check if we can do a shortcut */ 225 if (len == 0 || matchall) { 226 matchall = true; 227 return; 228 } 229 /* Increase size if necessary */ 230 if (patterns == pattern_sz) { 231 pattern_sz *= 2; 232 pattern = grep_realloc(pattern, ++pattern_sz * 233 sizeof(*pattern)); 234 } 235 if (len > 0 && pat[len - 1] == '\n') 236 --len; 237 /* pat may not be NUL-terminated */ 238 pattern[patterns] = grep_malloc(len + 1); 239 strlcpy(pattern[patterns], pat, len + 1); 240 ++patterns; 241} 242 243/* 244 * Adds a file include/exclude pattern to the internal array. 245 */ 246static void 247add_fpattern(const char *pat, int mode) 248{ 249 250 /* Increase size if necessary */ 251 if (fpatterns == fpattern_sz) { 252 fpattern_sz *= 2; 253 fpattern = grep_realloc(fpattern, ++fpattern_sz * 254 sizeof(struct epat)); 255 } 256 fpattern[fpatterns].pat = grep_strdup(pat); 257 fpattern[fpatterns].mode = mode; 258 ++fpatterns; 259} 260 261/* 262 * Adds a directory include/exclude pattern to the internal array. 263 */ 264static void 265add_dpattern(const char *pat, int mode) 266{ 267 268 /* Increase size if necessary */ 269 if (dpatterns == dpattern_sz) { 270 dpattern_sz *= 2; 271 dpattern = grep_realloc(dpattern, ++dpattern_sz * 272 sizeof(struct epat)); 273 } 274 dpattern[dpatterns].pat = grep_strdup(pat); 275 dpattern[dpatterns].mode = mode; 276 ++dpatterns; 277} 278 279/* 280 * Reads searching patterns from a file and adds them with add_pattern(). 281 */ 282static void 283read_patterns(const char *fn) 284{ 285 FILE *f; 286 char *line; 287 size_t len; 288 289 if ((f = fopen(fn, "r")) == NULL) 290 err(2, "%s", fn); 291 while ((line = fgetln(f, &len)) != NULL) 292 add_pattern(line, *line == '\n' ? 0 : len); 293 if (ferror(f)) 294 err(2, "%s", fn); 295 fclose(f); 296} 297 298static inline const char * 299init_color(const char *d) 300{ 301 char *c; 302 303 c = getenv("GREP_COLOR"); 304 return (c != NULL ? c : d); 305} 306 307int 308main(int argc, char *argv[]) 309{ 310 char **aargv, **eargv, *eopts; 311 char *ep; 312 unsigned long long l; 313 unsigned int aargc, eargc, i; 314 int c, lastc, needpattern, newarg, prevoptind; 315 316 setlocale(LC_ALL, ""); 317 318#ifndef WITHOUT_NLS 319 catalog = catopen("grep", NL_CAT_LOCALE); 320#endif 321 322 /* Check what is the program name of the binary. In this 323 way we can have all the funcionalities in one binary 324 without the need of scripting and using ugly hacks. */ 325 switch (__progname[0]) { 326 case 'e': 327 grepbehave = GREP_EXTENDED; 328 break; 329 case 'f': 330 grepbehave = GREP_FIXED; 331 break; 332 case 'g': 333 grepbehave = GREP_BASIC; 334 break; 335 case 'z': 336 filebehave = FILE_GZIP; 337 switch(__progname[1]) { 338 case 'e': 339 grepbehave = GREP_EXTENDED; 340 break; 341 case 'f': 342 grepbehave = GREP_FIXED; 343 break; 344 case 'g': 345 grepbehave = GREP_BASIC; 346 break; 347 } 348 break; 349 } 350 351 lastc = '\0'; 352 newarg = 1; 353 prevoptind = 1; 354 needpattern = 1; 355 356 eopts = getenv("GREP_OPTIONS"); 357 358 eargc = 1; 359 if (eopts != NULL) { 360 char *str; 361 362 for(i = 0; i < strlen(eopts); i++) 363 if (eopts[i] == ' ') 364 eargc++; 365 366 eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1)); 367 368 str = strtok(eopts, " "); 369 eargc = 0; 370 371 while(str != NULL) { 372 eargv[++eargc] = (char *)grep_malloc(sizeof(char) * 373 (strlen(str) + 1)); 374 strlcpy(eargv[eargc], str, strlen(str) + 1); 375 str = strtok(NULL, " "); 376 } 377 eargv[++eargc] = NULL; 378 379 aargv = (char **)grep_calloc(eargc + argc + 1, 380 sizeof(char *)); 381 aargv[0] = argv[0]; 382 383 for(i = 1; i < eargc; i++) 384 aargv[i] = eargv[i]; 385 for(int j = 1; j < argc; j++) 386 aargv[i++] = argv[j]; 387 388 aargc = eargc + argc - 1; 389 390 } else { 391 aargv = argv; 392 aargc = argc; 393 } 394 395 while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) != 396 -1)) { 397 switch (c) { 398 case '0': case '1': case '2': case '3': case '4': 399 case '5': case '6': case '7': case '8': case '9': 400 if (newarg || !isdigit(lastc)) 401 Aflag = 0; 402 else if (Aflag > LLONG_MAX / 10) { 403 errno = ERANGE; 404 err(2, NULL); 405 } 406 Aflag = Bflag = (Aflag * 10) + (c - '0'); 407 break; 408 case 'C': 409 if (optarg == NULL) { 410 Aflag = Bflag = 2; 411 break; 412 } 413 /* FALLTHROUGH */ 414 case 'A': 415 /* FALLTHROUGH */ 416 case 'B': 417 errno = 0; 418 l = strtoull(optarg, &ep, 10); 419 if (((errno == ERANGE) && (l == ULLONG_MAX)) || 420 ((errno == EINVAL) && (l == 0))) 421 err(2, NULL); 422 else if (ep[0] != '\0') { 423 errno = EINVAL; 424 err(2, NULL); 425 } 426 if (c == 'A') 427 Aflag = l; 428 else if (c == 'B') 429 Bflag = l; 430 else 431 Aflag = Bflag = l; 432 break; 433 case 'a': 434 binbehave = BINFILE_TEXT; 435 break; 436 case 'b': 437 bflag = true; 438 break; 439 case 'c': 440 cflag = true; 441 break; 442 case 'D': 443 if (strcasecmp(optarg, "skip") == 0) 444 devbehave = DEV_SKIP; 445 else if (strcasecmp(optarg, "read") == 0) 446 devbehave = DEV_READ;
|