1#! /bin/sh 2# 3# Copyright (c) 2010 Gordon Tetlow 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27# $FreeBSD$ 28 29# Usage: add_to_manpath path 30# Adds a variable to manpath while ensuring we don't have duplicates. 31# Returns true if we were able to add something. False otherwise. 32add_to_manpath() { 33 case "$manpath" in 34 *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 35 $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 36 *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 37 *) if [ -d "$1" ]; then 38 decho " Adding $1 to manpath" 39 manpath="$manpath:$1" 40 return 0 41 fi 42 ;; 43 esac 44 45 return 1 46} 47 48# Usage: build_manlocales 49# Builds a correct MANLOCALES variable. 50build_manlocales() { 51 # If the user has set manlocales, who are we to argue. 52 if [ -n "$MANLOCALES" ]; then 53 return 54 fi 55 56 parse_configs 57 58 # Trim leading colon 59 MANLOCALES=${manlocales#:} 60 61 decho "Available manual locales: $MANLOCALES" 62} 63 64# Usage: build_manpath 65# Builds a correct MANPATH variable. 66build_manpath() { 67 local IFS 68 69 # If the user has set a manpath, who are we to argue. 70 if [ -n "$MANPATH" ]; then 71 return 72 fi 73 74 search_path 75 76 decho "Adding default manpath entries" 77 IFS=: 78 for path in $man_default_path; do 79 add_to_manpath "$path" 80 done 81 unset IFS 82 83 parse_configs 84 85 # Trim leading colon 86 MANPATH=${manpath#:} 87 88 decho "Using manual path: $MANPATH" 89} 90 91# Usage: check_cat catglob 92# Checks to see if a cat glob is available. 93check_cat() { 94 if exists "$1"; then 95 use_cat=yes 96 catpage=$found 97 setup_cattool $catpage 98 decho " Found catpage $catpage" 99 return 0 100 else 101 return 1 102 fi 103} 104 105# Usage: check_man manglob catglob 106# Given 2 globs, figures out if the manglob is available, if so, check to 107# see if the catglob is also available and up to date. 108check_man() { 109 if exists "$1"; then 110 # We have a match, check for a cat page 111 manpage=$found 112 setup_cattool $manpage 113 decho " Found manpage $manpage" 114 115 if exists "$2" && is_newer $found $manpage; then 116 # cat page found and is newer, use that 117 use_cat=yes 118 catpage=$found 119 setup_cattool $catpage 120 decho " Using catpage $catpage" 121 else 122 # no cat page or is older 123 unset use_cat 124 decho " Skipping catpage: not found or old" 125 fi 126 return 0 127 fi 128 129 return 1 130} 131 132# Usage: decho "string" [debuglevel] 133# Echoes to stderr string prefaced with -- if high enough debuglevel. 134decho() { 135 if [ $debug -ge ${2:-1} ]; then 136 echo "-- $1" >&2 137 fi 138} 139 140# Usage: exists glob 141# Returns true if glob resolves to a real file. 142exists() { 143 local IFS 144 145 # Don't accidentally inherit callers IFS (breaks perl manpages) 146 unset IFS 147 148 # Use some globbing tricks in the shell to determine if a file 149 # exists or not. 150 set +f 151 set -- "$1" $1 152 set -f 153 154 if [ "$1" != "$2" -a -r "$2" ]; then 155 found="$2" 156 return 0 157 fi 158 159 return 1 160} 161 162# Usage: find_file path section subdir pagename 163# Returns: true if something is matched and found. 164# Search the given path/section combo for a given page. 165find_file() { 166 local manroot catroot mann man0 catn cat0 167 168 manroot="$1/man$2" 169 catroot="$1/cat$2" 170 if [ -n "$3" ]; then 171 manroot="$manroot/$3" 172 catroot="$catroot/$3" 173 fi 174 175 if [ ! -d "$manroot" ]; then 176 return 1 177 fi 178 decho " Searching directory $manroot" 2 179 180 mann="$manroot/$4.$2*" 181 man0="$manroot/$4.0*" 182 catn="$catroot/$4.$2*" 183 cat0="$catroot/$4.0*" 184 185 # This is the behavior as seen by the original man utility. 186 # Let's not change that which doesn't seem broken. 187 if check_man "$mann" "$catn"; then 188 return 0 189 elif check_man "$man0" "$cat0"; then 190 return 0 191 elif check_cat "$catn"; then 192 return 0 193 elif check_cat "$cat0"; then 194 return 0 195 fi 196 197 return 1 198} 199 200# Usage: is_newer file1 file2 201# Returns true if file1 is newer than file2 as calculated by mtime. 202is_newer() { 203 if ! [ "$1" -ot "$2" ]; then 204 decho " mtime: $1 not older than $2" 3 205 return 0 206 else 207 decho " mtime: $1 older than $2" 3 208 return 1 209 fi 210} 211 212# Usage: manpath_parse_args "$@" 213# Parses commandline options for manpath. 214manpath_parse_args() { 215 local cmd_arg 216 217 while getopts 'Ldq' cmd_arg; do 218 case "${cmd_arg}" in 219 L) Lflag=Lflag ;; 220 d) debug=$(( $debug + 1 )) ;; 221 q) qflag=qflag ;; 222 *) manpath_usage ;; 223 esac 224 done >&2 225} 226 227# Usage: manpath_usage 228# Display usage for the manpath(1) utility. 229manpath_usage() { 230 echo 'usage: manpath [-Ldq]' >&2 231 exit 1 232} 233 234# Usage: manpath_warnings 235# Display some warnings to stderr. 236manpath_warnings() { 237 if [ -z "$Lflag" -a -n "$MANPATH" ]; then 238 echo "(Warning: MANPATH environment variable set)" >&2 239 fi 240 241 if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 242 echo "(Warning: MANLOCALES environment variable set)" >&2 243 fi 244} 245 246# Usage: man_check_for_so page path 247# Returns: True if able to resolve the file, false if it ended in tears. 248# Detects the presence of the .so directive and causes the file to be 249# redirected to another source file. 250man_check_for_so() { 251 local IFS line tstr 252 253 unset IFS 254 255 # We need to loop to accommodate multiple .so directives. 256 while true 257 do 258 line=$($cattool $manpage | head -1) 259 case "$line" in 260 .so*) trim "${line#.so}" 261 decho "$manpage includes $tstr" 262 # Glob and check for the file. 263 if ! check_man "$path/$tstr*" ""; then 264 decho " Unable to find $tstr" 265 return 1 266 fi 267 ;; 268 *) break ;; 269 esac 270 done 271 272 return 0 273} 274 275# Usage: man_display_page 276# Display either the manpage or catpage depending on the use_cat variable 277man_display_page() { 278 local EQN COL NROFF PIC TBL TROFF REFER VGRIND 279 local IFS l nroff_dev pipeline preproc_arg tool 280 281 # We are called with IFS set to colon. This causes really weird 282 # things to happen for the variables that have spaces in them. 283 unset IFS 284 285 # If we are supposed to use a catpage and we aren't using troff(1) 286 # just zcat the catpage and we are done. 287 if [ -z "$tflag" -a -n "$use_cat" ]; then 288 if [ -n "$wflag" ]; then 289 echo "$catpage (source: $manpage)" 290 ret=0 291 else 292 if [ $debug -gt 0 ]; then 293 decho "Command: $cattool $catpage | $PAGER" 294 ret=0 295 else 296 eval "$cattool $catpage | $PAGER" 297 ret=$? 298 fi 299 fi 300 return 301 fi 302 303 # Okay, we are using the manpage, do we just need to output the 304 # name of the manpage? 305 if [ -n "$wflag" ]; then 306 echo "$manpage" 307 ret=0 308 return 309 fi 310 311 # So, we really do need to parse the manpage. First, figure out the 312 # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 313 # setup the pipeline of commands based on the user's request. 314 315 # If the manpage is from a particular charset, we need to setup nroff 316 # to properly output for the correct device. 317 case "${manpage}" in 318 *.${man_charset}/*) 319 # I don't pretend to know this; I'm just copying from the 320 # previous version of man(1). 321 case "$man_charset" in 322 KOI8-R) nroff_dev="koi8-r" ;; 323 ISO8859-1) nroff_dev="latin1" ;; 324 ISO8859-15) nroff_dev="latin1" ;; 325 UTF-8) nroff_dev="utf8" ;; 326 *) nroff_dev="ascii" ;; 327 esac 328 329 NROFF="$NROFF -T$nroff_dev" 330 EQN="$EQN -T$nroff_dev" 331 332 # Iff the manpage is from the locale and not just the charset, 333 # then we need to define the locale string. 334 case "${manpage}" in 335 */${man_lang}_${man_country}.${man_charset}/*) 336 NROFF="$NROFF -dlocale=$man_lang.$man_charset" 337 ;; 338 */${man_lang}.${man_charset}/*) 339 NROFF="$NROFF -dlocale=$man_lang.$man_charset" 340 ;; 341 esac 342 343 # Allow language specific calls to override the default 344 # set of utilities. 345 l=$(echo $man_lang | tr [:lower:] [:upper:]) 346 for tool in EQN COL NROFF PIC TBL TROFF REFER VGRIND; do 347 eval "$tool=\${${tool}_$l:-\$$tool}" 348 done 349 ;; 350 *) NROFF="$NROFF -Tascii" 351 EQN="$EQN -Tascii" 352 ;; 353 esac 354 355 if [ -n "$MANROFFSEQ" ]; then 356 set -- -$MANROFFSEQ 357 while getopts 'egprtv' preproc_arg; do 358 case "${preproc_arg}" in 359 e) pipeline="$pipeline | $EQN" ;; 360 g) ;; # Ignore for compatability. 361 p) pipeline="$pipeline | $PIC" ;; 362 r) pipeline="$pipeline | $REFER" ;; 363 t) pipeline="$pipeline | $TBL"; use_col=yes ;; 364 v) pipeline="$pipeline | $VGRIND" ;; 365 *) usage ;; 366 esac 367 done 368 # Strip the leading " | " from the resulting pipeline. 369 pipeline="${pipeline#" | "}" 370 else 371 pipeline="$TBL" 372 use_col=yes 373 fi 374 375 if [ -n "$tflag" ]; then 376 pipeline="$pipeline | $TROFF" 377 else 378 pipeline="$pipeline | $NROFF" 379 380 if [ -n "$use_col" ]; then 381 pipeline="$pipeline | $COL" 382 fi 383 384 pipeline="$pipeline | $PAGER" 385 fi 386 387 if [ $debug -gt 0 ]; then 388 decho "Command: $cattool $manpage | $pipeline" 389 ret=0 390 else 391 eval "$cattool $manpage | $pipeline" 392 ret=$? 393 fi 394} 395 396# Usage: man_find_and_display page 397# Search through the manpaths looking for the given page. 398man_find_and_display() { 399 local found_page locpath p path sect 400 401 # Check to see if it's a file. But only if it has a '/' in 402 # the filename. 403 case "$1" in 404 */*) if [ -f "$1" -a -r "$1" ]; then 405 decho "Found a usable page, displaying that" 406 unset use_cat 407 manpage="$1" 408 setup_cattool $manpage 409 if man_check_for_so $manpage $(dirname $manpage); then 410 found_page=yes 411 man_display_page 412 fi 413 return 414 fi 415 ;; 416 esac 417 418 IFS=: 419 for sect in $MANSECT; do 420 decho "Searching section $sect" 2 421 for path in $MANPATH; do 422 for locpath in $locpaths; do 423 p=$path/$locpath 424 p=${p%/.} # Rid ourselves of the trailing /. 425 426 # Check if there is a MACHINE specific manpath. 427 if find_file $p $sect $MACHINE "$1"; then 428 if man_check_for_so $manpage $p; then 429 found_page=yes 430 man_display_page 431 if [ -n "$aflag" ]; then 432 continue 2 433 else 434 return 435 fi 436 fi 437 fi 438 439 # Check if there is a MACHINE_ARCH 440 # specific manpath. 441 if find_file $p $sect $MACHINE_ARCH "$1"; then 442 if man_check_for_so $manpage $p; then 443 found_page=yes 444 man_display_page 445 if [ -n "$aflag" ]; then 446 continue 2 447 else 448 return 449 fi 450 fi 451 fi 452 453 # Check plain old manpath. 454 if find_file $p $sect '' "$1"; then 455 if man_check_for_so $manpage $p; then 456 found_page=yes 457 man_display_page 458 if [ -n "$aflag" ]; then 459 continue 2 460 else 461 return 462 fi 463 fi 464 fi 465 done 466 done 467 done 468 unset IFS 469 470 # Nothing? Well, we are done then. 471 if [ -z "$found_page" ]; then 472 echo "No manual entry for $1" >&2 473 ret=1 474 return 475 fi 476} 477 478# Usage: man_parse_args "$@" 479# Parses commandline options for man. 480man_parse_args() { 481 local IFS cmd_arg 482 483 while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do 484 case "${cmd_arg}" in 485 M) MANPATH=$OPTARG ;; 486 P) PAGER=$OPTARG ;; 487 S) MANSECT=$OPTARG ;; 488 a) aflag=aflag ;; 489 d) debug=$(( $debug + 1 )) ;; 490 f) fflag=fflag ;; 491 h) man_usage 0 ;; 492 k) kflag=kflag ;; 493 m) mflag=$OPTARG ;; 494 o) oflag=oflag ;; 495 p) MANROFFSEQ=$OPTARG ;; 496 t) tflag=tflag ;; 497 w) wflag=wflag ;; 498 *) man_usage ;; 499 esac 500 done >&2 501 502 shift $(( $OPTIND - 1 )) 503 504 # Check the args for incompatible options. 505 case "${fflag}${kflag}${tflag}${wflag}" in 506 fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 507 fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 508 fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 509 *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 510 *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 511 *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 512 esac 513 514 # Short circuit for whatis(1) and apropos(1) 515 if [ -n "$fflag" ]; then 516 do_whatis "$@" 517 exit 518 fi 519 520 if [ -n "$kflag" ]; then 521 do_apropos "$@" 522 exit 523 fi 524 525 IFS=: 526 for sect in $man_default_sections; do 527 if [ "$sect" = "$1" ]; then 528 decho "Detected manual section as first arg: $1" 529 MANSECT="$1" 530 shift 531 break 532 fi 533 done 534 unset IFS 535 536 pages="$*" 537} 538 539# Usage: man_setup 540# Setup various trivial but essential variables. 541man_setup() { 542 # Setup machine and architecture variables. 543 if [ -n "$mflag" ]; then 544 MACHINE_ARCH=${mflag%%:*} 545 MACHINE=${mflag##*:} 546 fi 547 if [ -z "$MACHINE_ARCH" ]; then 548 MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 549 fi 550 if [ -z "$MACHINE" ]; then 551 MACHINE=$($SYSCTL -n hw.machine) 552 fi 553 decho "Using architecture: $MACHINE_ARCH:$MACHINE" 554 555 setup_pager 556 557 # Setup manual sections to search. 558 if [ -z "$MANSECT" ]; then 559 MANSECT=$man_default_sections 560 fi 561 decho "Using manual sections: $MANSECT" 562 563 build_manpath 564 man_setup_locale 565} 566 567# Usage: man_setup_locale 568# Setup necessary locale variables. 569man_setup_locale() { 570 local lang_cc 571 572 locpaths='.' 573 man_charset='US-ASCII' 574 575 # Setup locale information. 576 if [ -n "$oflag" ]; then 577 decho 'Using non-localized manpages' 578 else 579 # Use the locale tool to give us the proper LC_CTYPE 580 eval $( $LOCALE ) 581 582 case "$LC_CTYPE" in 583 C) ;; 584 POSIX) ;; 585 [a-z][a-z]_[A-Z][A-Z]\.*) 586 lang_cc="${LC_CTYPE%.*}" 587 man_lang="${LC_CTYPE%_*}" 588 man_country="${lang_cc#*_}" 589 man_charset="${LC_CTYPE#*.}" 590 locpaths="$LC_CTYPE" 591 locpaths="$locpaths:$man_lang.$man_charset" 592 if [ "$man_lang" != "en" ]; then 593 locpaths="$locpaths:en.$man_charset" 594 fi 595 locpaths="$locpaths:." 596 ;; 597 *) echo 'Unknown locale, assuming C' >&2 598 ;; 599 esac 600 fi 601 602 decho "Using locale paths: $locpaths" 603} 604 605# Usage: man_usage [exitcode] 606# Display usage for the man utility. 607man_usage() { 608 echo 'Usage:' 609 echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]' 610 echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 611 echo ' man -f page [...] -- Emulates whatis(1)' 612 echo ' man -k page [...] -- Emulates apropos(1)' 613 614 # When exit'ing with -h, it's not an error. 615 exit ${1:-1} 616} 617 618# Usage: parse_configs 619# Reads the end-user adjustable config files. 620parse_configs() { 621 local IFS file files 622 623 if [ -n "$parsed_configs" ]; then 624 return 625 fi 626 627 unset IFS 628 629 # Read the global config first in case the user wants 630 # to override config_local. 631 if [ -r "$config_global" ]; then 632 parse_file "$config_global" 633 fi 634 635 # Glob the list of files to parse. 636 set +f 637 files=$(echo $config_local) 638 set -f 639 640 for file in $files; do 641 if [ -r "$file" ]; then 642 parse_file "$file" 643 fi 644 done 645 646 parsed_configs='yes' 647} 648 649# Usage: parse_file file 650# Reads the specified config files. 651parse_file() { 652 local file line tstr var 653 654 file="$1" 655 decho "Parsing config file: $file" 656 while read line; do 657 decho " $line" 2 658 case "$line" in 659 \#*) decho " Comment" 3 660 ;; 661 MANPATH*) decho " MANPATH" 3 662 trim "${line#MANPATH}" 663 add_to_manpath "$tstr" 664 ;; 665 MANLOCALE*) decho " MANLOCALE" 3 666 trim "${line#MANLOCALE}" 667 manlocales="$manlocales:$tstr" 668 ;; 669 MANCONFIG*) decho " MANCONFIG" 3 670 trim "${line#MANCONF}" 671 config_local="$tstr" 672 ;; 673 # Set variables in the form of FOO_BAR 674 *_*[\ \ ]*) var="${line%%[\ \ ]*}" 675 trim "${line#$var}" 676 eval "$var=\"$tstr\"" 677 decho " Parsed $var" 3 678 ;; 679 esac 680 done < "$file" 681} 682 683# Usage: search_path 684# Traverse $PATH looking for manpaths. 685search_path() { 686 local IFS p path 687 688 decho "Searching PATH for man directories" 689 690 IFS=: 691 for path in $PATH; do 692 # Do a little special casing since the base manpages 693 # are in /usr/share/man instead of /usr/man or /man. 694 case "$path" in 695 /bin|/usr/bin) add_to_manpath "/usr/share/man" ;; 696 *) if add_to_manpath "$path/man"; then 697 : 698 elif add_to_manpath "$path/MAN"; then 699 : 700 else 701 case "$path" in 702 */bin) p="${path%/bin}/man" 703 add_to_manpath "$p" 704 ;; 705 *) ;; 706 esac 707 fi 708 ;; 709 esac 710 done 711 unset IFS 712 713 if [ -z "$manpath" ]; then 714 decho ' Unable to find any manpaths, using default' 715 manpath=$man_default_path 716 fi 717} 718 719# Usage: search_whatis cmd [arglist] 720# Do the heavy lifting for apropos/whatis 721search_whatis() { 722 local IFS bad cmd f good key keywords loc opt out path rval wlist 723 724 cmd="$1" 725 shift 726 727 whatis_parse_args "$@" 728 729 build_manpath 730 build_manlocales 731 setup_pager 732 733 if [ "$cmd" = "whatis" ]; then 734 opt="-w" 735 fi 736 737 f='whatis' 738 739 IFS=: 740 for path in $MANPATH; do 741 if [ \! -d "$path" ]; then 742 decho "Skipping non-existent path: $path" 2 743 continue 744 fi 745 746 if [ -f "$path/$f" -a -r "$path/$f" ]; then 747 decho "Found whatis: $path/$f" 748 wlist="$wlist $path/$f" 749 fi 750 751 for loc in $MANLOCALES; do 752 if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 753 decho "Found whatis: $path/$loc/$f" 754 wlist="$wlist $path/$loc/$f" 755 fi 756 done 757 done 758 unset IFS 759 760 if [ -z "$wlist" ]; then 761 echo "$cmd: no whatis databases in $MANPATH" >&2 762 exit 1 763 fi 764 765 rval=0 766 for key in $keywords; do 767 out=$(grep -Ehi $opt -- "$key" $wlist) 768 if [ -n "$out" ]; then 769 good="$good\\n$out" 770 else 771 bad="$bad\\n$key: nothing appropriate" 772 rval=1 773 fi 774 done 775 776 # Strip leading carriage return. 777 good=${good#\\n} 778 bad=${bad#\\n} 779 780 if [ -n "$good" ]; then 781 echo -e "$good" | $PAGER 782 fi 783 784 if [ -n "$bad" ]; then 785 echo -e "$bad" >&2 786 fi 787 788 exit $rval 789} 790 791# Usage: setup_cattool page 792# Finds an appropriate decompressor based on extension 793setup_cattool() { 794 case "$1" in 795 *.bz) cattool='/usr/bin/bzcat' ;; 796 *.bz2) cattool='/usr/bin/bzcat' ;; 797 *.gz) cattool='/usr/bin/zcat' ;; 798 *.lzma) cattool='/usr/bin/lzcat' ;; 799 *.xz) cattool='/usr/bin/xzcat' ;; 800 *) cattool='/usr/bin/zcat -f' ;; 801 esac 802} 803 804# Usage: setup_pager 805# Correctly sets $PAGER 806setup_pager() { 807 # Setup pager. 808 if [ -z "$PAGER" ]; then 809 PAGER="more -s" 810 fi 811 decho "Using pager: $PAGER" 812} 813 814# Usage: trim string 815# Trims whitespace from beginning and end of a variable 816trim() { 817 tstr=$1 818 while true; do 819 case "$tstr" in 820 [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 821 *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 822 *) break ;; 823 esac 824 done 825} 826 827# Usage: whatis_parse_args "$@" 828# Parse commandline args for whatis and apropos. 829whatis_parse_args() { 830 local cmd_arg 831 while getopts 'd' cmd_arg; do 832 case "${cmd_arg}" in 833 d) debug=$(( $debug + 1 )) ;; 834 *) whatis_usage ;; 835 esac 836 done >&2 837 838 shift $(( $OPTIND - 1 )) 839 840 keywords="$*" 841} 842 843# Usage: whatis_usage 844# Display usage for the whatis/apropos utility. 845whatis_usage() { 846 echo "usage: $cmd [-d] keyword [...]" 847 exit 1 848} 849 850 851 852# Supported commands 853do_apropos() { 854 search_whatis apropos "$@" 855} 856 857do_man() { 858 man_parse_args "$@" 859 if [ -z "$pages" ]; then 860 echo 'What manual page do you want?' >&2 861 exit 1 862 fi 863 man_setup 864 865 for page in $pages; do 866 decho "Searching for $page" 867 man_find_and_display "$page" 868 done 869 870 exit ${ret:-0} 871} 872 873do_manpath() { 874 manpath_parse_args "$@" 875 if [ -z "$qflag" ]; then 876 manpath_warnings 877 fi 878 if [ -n "$Lflag" ]; then 879 build_manlocales 880 echo $MANLOCALES 881 else 882 build_manpath 883 echo $MANPATH 884 fi 885 exit 0 886} 887 888do_whatis() { 889 search_whatis whatis "$@" 890} 891 892EQN=/usr/bin/eqn 893COL=/usr/bin/col 894LOCALE=/usr/bin/locale 895NROFF='/usr/bin/groff -S -Wall -mtty-char -man' 896PIC=/usr/bin/pic 897SYSCTL=/sbin/sysctl 898TBL=/usr/bin/tbl 899TROFF='/usr/bin/groff -S -man' 900REFER=/usr/bin/refer 901VGRIND=/usr/bin/vgrind 902 903debug=0 904man_default_sections='1:1aout:8:2:3:n:4:5:6:7:9:l' 905man_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/man' 906cattool='/usr/bin/zcat -f' 907 908config_global='/etc/man.conf' 909 910# This can be overridden via a setting in /etc/man.conf. 911config_local='/usr/local/etc/man.d/*.conf' 912 913# Set noglobbing for now. I don't want spurious globbing. 914set -f 915 916case "$0" in 917*apropos) do_apropos "$@" ;; 918*manpath) do_manpath "$@" ;; 919*whatis) do_whatis "$@" ;; 920*) do_man "$@" ;; 921esac 922