1c535eb59SGordon Tetlow#! /bin/sh 2c535eb59SGordon Tetlow# 31de7b4b8SPedro F. Giffuni# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 41de7b4b8SPedro F. Giffuni# 5c535eb59SGordon Tetlow# Copyright (c) 2010 Gordon Tetlow 6c535eb59SGordon Tetlow# All rights reserved. 7c535eb59SGordon Tetlow# 8c535eb59SGordon Tetlow# Redistribution and use in source and binary forms, with or without 9c535eb59SGordon Tetlow# modification, are permitted provided that the following conditions 10c535eb59SGordon Tetlow# are met: 11c535eb59SGordon Tetlow# 1. Redistributions of source code must retain the above copyright 12c535eb59SGordon Tetlow# notice, this list of conditions and the following disclaimer. 13c535eb59SGordon Tetlow# 2. Redistributions in binary form must reproduce the above copyright 14c535eb59SGordon Tetlow# notice, this list of conditions and the following disclaimer in the 15c535eb59SGordon Tetlow# documentation and/or other materials provided with the distribution. 16c535eb59SGordon Tetlow# 17c535eb59SGordon Tetlow# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18c535eb59SGordon Tetlow# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19c535eb59SGordon Tetlow# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20c535eb59SGordon Tetlow# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21c535eb59SGordon Tetlow# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22c535eb59SGordon Tetlow# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23c535eb59SGordon Tetlow# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24c535eb59SGordon Tetlow# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25c535eb59SGordon Tetlow# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26c535eb59SGordon Tetlow# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27c535eb59SGordon Tetlow# SUCH DAMAGE. 28c535eb59SGordon Tetlow# 29c535eb59SGordon Tetlow# $FreeBSD$ 30c535eb59SGordon Tetlow 31c535eb59SGordon Tetlow# Usage: add_to_manpath path 32c535eb59SGordon Tetlow# Adds a variable to manpath while ensuring we don't have duplicates. 33c535eb59SGordon Tetlow# Returns true if we were able to add something. False otherwise. 34c535eb59SGordon Tetlowadd_to_manpath() { 35c535eb59SGordon Tetlow case "$manpath" in 36c535eb59SGordon Tetlow *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 37c535eb59SGordon Tetlow $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 38c535eb59SGordon Tetlow *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 39c535eb59SGordon Tetlow *) if [ -d "$1" ]; then 40c535eb59SGordon Tetlow decho " Adding $1 to manpath" 41c535eb59SGordon Tetlow manpath="$manpath:$1" 42c535eb59SGordon Tetlow return 0 43c535eb59SGordon Tetlow fi 44c535eb59SGordon Tetlow ;; 45c535eb59SGordon Tetlow esac 46c535eb59SGordon Tetlow 47c535eb59SGordon Tetlow return 1 48c535eb59SGordon Tetlow} 49c535eb59SGordon Tetlow 50c535eb59SGordon Tetlow# Usage: build_manlocales 51c535eb59SGordon Tetlow# Builds a correct MANLOCALES variable. 52c535eb59SGordon Tetlowbuild_manlocales() { 53c535eb59SGordon Tetlow # If the user has set manlocales, who are we to argue. 54c535eb59SGordon Tetlow if [ -n "$MANLOCALES" ]; then 55c535eb59SGordon Tetlow return 56c535eb59SGordon Tetlow fi 57c535eb59SGordon Tetlow 58c535eb59SGordon Tetlow parse_configs 59c535eb59SGordon Tetlow 60c535eb59SGordon Tetlow # Trim leading colon 61c535eb59SGordon Tetlow MANLOCALES=${manlocales#:} 62c535eb59SGordon Tetlow 63c535eb59SGordon Tetlow decho "Available manual locales: $MANLOCALES" 64c535eb59SGordon Tetlow} 65c535eb59SGordon Tetlow 66c535eb59SGordon Tetlow# Usage: build_manpath 67c535eb59SGordon Tetlow# Builds a correct MANPATH variable. 68c535eb59SGordon Tetlowbuild_manpath() { 69c535eb59SGordon Tetlow local IFS 70c535eb59SGordon Tetlow 71c535eb59SGordon Tetlow # If the user has set a manpath, who are we to argue. 72c535eb59SGordon Tetlow if [ -n "$MANPATH" ]; then 73b2394e73SBaptiste Daroussin case "$MANPATH" in 74b2394e73SBaptiste Daroussin *:) PREPEND_MANPATH=${MANPATH} ;; 75b2394e73SBaptiste Daroussin :*) APPEND_MANPATH=${MANPATH} ;; 76b2394e73SBaptiste Daroussin *::*) 77b2394e73SBaptiste Daroussin PREPEND_MANPATH=${MANPATH%%::*} 78b2394e73SBaptiste Daroussin APPEND_MANPATH=${MANPATH#*::} 79b2394e73SBaptiste Daroussin ;; 80b2394e73SBaptiste Daroussin *) return ;; 81b2394e73SBaptiste Daroussin esac 82b2394e73SBaptiste Daroussin fi 83b2394e73SBaptiste Daroussin 84b2394e73SBaptiste Daroussin if [ -n "$PREPEND_MANPATH" ]; then 85b2394e73SBaptiste Daroussin IFS=: 86b2394e73SBaptiste Daroussin for path in $PREPEND_MANPATH; do 87b2394e73SBaptiste Daroussin add_to_manpath "$path" 88b2394e73SBaptiste Daroussin done 89b2394e73SBaptiste Daroussin unset IFS 90c535eb59SGordon Tetlow fi 91c535eb59SGordon Tetlow 92c535eb59SGordon Tetlow search_path 93c535eb59SGordon Tetlow 94c535eb59SGordon Tetlow decho "Adding default manpath entries" 95c535eb59SGordon Tetlow IFS=: 96c535eb59SGordon Tetlow for path in $man_default_path; do 97c535eb59SGordon Tetlow add_to_manpath "$path" 98c535eb59SGordon Tetlow done 99c535eb59SGordon Tetlow unset IFS 100c535eb59SGordon Tetlow 101c535eb59SGordon Tetlow parse_configs 102c535eb59SGordon Tetlow 103b2394e73SBaptiste Daroussin if [ -n "$APPEND_MANPATH" ]; then 104b2394e73SBaptiste Daroussin IFS=: 105b2394e73SBaptiste Daroussin for path in $APPEND_MANPATH; do 106b2394e73SBaptiste Daroussin add_to_manpath "$path" 107b2394e73SBaptiste Daroussin done 108b2394e73SBaptiste Daroussin unset IFS 109b2394e73SBaptiste Daroussin fi 110c535eb59SGordon Tetlow # Trim leading colon 111c535eb59SGordon Tetlow MANPATH=${manpath#:} 112c535eb59SGordon Tetlow 113c535eb59SGordon Tetlow decho "Using manual path: $MANPATH" 114c535eb59SGordon Tetlow} 115c535eb59SGordon Tetlow 116c535eb59SGordon Tetlow# Usage: check_cat catglob 117c535eb59SGordon Tetlow# Checks to see if a cat glob is available. 118c535eb59SGordon Tetlowcheck_cat() { 119c535eb59SGordon Tetlow if exists "$1"; then 120c535eb59SGordon Tetlow use_cat=yes 121c535eb59SGordon Tetlow catpage=$found 12257cd9717SGordon Tetlow setup_cattool $catpage 123c535eb59SGordon Tetlow decho " Found catpage $catpage" 124c535eb59SGordon Tetlow return 0 125c535eb59SGordon Tetlow else 126c535eb59SGordon Tetlow return 1 127c535eb59SGordon Tetlow fi 128c535eb59SGordon Tetlow} 129c535eb59SGordon Tetlow 130c535eb59SGordon Tetlow# Usage: check_man manglob catglob 131c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to 132c535eb59SGordon Tetlow# see if the catglob is also available and up to date. 133c535eb59SGordon Tetlowcheck_man() { 134c535eb59SGordon Tetlow if exists "$1"; then 135c535eb59SGordon Tetlow # We have a match, check for a cat page 136c535eb59SGordon Tetlow manpage=$found 13757cd9717SGordon Tetlow setup_cattool $manpage 138c535eb59SGordon Tetlow decho " Found manpage $manpage" 139c535eb59SGordon Tetlow 140a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 141a0094449SRuslan Ermilov # non-standard width 142a0094449SRuslan Ermilov unset use_cat 143a0094449SRuslan Ermilov decho " Skipping catpage: non-standard page width" 144a0094449SRuslan Ermilov elif exists "$2" && is_newer $found $manpage; then 145c535eb59SGordon Tetlow # cat page found and is newer, use that 146c535eb59SGordon Tetlow use_cat=yes 147c535eb59SGordon Tetlow catpage=$found 14857cd9717SGordon Tetlow setup_cattool $catpage 149c535eb59SGordon Tetlow decho " Using catpage $catpage" 150c535eb59SGordon Tetlow else 151c535eb59SGordon Tetlow # no cat page or is older 152c535eb59SGordon Tetlow unset use_cat 153c535eb59SGordon Tetlow decho " Skipping catpage: not found or old" 154c535eb59SGordon Tetlow fi 155c535eb59SGordon Tetlow return 0 156c535eb59SGordon Tetlow fi 157c535eb59SGordon Tetlow 158c535eb59SGordon Tetlow return 1 159c535eb59SGordon Tetlow} 160c535eb59SGordon Tetlow 161c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel] 162c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel. 163c535eb59SGordon Tetlowdecho() { 164c535eb59SGordon Tetlow if [ $debug -ge ${2:-1} ]; then 165c535eb59SGordon Tetlow echo "-- $1" >&2 166c535eb59SGordon Tetlow fi 167c535eb59SGordon Tetlow} 168c535eb59SGordon Tetlow 169c535eb59SGordon Tetlow# Usage: exists glob 170c535eb59SGordon Tetlow# Returns true if glob resolves to a real file. 171c535eb59SGordon Tetlowexists() { 172c535eb59SGordon Tetlow local IFS 173c535eb59SGordon Tetlow 174c535eb59SGordon Tetlow # Don't accidentally inherit callers IFS (breaks perl manpages) 175c535eb59SGordon Tetlow unset IFS 176c535eb59SGordon Tetlow 177c535eb59SGordon Tetlow # Use some globbing tricks in the shell to determine if a file 178c535eb59SGordon Tetlow # exists or not. 179c535eb59SGordon Tetlow set +f 180c535eb59SGordon Tetlow set -- "$1" $1 181c535eb59SGordon Tetlow set -f 182c535eb59SGordon Tetlow 183c535eb59SGordon Tetlow if [ "$1" != "$2" -a -r "$2" ]; then 184c535eb59SGordon Tetlow found="$2" 185c535eb59SGordon Tetlow return 0 186c535eb59SGordon Tetlow fi 187c535eb59SGordon Tetlow 188c535eb59SGordon Tetlow return 1 189c535eb59SGordon Tetlow} 190c535eb59SGordon Tetlow 191c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename 192c535eb59SGordon Tetlow# Returns: true if something is matched and found. 193c535eb59SGordon Tetlow# Search the given path/section combo for a given page. 194c535eb59SGordon Tetlowfind_file() { 195c535eb59SGordon Tetlow local manroot catroot mann man0 catn cat0 196c535eb59SGordon Tetlow 197c535eb59SGordon Tetlow manroot="$1/man$2" 198c535eb59SGordon Tetlow catroot="$1/cat$2" 199c535eb59SGordon Tetlow if [ -n "$3" ]; then 200c535eb59SGordon Tetlow manroot="$manroot/$3" 201c535eb59SGordon Tetlow catroot="$catroot/$3" 202c535eb59SGordon Tetlow fi 203c535eb59SGordon Tetlow 204625490e8SBaptiste Daroussin if [ ! -d "$manroot" -a ! -d "$catroot" ]; then 205c535eb59SGordon Tetlow return 1 206c535eb59SGordon Tetlow fi 207c535eb59SGordon Tetlow decho " Searching directory $manroot" 2 208c535eb59SGordon Tetlow 209c535eb59SGordon Tetlow mann="$manroot/$4.$2*" 210c535eb59SGordon Tetlow man0="$manroot/$4.0*" 211c535eb59SGordon Tetlow catn="$catroot/$4.$2*" 212c535eb59SGordon Tetlow cat0="$catroot/$4.0*" 213c535eb59SGordon Tetlow 214c535eb59SGordon Tetlow # This is the behavior as seen by the original man utility. 215c535eb59SGordon Tetlow # Let's not change that which doesn't seem broken. 216c535eb59SGordon Tetlow if check_man "$mann" "$catn"; then 217c535eb59SGordon Tetlow return 0 218c535eb59SGordon Tetlow elif check_man "$man0" "$cat0"; then 219c535eb59SGordon Tetlow return 0 220c535eb59SGordon Tetlow elif check_cat "$catn"; then 221c535eb59SGordon Tetlow return 0 222c535eb59SGordon Tetlow elif check_cat "$cat0"; then 223c535eb59SGordon Tetlow return 0 224c535eb59SGordon Tetlow fi 225c535eb59SGordon Tetlow 226c535eb59SGordon Tetlow return 1 227c535eb59SGordon Tetlow} 228c535eb59SGordon Tetlow 229c535eb59SGordon Tetlow# Usage: is_newer file1 file2 230c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime. 231c535eb59SGordon Tetlowis_newer() { 2329b61837aSUlrich Spörlein if ! [ "$1" -ot "$2" ]; then 2339b61837aSUlrich Spörlein decho " mtime: $1 not older than $2" 3 234c535eb59SGordon Tetlow return 0 235c535eb59SGordon Tetlow else 236c535eb59SGordon Tetlow decho " mtime: $1 older than $2" 3 237c535eb59SGordon Tetlow return 1 238c535eb59SGordon Tetlow fi 239c535eb59SGordon Tetlow} 240c535eb59SGordon Tetlow 241c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@" 242c535eb59SGordon Tetlow# Parses commandline options for manpath. 243c535eb59SGordon Tetlowmanpath_parse_args() { 244c535eb59SGordon Tetlow local cmd_arg 245c535eb59SGordon Tetlow 246*f555b39eSKyle Evans OPTIND=1 247c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 248c535eb59SGordon Tetlow case "${cmd_arg}" in 249c535eb59SGordon Tetlow L) Lflag=Lflag ;; 250c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 251c535eb59SGordon Tetlow q) qflag=qflag ;; 252c535eb59SGordon Tetlow *) manpath_usage ;; 253c535eb59SGordon Tetlow esac 254c535eb59SGordon Tetlow done >&2 255c535eb59SGordon Tetlow} 256c535eb59SGordon Tetlow 257c535eb59SGordon Tetlow# Usage: manpath_usage 258c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 259c535eb59SGordon Tetlowmanpath_usage() { 260c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 261c535eb59SGordon Tetlow exit 1 262c535eb59SGordon Tetlow} 263c535eb59SGordon Tetlow 264c535eb59SGordon Tetlow# Usage: manpath_warnings 265c535eb59SGordon Tetlow# Display some warnings to stderr. 266c535eb59SGordon Tetlowmanpath_warnings() { 267c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 268c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 269c535eb59SGordon Tetlow fi 270c535eb59SGordon Tetlow} 271c535eb59SGordon Tetlow 27257cd9717SGordon Tetlow# Usage: man_check_for_so page path 27357cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 27457cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 27557cd9717SGordon Tetlow# redirected to another source file. 27657cd9717SGordon Tetlowman_check_for_so() { 27757cd9717SGordon Tetlow local IFS line tstr 27857cd9717SGordon Tetlow 27957cd9717SGordon Tetlow unset IFS 280d9405a92SBaptiste Daroussin if [ -n "$catpage" ]; then 281d9405a92SBaptiste Daroussin return 0 282d9405a92SBaptiste Daroussin fi 28357cd9717SGordon Tetlow 28457cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 28557cd9717SGordon Tetlow while true 28657cd9717SGordon Tetlow do 28757cd9717SGordon Tetlow line=$($cattool $manpage | head -1) 28857cd9717SGordon Tetlow case "$line" in 28957cd9717SGordon Tetlow .so*) trim "${line#.so}" 29057cd9717SGordon Tetlow decho "$manpage includes $tstr" 29157cd9717SGordon Tetlow # Glob and check for the file. 29257cd9717SGordon Tetlow if ! check_man "$path/$tstr*" ""; then 29357cd9717SGordon Tetlow decho " Unable to find $tstr" 29457cd9717SGordon Tetlow return 1 29557cd9717SGordon Tetlow fi 29657cd9717SGordon Tetlow ;; 29757cd9717SGordon Tetlow *) break ;; 29857cd9717SGordon Tetlow esac 29957cd9717SGordon Tetlow done 30057cd9717SGordon Tetlow 30157cd9717SGordon Tetlow return 0 30257cd9717SGordon Tetlow} 30357cd9717SGordon Tetlow 304b43edc06SBaptiste Daroussin# Usage: man_display_page 305b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 306c535eb59SGordon Tetlowman_display_page() { 3071fb816daSBaptiste Daroussin local IFS pipeline testline 308c535eb59SGordon Tetlow 309c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 310c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 311c535eb59SGordon Tetlow unset IFS 312c535eb59SGordon Tetlow 313c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 314c535eb59SGordon Tetlow # just zcat the catpage and we are done. 315c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 316c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 317c535eb59SGordon Tetlow echo "$catpage (source: $manpage)" 318c535eb59SGordon Tetlow ret=0 319c535eb59SGordon Tetlow else 320c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 321a6a3e856SRuslan Ermilov decho "Command: $cattool $catpage | $MANPAGER" 322c535eb59SGordon Tetlow ret=0 323c535eb59SGordon Tetlow else 324a6a3e856SRuslan Ermilov eval "$cattool $catpage | $MANPAGER" 325c535eb59SGordon Tetlow ret=$? 326c535eb59SGordon Tetlow fi 327c535eb59SGordon Tetlow fi 328c535eb59SGordon Tetlow return 329c535eb59SGordon Tetlow fi 330c535eb59SGordon Tetlow 331c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 332c535eb59SGordon Tetlow # name of the manpage? 333c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 334c535eb59SGordon Tetlow echo "$manpage" 335c535eb59SGordon Tetlow ret=0 336c535eb59SGordon Tetlow return 337c535eb59SGordon Tetlow fi 338c535eb59SGordon Tetlow 339d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 340d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 341d433cf9aSBaptiste Daroussin fi 342451c2becSBaptiste Daroussin testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 343449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 344449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 345449a792dSBaptiste Daroussin else 346d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 347449a792dSBaptiste Daroussin fi 348d6096801SBaptiste Daroussin 349d6096801SBaptiste Daroussin if ! eval "$cattool $manpage | $testline" ;then 350f17575acSBaptiste Daroussin if which -s groff; then 351d6096801SBaptiste Daroussin man_display_page_groff 352d6096801SBaptiste Daroussin else 353d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 354d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 355d6096801SBaptiste Daroussin echo "pkg install groff " >&2 356d6096801SBaptiste Daroussin ret=1 357d6096801SBaptiste Daroussin fi 358d6096801SBaptiste Daroussin return 359d6096801SBaptiste Daroussin fi 360d6096801SBaptiste Daroussin 361d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 362d6096801SBaptiste Daroussin decho "Command: $cattool $manpage | $pipeline" 363d6096801SBaptiste Daroussin ret=0 364d6096801SBaptiste Daroussin else 365d6096801SBaptiste Daroussin eval "$cattool $manpage | $pipeline" 366d6096801SBaptiste Daroussin ret=$? 367d6096801SBaptiste Daroussin fi 368d6096801SBaptiste Daroussin} 369d6096801SBaptiste Daroussin 370b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 371b43edc06SBaptiste Daroussin# Display the manpage using groff 372d6096801SBaptiste Daroussinman_display_page_groff() { 373d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 374d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 375d6096801SBaptiste Daroussin 376c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 377c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 378c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 379c535eb59SGordon Tetlow 380deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 381deeff310SGordon Tetlow # to properly output for the correct device. 382deeff310SGordon Tetlow case "${manpage}" in 383deeff310SGordon Tetlow *.${man_charset}/*) 384c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 385c535eb59SGordon Tetlow # previous version of man(1). 386c535eb59SGordon Tetlow case "$man_charset" in 387c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 388c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 389c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 390c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 391c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 392c535eb59SGordon Tetlow esac 393c535eb59SGordon Tetlow 394deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 395c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 396c535eb59SGordon Tetlow 397deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 398deeff310SGordon Tetlow # then we need to define the locale string. 399deeff310SGordon Tetlow case "${manpage}" in 400deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 401deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 402deeff310SGordon Tetlow ;; 403deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 404deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 405deeff310SGordon Tetlow ;; 406deeff310SGordon Tetlow esac 407deeff310SGordon Tetlow 408c535eb59SGordon Tetlow # Allow language specific calls to override the default 409c535eb59SGordon Tetlow # set of utilities. 410c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 411b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 412c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 413c535eb59SGordon Tetlow done 414c535eb59SGordon Tetlow ;; 415c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 416c535eb59SGordon Tetlow EQN="$EQN -Tascii" 417c535eb59SGordon Tetlow ;; 418c535eb59SGordon Tetlow esac 419c535eb59SGordon Tetlow 420a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 421a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 422a6a3e856SRuslan Ermilov fi 423a6a3e856SRuslan Ermilov 424a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 425a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 426a0094449SRuslan Ermilov fi 427a0094449SRuslan Ermilov 428c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 429c535eb59SGordon Tetlow set -- -$MANROFFSEQ 430*f555b39eSKyle Evans OPTIND=1 431c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 432c535eb59SGordon Tetlow case "${preproc_arg}" in 433c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 434487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 435c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 436c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 437b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 438c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 439c535eb59SGordon Tetlow *) usage ;; 440c535eb59SGordon Tetlow esac 441c535eb59SGordon Tetlow done 442c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 443c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 444c535eb59SGordon Tetlow else 445c535eb59SGordon Tetlow pipeline="$TBL" 446c535eb59SGordon Tetlow fi 447c535eb59SGordon Tetlow 448c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 449c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 450c535eb59SGordon Tetlow else 451a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 452c535eb59SGordon Tetlow fi 453c535eb59SGordon Tetlow 454c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 45557cd9717SGordon Tetlow decho "Command: $cattool $manpage | $pipeline" 456c535eb59SGordon Tetlow ret=0 457c535eb59SGordon Tetlow else 45857cd9717SGordon Tetlow eval "$cattool $manpage | $pipeline" 459c535eb59SGordon Tetlow ret=$? 460c535eb59SGordon Tetlow fi 461c535eb59SGordon Tetlow} 462c535eb59SGordon Tetlow 463c535eb59SGordon Tetlow# Usage: man_find_and_display page 464c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 465c535eb59SGordon Tetlowman_find_and_display() { 466c535eb59SGordon Tetlow local found_page locpath p path sect 467c535eb59SGordon Tetlow 4683d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 4693d9127f1SGordon Tetlow # the filename. 4703d9127f1SGordon Tetlow case "$1" in 4713d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 4723d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 4733d9127f1SGordon Tetlow unset use_cat 4743d9127f1SGordon Tetlow manpage="$1" 47557cd9717SGordon Tetlow setup_cattool $manpage 47657cd9717SGordon Tetlow if man_check_for_so $manpage $(dirname $manpage); then 47757cd9717SGordon Tetlow found_page=yes 4783d9127f1SGordon Tetlow man_display_page 47957cd9717SGordon Tetlow fi 4803d9127f1SGordon Tetlow return 4813d9127f1SGordon Tetlow fi 4823d9127f1SGordon Tetlow ;; 4833d9127f1SGordon Tetlow esac 4843d9127f1SGordon Tetlow 485c535eb59SGordon Tetlow IFS=: 486c535eb59SGordon Tetlow for sect in $MANSECT; do 487c535eb59SGordon Tetlow decho "Searching section $sect" 2 488c535eb59SGordon Tetlow for path in $MANPATH; do 489c535eb59SGordon Tetlow for locpath in $locpaths; do 490c535eb59SGordon Tetlow p=$path/$locpath 491c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 492c535eb59SGordon Tetlow 493c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 494c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 49557cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 496c535eb59SGordon Tetlow found_page=yes 497c535eb59SGordon Tetlow man_display_page 4981d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 4991d7c660aSGordon Tetlow continue 2 5001d7c660aSGordon Tetlow else 501c535eb59SGordon Tetlow return 502c535eb59SGordon Tetlow fi 503c535eb59SGordon Tetlow fi 50457cd9717SGordon Tetlow fi 505c535eb59SGordon Tetlow 506c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 507c535eb59SGordon Tetlow # specific manpath. 508c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 50957cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 510c535eb59SGordon Tetlow found_page=yes 511c535eb59SGordon Tetlow man_display_page 5121d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5131d7c660aSGordon Tetlow continue 2 5141d7c660aSGordon Tetlow else 515c535eb59SGordon Tetlow return 516c535eb59SGordon Tetlow fi 517c535eb59SGordon Tetlow fi 51857cd9717SGordon Tetlow fi 519c535eb59SGordon Tetlow 520c535eb59SGordon Tetlow # Check plain old manpath. 521c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 52257cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 523c535eb59SGordon Tetlow found_page=yes 524c535eb59SGordon Tetlow man_display_page 5251d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5261d7c660aSGordon Tetlow continue 2 5271d7c660aSGordon Tetlow else 528c535eb59SGordon Tetlow return 529c535eb59SGordon Tetlow fi 530c535eb59SGordon Tetlow fi 53157cd9717SGordon Tetlow fi 532c535eb59SGordon Tetlow done 533c535eb59SGordon Tetlow done 534c535eb59SGordon Tetlow done 535c535eb59SGordon Tetlow unset IFS 536c535eb59SGordon Tetlow 537c535eb59SGordon Tetlow # Nothing? Well, we are done then. 538c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 539c535eb59SGordon Tetlow echo "No manual entry for $1" >&2 540c535eb59SGordon Tetlow ret=1 541c535eb59SGordon Tetlow return 542c535eb59SGordon Tetlow fi 543c535eb59SGordon Tetlow} 544c535eb59SGordon Tetlow 545c535eb59SGordon Tetlow# Usage: man_parse_args "$@" 546c535eb59SGordon Tetlow# Parses commandline options for man. 547c535eb59SGordon Tetlowman_parse_args() { 548c535eb59SGordon Tetlow local IFS cmd_arg 549c535eb59SGordon Tetlow 550*f555b39eSKyle Evans OPTIND=1 551c535eb59SGordon Tetlow while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do 552c535eb59SGordon Tetlow case "${cmd_arg}" in 553c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 554a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 555c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 556c535eb59SGordon Tetlow a) aflag=aflag ;; 557c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 558c535eb59SGordon Tetlow f) fflag=fflag ;; 559c535eb59SGordon Tetlow h) man_usage 0 ;; 560c535eb59SGordon Tetlow k) kflag=kflag ;; 561c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 562c535eb59SGordon Tetlow o) oflag=oflag ;; 563c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 564c535eb59SGordon Tetlow t) tflag=tflag ;; 565c535eb59SGordon Tetlow w) wflag=wflag ;; 566c535eb59SGordon Tetlow *) man_usage ;; 567c535eb59SGordon Tetlow esac 568c535eb59SGordon Tetlow done >&2 569c535eb59SGordon Tetlow 570c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 571c535eb59SGordon Tetlow 572c535eb59SGordon Tetlow # Check the args for incompatible options. 573c535eb59SGordon Tetlow case "${fflag}${kflag}${tflag}${wflag}" in 574c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 575c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 576c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 577c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 578c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 579c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 580c535eb59SGordon Tetlow esac 581c535eb59SGordon Tetlow 582c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 583c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 584c535eb59SGordon Tetlow do_whatis "$@" 585c535eb59SGordon Tetlow exit 586c535eb59SGordon Tetlow fi 587c535eb59SGordon Tetlow 588c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 589c535eb59SGordon Tetlow do_apropos "$@" 590c535eb59SGordon Tetlow exit 591c535eb59SGordon Tetlow fi 592c535eb59SGordon Tetlow 593c535eb59SGordon Tetlow IFS=: 594c535eb59SGordon Tetlow for sect in $man_default_sections; do 595c535eb59SGordon Tetlow if [ "$sect" = "$1" ]; then 596c535eb59SGordon Tetlow decho "Detected manual section as first arg: $1" 597c535eb59SGordon Tetlow MANSECT="$1" 598c535eb59SGordon Tetlow shift 599c535eb59SGordon Tetlow break 600c535eb59SGordon Tetlow fi 601c535eb59SGordon Tetlow done 602c535eb59SGordon Tetlow unset IFS 603c535eb59SGordon Tetlow 604c535eb59SGordon Tetlow pages="$*" 605c535eb59SGordon Tetlow} 606c535eb59SGordon Tetlow 607c535eb59SGordon Tetlow# Usage: man_setup 608c535eb59SGordon Tetlow# Setup various trivial but essential variables. 609c535eb59SGordon Tetlowman_setup() { 610c535eb59SGordon Tetlow # Setup machine and architecture variables. 611c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 612c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 613c535eb59SGordon Tetlow MACHINE=${mflag##*:} 614c535eb59SGordon Tetlow fi 615c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 61682db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 617c535eb59SGordon Tetlow fi 618c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 61982db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 620c535eb59SGordon Tetlow fi 621c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 622c535eb59SGordon Tetlow 623c535eb59SGordon Tetlow setup_pager 624c535eb59SGordon Tetlow 625c535eb59SGordon Tetlow # Setup manual sections to search. 626c535eb59SGordon Tetlow if [ -z "$MANSECT" ]; then 627c535eb59SGordon Tetlow MANSECT=$man_default_sections 628c535eb59SGordon Tetlow fi 629c535eb59SGordon Tetlow decho "Using manual sections: $MANSECT" 630c535eb59SGordon Tetlow 631c535eb59SGordon Tetlow build_manpath 632c535eb59SGordon Tetlow man_setup_locale 633a0094449SRuslan Ermilov man_setup_width 634a0094449SRuslan Ermilov} 635a0094449SRuslan Ermilov 636a0094449SRuslan Ermilov# Usage: man_setup_width 637a0094449SRuslan Ermilov# Set up page width. 638a0094449SRuslan Ermilovman_setup_width() { 639a0094449SRuslan Ermilov local sizes 640a0094449SRuslan Ermilov 641a0094449SRuslan Ermilov unset use_width 642a0094449SRuslan Ermilov case "$MANWIDTH" in 643a0094449SRuslan Ermilov [0-9]*) 644a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 645a0094449SRuslan Ermilov use_width=$MANWIDTH 646a0094449SRuslan Ermilov fi 647a0094449SRuslan Ermilov ;; 648a0094449SRuslan Ermilov [Tt][Tt][Yy]) 649a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 650a0094449SRuslan Ermilov set -- $sizes 651a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 652a0094449SRuslan Ermilov use_width=$(($2-2)) 653a0094449SRuslan Ermilov fi 654a0094449SRuslan Ermilov fi 655a0094449SRuslan Ermilov ;; 656a0094449SRuslan Ermilov esac 657a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 658a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 659a0094449SRuslan Ermilov else 660a0094449SRuslan Ermilov decho 'Using standard page width' 661a0094449SRuslan Ermilov fi 662c535eb59SGordon Tetlow} 663c535eb59SGordon Tetlow 664c535eb59SGordon Tetlow# Usage: man_setup_locale 665c535eb59SGordon Tetlow# Setup necessary locale variables. 666c535eb59SGordon Tetlowman_setup_locale() { 667deeff310SGordon Tetlow local lang_cc 6689508f8c0SYuri Pankov local locstr 669deeff310SGordon Tetlow 670deeff310SGordon Tetlow locpaths='.' 671deeff310SGordon Tetlow man_charset='US-ASCII' 672deeff310SGordon Tetlow 673c535eb59SGordon Tetlow # Setup locale information. 674c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 675deeff310SGordon Tetlow decho 'Using non-localized manpages' 676deeff310SGordon Tetlow else 6779508f8c0SYuri Pankov # Use the locale tool to give us proper locale information 678deeff310SGordon Tetlow eval $( $LOCALE ) 679c535eb59SGordon Tetlow 6809508f8c0SYuri Pankov if [ -n "$LANG" ]; then 6819508f8c0SYuri Pankov locstr=$LANG 6829508f8c0SYuri Pankov else 6839508f8c0SYuri Pankov locstr=$LC_CTYPE 6849508f8c0SYuri Pankov fi 6859508f8c0SYuri Pankov 6869508f8c0SYuri Pankov case "$locstr" in 687deeff310SGordon Tetlow C) ;; 6889508f8c0SYuri Pankov C.UTF-8) ;; 689deeff310SGordon Tetlow POSIX) ;; 690deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 6919508f8c0SYuri Pankov lang_cc="${locstr%.*}" 6929508f8c0SYuri Pankov man_lang="${locstr%_*}" 693deeff310SGordon Tetlow man_country="${lang_cc#*_}" 6949508f8c0SYuri Pankov man_charset="${locstr#*.}" 6959508f8c0SYuri Pankov locpaths="$locstr" 696c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 697c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 698c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 699c535eb59SGordon Tetlow fi 700c535eb59SGordon Tetlow locpaths="$locpaths:." 701deeff310SGordon Tetlow ;; 702deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 703deeff310SGordon Tetlow ;; 704deeff310SGordon Tetlow esac 705c535eb59SGordon Tetlow fi 706deeff310SGordon Tetlow 707c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 708c535eb59SGordon Tetlow} 709c535eb59SGordon Tetlow 710c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 711c535eb59SGordon Tetlow# Display usage for the man utility. 712c535eb59SGordon Tetlowman_usage() { 713c535eb59SGordon Tetlow echo 'Usage:' 714c535eb59SGordon Tetlow echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]' 715c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 716c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 717c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 718c535eb59SGordon Tetlow 719c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 720c535eb59SGordon Tetlow exit ${1:-1} 721c535eb59SGordon Tetlow} 722c535eb59SGordon Tetlow 723c535eb59SGordon Tetlow# Usage: parse_configs 724c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 725c535eb59SGordon Tetlowparse_configs() { 726c535eb59SGordon Tetlow local IFS file files 727c535eb59SGordon Tetlow 728c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 729c535eb59SGordon Tetlow return 730c535eb59SGordon Tetlow fi 731c535eb59SGordon Tetlow 732c535eb59SGordon Tetlow unset IFS 733c535eb59SGordon Tetlow 734c535eb59SGordon Tetlow # Read the global config first in case the user wants 735c535eb59SGordon Tetlow # to override config_local. 736c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 737c535eb59SGordon Tetlow parse_file "$config_global" 738c535eb59SGordon Tetlow fi 739c535eb59SGordon Tetlow 740c535eb59SGordon Tetlow # Glob the list of files to parse. 741c535eb59SGordon Tetlow set +f 742c535eb59SGordon Tetlow files=$(echo $config_local) 743c535eb59SGordon Tetlow set -f 744c535eb59SGordon Tetlow 745c535eb59SGordon Tetlow for file in $files; do 746c535eb59SGordon Tetlow if [ -r "$file" ]; then 747c535eb59SGordon Tetlow parse_file "$file" 748c535eb59SGordon Tetlow fi 749c535eb59SGordon Tetlow done 750c535eb59SGordon Tetlow 751c535eb59SGordon Tetlow parsed_configs='yes' 752c535eb59SGordon Tetlow} 753c535eb59SGordon Tetlow 754c535eb59SGordon Tetlow# Usage: parse_file file 755c535eb59SGordon Tetlow# Reads the specified config files. 756c535eb59SGordon Tetlowparse_file() { 757c535eb59SGordon Tetlow local file line tstr var 758c535eb59SGordon Tetlow 759c535eb59SGordon Tetlow file="$1" 760c535eb59SGordon Tetlow decho "Parsing config file: $file" 761c535eb59SGordon Tetlow while read line; do 762c535eb59SGordon Tetlow decho " $line" 2 763c535eb59SGordon Tetlow case "$line" in 764c535eb59SGordon Tetlow \#*) decho " Comment" 3 765c535eb59SGordon Tetlow ;; 766c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 767c535eb59SGordon Tetlow trim "${line#MANPATH}" 768c535eb59SGordon Tetlow add_to_manpath "$tstr" 769c535eb59SGordon Tetlow ;; 770c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 771c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 772c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 773c535eb59SGordon Tetlow ;; 774c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 775a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 776c535eb59SGordon Tetlow config_local="$tstr" 777c535eb59SGordon Tetlow ;; 778c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 779c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 780c535eb59SGordon Tetlow trim "${line#$var}" 781c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 782c535eb59SGordon Tetlow decho " Parsed $var" 3 783c535eb59SGordon Tetlow ;; 784c535eb59SGordon Tetlow esac 785c535eb59SGordon Tetlow done < "$file" 786c535eb59SGordon Tetlow} 787c535eb59SGordon Tetlow 788c535eb59SGordon Tetlow# Usage: search_path 789c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 790c535eb59SGordon Tetlowsearch_path() { 791c535eb59SGordon Tetlow local IFS p path 792c535eb59SGordon Tetlow 793c535eb59SGordon Tetlow decho "Searching PATH for man directories" 794c535eb59SGordon Tetlow 795c535eb59SGordon Tetlow IFS=: 796c535eb59SGordon Tetlow for path in $PATH; do 797971c1c42STijl Coosemans if add_to_manpath "$path/man"; then 798c535eb59SGordon Tetlow : 799c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 800c535eb59SGordon Tetlow : 801c535eb59SGordon Tetlow else 802c535eb59SGordon Tetlow case "$path" in 803971c1c42STijl Coosemans */bin) p="${path%/bin}/share/man" 804c535eb59SGordon Tetlow add_to_manpath "$p" 805971c1c42STijl Coosemans p="${path%/bin}/man" 80661d5f2d1SBaptiste Daroussin add_to_manpath "$p" 807c535eb59SGordon Tetlow ;; 808c535eb59SGordon Tetlow esac 809c535eb59SGordon Tetlow fi 810c535eb59SGordon Tetlow done 811c535eb59SGordon Tetlow unset IFS 812c535eb59SGordon Tetlow 813c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 814c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 815c535eb59SGordon Tetlow manpath=$man_default_path 816c535eb59SGordon Tetlow fi 817c535eb59SGordon Tetlow} 818c535eb59SGordon Tetlow 819c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 820c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 821c535eb59SGordon Tetlowsearch_whatis() { 822c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 823c535eb59SGordon Tetlow 824c535eb59SGordon Tetlow cmd="$1" 825c535eb59SGordon Tetlow shift 826c535eb59SGordon Tetlow 827c535eb59SGordon Tetlow whatis_parse_args "$@" 828c535eb59SGordon Tetlow 829c535eb59SGordon Tetlow build_manpath 830c535eb59SGordon Tetlow build_manlocales 831c535eb59SGordon Tetlow setup_pager 832c535eb59SGordon Tetlow 833c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 834c535eb59SGordon Tetlow opt="-w" 835c535eb59SGordon Tetlow fi 836c535eb59SGordon Tetlow 837c535eb59SGordon Tetlow f='whatis' 838c535eb59SGordon Tetlow 839c535eb59SGordon Tetlow IFS=: 840c535eb59SGordon Tetlow for path in $MANPATH; do 841c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 842c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 843c535eb59SGordon Tetlow continue 844c535eb59SGordon Tetlow fi 845c535eb59SGordon Tetlow 846c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 847c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 848c535eb59SGordon Tetlow wlist="$wlist $path/$f" 849c535eb59SGordon Tetlow fi 850c535eb59SGordon Tetlow 851c535eb59SGordon Tetlow for loc in $MANLOCALES; do 852c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 853c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 854c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 855c535eb59SGordon Tetlow fi 856c535eb59SGordon Tetlow done 857c535eb59SGordon Tetlow done 858c535eb59SGordon Tetlow unset IFS 859c535eb59SGordon Tetlow 860c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 861c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 862c535eb59SGordon Tetlow exit 1 863c535eb59SGordon Tetlow fi 864c535eb59SGordon Tetlow 865c535eb59SGordon Tetlow rval=0 866c535eb59SGordon Tetlow for key in $keywords; do 867c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 868c535eb59SGordon Tetlow if [ -n "$out" ]; then 869c535eb59SGordon Tetlow good="$good\\n$out" 870c535eb59SGordon Tetlow else 871c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 872c535eb59SGordon Tetlow rval=1 873c535eb59SGordon Tetlow fi 874c535eb59SGordon Tetlow done 875c535eb59SGordon Tetlow 876c535eb59SGordon Tetlow # Strip leading carriage return. 877c535eb59SGordon Tetlow good=${good#\\n} 878c535eb59SGordon Tetlow bad=${bad#\\n} 879c535eb59SGordon Tetlow 880c535eb59SGordon Tetlow if [ -n "$good" ]; then 881a6a3e856SRuslan Ermilov echo -e "$good" | $MANPAGER 882c535eb59SGordon Tetlow fi 883c535eb59SGordon Tetlow 884c535eb59SGordon Tetlow if [ -n "$bad" ]; then 88500e05e69SGordon Tetlow echo -e "$bad" >&2 886c535eb59SGordon Tetlow fi 887c535eb59SGordon Tetlow 888c535eb59SGordon Tetlow exit $rval 889c535eb59SGordon Tetlow} 890c535eb59SGordon Tetlow 89157cd9717SGordon Tetlow# Usage: setup_cattool page 89257cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 89357cd9717SGordon Tetlowsetup_cattool() { 89457cd9717SGordon Tetlow case "$1" in 89557cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 89657cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 89757cd9717SGordon Tetlow *.gz) cattool='/usr/bin/zcat' ;; 89857cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 89957cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 90057cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 90157cd9717SGordon Tetlow esac 90257cd9717SGordon Tetlow} 90357cd9717SGordon Tetlow 904c535eb59SGordon Tetlow# Usage: setup_pager 905a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 906c535eb59SGordon Tetlowsetup_pager() { 907c535eb59SGordon Tetlow # Setup pager. 908a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 909a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 910a6a3e856SRuslan Ermilov MANPAGER="less -sR" 911a6a3e856SRuslan Ermilov else 912a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 913a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 914a6a3e856SRuslan Ermilov else 91547cc9ee1SAlan Somers MANPAGER="less -s" 916c535eb59SGordon Tetlow fi 917a6a3e856SRuslan Ermilov fi 918a6a3e856SRuslan Ermilov fi 919a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 920c535eb59SGordon Tetlow} 921c535eb59SGordon Tetlow 922c535eb59SGordon Tetlow# Usage: trim string 923c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 924c535eb59SGordon Tetlowtrim() { 925c535eb59SGordon Tetlow tstr=$1 926c535eb59SGordon Tetlow while true; do 927c535eb59SGordon Tetlow case "$tstr" in 928c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 929c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 930c535eb59SGordon Tetlow *) break ;; 931c535eb59SGordon Tetlow esac 932c535eb59SGordon Tetlow done 933c535eb59SGordon Tetlow} 934c535eb59SGordon Tetlow 935c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 936c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 937c535eb59SGordon Tetlowwhatis_parse_args() { 938c535eb59SGordon Tetlow local cmd_arg 939*f555b39eSKyle Evans OPTIND=1 940c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 941c535eb59SGordon Tetlow case "${cmd_arg}" in 942c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 943c535eb59SGordon Tetlow *) whatis_usage ;; 944c535eb59SGordon Tetlow esac 945c535eb59SGordon Tetlow done >&2 946c535eb59SGordon Tetlow 947c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 948c535eb59SGordon Tetlow 949c535eb59SGordon Tetlow keywords="$*" 950c535eb59SGordon Tetlow} 951c535eb59SGordon Tetlow 952c535eb59SGordon Tetlow# Usage: whatis_usage 953c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 954c535eb59SGordon Tetlowwhatis_usage() { 955c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 956c535eb59SGordon Tetlow exit 1 957c535eb59SGordon Tetlow} 958c535eb59SGordon Tetlow 959c535eb59SGordon Tetlow 960c535eb59SGordon Tetlow 961c535eb59SGordon Tetlow# Supported commands 962c535eb59SGordon Tetlowdo_apropos() { 96324ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 964772246efSBaptiste Daroussin exec apropos "$@" 965c535eb59SGordon Tetlow search_whatis apropos "$@" 966c535eb59SGordon Tetlow} 967c535eb59SGordon Tetlow 968c535eb59SGordon Tetlowdo_man() { 969c535eb59SGordon Tetlow man_parse_args "$@" 970c535eb59SGordon Tetlow if [ -z "$pages" ]; then 971c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 972c535eb59SGordon Tetlow exit 1 973c535eb59SGordon Tetlow fi 974c535eb59SGordon Tetlow man_setup 975c535eb59SGordon Tetlow 976c535eb59SGordon Tetlow for page in $pages; do 977c535eb59SGordon Tetlow decho "Searching for $page" 978c535eb59SGordon Tetlow man_find_and_display "$page" 979c535eb59SGordon Tetlow done 980c535eb59SGordon Tetlow 981c535eb59SGordon Tetlow exit ${ret:-0} 982c535eb59SGordon Tetlow} 983c535eb59SGordon Tetlow 984c535eb59SGordon Tetlowdo_manpath() { 985c535eb59SGordon Tetlow manpath_parse_args "$@" 986c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 987c535eb59SGordon Tetlow manpath_warnings 988c535eb59SGordon Tetlow fi 989c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 990c535eb59SGordon Tetlow build_manlocales 991c535eb59SGordon Tetlow echo $MANLOCALES 992c535eb59SGordon Tetlow else 993c535eb59SGordon Tetlow build_manpath 994c535eb59SGordon Tetlow echo $MANPATH 995c535eb59SGordon Tetlow fi 996c535eb59SGordon Tetlow exit 0 997c535eb59SGordon Tetlow} 998c535eb59SGordon Tetlow 999c535eb59SGordon Tetlowdo_whatis() { 100024ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 1001772246efSBaptiste Daroussin exec whatis "$@" 1002c535eb59SGordon Tetlow search_whatis whatis "$@" 1003c535eb59SGordon Tetlow} 1004c535eb59SGordon Tetlow 1005aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 1006aeea395eSUlrich SpörleinEQN=eqn 1007a6a3e856SRuslan ErmilovNROFF='groff -S -P-h -Wall -mtty-char -man' 1008aeea395eSUlrich SpörleinPIC=pic 1009aeea395eSUlrich SpörleinREFER=refer 1010aeea395eSUlrich SpörleinTBL=tbl 10113d120968SUlrich SpörleinTROFF='groff -S -man' 1012aeea395eSUlrich SpörleinVGRIND=vgrind 1013aeea395eSUlrich Spörlein 1014deeff310SGordon TetlowLOCALE=/usr/bin/locale 1015a0094449SRuslan ErmilovSTTY=/bin/stty 101682db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1017c535eb59SGordon Tetlow 1018c535eb59SGordon Tetlowdebug=0 101973577bf0SRyan Moellerman_default_sections='1:8:2:3:3lua:n:4:5:6:7:9:l' 1020971c1c42STijl Coosemansman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man' 102157cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1022c535eb59SGordon Tetlow 1023c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1024c535eb59SGordon Tetlow 1025c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1026c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1027c535eb59SGordon Tetlow 1028c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1029c535eb59SGordon Tetlowset -f 1030c535eb59SGordon Tetlow 1031c535eb59SGordon Tetlowcase "$0" in 1032c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1033c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1034c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1035c535eb59SGordon Tetlow*) do_man "$@" ;; 1036c535eb59SGordon Tetlowesac 1037