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 71*b2394e73SBaptiste Daroussin case "$MANPATH" in 72*b2394e73SBaptiste Daroussin *:) PREPEND_MANPATH=${MANPATH} ;; 73*b2394e73SBaptiste Daroussin :*) APPEND_MANPATH=${MANPATH} ;; 74*b2394e73SBaptiste Daroussin *::*) 75*b2394e73SBaptiste Daroussin PREPEND_MANPATH=${MANPATH%%::*} 76*b2394e73SBaptiste Daroussin APPEND_MANPATH=${MANPATH#*::} 77*b2394e73SBaptiste Daroussin ;; 78*b2394e73SBaptiste Daroussin *) return ;; 79*b2394e73SBaptiste Daroussin esac 80*b2394e73SBaptiste Daroussin fi 81*b2394e73SBaptiste Daroussin 82*b2394e73SBaptiste Daroussin if [ -n "$PREPEND_MANPATH" ]; then 83*b2394e73SBaptiste Daroussin IFS=: 84*b2394e73SBaptiste Daroussin for path in $PREPEND_MANPATH; do 85*b2394e73SBaptiste Daroussin add_to_manpath "$path" 86*b2394e73SBaptiste Daroussin done 87*b2394e73SBaptiste Daroussin unset IFS 88c535eb59SGordon Tetlow fi 89c535eb59SGordon Tetlow 90c535eb59SGordon Tetlow search_path 91c535eb59SGordon Tetlow 92c535eb59SGordon Tetlow decho "Adding default manpath entries" 93c535eb59SGordon Tetlow IFS=: 94c535eb59SGordon Tetlow for path in $man_default_path; do 95c535eb59SGordon Tetlow add_to_manpath "$path" 96c535eb59SGordon Tetlow done 97c535eb59SGordon Tetlow unset IFS 98c535eb59SGordon Tetlow 99c535eb59SGordon Tetlow parse_configs 100c535eb59SGordon Tetlow 101*b2394e73SBaptiste Daroussin if [ -n "$APPEND_MANPATH" ]; then 102*b2394e73SBaptiste Daroussin IFS=: 103*b2394e73SBaptiste Daroussin for path in $APPEND_MANPATH; do 104*b2394e73SBaptiste Daroussin add_to_manpath "$path" 105*b2394e73SBaptiste Daroussin done 106*b2394e73SBaptiste Daroussin unset IFS 107*b2394e73SBaptiste Daroussin fi 108c535eb59SGordon Tetlow # Trim leading colon 109c535eb59SGordon Tetlow MANPATH=${manpath#:} 110c535eb59SGordon Tetlow 111c535eb59SGordon Tetlow decho "Using manual path: $MANPATH" 112c535eb59SGordon Tetlow} 113c535eb59SGordon Tetlow 114c535eb59SGordon Tetlow# Usage: check_cat catglob 115c535eb59SGordon Tetlow# Checks to see if a cat glob is available. 116c535eb59SGordon Tetlowcheck_cat() { 117c535eb59SGordon Tetlow if exists "$1"; then 118c535eb59SGordon Tetlow use_cat=yes 119c535eb59SGordon Tetlow catpage=$found 12057cd9717SGordon Tetlow setup_cattool $catpage 121c535eb59SGordon Tetlow decho " Found catpage $catpage" 122c535eb59SGordon Tetlow return 0 123c535eb59SGordon Tetlow else 124c535eb59SGordon Tetlow return 1 125c535eb59SGordon Tetlow fi 126c535eb59SGordon Tetlow} 127c535eb59SGordon Tetlow 128c535eb59SGordon Tetlow# Usage: check_man manglob catglob 129c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to 130c535eb59SGordon Tetlow# see if the catglob is also available and up to date. 131c535eb59SGordon Tetlowcheck_man() { 132c535eb59SGordon Tetlow if exists "$1"; then 133c535eb59SGordon Tetlow # We have a match, check for a cat page 134c535eb59SGordon Tetlow manpage=$found 13557cd9717SGordon Tetlow setup_cattool $manpage 136c535eb59SGordon Tetlow decho " Found manpage $manpage" 137c535eb59SGordon Tetlow 138a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 139a0094449SRuslan Ermilov # non-standard width 140a0094449SRuslan Ermilov unset use_cat 141a0094449SRuslan Ermilov decho " Skipping catpage: non-standard page width" 142a0094449SRuslan Ermilov elif exists "$2" && is_newer $found $manpage; then 143c535eb59SGordon Tetlow # cat page found and is newer, use that 144c535eb59SGordon Tetlow use_cat=yes 145c535eb59SGordon Tetlow catpage=$found 14657cd9717SGordon Tetlow setup_cattool $catpage 147c535eb59SGordon Tetlow decho " Using catpage $catpage" 148c535eb59SGordon Tetlow else 149c535eb59SGordon Tetlow # no cat page or is older 150c535eb59SGordon Tetlow unset use_cat 151c535eb59SGordon Tetlow decho " Skipping catpage: not found or old" 152c535eb59SGordon Tetlow fi 153c535eb59SGordon Tetlow return 0 154c535eb59SGordon Tetlow fi 155c535eb59SGordon Tetlow 156c535eb59SGordon Tetlow return 1 157c535eb59SGordon Tetlow} 158c535eb59SGordon Tetlow 159c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel] 160c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel. 161c535eb59SGordon Tetlowdecho() { 162c535eb59SGordon Tetlow if [ $debug -ge ${2:-1} ]; then 163c535eb59SGordon Tetlow echo "-- $1" >&2 164c535eb59SGordon Tetlow fi 165c535eb59SGordon Tetlow} 166c535eb59SGordon Tetlow 167c535eb59SGordon Tetlow# Usage: exists glob 168c535eb59SGordon Tetlow# Returns true if glob resolves to a real file. 169c535eb59SGordon Tetlowexists() { 170c535eb59SGordon Tetlow local IFS 171c535eb59SGordon Tetlow 172c535eb59SGordon Tetlow # Don't accidentally inherit callers IFS (breaks perl manpages) 173c535eb59SGordon Tetlow unset IFS 174c535eb59SGordon Tetlow 175c535eb59SGordon Tetlow # Use some globbing tricks in the shell to determine if a file 176c535eb59SGordon Tetlow # exists or not. 177c535eb59SGordon Tetlow set +f 178c535eb59SGordon Tetlow set -- "$1" $1 179c535eb59SGordon Tetlow set -f 180c535eb59SGordon Tetlow 181c535eb59SGordon Tetlow if [ "$1" != "$2" -a -r "$2" ]; then 182c535eb59SGordon Tetlow found="$2" 183c535eb59SGordon Tetlow return 0 184c535eb59SGordon Tetlow fi 185c535eb59SGordon Tetlow 186c535eb59SGordon Tetlow return 1 187c535eb59SGordon Tetlow} 188c535eb59SGordon Tetlow 189c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename 190c535eb59SGordon Tetlow# Returns: true if something is matched and found. 191c535eb59SGordon Tetlow# Search the given path/section combo for a given page. 192c535eb59SGordon Tetlowfind_file() { 193c535eb59SGordon Tetlow local manroot catroot mann man0 catn cat0 194c535eb59SGordon Tetlow 195c535eb59SGordon Tetlow manroot="$1/man$2" 196c535eb59SGordon Tetlow catroot="$1/cat$2" 197c535eb59SGordon Tetlow if [ -n "$3" ]; then 198c535eb59SGordon Tetlow manroot="$manroot/$3" 199c535eb59SGordon Tetlow catroot="$catroot/$3" 200c535eb59SGordon Tetlow fi 201c535eb59SGordon Tetlow 202c535eb59SGordon Tetlow if [ ! -d "$manroot" ]; then 203c535eb59SGordon Tetlow return 1 204c535eb59SGordon Tetlow fi 205c535eb59SGordon Tetlow decho " Searching directory $manroot" 2 206c535eb59SGordon Tetlow 207c535eb59SGordon Tetlow mann="$manroot/$4.$2*" 208c535eb59SGordon Tetlow man0="$manroot/$4.0*" 209c535eb59SGordon Tetlow catn="$catroot/$4.$2*" 210c535eb59SGordon Tetlow cat0="$catroot/$4.0*" 211c535eb59SGordon Tetlow 212c535eb59SGordon Tetlow # This is the behavior as seen by the original man utility. 213c535eb59SGordon Tetlow # Let's not change that which doesn't seem broken. 214c535eb59SGordon Tetlow if check_man "$mann" "$catn"; then 215c535eb59SGordon Tetlow return 0 216c535eb59SGordon Tetlow elif check_man "$man0" "$cat0"; then 217c535eb59SGordon Tetlow return 0 218c535eb59SGordon Tetlow elif check_cat "$catn"; then 219c535eb59SGordon Tetlow return 0 220c535eb59SGordon Tetlow elif check_cat "$cat0"; then 221c535eb59SGordon Tetlow return 0 222c535eb59SGordon Tetlow fi 223c535eb59SGordon Tetlow 224c535eb59SGordon Tetlow return 1 225c535eb59SGordon Tetlow} 226c535eb59SGordon Tetlow 227c535eb59SGordon Tetlow# Usage: is_newer file1 file2 228c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime. 229c535eb59SGordon Tetlowis_newer() { 2309b61837aSUlrich Spörlein if ! [ "$1" -ot "$2" ]; then 2319b61837aSUlrich Spörlein decho " mtime: $1 not older than $2" 3 232c535eb59SGordon Tetlow return 0 233c535eb59SGordon Tetlow else 234c535eb59SGordon Tetlow decho " mtime: $1 older than $2" 3 235c535eb59SGordon Tetlow return 1 236c535eb59SGordon Tetlow fi 237c535eb59SGordon Tetlow} 238c535eb59SGordon Tetlow 239c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@" 240c535eb59SGordon Tetlow# Parses commandline options for manpath. 241c535eb59SGordon Tetlowmanpath_parse_args() { 242c535eb59SGordon Tetlow local cmd_arg 243c535eb59SGordon Tetlow 244c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 245c535eb59SGordon Tetlow case "${cmd_arg}" in 246c535eb59SGordon Tetlow L) Lflag=Lflag ;; 247c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 248c535eb59SGordon Tetlow q) qflag=qflag ;; 249c535eb59SGordon Tetlow *) manpath_usage ;; 250c535eb59SGordon Tetlow esac 251c535eb59SGordon Tetlow done >&2 252c535eb59SGordon Tetlow} 253c535eb59SGordon Tetlow 254c535eb59SGordon Tetlow# Usage: manpath_usage 255c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 256c535eb59SGordon Tetlowmanpath_usage() { 257c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 258c535eb59SGordon Tetlow exit 1 259c535eb59SGordon Tetlow} 260c535eb59SGordon Tetlow 261c535eb59SGordon Tetlow# Usage: manpath_warnings 262c535eb59SGordon Tetlow# Display some warnings to stderr. 263c535eb59SGordon Tetlowmanpath_warnings() { 264c535eb59SGordon Tetlow if [ -z "$Lflag" -a -n "$MANPATH" ]; then 265c535eb59SGordon Tetlow echo "(Warning: MANPATH environment variable set)" >&2 266c535eb59SGordon Tetlow fi 267c535eb59SGordon Tetlow 268c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 269c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 270c535eb59SGordon Tetlow fi 271c535eb59SGordon Tetlow} 272c535eb59SGordon Tetlow 27357cd9717SGordon Tetlow# Usage: man_check_for_so page path 27457cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 27557cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 27657cd9717SGordon Tetlow# redirected to another source file. 27757cd9717SGordon Tetlowman_check_for_so() { 27857cd9717SGordon Tetlow local IFS line tstr 27957cd9717SGordon Tetlow 28057cd9717SGordon Tetlow unset IFS 28157cd9717SGordon Tetlow 28257cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 28357cd9717SGordon Tetlow while true 28457cd9717SGordon Tetlow do 28557cd9717SGordon Tetlow line=$($cattool $manpage | head -1) 28657cd9717SGordon Tetlow case "$line" in 28757cd9717SGordon Tetlow .so*) trim "${line#.so}" 28857cd9717SGordon Tetlow decho "$manpage includes $tstr" 28957cd9717SGordon Tetlow # Glob and check for the file. 29057cd9717SGordon Tetlow if ! check_man "$path/$tstr*" ""; then 29157cd9717SGordon Tetlow decho " Unable to find $tstr" 29257cd9717SGordon Tetlow return 1 29357cd9717SGordon Tetlow fi 29457cd9717SGordon Tetlow ;; 29557cd9717SGordon Tetlow *) break ;; 29657cd9717SGordon Tetlow esac 29757cd9717SGordon Tetlow done 29857cd9717SGordon Tetlow 29957cd9717SGordon Tetlow return 0 30057cd9717SGordon Tetlow} 30157cd9717SGordon Tetlow 302b43edc06SBaptiste Daroussin# Usage: man_display_page 303b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 304c535eb59SGordon Tetlowman_display_page() { 3051fb816daSBaptiste Daroussin local IFS pipeline testline 306c535eb59SGordon Tetlow 307c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 308c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 309c535eb59SGordon Tetlow unset IFS 310c535eb59SGordon Tetlow 311c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 312c535eb59SGordon Tetlow # just zcat the catpage and we are done. 313c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 314c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 315c535eb59SGordon Tetlow echo "$catpage (source: $manpage)" 316c535eb59SGordon Tetlow ret=0 317c535eb59SGordon Tetlow else 318c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 319a6a3e856SRuslan Ermilov decho "Command: $cattool $catpage | $MANPAGER" 320c535eb59SGordon Tetlow ret=0 321c535eb59SGordon Tetlow else 322a6a3e856SRuslan Ermilov eval "$cattool $catpage | $MANPAGER" 323c535eb59SGordon Tetlow ret=$? 324c535eb59SGordon Tetlow fi 325c535eb59SGordon Tetlow fi 326c535eb59SGordon Tetlow return 327c535eb59SGordon Tetlow fi 328c535eb59SGordon Tetlow 329c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 330c535eb59SGordon Tetlow # name of the manpage? 331c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 332c535eb59SGordon Tetlow echo "$manpage" 333c535eb59SGordon Tetlow ret=0 334c535eb59SGordon Tetlow return 335c535eb59SGordon Tetlow fi 336c535eb59SGordon Tetlow 337d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 338d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 339d433cf9aSBaptiste Daroussin fi 340849684b0SBaptiste Daroussin testline="mandoc -Tlint -Wunsupp 2>/dev/null" 341449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 342449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 343449a792dSBaptiste Daroussin else 344d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 345449a792dSBaptiste Daroussin fi 346d6096801SBaptiste Daroussin 347d6096801SBaptiste Daroussin if ! eval "$cattool $manpage | $testline" ;then 348f17575acSBaptiste Daroussin if which -s groff; then 349d6096801SBaptiste Daroussin man_display_page_groff 350d6096801SBaptiste Daroussin else 351d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 352d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 353d6096801SBaptiste Daroussin echo "pkg install groff " >&2 354d6096801SBaptiste Daroussin ret=1 355d6096801SBaptiste Daroussin fi 356d6096801SBaptiste Daroussin return 357d6096801SBaptiste Daroussin fi 358d6096801SBaptiste Daroussin 359d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 360d6096801SBaptiste Daroussin decho "Command: $cattool $manpage | $pipeline" 361d6096801SBaptiste Daroussin ret=0 362d6096801SBaptiste Daroussin else 363d6096801SBaptiste Daroussin eval "$cattool $manpage | $pipeline" 364d6096801SBaptiste Daroussin ret=$? 365d6096801SBaptiste Daroussin fi 366d6096801SBaptiste Daroussin} 367d6096801SBaptiste Daroussin 368b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 369b43edc06SBaptiste Daroussin# Display the manpage using groff 370d6096801SBaptiste Daroussinman_display_page_groff() { 371d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 372d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 373d6096801SBaptiste Daroussin 374c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 375c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 376c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 377c535eb59SGordon Tetlow 378deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 379deeff310SGordon Tetlow # to properly output for the correct device. 380deeff310SGordon Tetlow case "${manpage}" in 381deeff310SGordon Tetlow *.${man_charset}/*) 382c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 383c535eb59SGordon Tetlow # previous version of man(1). 384c535eb59SGordon Tetlow case "$man_charset" in 385c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 386c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 387c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 388c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 389c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 390c535eb59SGordon Tetlow esac 391c535eb59SGordon Tetlow 392deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 393c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 394c535eb59SGordon Tetlow 395deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 396deeff310SGordon Tetlow # then we need to define the locale string. 397deeff310SGordon Tetlow case "${manpage}" in 398deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 399deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 400deeff310SGordon Tetlow ;; 401deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 402deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 403deeff310SGordon Tetlow ;; 404deeff310SGordon Tetlow esac 405deeff310SGordon Tetlow 406c535eb59SGordon Tetlow # Allow language specific calls to override the default 407c535eb59SGordon Tetlow # set of utilities. 408c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 409b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 410c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 411c535eb59SGordon Tetlow done 412c535eb59SGordon Tetlow ;; 413c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 414c535eb59SGordon Tetlow EQN="$EQN -Tascii" 415c535eb59SGordon Tetlow ;; 416c535eb59SGordon Tetlow esac 417c535eb59SGordon Tetlow 418a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 419a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 420a6a3e856SRuslan Ermilov fi 421a6a3e856SRuslan Ermilov 422a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 423a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 424a0094449SRuslan Ermilov fi 425a0094449SRuslan Ermilov 426c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 427c535eb59SGordon Tetlow set -- -$MANROFFSEQ 428c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 429c535eb59SGordon Tetlow case "${preproc_arg}" in 430c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 431487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 432c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 433c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 434b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 435c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 436c535eb59SGordon Tetlow *) usage ;; 437c535eb59SGordon Tetlow esac 438c535eb59SGordon Tetlow done 439c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 440c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 441c535eb59SGordon Tetlow else 442c535eb59SGordon Tetlow pipeline="$TBL" 443c535eb59SGordon Tetlow fi 444c535eb59SGordon Tetlow 445c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 446c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 447c535eb59SGordon Tetlow else 448a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 449c535eb59SGordon Tetlow fi 450c535eb59SGordon Tetlow 451c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 45257cd9717SGordon Tetlow decho "Command: $cattool $manpage | $pipeline" 453c535eb59SGordon Tetlow ret=0 454c535eb59SGordon Tetlow else 45557cd9717SGordon Tetlow eval "$cattool $manpage | $pipeline" 456c535eb59SGordon Tetlow ret=$? 457c535eb59SGordon Tetlow fi 458c535eb59SGordon Tetlow} 459c535eb59SGordon Tetlow 460c535eb59SGordon Tetlow# Usage: man_find_and_display page 461c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 462c535eb59SGordon Tetlowman_find_and_display() { 463c535eb59SGordon Tetlow local found_page locpath p path sect 464c535eb59SGordon Tetlow 4653d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 4663d9127f1SGordon Tetlow # the filename. 4673d9127f1SGordon Tetlow case "$1" in 4683d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 4693d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 4703d9127f1SGordon Tetlow unset use_cat 4713d9127f1SGordon Tetlow manpage="$1" 47257cd9717SGordon Tetlow setup_cattool $manpage 47357cd9717SGordon Tetlow if man_check_for_so $manpage $(dirname $manpage); then 47457cd9717SGordon Tetlow found_page=yes 4753d9127f1SGordon Tetlow man_display_page 47657cd9717SGordon Tetlow fi 4773d9127f1SGordon Tetlow return 4783d9127f1SGordon Tetlow fi 4793d9127f1SGordon Tetlow ;; 4803d9127f1SGordon Tetlow esac 4813d9127f1SGordon Tetlow 482c535eb59SGordon Tetlow IFS=: 483c535eb59SGordon Tetlow for sect in $MANSECT; do 484c535eb59SGordon Tetlow decho "Searching section $sect" 2 485c535eb59SGordon Tetlow for path in $MANPATH; do 486c535eb59SGordon Tetlow for locpath in $locpaths; do 487c535eb59SGordon Tetlow p=$path/$locpath 488c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 489c535eb59SGordon Tetlow 490c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 491c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 49257cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 493c535eb59SGordon Tetlow found_page=yes 494c535eb59SGordon Tetlow man_display_page 4951d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 4961d7c660aSGordon Tetlow continue 2 4971d7c660aSGordon Tetlow else 498c535eb59SGordon Tetlow return 499c535eb59SGordon Tetlow fi 500c535eb59SGordon Tetlow fi 50157cd9717SGordon Tetlow fi 502c535eb59SGordon Tetlow 503c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 504c535eb59SGordon Tetlow # specific manpath. 505c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 50657cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 507c535eb59SGordon Tetlow found_page=yes 508c535eb59SGordon Tetlow man_display_page 5091d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5101d7c660aSGordon Tetlow continue 2 5111d7c660aSGordon Tetlow else 512c535eb59SGordon Tetlow return 513c535eb59SGordon Tetlow fi 514c535eb59SGordon Tetlow fi 51557cd9717SGordon Tetlow fi 516c535eb59SGordon Tetlow 517c535eb59SGordon Tetlow # Check plain old manpath. 518c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 51957cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 520c535eb59SGordon Tetlow found_page=yes 521c535eb59SGordon Tetlow man_display_page 5221d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5231d7c660aSGordon Tetlow continue 2 5241d7c660aSGordon Tetlow else 525c535eb59SGordon Tetlow return 526c535eb59SGordon Tetlow fi 527c535eb59SGordon Tetlow fi 52857cd9717SGordon Tetlow fi 529c535eb59SGordon Tetlow done 530c535eb59SGordon Tetlow done 531c535eb59SGordon Tetlow done 532c535eb59SGordon Tetlow unset IFS 533c535eb59SGordon Tetlow 534c535eb59SGordon Tetlow # Nothing? Well, we are done then. 535c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 536c535eb59SGordon Tetlow echo "No manual entry for $1" >&2 537c535eb59SGordon Tetlow ret=1 538c535eb59SGordon Tetlow return 539c535eb59SGordon Tetlow fi 540c535eb59SGordon Tetlow} 541c535eb59SGordon Tetlow 542c535eb59SGordon Tetlow# Usage: man_parse_args "$@" 543c535eb59SGordon Tetlow# Parses commandline options for man. 544c535eb59SGordon Tetlowman_parse_args() { 545c535eb59SGordon Tetlow local IFS cmd_arg 546c535eb59SGordon Tetlow 547c535eb59SGordon Tetlow while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do 548c535eb59SGordon Tetlow case "${cmd_arg}" in 549c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 550a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 551c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 552c535eb59SGordon Tetlow a) aflag=aflag ;; 553c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 554c535eb59SGordon Tetlow f) fflag=fflag ;; 555c535eb59SGordon Tetlow h) man_usage 0 ;; 556c535eb59SGordon Tetlow k) kflag=kflag ;; 557c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 558c535eb59SGordon Tetlow o) oflag=oflag ;; 559c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 560c535eb59SGordon Tetlow t) tflag=tflag ;; 561c535eb59SGordon Tetlow w) wflag=wflag ;; 562c535eb59SGordon Tetlow *) man_usage ;; 563c535eb59SGordon Tetlow esac 564c535eb59SGordon Tetlow done >&2 565c535eb59SGordon Tetlow 566c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 567c535eb59SGordon Tetlow 568c535eb59SGordon Tetlow # Check the args for incompatible options. 569c535eb59SGordon Tetlow case "${fflag}${kflag}${tflag}${wflag}" in 570c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 571c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 572c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 573c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 574c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 575c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 576c535eb59SGordon Tetlow esac 577c535eb59SGordon Tetlow 578c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 579c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 580c535eb59SGordon Tetlow do_whatis "$@" 581c535eb59SGordon Tetlow exit 582c535eb59SGordon Tetlow fi 583c535eb59SGordon Tetlow 584c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 585c535eb59SGordon Tetlow do_apropos "$@" 586c535eb59SGordon Tetlow exit 587c535eb59SGordon Tetlow fi 588c535eb59SGordon Tetlow 589c535eb59SGordon Tetlow IFS=: 590c535eb59SGordon Tetlow for sect in $man_default_sections; do 591c535eb59SGordon Tetlow if [ "$sect" = "$1" ]; then 592c535eb59SGordon Tetlow decho "Detected manual section as first arg: $1" 593c535eb59SGordon Tetlow MANSECT="$1" 594c535eb59SGordon Tetlow shift 595c535eb59SGordon Tetlow break 596c535eb59SGordon Tetlow fi 597c535eb59SGordon Tetlow done 598c535eb59SGordon Tetlow unset IFS 599c535eb59SGordon Tetlow 600c535eb59SGordon Tetlow pages="$*" 601c535eb59SGordon Tetlow} 602c535eb59SGordon Tetlow 603c535eb59SGordon Tetlow# Usage: man_setup 604c535eb59SGordon Tetlow# Setup various trivial but essential variables. 605c535eb59SGordon Tetlowman_setup() { 606c535eb59SGordon Tetlow # Setup machine and architecture variables. 607c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 608c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 609c535eb59SGordon Tetlow MACHINE=${mflag##*:} 610c535eb59SGordon Tetlow fi 611c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 61282db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 613c535eb59SGordon Tetlow fi 614c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 61582db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 616c535eb59SGordon Tetlow fi 617c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 618c535eb59SGordon Tetlow 619c535eb59SGordon Tetlow setup_pager 620c535eb59SGordon Tetlow 621c535eb59SGordon Tetlow # Setup manual sections to search. 622c535eb59SGordon Tetlow if [ -z "$MANSECT" ]; then 623c535eb59SGordon Tetlow MANSECT=$man_default_sections 624c535eb59SGordon Tetlow fi 625c535eb59SGordon Tetlow decho "Using manual sections: $MANSECT" 626c535eb59SGordon Tetlow 627c535eb59SGordon Tetlow build_manpath 628c535eb59SGordon Tetlow man_setup_locale 629a0094449SRuslan Ermilov man_setup_width 630a0094449SRuslan Ermilov} 631a0094449SRuslan Ermilov 632a0094449SRuslan Ermilov# Usage: man_setup_width 633a0094449SRuslan Ermilov# Set up page width. 634a0094449SRuslan Ermilovman_setup_width() { 635a0094449SRuslan Ermilov local sizes 636a0094449SRuslan Ermilov 637a0094449SRuslan Ermilov unset use_width 638a0094449SRuslan Ermilov case "$MANWIDTH" in 639a0094449SRuslan Ermilov [0-9]*) 640a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 641a0094449SRuslan Ermilov use_width=$MANWIDTH 642a0094449SRuslan Ermilov fi 643a0094449SRuslan Ermilov ;; 644a0094449SRuslan Ermilov [Tt][Tt][Yy]) 645a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 646a0094449SRuslan Ermilov set -- $sizes 647a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 648a0094449SRuslan Ermilov use_width=$(($2-2)) 649a0094449SRuslan Ermilov fi 650a0094449SRuslan Ermilov fi 651a0094449SRuslan Ermilov ;; 652a0094449SRuslan Ermilov esac 653a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 654a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 655a0094449SRuslan Ermilov else 656a0094449SRuslan Ermilov decho 'Using standard page width' 657a0094449SRuslan Ermilov fi 658c535eb59SGordon Tetlow} 659c535eb59SGordon Tetlow 660c535eb59SGordon Tetlow# Usage: man_setup_locale 661c535eb59SGordon Tetlow# Setup necessary locale variables. 662c535eb59SGordon Tetlowman_setup_locale() { 663deeff310SGordon Tetlow local lang_cc 664deeff310SGordon Tetlow 665deeff310SGordon Tetlow locpaths='.' 666deeff310SGordon Tetlow man_charset='US-ASCII' 667deeff310SGordon Tetlow 668c535eb59SGordon Tetlow # Setup locale information. 669c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 670deeff310SGordon Tetlow decho 'Using non-localized manpages' 671deeff310SGordon Tetlow else 672deeff310SGordon Tetlow # Use the locale tool to give us the proper LC_CTYPE 673deeff310SGordon Tetlow eval $( $LOCALE ) 674c535eb59SGordon Tetlow 675deeff310SGordon Tetlow case "$LC_CTYPE" in 676deeff310SGordon Tetlow C) ;; 677deeff310SGordon Tetlow POSIX) ;; 678deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 679deeff310SGordon Tetlow lang_cc="${LC_CTYPE%.*}" 680deeff310SGordon Tetlow man_lang="${LC_CTYPE%_*}" 681deeff310SGordon Tetlow man_country="${lang_cc#*_}" 682deeff310SGordon Tetlow man_charset="${LC_CTYPE#*.}" 683deeff310SGordon Tetlow locpaths="$LC_CTYPE" 684c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 685c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 686c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 687c535eb59SGordon Tetlow fi 688c535eb59SGordon Tetlow locpaths="$locpaths:." 689deeff310SGordon Tetlow ;; 690deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 691deeff310SGordon Tetlow ;; 692deeff310SGordon Tetlow esac 693c535eb59SGordon Tetlow fi 694deeff310SGordon Tetlow 695c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 696c535eb59SGordon Tetlow} 697c535eb59SGordon Tetlow 698c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 699c535eb59SGordon Tetlow# Display usage for the man utility. 700c535eb59SGordon Tetlowman_usage() { 701c535eb59SGordon Tetlow echo 'Usage:' 702c535eb59SGordon Tetlow echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]' 703c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 704c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 705c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 706c535eb59SGordon Tetlow 707c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 708c535eb59SGordon Tetlow exit ${1:-1} 709c535eb59SGordon Tetlow} 710c535eb59SGordon Tetlow 711c535eb59SGordon Tetlow# Usage: parse_configs 712c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 713c535eb59SGordon Tetlowparse_configs() { 714c535eb59SGordon Tetlow local IFS file files 715c535eb59SGordon Tetlow 716c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 717c535eb59SGordon Tetlow return 718c535eb59SGordon Tetlow fi 719c535eb59SGordon Tetlow 720c535eb59SGordon Tetlow unset IFS 721c535eb59SGordon Tetlow 722c535eb59SGordon Tetlow # Read the global config first in case the user wants 723c535eb59SGordon Tetlow # to override config_local. 724c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 725c535eb59SGordon Tetlow parse_file "$config_global" 726c535eb59SGordon Tetlow fi 727c535eb59SGordon Tetlow 728c535eb59SGordon Tetlow # Glob the list of files to parse. 729c535eb59SGordon Tetlow set +f 730c535eb59SGordon Tetlow files=$(echo $config_local) 731c535eb59SGordon Tetlow set -f 732c535eb59SGordon Tetlow 733c535eb59SGordon Tetlow for file in $files; do 734c535eb59SGordon Tetlow if [ -r "$file" ]; then 735c535eb59SGordon Tetlow parse_file "$file" 736c535eb59SGordon Tetlow fi 737c535eb59SGordon Tetlow done 738c535eb59SGordon Tetlow 739c535eb59SGordon Tetlow parsed_configs='yes' 740c535eb59SGordon Tetlow} 741c535eb59SGordon Tetlow 742c535eb59SGordon Tetlow# Usage: parse_file file 743c535eb59SGordon Tetlow# Reads the specified config files. 744c535eb59SGordon Tetlowparse_file() { 745c535eb59SGordon Tetlow local file line tstr var 746c535eb59SGordon Tetlow 747c535eb59SGordon Tetlow file="$1" 748c535eb59SGordon Tetlow decho "Parsing config file: $file" 749c535eb59SGordon Tetlow while read line; do 750c535eb59SGordon Tetlow decho " $line" 2 751c535eb59SGordon Tetlow case "$line" in 752c535eb59SGordon Tetlow \#*) decho " Comment" 3 753c535eb59SGordon Tetlow ;; 754c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 755c535eb59SGordon Tetlow trim "${line#MANPATH}" 756c535eb59SGordon Tetlow add_to_manpath "$tstr" 757c535eb59SGordon Tetlow ;; 758c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 759c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 760c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 761c535eb59SGordon Tetlow ;; 762c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 763a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 764c535eb59SGordon Tetlow config_local="$tstr" 765c535eb59SGordon Tetlow ;; 766c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 767c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 768c535eb59SGordon Tetlow trim "${line#$var}" 769c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 770c535eb59SGordon Tetlow decho " Parsed $var" 3 771c535eb59SGordon Tetlow ;; 772c535eb59SGordon Tetlow esac 773c535eb59SGordon Tetlow done < "$file" 774c535eb59SGordon Tetlow} 775c535eb59SGordon Tetlow 776c535eb59SGordon Tetlow# Usage: search_path 777c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 778c535eb59SGordon Tetlowsearch_path() { 779c535eb59SGordon Tetlow local IFS p path 780c535eb59SGordon Tetlow 781c535eb59SGordon Tetlow decho "Searching PATH for man directories" 782c535eb59SGordon Tetlow 783c535eb59SGordon Tetlow IFS=: 784c535eb59SGordon Tetlow for path in $PATH; do 785c535eb59SGordon Tetlow # Do a little special casing since the base manpages 786c535eb59SGordon Tetlow # are in /usr/share/man instead of /usr/man or /man. 787c535eb59SGordon Tetlow case "$path" in 788c535eb59SGordon Tetlow /bin|/usr/bin) add_to_manpath "/usr/share/man" ;; 789c535eb59SGordon Tetlow *) if add_to_manpath "$path/man"; then 790c535eb59SGordon Tetlow : 791c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 792c535eb59SGordon Tetlow : 793c535eb59SGordon Tetlow else 794c535eb59SGordon Tetlow case "$path" in 795c535eb59SGordon Tetlow */bin) p="${path%/bin}/man" 796c535eb59SGordon Tetlow add_to_manpath "$p" 79761d5f2d1SBaptiste Daroussin p="${path%/bin}/share/man" 79861d5f2d1SBaptiste Daroussin add_to_manpath "$p" 799c535eb59SGordon Tetlow ;; 800c535eb59SGordon Tetlow *) ;; 801c535eb59SGordon Tetlow esac 802c535eb59SGordon Tetlow fi 803c535eb59SGordon Tetlow ;; 804c535eb59SGordon Tetlow esac 805c535eb59SGordon Tetlow done 806c535eb59SGordon Tetlow unset IFS 807c535eb59SGordon Tetlow 808c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 809c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 810c535eb59SGordon Tetlow manpath=$man_default_path 811c535eb59SGordon Tetlow fi 812c535eb59SGordon Tetlow} 813c535eb59SGordon Tetlow 814c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 815c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 816c535eb59SGordon Tetlowsearch_whatis() { 817c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 818c535eb59SGordon Tetlow 819c535eb59SGordon Tetlow cmd="$1" 820c535eb59SGordon Tetlow shift 821c535eb59SGordon Tetlow 822c535eb59SGordon Tetlow whatis_parse_args "$@" 823c535eb59SGordon Tetlow 824c535eb59SGordon Tetlow build_manpath 825c535eb59SGordon Tetlow build_manlocales 826c535eb59SGordon Tetlow setup_pager 827c535eb59SGordon Tetlow 828c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 829c535eb59SGordon Tetlow opt="-w" 830c535eb59SGordon Tetlow fi 831c535eb59SGordon Tetlow 832c535eb59SGordon Tetlow f='whatis' 833c535eb59SGordon Tetlow 834c535eb59SGordon Tetlow IFS=: 835c535eb59SGordon Tetlow for path in $MANPATH; do 836c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 837c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 838c535eb59SGordon Tetlow continue 839c535eb59SGordon Tetlow fi 840c535eb59SGordon Tetlow 841c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 842c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 843c535eb59SGordon Tetlow wlist="$wlist $path/$f" 844c535eb59SGordon Tetlow fi 845c535eb59SGordon Tetlow 846c535eb59SGordon Tetlow for loc in $MANLOCALES; do 847c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 848c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 849c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 850c535eb59SGordon Tetlow fi 851c535eb59SGordon Tetlow done 852c535eb59SGordon Tetlow done 853c535eb59SGordon Tetlow unset IFS 854c535eb59SGordon Tetlow 855c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 856c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 857c535eb59SGordon Tetlow exit 1 858c535eb59SGordon Tetlow fi 859c535eb59SGordon Tetlow 860c535eb59SGordon Tetlow rval=0 861c535eb59SGordon Tetlow for key in $keywords; do 862c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 863c535eb59SGordon Tetlow if [ -n "$out" ]; then 864c535eb59SGordon Tetlow good="$good\\n$out" 865c535eb59SGordon Tetlow else 866c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 867c535eb59SGordon Tetlow rval=1 868c535eb59SGordon Tetlow fi 869c535eb59SGordon Tetlow done 870c535eb59SGordon Tetlow 871c535eb59SGordon Tetlow # Strip leading carriage return. 872c535eb59SGordon Tetlow good=${good#\\n} 873c535eb59SGordon Tetlow bad=${bad#\\n} 874c535eb59SGordon Tetlow 875c535eb59SGordon Tetlow if [ -n "$good" ]; then 876a6a3e856SRuslan Ermilov echo -e "$good" | $MANPAGER 877c535eb59SGordon Tetlow fi 878c535eb59SGordon Tetlow 879c535eb59SGordon Tetlow if [ -n "$bad" ]; then 88000e05e69SGordon Tetlow echo -e "$bad" >&2 881c535eb59SGordon Tetlow fi 882c535eb59SGordon Tetlow 883c535eb59SGordon Tetlow exit $rval 884c535eb59SGordon Tetlow} 885c535eb59SGordon Tetlow 88657cd9717SGordon Tetlow# Usage: setup_cattool page 88757cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 88857cd9717SGordon Tetlowsetup_cattool() { 88957cd9717SGordon Tetlow case "$1" in 89057cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 89157cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 89257cd9717SGordon Tetlow *.gz) cattool='/usr/bin/zcat' ;; 89357cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 89457cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 89557cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 89657cd9717SGordon Tetlow esac 89757cd9717SGordon Tetlow} 89857cd9717SGordon Tetlow 899c535eb59SGordon Tetlow# Usage: setup_pager 900a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 901c535eb59SGordon Tetlowsetup_pager() { 902c535eb59SGordon Tetlow # Setup pager. 903a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 904a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 905a6a3e856SRuslan Ermilov MANPAGER="less -sR" 906a6a3e856SRuslan Ermilov else 907a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 908a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 909a6a3e856SRuslan Ermilov else 910a6a3e856SRuslan Ermilov MANPAGER="more -s" 911c535eb59SGordon Tetlow fi 912a6a3e856SRuslan Ermilov fi 913a6a3e856SRuslan Ermilov fi 914a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 915c535eb59SGordon Tetlow} 916c535eb59SGordon Tetlow 917c535eb59SGordon Tetlow# Usage: trim string 918c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 919c535eb59SGordon Tetlowtrim() { 920c535eb59SGordon Tetlow tstr=$1 921c535eb59SGordon Tetlow while true; do 922c535eb59SGordon Tetlow case "$tstr" in 923c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 924c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 925c535eb59SGordon Tetlow *) break ;; 926c535eb59SGordon Tetlow esac 927c535eb59SGordon Tetlow done 928c535eb59SGordon Tetlow} 929c535eb59SGordon Tetlow 930c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 931c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 932c535eb59SGordon Tetlowwhatis_parse_args() { 933c535eb59SGordon Tetlow local cmd_arg 934c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 935c535eb59SGordon Tetlow case "${cmd_arg}" in 936c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 937c535eb59SGordon Tetlow *) whatis_usage ;; 938c535eb59SGordon Tetlow esac 939c535eb59SGordon Tetlow done >&2 940c535eb59SGordon Tetlow 941c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 942c535eb59SGordon Tetlow 943c535eb59SGordon Tetlow keywords="$*" 944c535eb59SGordon Tetlow} 945c535eb59SGordon Tetlow 946c535eb59SGordon Tetlow# Usage: whatis_usage 947c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 948c535eb59SGordon Tetlowwhatis_usage() { 949c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 950c535eb59SGordon Tetlow exit 1 951c535eb59SGordon Tetlow} 952c535eb59SGordon Tetlow 953c535eb59SGordon Tetlow 954c535eb59SGordon Tetlow 955c535eb59SGordon Tetlow# Supported commands 956c535eb59SGordon Tetlowdo_apropos() { 95724ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 958772246efSBaptiste Daroussin exec apropos "$@" 959c535eb59SGordon Tetlow search_whatis apropos "$@" 960c535eb59SGordon Tetlow} 961c535eb59SGordon Tetlow 962c535eb59SGordon Tetlowdo_man() { 963c535eb59SGordon Tetlow man_parse_args "$@" 964c535eb59SGordon Tetlow if [ -z "$pages" ]; then 965c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 966c535eb59SGordon Tetlow exit 1 967c535eb59SGordon Tetlow fi 968c535eb59SGordon Tetlow man_setup 969c535eb59SGordon Tetlow 970c535eb59SGordon Tetlow for page in $pages; do 971c535eb59SGordon Tetlow decho "Searching for $page" 972c535eb59SGordon Tetlow man_find_and_display "$page" 973c535eb59SGordon Tetlow done 974c535eb59SGordon Tetlow 975c535eb59SGordon Tetlow exit ${ret:-0} 976c535eb59SGordon Tetlow} 977c535eb59SGordon Tetlow 978c535eb59SGordon Tetlowdo_manpath() { 979c535eb59SGordon Tetlow manpath_parse_args "$@" 980c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 981c535eb59SGordon Tetlow manpath_warnings 982c535eb59SGordon Tetlow fi 983c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 984c535eb59SGordon Tetlow build_manlocales 985c535eb59SGordon Tetlow echo $MANLOCALES 986c535eb59SGordon Tetlow else 987c535eb59SGordon Tetlow build_manpath 988c535eb59SGordon Tetlow echo $MANPATH 989c535eb59SGordon Tetlow fi 990c535eb59SGordon Tetlow exit 0 991c535eb59SGordon Tetlow} 992c535eb59SGordon Tetlow 993c535eb59SGordon Tetlowdo_whatis() { 99424ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 995772246efSBaptiste Daroussin exec whatis "$@" 996c535eb59SGordon Tetlow search_whatis whatis "$@" 997c535eb59SGordon Tetlow} 998c535eb59SGordon Tetlow 999aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 1000aeea395eSUlrich SpörleinEQN=eqn 1001a6a3e856SRuslan ErmilovNROFF='groff -S -P-h -Wall -mtty-char -man' 1002aeea395eSUlrich SpörleinPIC=pic 1003aeea395eSUlrich SpörleinREFER=refer 1004aeea395eSUlrich SpörleinTBL=tbl 10053d120968SUlrich SpörleinTROFF='groff -S -man' 1006aeea395eSUlrich SpörleinVGRIND=vgrind 1007aeea395eSUlrich Spörlein 1008deeff310SGordon TetlowLOCALE=/usr/bin/locale 1009a0094449SRuslan ErmilovSTTY=/bin/stty 101082db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1011c535eb59SGordon Tetlow 1012c535eb59SGordon Tetlowdebug=0 101340449c74SBrooks Davisman_default_sections='1:8:2:3:n:4:5:6:7:9:l' 1014c535eb59SGordon Tetlowman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/man' 101557cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1016c535eb59SGordon Tetlow 1017c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1018c535eb59SGordon Tetlow 1019c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1020c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1021c535eb59SGordon Tetlow 1022c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1023c535eb59SGordon Tetlowset -f 1024c535eb59SGordon Tetlow 1025c535eb59SGordon Tetlowcase "$0" in 1026c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1027c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1028c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1029c535eb59SGordon Tetlow*) do_man "$@" ;; 1030c535eb59SGordon Tetlowesac 1031