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 ---