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 204*625490e8SBaptiste 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 246c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 247c535eb59SGordon Tetlow case "${cmd_arg}" in 248c535eb59SGordon Tetlow L) Lflag=Lflag ;; 249c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 250c535eb59SGordon Tetlow q) qflag=qflag ;; 251c535eb59SGordon Tetlow *) manpath_usage ;; 252c535eb59SGordon Tetlow esac 253c535eb59SGordon Tetlow done >&2 254c535eb59SGordon Tetlow} 255c535eb59SGordon Tetlow 256c535eb59SGordon Tetlow# Usage: manpath_usage 257c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 258c535eb59SGordon Tetlowmanpath_usage() { 259c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 260c535eb59SGordon Tetlow exit 1 261c535eb59SGordon Tetlow} 262c535eb59SGordon Tetlow 263c535eb59SGordon Tetlow# Usage: manpath_warnings 264c535eb59SGordon Tetlow# Display some warnings to stderr. 265c535eb59SGordon Tetlowmanpath_warnings() { 266c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 267c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 268c535eb59SGordon Tetlow fi 269c535eb59SGordon Tetlow} 270c535eb59SGordon Tetlow 27157cd9717SGordon Tetlow# Usage: man_check_for_so page path 27257cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 27357cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 27457cd9717SGordon Tetlow# redirected to another source file. 27557cd9717SGordon Tetlowman_check_for_so() { 27657cd9717SGordon Tetlow local IFS line tstr 27757cd9717SGordon Tetlow 27857cd9717SGordon Tetlow unset IFS 279d9405a92SBaptiste Daroussin if [ -n "$catpage" ]; then 280d9405a92SBaptiste Daroussin return 0 281d9405a92SBaptiste Daroussin fi 28257cd9717SGordon Tetlow 28357cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 28457cd9717SGordon Tetlow while true 28557cd9717SGordon Tetlow do 28657cd9717SGordon Tetlow line=$($cattool $manpage | head -1) 28757cd9717SGordon Tetlow case "$line" in 28857cd9717SGordon Tetlow .so*) trim "${line#.so}" 28957cd9717SGordon Tetlow decho "$manpage includes $tstr" 29057cd9717SGordon Tetlow # Glob and check for the file. 29157cd9717SGordon Tetlow if ! check_man "$path/$tstr*" ""; then 29257cd9717SGordon Tetlow decho " Unable to find $tstr" 29357cd9717SGordon Tetlow return 1 29457cd9717SGordon Tetlow fi 29557cd9717SGordon Tetlow ;; 29657cd9717SGordon Tetlow *) break ;; 29757cd9717SGordon Tetlow esac 29857cd9717SGordon Tetlow done 29957cd9717SGordon Tetlow 30057cd9717SGordon Tetlow return 0 30157cd9717SGordon Tetlow} 30257cd9717SGordon Tetlow 303b43edc06SBaptiste Daroussin# Usage: man_display_page 304b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 305c535eb59SGordon Tetlowman_display_page() { 3061fb816daSBaptiste Daroussin local IFS pipeline testline 307c535eb59SGordon Tetlow 308c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 309c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 310c535eb59SGordon Tetlow unset IFS 311c535eb59SGordon Tetlow 312c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 313c535eb59SGordon Tetlow # just zcat the catpage and we are done. 314c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 315c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 316c535eb59SGordon Tetlow echo "$catpage (source: $manpage)" 317c535eb59SGordon Tetlow ret=0 318c535eb59SGordon Tetlow else 319c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 320a6a3e856SRuslan Ermilov decho "Command: $cattool $catpage | $MANPAGER" 321c535eb59SGordon Tetlow ret=0 322c535eb59SGordon Tetlow else 323a6a3e856SRuslan Ermilov eval "$cattool $catpage | $MANPAGER" 324c535eb59SGordon Tetlow ret=$? 325c535eb59SGordon Tetlow fi 326c535eb59SGordon Tetlow fi 327c535eb59SGordon Tetlow return 328c535eb59SGordon Tetlow fi 329c535eb59SGordon Tetlow 330c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 331c535eb59SGordon Tetlow # name of the manpage? 332c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 333c535eb59SGordon Tetlow echo "$manpage" 334c535eb59SGordon Tetlow ret=0 335c535eb59SGordon Tetlow return 336c535eb59SGordon Tetlow fi 337c535eb59SGordon Tetlow 338d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 339d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 340d433cf9aSBaptiste Daroussin fi 341451c2becSBaptiste Daroussin testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 342449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 343449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 344449a792dSBaptiste Daroussin else 345d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 346449a792dSBaptiste Daroussin fi 347d6096801SBaptiste Daroussin 348d6096801SBaptiste Daroussin if ! eval "$cattool $manpage | $testline" ;then 349f17575acSBaptiste Daroussin if which -s groff; then 350d6096801SBaptiste Daroussin man_display_page_groff 351d6096801SBaptiste Daroussin else 352d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 353d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 354d6096801SBaptiste Daroussin echo "pkg install groff " >&2 355d6096801SBaptiste Daroussin ret=1 356d6096801SBaptiste Daroussin fi 357d6096801SBaptiste Daroussin return 358d6096801SBaptiste Daroussin fi 359d6096801SBaptiste Daroussin 360d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 361d6096801SBaptiste Daroussin decho "Command: $cattool $manpage | $pipeline" 362d6096801SBaptiste Daroussin ret=0 363d6096801SBaptiste Daroussin else 364d6096801SBaptiste Daroussin eval "$cattool $manpage | $pipeline" 365d6096801SBaptiste Daroussin ret=$? 366d6096801SBaptiste Daroussin fi 367d6096801SBaptiste Daroussin} 368d6096801SBaptiste Daroussin 369b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 370b43edc06SBaptiste Daroussin# Display the manpage using groff 371d6096801SBaptiste Daroussinman_display_page_groff() { 372d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 373d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 374d6096801SBaptiste Daroussin 375c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 376c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 377c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 378c535eb59SGordon Tetlow 379deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 380deeff310SGordon Tetlow # to properly output for the correct device. 381deeff310SGordon Tetlow case "${manpage}" in 382deeff310SGordon Tetlow *.${man_charset}/*) 383c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 384c535eb59SGordon Tetlow # previous version of man(1). 385c535eb59SGordon Tetlow case "$man_charset" in 386c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 387c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 388c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 389c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 390c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 391c535eb59SGordon Tetlow esac 392c535eb59SGordon Tetlow 393deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 394c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 395c535eb59SGordon Tetlow 396deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 397deeff310SGordon Tetlow # then we need to define the locale string. 398deeff310SGordon Tetlow case "${manpage}" in 399deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 400deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 401deeff310SGordon Tetlow ;; 402deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 403deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 404deeff310SGordon Tetlow ;; 405deeff310SGordon Tetlow esac 406deeff310SGordon Tetlow 407c535eb59SGordon Tetlow # Allow language specific calls to override the default 408c535eb59SGordon Tetlow # set of utilities. 409c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 410b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 411c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 412c535eb59SGordon Tetlow done 413c535eb59SGordon Tetlow ;; 414c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 415c535eb59SGordon Tetlow EQN="$EQN -Tascii" 416c535eb59SGordon Tetlow ;; 417c535eb59SGordon Tetlow esac 418c535eb59SGordon Tetlow 419a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 420a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 421a6a3e856SRuslan Ermilov fi 422a6a3e856SRuslan Ermilov 423a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 424a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 425a0094449SRuslan Ermilov fi 426a0094449SRuslan Ermilov 427c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 428c535eb59SGordon Tetlow set -- -$MANROFFSEQ 429c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 430c535eb59SGordon Tetlow case "${preproc_arg}" in 431c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 432487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 433c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 434c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 435b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 436c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 437c535eb59SGordon Tetlow *) usage ;; 438c535eb59SGordon Tetlow esac 439c535eb59SGordon Tetlow done 440c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 441c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 442c535eb59SGordon Tetlow else 443c535eb59SGordon Tetlow pipeline="$TBL" 444c535eb59SGordon Tetlow fi 445c535eb59SGordon Tetlow 446c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 447c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 448c535eb59SGordon Tetlow else 449a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 450c535eb59SGordon Tetlow fi 451c535eb59SGordon Tetlow 452c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 45357cd9717SGordon Tetlow decho "Command: $cattool $manpage | $pipeline" 454c535eb59SGordon Tetlow ret=0 455c535eb59SGordon Tetlow else 45657cd9717SGordon Tetlow eval "$cattool $manpage | $pipeline" 457c535eb59SGordon Tetlow ret=$? 458c535eb59SGordon Tetlow fi 459c535eb59SGordon Tetlow} 460c535eb59SGordon Tetlow 461c535eb59SGordon Tetlow# Usage: man_find_and_display page 462c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 463c535eb59SGordon Tetlowman_find_and_display() { 464c535eb59SGordon Tetlow local found_page locpath p path sect 465c535eb59SGordon Tetlow 4663d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 4673d9127f1SGordon Tetlow # the filename. 4683d9127f1SGordon Tetlow case "$1" in 4693d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 4703d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 4713d9127f1SGordon Tetlow unset use_cat 4723d9127f1SGordon Tetlow manpage="$1" 47357cd9717SGordon Tetlow setup_cattool $manpage 47457cd9717SGordon Tetlow if man_check_for_so $manpage $(dirname $manpage); then 47557cd9717SGordon Tetlow found_page=yes 4763d9127f1SGordon Tetlow man_display_page 47757cd9717SGordon Tetlow fi 4783d9127f1SGordon Tetlow return 4793d9127f1SGordon Tetlow fi 4803d9127f1SGordon Tetlow ;; 4813d9127f1SGordon Tetlow esac 4823d9127f1SGordon Tetlow 483c535eb59SGordon Tetlow IFS=: 484c535eb59SGordon Tetlow for sect in $MANSECT; do 485c535eb59SGordon Tetlow decho "Searching section $sect" 2 486c535eb59SGordon Tetlow for path in $MANPATH; do 487c535eb59SGordon Tetlow for locpath in $locpaths; do 488c535eb59SGordon Tetlow p=$path/$locpath 489c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 490c535eb59SGordon Tetlow 491c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 492c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 49357cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 494c535eb59SGordon Tetlow found_page=yes 495c535eb59SGordon Tetlow man_display_page 4961d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 4971d7c660aSGordon Tetlow continue 2 4981d7c660aSGordon Tetlow else 499c535eb59SGordon Tetlow return 500c535eb59SGordon Tetlow fi 501c535eb59SGordon Tetlow fi 50257cd9717SGordon Tetlow fi 503c535eb59SGordon Tetlow 504c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 505c535eb59SGordon Tetlow # specific manpath. 506c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 50757cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 508c535eb59SGordon Tetlow found_page=yes 509c535eb59SGordon Tetlow man_display_page 5101d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5111d7c660aSGordon Tetlow continue 2 5121d7c660aSGordon Tetlow else 513c535eb59SGordon Tetlow return 514c535eb59SGordon Tetlow fi 515c535eb59SGordon Tetlow fi 51657cd9717SGordon Tetlow fi 517c535eb59SGordon Tetlow 518c535eb59SGordon Tetlow # Check plain old manpath. 519c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 52057cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 521c535eb59SGordon Tetlow found_page=yes 522c535eb59SGordon Tetlow man_display_page 5231d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5241d7c660aSGordon Tetlow continue 2 5251d7c660aSGordon Tetlow else 526c535eb59SGordon Tetlow return 527c535eb59SGordon Tetlow fi 528c535eb59SGordon Tetlow fi 52957cd9717SGordon Tetlow fi 530c535eb59SGordon Tetlow done 531c535eb59SGordon Tetlow done 532c535eb59SGordon Tetlow done 533c535eb59SGordon Tetlow unset IFS 534c535eb59SGordon Tetlow 535c535eb59SGordon Tetlow # Nothing? Well, we are done then. 536c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 537c535eb59SGordon Tetlow echo "No manual entry for $1" >&2 538c535eb59SGordon Tetlow ret=1 539c535eb59SGordon Tetlow return 540c535eb59SGordon Tetlow fi 541c535eb59SGordon Tetlow} 542c535eb59SGordon Tetlow 543c535eb59SGordon Tetlow# Usage: man_parse_args "$@" 544c535eb59SGordon Tetlow# Parses commandline options for man. 545c535eb59SGordon Tetlowman_parse_args() { 546c535eb59SGordon Tetlow local IFS cmd_arg 547c535eb59SGordon Tetlow 548c535eb59SGordon Tetlow while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do 549c535eb59SGordon Tetlow case "${cmd_arg}" in 550c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 551a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 552c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 553c535eb59SGordon Tetlow a) aflag=aflag ;; 554c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 555c535eb59SGordon Tetlow f) fflag=fflag ;; 556c535eb59SGordon Tetlow h) man_usage 0 ;; 557c535eb59SGordon Tetlow k) kflag=kflag ;; 558c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 559c535eb59SGordon Tetlow o) oflag=oflag ;; 560c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 561c535eb59SGordon Tetlow t) tflag=tflag ;; 562c535eb59SGordon Tetlow w) wflag=wflag ;; 563c535eb59SGordon Tetlow *) man_usage ;; 564c535eb59SGordon Tetlow esac 565c535eb59SGordon Tetlow done >&2 566c535eb59SGordon Tetlow 567c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 568c535eb59SGordon Tetlow 569c535eb59SGordon Tetlow # Check the args for incompatible options. 570c535eb59SGordon Tetlow case "${fflag}${kflag}${tflag}${wflag}" in 571c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 572c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 573c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 574c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 575c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 576c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 577c535eb59SGordon Tetlow esac 578c535eb59SGordon Tetlow 579c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 580c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 581c535eb59SGordon Tetlow do_whatis "$@" 582c535eb59SGordon Tetlow exit 583c535eb59SGordon Tetlow fi 584c535eb59SGordon Tetlow 585c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 586c535eb59SGordon Tetlow do_apropos "$@" 587c535eb59SGordon Tetlow exit 588c535eb59SGordon Tetlow fi 589c535eb59SGordon Tetlow 590c535eb59SGordon Tetlow IFS=: 591c535eb59SGordon Tetlow for sect in $man_default_sections; do 592c535eb59SGordon Tetlow if [ "$sect" = "$1" ]; then 593c535eb59SGordon Tetlow decho "Detected manual section as first arg: $1" 594c535eb59SGordon Tetlow MANSECT="$1" 595c535eb59SGordon Tetlow shift 596c535eb59SGordon Tetlow break 597c535eb59SGordon Tetlow fi 598c535eb59SGordon Tetlow done 599c535eb59SGordon Tetlow unset IFS 600c535eb59SGordon Tetlow 601c535eb59SGordon Tetlow pages="$*" 602c535eb59SGordon Tetlow} 603c535eb59SGordon Tetlow 604c535eb59SGordon Tetlow# Usage: man_setup 605c535eb59SGordon Tetlow# Setup various trivial but essential variables. 606c535eb59SGordon Tetlowman_setup() { 607c535eb59SGordon Tetlow # Setup machine and architecture variables. 608c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 609c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 610c535eb59SGordon Tetlow MACHINE=${mflag##*:} 611c535eb59SGordon Tetlow fi 612c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 61382db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 614c535eb59SGordon Tetlow fi 615c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 61682db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 617c535eb59SGordon Tetlow fi 618c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 619c535eb59SGordon Tetlow 620c535eb59SGordon Tetlow setup_pager 621c535eb59SGordon Tetlow 622c535eb59SGordon Tetlow # Setup manual sections to search. 623c535eb59SGordon Tetlow if [ -z "$MANSECT" ]; then 624c535eb59SGordon Tetlow MANSECT=$man_default_sections 625c535eb59SGordon Tetlow fi 626c535eb59SGordon Tetlow decho "Using manual sections: $MANSECT" 627c535eb59SGordon Tetlow 628c535eb59SGordon Tetlow build_manpath 629c535eb59SGordon Tetlow man_setup_locale 630a0094449SRuslan Ermilov man_setup_width 631a0094449SRuslan Ermilov} 632a0094449SRuslan Ermilov 633a0094449SRuslan Ermilov# Usage: man_setup_width 634a0094449SRuslan Ermilov# Set up page width. 635a0094449SRuslan Ermilovman_setup_width() { 636a0094449SRuslan Ermilov local sizes 637a0094449SRuslan Ermilov 638a0094449SRuslan Ermilov unset use_width 639a0094449SRuslan Ermilov case "$MANWIDTH" in 640a0094449SRuslan Ermilov [0-9]*) 641a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 642a0094449SRuslan Ermilov use_width=$MANWIDTH 643a0094449SRuslan Ermilov fi 644a0094449SRuslan Ermilov ;; 645a0094449SRuslan Ermilov [Tt][Tt][Yy]) 646a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 647a0094449SRuslan Ermilov set -- $sizes 648a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 649a0094449SRuslan Ermilov use_width=$(($2-2)) 650a0094449SRuslan Ermilov fi 651a0094449SRuslan Ermilov fi 652a0094449SRuslan Ermilov ;; 653a0094449SRuslan Ermilov esac 654a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 655a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 656a0094449SRuslan Ermilov else 657a0094449SRuslan Ermilov decho 'Using standard page width' 658a0094449SRuslan Ermilov fi 659c535eb59SGordon Tetlow} 660c535eb59SGordon Tetlow 661c535eb59SGordon Tetlow# Usage: man_setup_locale 662c535eb59SGordon Tetlow# Setup necessary locale variables. 663c535eb59SGordon Tetlowman_setup_locale() { 664deeff310SGordon Tetlow local lang_cc 665deeff310SGordon Tetlow 666deeff310SGordon Tetlow locpaths='.' 667deeff310SGordon Tetlow man_charset='US-ASCII' 668deeff310SGordon Tetlow 669c535eb59SGordon Tetlow # Setup locale information. 670c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 671deeff310SGordon Tetlow decho 'Using non-localized manpages' 672deeff310SGordon Tetlow else 673deeff310SGordon Tetlow # Use the locale tool to give us the proper LC_CTYPE 674deeff310SGordon Tetlow eval $( $LOCALE ) 675c535eb59SGordon Tetlow 676deeff310SGordon Tetlow case "$LC_CTYPE" in 677deeff310SGordon Tetlow C) ;; 678deeff310SGordon Tetlow POSIX) ;; 679deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 680deeff310SGordon Tetlow lang_cc="${LC_CTYPE%.*}" 681deeff310SGordon Tetlow man_lang="${LC_CTYPE%_*}" 682deeff310SGordon Tetlow man_country="${lang_cc#*_}" 683deeff310SGordon Tetlow man_charset="${LC_CTYPE#*.}" 684deeff310SGordon Tetlow locpaths="$LC_CTYPE" 685c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 686c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 687c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 688c535eb59SGordon Tetlow fi 689c535eb59SGordon Tetlow locpaths="$locpaths:." 690deeff310SGordon Tetlow ;; 691deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 692deeff310SGordon Tetlow ;; 693deeff310SGordon Tetlow esac 694c535eb59SGordon Tetlow fi 695deeff310SGordon Tetlow 696c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 697c535eb59SGordon Tetlow} 698c535eb59SGordon Tetlow 699c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 700c535eb59SGordon Tetlow# Display usage for the man utility. 701c535eb59SGordon Tetlowman_usage() { 702c535eb59SGordon Tetlow echo 'Usage:' 703c535eb59SGordon Tetlow echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]' 704c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 705c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 706c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 707c535eb59SGordon Tetlow 708c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 709c535eb59SGordon Tetlow exit ${1:-1} 710c535eb59SGordon Tetlow} 711c535eb59SGordon Tetlow 712c535eb59SGordon Tetlow# Usage: parse_configs 713c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 714c535eb59SGordon Tetlowparse_configs() { 715c535eb59SGordon Tetlow local IFS file files 716c535eb59SGordon Tetlow 717c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 718c535eb59SGordon Tetlow return 719c535eb59SGordon Tetlow fi 720c535eb59SGordon Tetlow 721c535eb59SGordon Tetlow unset IFS 722c535eb59SGordon Tetlow 723c535eb59SGordon Tetlow # Read the global config first in case the user wants 724c535eb59SGordon Tetlow # to override config_local. 725c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 726c535eb59SGordon Tetlow parse_file "$config_global" 727c535eb59SGordon Tetlow fi 728c535eb59SGordon Tetlow 729c535eb59SGordon Tetlow # Glob the list of files to parse. 730c535eb59SGordon Tetlow set +f 731c535eb59SGordon Tetlow files=$(echo $config_local) 732c535eb59SGordon Tetlow set -f 733c535eb59SGordon Tetlow 734c535eb59SGordon Tetlow for file in $files; do 735c535eb59SGordon Tetlow if [ -r "$file" ]; then 736c535eb59SGordon Tetlow parse_file "$file" 737c535eb59SGordon Tetlow fi 738c535eb59SGordon Tetlow done 739c535eb59SGordon Tetlow 740c535eb59SGordon Tetlow parsed_configs='yes' 741c535eb59SGordon Tetlow} 742c535eb59SGordon Tetlow 743c535eb59SGordon Tetlow# Usage: parse_file file 744c535eb59SGordon Tetlow# Reads the specified config files. 745c535eb59SGordon Tetlowparse_file() { 746c535eb59SGordon Tetlow local file line tstr var 747c535eb59SGordon Tetlow 748c535eb59SGordon Tetlow file="$1" 749c535eb59SGordon Tetlow decho "Parsing config file: $file" 750c535eb59SGordon Tetlow while read line; do 751c535eb59SGordon Tetlow decho " $line" 2 752c535eb59SGordon Tetlow case "$line" in 753c535eb59SGordon Tetlow \#*) decho " Comment" 3 754c535eb59SGordon Tetlow ;; 755c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 756c535eb59SGordon Tetlow trim "${line#MANPATH}" 757c535eb59SGordon Tetlow add_to_manpath "$tstr" 758c535eb59SGordon Tetlow ;; 759c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 760c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 761c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 762c535eb59SGordon Tetlow ;; 763c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 764a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 765c535eb59SGordon Tetlow config_local="$tstr" 766c535eb59SGordon Tetlow ;; 767c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 768c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 769c535eb59SGordon Tetlow trim "${line#$var}" 770c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 771c535eb59SGordon Tetlow decho " Parsed $var" 3 772c535eb59SGordon Tetlow ;; 773c535eb59SGordon Tetlow esac 774c535eb59SGordon Tetlow done < "$file" 775c535eb59SGordon Tetlow} 776c535eb59SGordon Tetlow 777c535eb59SGordon Tetlow# Usage: search_path 778c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 779c535eb59SGordon Tetlowsearch_path() { 780c535eb59SGordon Tetlow local IFS p path 781c535eb59SGordon Tetlow 782c535eb59SGordon Tetlow decho "Searching PATH for man directories" 783c535eb59SGordon Tetlow 784c535eb59SGordon Tetlow IFS=: 785c535eb59SGordon Tetlow for path in $PATH; do 786971c1c42STijl Coosemans if add_to_manpath "$path/man"; then 787c535eb59SGordon Tetlow : 788c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 789c535eb59SGordon Tetlow : 790c535eb59SGordon Tetlow else 791c535eb59SGordon Tetlow case "$path" in 792971c1c42STijl Coosemans */bin) p="${path%/bin}/share/man" 793c535eb59SGordon Tetlow add_to_manpath "$p" 794971c1c42STijl Coosemans p="${path%/bin}/man" 79561d5f2d1SBaptiste Daroussin add_to_manpath "$p" 796c535eb59SGordon Tetlow ;; 797c535eb59SGordon Tetlow esac 798c535eb59SGordon Tetlow fi 799c535eb59SGordon Tetlow done 800c535eb59SGordon Tetlow unset IFS 801c535eb59SGordon Tetlow 802c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 803c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 804c535eb59SGordon Tetlow manpath=$man_default_path 805c535eb59SGordon Tetlow fi 806c535eb59SGordon Tetlow} 807c535eb59SGordon Tetlow 808c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 809c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 810c535eb59SGordon Tetlowsearch_whatis() { 811c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 812c535eb59SGordon Tetlow 813c535eb59SGordon Tetlow cmd="$1" 814c535eb59SGordon Tetlow shift 815c535eb59SGordon Tetlow 816c535eb59SGordon Tetlow whatis_parse_args "$@" 817c535eb59SGordon Tetlow 818c535eb59SGordon Tetlow build_manpath 819c535eb59SGordon Tetlow build_manlocales 820c535eb59SGordon Tetlow setup_pager 821c535eb59SGordon Tetlow 822c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 823c535eb59SGordon Tetlow opt="-w" 824c535eb59SGordon Tetlow fi 825c535eb59SGordon Tetlow 826c535eb59SGordon Tetlow f='whatis' 827c535eb59SGordon Tetlow 828c535eb59SGordon Tetlow IFS=: 829c535eb59SGordon Tetlow for path in $MANPATH; do 830c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 831c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 832c535eb59SGordon Tetlow continue 833c535eb59SGordon Tetlow fi 834c535eb59SGordon Tetlow 835c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 836c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 837c535eb59SGordon Tetlow wlist="$wlist $path/$f" 838c535eb59SGordon Tetlow fi 839c535eb59SGordon Tetlow 840c535eb59SGordon Tetlow for loc in $MANLOCALES; do 841c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 842c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 843c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 844c535eb59SGordon Tetlow fi 845c535eb59SGordon Tetlow done 846c535eb59SGordon Tetlow done 847c535eb59SGordon Tetlow unset IFS 848c535eb59SGordon Tetlow 849c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 850c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 851c535eb59SGordon Tetlow exit 1 852c535eb59SGordon Tetlow fi 853c535eb59SGordon Tetlow 854c535eb59SGordon Tetlow rval=0 855c535eb59SGordon Tetlow for key in $keywords; do 856c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 857c535eb59SGordon Tetlow if [ -n "$out" ]; then 858c535eb59SGordon Tetlow good="$good\\n$out" 859c535eb59SGordon Tetlow else 860c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 861c535eb59SGordon Tetlow rval=1 862c535eb59SGordon Tetlow fi 863c535eb59SGordon Tetlow done 864c535eb59SGordon Tetlow 865c535eb59SGordon Tetlow # Strip leading carriage return. 866c535eb59SGordon Tetlow good=${good#\\n} 867c535eb59SGordon Tetlow bad=${bad#\\n} 868c535eb59SGordon Tetlow 869c535eb59SGordon Tetlow if [ -n "$good" ]; then 870a6a3e856SRuslan Ermilov echo -e "$good" | $MANPAGER 871c535eb59SGordon Tetlow fi 872c535eb59SGordon Tetlow 873c535eb59SGordon Tetlow if [ -n "$bad" ]; then 87400e05e69SGordon Tetlow echo -e "$bad" >&2 875c535eb59SGordon Tetlow fi 876c535eb59SGordon Tetlow 877c535eb59SGordon Tetlow exit $rval 878c535eb59SGordon Tetlow} 879c535eb59SGordon Tetlow 88057cd9717SGordon Tetlow# Usage: setup_cattool page 88157cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 88257cd9717SGordon Tetlowsetup_cattool() { 88357cd9717SGordon Tetlow case "$1" in 88457cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 88557cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 88657cd9717SGordon Tetlow *.gz) cattool='/usr/bin/zcat' ;; 88757cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 88857cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 88957cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 89057cd9717SGordon Tetlow esac 89157cd9717SGordon Tetlow} 89257cd9717SGordon Tetlow 893c535eb59SGordon Tetlow# Usage: setup_pager 894a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 895c535eb59SGordon Tetlowsetup_pager() { 896c535eb59SGordon Tetlow # Setup pager. 897a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 898a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 899a6a3e856SRuslan Ermilov MANPAGER="less -sR" 900a6a3e856SRuslan Ermilov else 901a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 902a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 903a6a3e856SRuslan Ermilov else 904a6a3e856SRuslan Ermilov MANPAGER="more -s" 905c535eb59SGordon Tetlow fi 906a6a3e856SRuslan Ermilov fi 907a6a3e856SRuslan Ermilov fi 908a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 909c535eb59SGordon Tetlow} 910c535eb59SGordon Tetlow 911c535eb59SGordon Tetlow# Usage: trim string 912c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 913c535eb59SGordon Tetlowtrim() { 914c535eb59SGordon Tetlow tstr=$1 915c535eb59SGordon Tetlow while true; do 916c535eb59SGordon Tetlow case "$tstr" in 917c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 918c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 919c535eb59SGordon Tetlow *) break ;; 920c535eb59SGordon Tetlow esac 921c535eb59SGordon Tetlow done 922c535eb59SGordon Tetlow} 923c535eb59SGordon Tetlow 924c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 925c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 926c535eb59SGordon Tetlowwhatis_parse_args() { 927c535eb59SGordon Tetlow local cmd_arg 928c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 929c535eb59SGordon Tetlow case "${cmd_arg}" in 930c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 931c535eb59SGordon Tetlow *) whatis_usage ;; 932c535eb59SGordon Tetlow esac 933c535eb59SGordon Tetlow done >&2 934c535eb59SGordon Tetlow 935c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 936c535eb59SGordon Tetlow 937c535eb59SGordon Tetlow keywords="$*" 938c535eb59SGordon Tetlow} 939c535eb59SGordon Tetlow 940c535eb59SGordon Tetlow# Usage: whatis_usage 941c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 942c535eb59SGordon Tetlowwhatis_usage() { 943c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 944c535eb59SGordon Tetlow exit 1 945c535eb59SGordon Tetlow} 946c535eb59SGordon Tetlow 947c535eb59SGordon Tetlow 948c535eb59SGordon Tetlow 949c535eb59SGordon Tetlow# Supported commands 950c535eb59SGordon Tetlowdo_apropos() { 95124ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 952772246efSBaptiste Daroussin exec apropos "$@" 953c535eb59SGordon Tetlow search_whatis apropos "$@" 954c535eb59SGordon Tetlow} 955c535eb59SGordon Tetlow 956c535eb59SGordon Tetlowdo_man() { 957c535eb59SGordon Tetlow man_parse_args "$@" 958c535eb59SGordon Tetlow if [ -z "$pages" ]; then 959c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 960c535eb59SGordon Tetlow exit 1 961c535eb59SGordon Tetlow fi 962c535eb59SGordon Tetlow man_setup 963c535eb59SGordon Tetlow 964c535eb59SGordon Tetlow for page in $pages; do 965c535eb59SGordon Tetlow decho "Searching for $page" 966c535eb59SGordon Tetlow man_find_and_display "$page" 967c535eb59SGordon Tetlow done 968c535eb59SGordon Tetlow 969c535eb59SGordon Tetlow exit ${ret:-0} 970c535eb59SGordon Tetlow} 971c535eb59SGordon Tetlow 972c535eb59SGordon Tetlowdo_manpath() { 973c535eb59SGordon Tetlow manpath_parse_args "$@" 974c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 975c535eb59SGordon Tetlow manpath_warnings 976c535eb59SGordon Tetlow fi 977c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 978c535eb59SGordon Tetlow build_manlocales 979c535eb59SGordon Tetlow echo $MANLOCALES 980c535eb59SGordon Tetlow else 981c535eb59SGordon Tetlow build_manpath 982c535eb59SGordon Tetlow echo $MANPATH 983c535eb59SGordon Tetlow fi 984c535eb59SGordon Tetlow exit 0 985c535eb59SGordon Tetlow} 986c535eb59SGordon Tetlow 987c535eb59SGordon Tetlowdo_whatis() { 98824ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 989772246efSBaptiste Daroussin exec whatis "$@" 990c535eb59SGordon Tetlow search_whatis whatis "$@" 991c535eb59SGordon Tetlow} 992c535eb59SGordon Tetlow 993aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 994aeea395eSUlrich SpörleinEQN=eqn 995a6a3e856SRuslan ErmilovNROFF='groff -S -P-h -Wall -mtty-char -man' 996aeea395eSUlrich SpörleinPIC=pic 997aeea395eSUlrich SpörleinREFER=refer 998aeea395eSUlrich SpörleinTBL=tbl 9993d120968SUlrich SpörleinTROFF='groff -S -man' 1000aeea395eSUlrich SpörleinVGRIND=vgrind 1001aeea395eSUlrich Spörlein 1002deeff310SGordon TetlowLOCALE=/usr/bin/locale 1003a0094449SRuslan ErmilovSTTY=/bin/stty 100482db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1005c535eb59SGordon Tetlow 1006c535eb59SGordon Tetlowdebug=0 100740449c74SBrooks Davisman_default_sections='1:8:2:3:n:4:5:6:7:9:l' 1008971c1c42STijl Coosemansman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man' 100957cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1010c535eb59SGordon Tetlow 1011c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1012c535eb59SGordon Tetlow 1013c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1014c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1015c535eb59SGordon Tetlow 1016c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1017c535eb59SGordon Tetlowset -f 1018c535eb59SGordon Tetlow 1019c535eb59SGordon Tetlowcase "$0" in 1020c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1021c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1022c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1023c535eb59SGordon Tetlow*) do_man "$@" ;; 1024c535eb59SGordon Tetlowesac 1025