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