whereis.c (ad23c583180ae290bdfdf121707c1b6b9bca1095) | whereis.c (1f05bc6c92b037a24315c8408aab875bbd6453b8) |
---|---|
1/* 2 * Copyright � 2002, J�rg Wunsch 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 35 unchanged lines hidden (view full) --- 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <sysexits.h> 48#include <unistd.h> 49 50#include "pathnames.h" 51 | 1/* 2 * Copyright � 2002, J�rg Wunsch 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 35 unchanged lines hidden (view full) --- 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <sysexits.h> 48#include <unistd.h> 49 50#include "pathnames.h" 51 |
52#define NO_BIN_FOUND 1 53#define NO_MAN_FOUND 2 54#define NO_SRC_FOUND 4 55 |
|
52typedef const char *ccharp; 53 | 56typedef const char *ccharp; 57 |
54int opt_b, opt_m, opt_q, opt_s, opt_u, opt_x; | 58int opt_a, opt_b, opt_m, opt_q, opt_s, opt_u, opt_x; |
55ccharp *bindirs, *mandirs, *sourcedirs; 56char **query; 57 58const char *sourcepath = PATH_SOURCES; 59 60char *colonify(ccharp *); 61int contains(ccharp *, const char *); 62void decolonify(char *, ccharp **, int *); --- 16 unchanged lines hidden (view full) --- 79 * a virtual memory environment), thus we simply bail out using 80 * abort(3) in case of an allocation failure. 81 */ 82 83void 84usage(void) 85{ 86 errx(EX_USAGE, | 59ccharp *bindirs, *mandirs, *sourcedirs; 60char **query; 61 62const char *sourcepath = PATH_SOURCES; 63 64char *colonify(ccharp *); 65int contains(ccharp *, const char *); 66void decolonify(char *, ccharp **, int *); --- 16 unchanged lines hidden (view full) --- 83 * a virtual memory environment), thus we simply bail out using 84 * abort(3) in case of an allocation failure. 85 */ 86 87void 88usage(void) 89{ 90 errx(EX_USAGE, |
87 "usage: whereis [-bmqsux] [-BMS dir... -f] name ..."); | 91 "usage: whereis [-abmqsux] [-BMS dir... -f] name ..."); |
88} 89 90/* 91 * Scan options passed to program. 92 * 93 * Note that the -B/-M/-S options expect a list of directory 94 * names that must be terminated with -f. 95 */ 96void 97scanopts(int argc, char **argv) 98{ 99 int c, i, opt_f; 100 ccharp **dirlist; 101 102 opt_f = 0; | 92} 93 94/* 95 * Scan options passed to program. 96 * 97 * Note that the -B/-M/-S options expect a list of directory 98 * names that must be terminated with -f. 99 */ 100void 101scanopts(int argc, char **argv) 102{ 103 int c, i, opt_f; 104 ccharp **dirlist; 105 106 opt_f = 0; |
103 while ((c = getopt(argc, argv, "BMSbfmqsux")) != -1) | 107 while ((c = getopt(argc, argv, "BMSabfmqsux")) != -1) |
104 switch (c) { 105 case 'B': 106 dirlist = &bindirs; 107 goto dolist; 108 109 case 'M': 110 dirlist = &mandirs; 111 goto dolist; --- 9 unchanged lines hidden (view full) --- 121 strcmp(argv[optind], "-B") != 0 && 122 strcmp(argv[optind], "-M") != 0 && 123 strcmp(argv[optind], "-S") != 0) { 124 decolonify(argv[optind], dirlist, &i); 125 optind++; 126 } 127 break; 128 | 108 switch (c) { 109 case 'B': 110 dirlist = &bindirs; 111 goto dolist; 112 113 case 'M': 114 dirlist = &mandirs; 115 goto dolist; --- 9 unchanged lines hidden (view full) --- 125 strcmp(argv[optind], "-B") != 0 && 126 strcmp(argv[optind], "-M") != 0 && 127 strcmp(argv[optind], "-S") != 0) { 128 decolonify(argv[optind], dirlist, &i); 129 optind++; 130 } 131 break; 132 |
133 case 'a': 134 opt_a = 1; 135 break; 136 |
|
129 case 'b': 130 opt_b = 1; 131 break; 132 133 case 'f': 134 goto breakout; 135 136 case 'm': --- 211 unchanged lines hidden (view full) --- 348} 349 350int 351main(int argc, char **argv) 352{ 353 int unusual, i, printed; 354 char *bin, buf[BUFSIZ], *cp, *cp2, *man, *name, *src; 355 ccharp *dp; | 137 case 'b': 138 opt_b = 1; 139 break; 140 141 case 'f': 142 goto breakout; 143 144 case 'm': --- 211 unchanged lines hidden (view full) --- 356} 357 358int 359main(int argc, char **argv) 360{ 361 int unusual, i, printed; 362 char *bin, buf[BUFSIZ], *cp, *cp2, *man, *name, *src; 363 ccharp *dp; |
356 size_t s; | 364 size_t nlen, olen, s; |
357 struct stat sb; 358 regex_t re, re2; 359 regmatch_t matches[2]; 360 regoff_t rlen; 361 FILE *p; 362 363 scanopts(argc, argv); 364 defaults(); --- 42 unchanged lines hidden (view full) --- 407 bin = man = src = NULL; 408 s = strlen(name); 409 410 if (opt_b) { 411 /* 412 * Binaries have to match exactly, and must be regular 413 * executable files. 414 */ | 365 struct stat sb; 366 regex_t re, re2; 367 regmatch_t matches[2]; 368 regoff_t rlen; 369 FILE *p; 370 371 scanopts(argc, argv); 372 defaults(); --- 42 unchanged lines hidden (view full) --- 415 bin = man = src = NULL; 416 s = strlen(name); 417 418 if (opt_b) { 419 /* 420 * Binaries have to match exactly, and must be regular 421 * executable files. 422 */ |
415 unusual++; | 423 unusual = unusual | NO_BIN_FOUND; |
416 for (dp = bindirs; *dp != NULL; dp++) { 417 cp = malloc(strlen(*dp) + 1 + s + 1); 418 if (cp == NULL) 419 abort(); 420 strcpy(cp, *dp); 421 strcat(cp, "/"); 422 strcat(cp, name); 423 if (stat(cp, &sb) == 0 && 424 (sb.st_mode & S_IFMT) == S_IFREG && 425 (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) 426 != 0) { | 424 for (dp = bindirs; *dp != NULL; dp++) { 425 cp = malloc(strlen(*dp) + 1 + s + 1); 426 if (cp == NULL) 427 abort(); 428 strcpy(cp, *dp); 429 strcat(cp, "/"); 430 strcat(cp, name); 431 if (stat(cp, &sb) == 0 && 432 (sb.st_mode & S_IFMT) == S_IFREG && 433 (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) 434 != 0) { |
427 unusual--; 428 bin = cp; 429 break; | 435 unusual = unusual & ~NO_BIN_FOUND; 436 if (bin == NULL) { 437 bin = strdup(cp); 438 } else { 439 olen = strlen(bin); 440 nlen = strlen(cp); 441 bin = realloc(bin, 442 olen + nlen + 2); 443 if (bin == 0) 444 abort(); 445 strcat(bin, " "); 446 strcat(bin, cp); 447 } 448 if (!opt_a) { 449 free(cp); 450 break; 451 } |
430 } 431 free(cp); 432 } 433 } 434 435 if (opt_m) { 436 /* 437 * Ask the man command to perform the search for us. 438 */ | 452 } 453 free(cp); 454 } 455 } 456 457 if (opt_m) { 458 /* 459 * Ask the man command to perform the search for us. 460 */ |
439 unusual++; 440 cp = malloc(sizeof MANWHEREISCMD - 2 + s); | 461 unusual = unusual | NO_MAN_FOUND; 462 if (opt_a) 463 cp = malloc(sizeof MANWHEREISALLCMD - 2 + s); 464 else 465 cp = malloc(sizeof MANWHEREISCMD - 2 + s); 466 |
441 if (cp == NULL) 442 abort(); | 467 if (cp == NULL) 468 abort(); |
443 sprintf(cp, MANWHEREISCMD, name); 444 if ((p = popen(cp, "r")) != NULL && 445 fgets(buf, BUFSIZ - 1, p) != NULL && 446 pclose(p) == 0) { 447 unusual--; 448 if ((cp2 = strchr(buf, '\n')) != NULL) 449 *cp2 = '\0'; 450 if (regexec(&re, buf, 2, matches, 0) == 0 && 451 (rlen = matches[1].rm_eo - matches[1].rm_so) 452 > 0) { 453 /* 454 * man -w found compressed 455 * page, need to pick up 456 * source page name. 457 */ 458 cp2 = malloc(rlen + 1); 459 if (cp2 == NULL) 460 abort(); 461 memcpy(cp2, buf + matches[1].rm_so, 462 rlen); 463 cp2[rlen] = '\0'; 464 man = cp2; 465 } else { 466 /* 467 * man -w found plain source 468 * page, use it. 469 */ 470 s = strlen(buf); 471 cp2 = malloc(s + 1); 472 if (cp2 == NULL) 473 abort(); 474 strcpy(cp2, buf); 475 man = cp2; | 469 470 if (opt_a) 471 sprintf(cp, MANWHEREISALLCMD, name); 472 else 473 sprintf(cp, MANWHEREISCMD, name); 474 475 if ((p = popen(cp, "r")) != NULL) { 476 477 while (fgets(buf, BUFSIZ - 1, p) != NULL) { 478 unusual = unusual & ~NO_MAN_FOUND; 479 480 if ((cp2 = strchr(buf, '\n')) != NULL) 481 *cp2 = '\0'; 482 if (regexec(&re, buf, 2, 483 matches, 0) == 0 && 484 (rlen = matches[1].rm_eo - 485 matches[1].rm_so) > 0) { 486 /* 487 * man -w found formated 488 * page, need to pick up 489 * source page name. 490 */ 491 cp2 = malloc(rlen + 1); 492 if (cp2 == NULL) 493 abort(); 494 memcpy(cp2, 495 buf + matches[1].rm_so, 496 rlen); 497 cp2[rlen] = '\0'; 498 } else { 499 /* 500 * man -w found plain source 501 * page, use it. 502 */ 503 s = strlen(buf); 504 cp2 = malloc(s + 1); 505 if (cp2 == NULL) 506 abort(); 507 strcpy(cp2, buf); 508 } 509 510 if (man == NULL) { 511 man = strdup(cp2); 512 } else { 513 olen = strlen(man); 514 nlen = strlen(cp2); 515 man = realloc(man, 516 olen + nlen + 2); 517 if (man == 0) 518 abort(); 519 strcat(man, " "); 520 strcat(man, cp2); 521 } 522 523 free(cp2); 524 525 if (!opt_a) 526 break; |
476 } | 527 } |
528 pclose(p); 529 free(cp); |
|
477 } | 530 } |
478 free(cp); | |
479 } 480 481 if (opt_s) { 482 /* 483 * Sources match if a subdir with the exact 484 * name is found. 485 */ | 531 } 532 533 if (opt_s) { 534 /* 535 * Sources match if a subdir with the exact 536 * name is found. 537 */ |
486 unusual++; | 538 unusual = unusual | NO_SRC_FOUND; |
487 for (dp = sourcedirs; *dp != NULL; dp++) { 488 cp = malloc(strlen(*dp) + 1 + s + 1); 489 if (cp == NULL) 490 abort(); 491 strcpy(cp, *dp); 492 strcat(cp, "/"); 493 strcat(cp, name); 494 if (stat(cp, &sb) == 0 && 495 (sb.st_mode & S_IFMT) == S_IFDIR) { | 539 for (dp = sourcedirs; *dp != NULL; dp++) { 540 cp = malloc(strlen(*dp) + 1 + s + 1); 541 if (cp == NULL) 542 abort(); 543 strcpy(cp, *dp); 544 strcat(cp, "/"); 545 strcat(cp, name); 546 if (stat(cp, &sb) == 0 && 547 (sb.st_mode & S_IFMT) == S_IFDIR) { |
496 unusual--; 497 src = cp; 498 break; | 548 unusual = unusual & ~NO_SRC_FOUND; 549 if (src == NULL) { 550 src = strdup(cp); 551 } else { 552 olen = strlen(src); 553 nlen = strlen(cp); 554 src = realloc(src, 555 olen + nlen + 2); 556 if (src == 0) 557 abort(); 558 strcat(src, " "); 559 strcat(src, cp); 560 } 561 if (!opt_a) { 562 free(cp); 563 break; 564 } |
499 } 500 free(cp); 501 } 502 /* 503 * If still not found, ask locate to search it 504 * for us. This will find sources for things 505 * like lpr that are well hidden in the 506 * /usr/src tree, but takes a lot longer. 507 * Thus, option -x (`expensive') prevents this 508 * search. 509 * 510 * Do only match locate output that starts 511 * with one of our source directories, and at 512 * least one further level of subdirectories. 513 */ | 565 } 566 free(cp); 567 } 568 /* 569 * If still not found, ask locate to search it 570 * for us. This will find sources for things 571 * like lpr that are well hidden in the 572 * /usr/src tree, but takes a lot longer. 573 * Thus, option -x (`expensive') prevents this 574 * search. 575 * 576 * Do only match locate output that starts 577 * with one of our source directories, and at 578 * least one further level of subdirectories. 579 */ |
514 if (opt_x || src) | 580 if (opt_x || (src && !opt_a)) |
515 goto done_sources; 516 517 cp = malloc(sizeof LOCATECMD - 2 + s); 518 if (cp == NULL) 519 abort(); 520 sprintf(cp, LOCATECMD, name); 521 if ((p = popen(cp, "r")) == NULL) 522 goto done_sources; | 581 goto done_sources; 582 583 cp = malloc(sizeof LOCATECMD - 2 + s); 584 if (cp == NULL) 585 abort(); 586 sprintf(cp, LOCATECMD, name); 587 if ((p = popen(cp, "r")) == NULL) 588 goto done_sources; |
523 while (src == NULL && | 589 while ((src == NULL || opt_a) && |
524 (fgets(buf, BUFSIZ - 1, p)) != NULL) { 525 if ((cp2 = strchr(buf, '\n')) != NULL) 526 *cp2 = '\0'; 527 for (dp = sourcedirs; | 590 (fgets(buf, BUFSIZ - 1, p)) != NULL) { 591 if ((cp2 = strchr(buf, '\n')) != NULL) 592 *cp2 = '\0'; 593 for (dp = sourcedirs; |
528 src == NULL && *dp != NULL; | 594 (src == NULL || opt_a) && *dp != NULL; |
529 dp++) { 530 cp2 = malloc(strlen(*dp) + 9); 531 if (cp2 == NULL) 532 abort(); 533 strcpy(cp2, "^"); 534 strcat(cp2, *dp); 535 strcat(cp2, "/[^/]+/"); 536 if ((i = regcomp(&re2, cp2, --- 4 unchanged lines hidden (view full) --- 541 errx(EX_UNAVAILABLE, 542 "regcomp(%s) failed: %s", 543 cp2, buf); 544 } 545 free(cp2); 546 if (regexec(&re2, buf, 0, 547 (regmatch_t *)NULL, 0) 548 == 0) { | 595 dp++) { 596 cp2 = malloc(strlen(*dp) + 9); 597 if (cp2 == NULL) 598 abort(); 599 strcpy(cp2, "^"); 600 strcat(cp2, *dp); 601 strcat(cp2, "/[^/]+/"); 602 if ((i = regcomp(&re2, cp2, --- 4 unchanged lines hidden (view full) --- 607 errx(EX_UNAVAILABLE, 608 "regcomp(%s) failed: %s", 609 cp2, buf); 610 } 611 free(cp2); 612 if (regexec(&re2, buf, 0, 613 (regmatch_t *)NULL, 0) 614 == 0) { |
549 unusual--; 550 src = buf; | 615 unusual = unusual & 616 ~NO_SRC_FOUND; 617 if (src == NULL) { 618 src = strdup(buf); 619 } else { 620 olen = strlen(src); 621 nlen = strlen(buf); 622 src = realloc(src, 623 olen + 624 nlen + 2); 625 if (src == 0) 626 abort(); 627 strcat(src, " "); 628 strcat(src, buf); 629 } |
551 } 552 regfree(&re2); 553 } 554 } 555 pclose(p); 556 free(cp); 557 } 558 done_sources: --- 33 unchanged lines hidden --- | 630 } 631 regfree(&re2); 632 } 633 } 634 pclose(p); 635 free(cp); 636 } 637 done_sources: --- 33 unchanged lines hidden --- |