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 31*433c5a8aSWolfram Schneider# Rendering a manual page is fast. Even a manual page several 100k in size 32*433c5a8aSWolfram Schneider# takes less than a CPU second. If it takes much longer, it is very likely 33*433c5a8aSWolfram Schneider# that a tool like mandoc(1) is running in an infinite loop. In this case 34*433c5a8aSWolfram Schneider# it is better to terminate it. 35*433c5a8aSWolfram Schneiderulimit -t 20 36*433c5a8aSWolfram Schneider 37c535eb59SGordon Tetlow# Usage: add_to_manpath path 38c535eb59SGordon Tetlow# Adds a variable to manpath while ensuring we don't have duplicates. 39c535eb59SGordon Tetlow# Returns true if we were able to add something. False otherwise. 40c535eb59SGordon Tetlowadd_to_manpath() { 41c535eb59SGordon Tetlow case "$manpath" in 42c535eb59SGordon Tetlow *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 43c535eb59SGordon Tetlow $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 44c535eb59SGordon Tetlow *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 45c535eb59SGordon Tetlow *) if [ -d "$1" ]; then 46c535eb59SGordon Tetlow decho " Adding $1 to manpath" 47c535eb59SGordon Tetlow manpath="$manpath:$1" 48c535eb59SGordon Tetlow return 0 49c535eb59SGordon Tetlow fi 50c535eb59SGordon Tetlow ;; 51c535eb59SGordon Tetlow esac 52c535eb59SGordon Tetlow 53c535eb59SGordon Tetlow return 1 54c535eb59SGordon Tetlow} 55c535eb59SGordon Tetlow 56c535eb59SGordon Tetlow# Usage: build_manlocales 57c535eb59SGordon Tetlow# Builds a correct MANLOCALES variable. 58c535eb59SGordon Tetlowbuild_manlocales() { 59c535eb59SGordon Tetlow # If the user has set manlocales, who are we to argue. 60c535eb59SGordon Tetlow if [ -n "$MANLOCALES" ]; then 61c535eb59SGordon Tetlow return 62c535eb59SGordon Tetlow fi 63c535eb59SGordon Tetlow 64c535eb59SGordon Tetlow parse_configs 65c535eb59SGordon Tetlow 66c535eb59SGordon Tetlow # Trim leading colon 67c535eb59SGordon Tetlow MANLOCALES=${manlocales#:} 68c535eb59SGordon Tetlow 69c535eb59SGordon Tetlow decho "Available manual locales: $MANLOCALES" 70c535eb59SGordon Tetlow} 71c535eb59SGordon Tetlow 72c535eb59SGordon Tetlow# Usage: build_manpath 73c535eb59SGordon Tetlow# Builds a correct MANPATH variable. 74c535eb59SGordon Tetlowbuild_manpath() { 75c535eb59SGordon Tetlow local IFS 76c535eb59SGordon Tetlow 77c535eb59SGordon Tetlow # If the user has set a manpath, who are we to argue. 78c535eb59SGordon Tetlow if [ -n "$MANPATH" ]; then 79b2394e73SBaptiste Daroussin case "$MANPATH" in 80b2394e73SBaptiste Daroussin *:) PREPEND_MANPATH=${MANPATH} ;; 81b2394e73SBaptiste Daroussin :*) APPEND_MANPATH=${MANPATH} ;; 82b2394e73SBaptiste Daroussin *::*) 83b2394e73SBaptiste Daroussin PREPEND_MANPATH=${MANPATH%%::*} 84b2394e73SBaptiste Daroussin APPEND_MANPATH=${MANPATH#*::} 85b2394e73SBaptiste Daroussin ;; 86b2394e73SBaptiste Daroussin *) return ;; 87b2394e73SBaptiste Daroussin esac 88b2394e73SBaptiste Daroussin fi 89b2394e73SBaptiste Daroussin 90b2394e73SBaptiste Daroussin if [ -n "$PREPEND_MANPATH" ]; then 91b2394e73SBaptiste Daroussin IFS=: 92b2394e73SBaptiste Daroussin for path in $PREPEND_MANPATH; do 93b2394e73SBaptiste Daroussin add_to_manpath "$path" 94b2394e73SBaptiste Daroussin done 95b2394e73SBaptiste Daroussin unset IFS 96c535eb59SGordon Tetlow fi 97c535eb59SGordon Tetlow 98c535eb59SGordon Tetlow search_path 99c535eb59SGordon Tetlow 100c535eb59SGordon Tetlow decho "Adding default manpath entries" 101c535eb59SGordon Tetlow IFS=: 102c535eb59SGordon Tetlow for path in $man_default_path; do 103c535eb59SGordon Tetlow add_to_manpath "$path" 104c535eb59SGordon Tetlow done 105c535eb59SGordon Tetlow unset IFS 106c535eb59SGordon Tetlow 107c535eb59SGordon Tetlow parse_configs 108c535eb59SGordon Tetlow 109b2394e73SBaptiste Daroussin if [ -n "$APPEND_MANPATH" ]; then 110b2394e73SBaptiste Daroussin IFS=: 111b2394e73SBaptiste Daroussin for path in $APPEND_MANPATH; do 112b2394e73SBaptiste Daroussin add_to_manpath "$path" 113b2394e73SBaptiste Daroussin done 114b2394e73SBaptiste Daroussin unset IFS 115b2394e73SBaptiste Daroussin fi 116c535eb59SGordon Tetlow # Trim leading colon 117c535eb59SGordon Tetlow MANPATH=${manpath#:} 118c535eb59SGordon Tetlow 119c535eb59SGordon Tetlow decho "Using manual path: $MANPATH" 120c535eb59SGordon Tetlow} 121c535eb59SGordon Tetlow 122c535eb59SGordon Tetlow# Usage: check_cat catglob 123c535eb59SGordon Tetlow# Checks to see if a cat glob is available. 124c535eb59SGordon Tetlowcheck_cat() { 125c535eb59SGordon Tetlow if exists "$1"; then 126c535eb59SGordon Tetlow use_cat=yes 127c535eb59SGordon Tetlow catpage=$found 12857cd9717SGordon Tetlow setup_cattool $catpage 129c535eb59SGordon Tetlow decho " Found catpage $catpage" 130c535eb59SGordon Tetlow return 0 131c535eb59SGordon Tetlow else 132c535eb59SGordon Tetlow return 1 133c535eb59SGordon Tetlow fi 134c535eb59SGordon Tetlow} 135c535eb59SGordon Tetlow 136c535eb59SGordon Tetlow# Usage: check_man manglob catglob 137c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to 138c535eb59SGordon Tetlow# see if the catglob is also available and up to date. 139c535eb59SGordon Tetlowcheck_man() { 140c535eb59SGordon Tetlow if exists "$1"; then 141c535eb59SGordon Tetlow # We have a match, check for a cat page 142c535eb59SGordon Tetlow manpage=$found 14357cd9717SGordon Tetlow setup_cattool $manpage 144c535eb59SGordon Tetlow decho " Found manpage $manpage" 145c535eb59SGordon Tetlow 146a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 147a0094449SRuslan Ermilov # non-standard width 148a0094449SRuslan Ermilov unset use_cat 149a0094449SRuslan Ermilov decho " Skipping catpage: non-standard page width" 150a0094449SRuslan Ermilov elif exists "$2" && is_newer $found $manpage; then 151c535eb59SGordon Tetlow # cat page found and is newer, use that 152c535eb59SGordon Tetlow use_cat=yes 153c535eb59SGordon Tetlow catpage=$found 15457cd9717SGordon Tetlow setup_cattool $catpage 155c535eb59SGordon Tetlow decho " Using catpage $catpage" 156c535eb59SGordon Tetlow else 157c535eb59SGordon Tetlow # no cat page or is older 158c535eb59SGordon Tetlow unset use_cat 159c535eb59SGordon Tetlow decho " Skipping catpage: not found or old" 160c535eb59SGordon Tetlow fi 161c535eb59SGordon Tetlow return 0 162c535eb59SGordon Tetlow fi 163c535eb59SGordon Tetlow 164c535eb59SGordon Tetlow return 1 165c535eb59SGordon Tetlow} 166c535eb59SGordon Tetlow 167c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel] 168c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel. 169c535eb59SGordon Tetlowdecho() { 170c535eb59SGordon Tetlow if [ $debug -ge ${2:-1} ]; then 171c535eb59SGordon Tetlow echo "-- $1" >&2 172c535eb59SGordon Tetlow fi 173c535eb59SGordon Tetlow} 174c535eb59SGordon Tetlow 175c535eb59SGordon Tetlow# Usage: exists glob 176c535eb59SGordon Tetlow# Returns true if glob resolves to a real file. 177c535eb59SGordon Tetlowexists() { 178c535eb59SGordon Tetlow local IFS 179c535eb59SGordon Tetlow 180c535eb59SGordon Tetlow # Don't accidentally inherit callers IFS (breaks perl manpages) 181c535eb59SGordon Tetlow unset IFS 182c535eb59SGordon Tetlow 183c535eb59SGordon Tetlow # Use some globbing tricks in the shell to determine if a file 184c535eb59SGordon Tetlow # exists or not. 185c535eb59SGordon Tetlow set +f 186c535eb59SGordon Tetlow set -- "$1" $1 187c535eb59SGordon Tetlow set -f 188c535eb59SGordon Tetlow 189c535eb59SGordon Tetlow if [ "$1" != "$2" -a -r "$2" ]; then 190c535eb59SGordon Tetlow found="$2" 191c535eb59SGordon Tetlow return 0 192c535eb59SGordon Tetlow fi 193c535eb59SGordon Tetlow 194c535eb59SGordon Tetlow return 1 195c535eb59SGordon Tetlow} 196c535eb59SGordon Tetlow 197c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename 198c535eb59SGordon Tetlow# Returns: true if something is matched and found. 199c535eb59SGordon Tetlow# Search the given path/section combo for a given page. 200c535eb59SGordon Tetlowfind_file() { 201c535eb59SGordon Tetlow local manroot catroot mann man0 catn cat0 202c535eb59SGordon Tetlow 203c535eb59SGordon Tetlow manroot="$1/man$2" 204c535eb59SGordon Tetlow catroot="$1/cat$2" 205c535eb59SGordon Tetlow if [ -n "$3" ]; then 206c535eb59SGordon Tetlow manroot="$manroot/$3" 207c535eb59SGordon Tetlow catroot="$catroot/$3" 208c535eb59SGordon Tetlow fi 209c535eb59SGordon Tetlow 210625490e8SBaptiste Daroussin if [ ! -d "$manroot" -a ! -d "$catroot" ]; then 211c535eb59SGordon Tetlow return 1 212c535eb59SGordon Tetlow fi 213c535eb59SGordon Tetlow decho " Searching directory $manroot" 2 214c535eb59SGordon Tetlow 215c535eb59SGordon Tetlow mann="$manroot/$4.$2*" 216c535eb59SGordon Tetlow man0="$manroot/$4.0*" 217c535eb59SGordon Tetlow catn="$catroot/$4.$2*" 218c535eb59SGordon Tetlow cat0="$catroot/$4.0*" 219c535eb59SGordon Tetlow 220c535eb59SGordon Tetlow # This is the behavior as seen by the original man utility. 221c535eb59SGordon Tetlow # Let's not change that which doesn't seem broken. 222c535eb59SGordon Tetlow if check_man "$mann" "$catn"; then 223c535eb59SGordon Tetlow return 0 224c535eb59SGordon Tetlow elif check_man "$man0" "$cat0"; then 225c535eb59SGordon Tetlow return 0 226c535eb59SGordon Tetlow elif check_cat "$catn"; then 227c535eb59SGordon Tetlow return 0 228c535eb59SGordon Tetlow elif check_cat "$cat0"; then 229c535eb59SGordon Tetlow return 0 230c535eb59SGordon Tetlow fi 231c535eb59SGordon Tetlow 232c535eb59SGordon Tetlow return 1 233c535eb59SGordon Tetlow} 234c535eb59SGordon Tetlow 235c535eb59SGordon Tetlow# Usage: is_newer file1 file2 236c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime. 237c535eb59SGordon Tetlowis_newer() { 2389b61837aSUlrich Spörlein if ! [ "$1" -ot "$2" ]; then 2399b61837aSUlrich Spörlein decho " mtime: $1 not older than $2" 3 240c535eb59SGordon Tetlow return 0 241c535eb59SGordon Tetlow else 242c535eb59SGordon Tetlow decho " mtime: $1 older than $2" 3 243c535eb59SGordon Tetlow return 1 244c535eb59SGordon Tetlow fi 245c535eb59SGordon Tetlow} 246c535eb59SGordon Tetlow 247c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@" 248c535eb59SGordon Tetlow# Parses commandline options for manpath. 249c535eb59SGordon Tetlowmanpath_parse_args() { 250c535eb59SGordon Tetlow local cmd_arg 251c535eb59SGordon Tetlow 252f555b39eSKyle Evans OPTIND=1 253c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 254c535eb59SGordon Tetlow case "${cmd_arg}" in 255c535eb59SGordon Tetlow L) Lflag=Lflag ;; 256c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 257c535eb59SGordon Tetlow q) qflag=qflag ;; 258c535eb59SGordon Tetlow *) manpath_usage ;; 259c535eb59SGordon Tetlow esac 260c535eb59SGordon Tetlow done >&2 261c535eb59SGordon Tetlow} 262c535eb59SGordon Tetlow 263c535eb59SGordon Tetlow# Usage: manpath_usage 264c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 265c535eb59SGordon Tetlowmanpath_usage() { 266c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 267c535eb59SGordon Tetlow exit 1 268c535eb59SGordon Tetlow} 269c535eb59SGordon Tetlow 270c535eb59SGordon Tetlow# Usage: manpath_warnings 271c535eb59SGordon Tetlow# Display some warnings to stderr. 272c535eb59SGordon Tetlowmanpath_warnings() { 273c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 274c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 275c535eb59SGordon Tetlow fi 276c535eb59SGordon Tetlow} 277c535eb59SGordon Tetlow 27857cd9717SGordon Tetlow# Usage: man_check_for_so page path 27957cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 28057cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 28157cd9717SGordon Tetlow# redirected to another source file. 28257cd9717SGordon Tetlowman_check_for_so() { 28357cd9717SGordon Tetlow local IFS line tstr 28457cd9717SGordon Tetlow 28557cd9717SGordon Tetlow unset IFS 286d9405a92SBaptiste Daroussin if [ -n "$catpage" ]; then 287d9405a92SBaptiste Daroussin return 0 288d9405a92SBaptiste Daroussin fi 28957cd9717SGordon Tetlow 29057cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 29157cd9717SGordon Tetlow while true 29257cd9717SGordon Tetlow do 29357cd9717SGordon Tetlow line=$($cattool $manpage | head -1) 29457cd9717SGordon Tetlow case "$line" in 29557cd9717SGordon Tetlow .so*) trim "${line#.so}" 29657cd9717SGordon Tetlow decho "$manpage includes $tstr" 29757cd9717SGordon Tetlow # Glob and check for the file. 29857cd9717SGordon Tetlow if ! check_man "$path/$tstr*" ""; then 29957cd9717SGordon Tetlow decho " Unable to find $tstr" 30057cd9717SGordon Tetlow return 1 30157cd9717SGordon Tetlow fi 30257cd9717SGordon Tetlow ;; 30357cd9717SGordon Tetlow *) break ;; 30457cd9717SGordon Tetlow esac 30557cd9717SGordon Tetlow done 30657cd9717SGordon Tetlow 30757cd9717SGordon Tetlow return 0 30857cd9717SGordon Tetlow} 30957cd9717SGordon Tetlow 310b43edc06SBaptiste Daroussin# Usage: man_display_page 311b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 312c535eb59SGordon Tetlowman_display_page() { 3131fb816daSBaptiste Daroussin local IFS pipeline testline 314c535eb59SGordon Tetlow 315c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 316c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 317c535eb59SGordon Tetlow unset IFS 318c535eb59SGordon Tetlow 319c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 320c535eb59SGordon Tetlow # just zcat the catpage and we are done. 321c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 322c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 323c535eb59SGordon Tetlow echo "$catpage (source: $manpage)" 324c535eb59SGordon Tetlow ret=0 325c535eb59SGordon Tetlow else 326c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 327a6a3e856SRuslan Ermilov decho "Command: $cattool $catpage | $MANPAGER" 328c535eb59SGordon Tetlow ret=0 329c535eb59SGordon Tetlow else 330a6a3e856SRuslan Ermilov eval "$cattool $catpage | $MANPAGER" 331c535eb59SGordon Tetlow ret=$? 332c535eb59SGordon Tetlow fi 333c535eb59SGordon Tetlow fi 334c535eb59SGordon Tetlow return 335c535eb59SGordon Tetlow fi 336c535eb59SGordon Tetlow 337c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 338c535eb59SGordon Tetlow # name of the manpage? 339c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 340c535eb59SGordon Tetlow echo "$manpage" 341c535eb59SGordon Tetlow ret=0 342c535eb59SGordon Tetlow return 343c535eb59SGordon Tetlow fi 344c535eb59SGordon Tetlow 345d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 346d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 347d433cf9aSBaptiste Daroussin fi 348451c2becSBaptiste Daroussin testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 349449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 350449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 351449a792dSBaptiste Daroussin else 352d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 353449a792dSBaptiste Daroussin fi 354d6096801SBaptiste Daroussin 355d6096801SBaptiste Daroussin if ! eval "$cattool $manpage | $testline" ;then 356f17575acSBaptiste Daroussin if which -s groff; then 357d6096801SBaptiste Daroussin man_display_page_groff 358d6096801SBaptiste Daroussin else 359d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 360d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 361d6096801SBaptiste Daroussin echo "pkg install groff " >&2 362d6096801SBaptiste Daroussin ret=1 363d6096801SBaptiste Daroussin fi 364d6096801SBaptiste Daroussin return 365d6096801SBaptiste Daroussin fi 366d6096801SBaptiste Daroussin 367d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 368d6096801SBaptiste Daroussin decho "Command: $cattool $manpage | $pipeline" 369d6096801SBaptiste Daroussin ret=0 370d6096801SBaptiste Daroussin else 371d6096801SBaptiste Daroussin eval "$cattool $manpage | $pipeline" 372d6096801SBaptiste Daroussin ret=$? 373d6096801SBaptiste Daroussin fi 374d6096801SBaptiste Daroussin} 375d6096801SBaptiste Daroussin 376b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 377b43edc06SBaptiste Daroussin# Display the manpage using groff 378d6096801SBaptiste Daroussinman_display_page_groff() { 379d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 380d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 381d6096801SBaptiste Daroussin 382c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 383c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 384c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 385c535eb59SGordon Tetlow 386deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 387deeff310SGordon Tetlow # to properly output for the correct device. 388deeff310SGordon Tetlow case "${manpage}" in 389deeff310SGordon Tetlow *.${man_charset}/*) 390c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 391c535eb59SGordon Tetlow # previous version of man(1). 392c535eb59SGordon Tetlow case "$man_charset" in 393c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 394c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 395c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 396c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 397c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 398c535eb59SGordon Tetlow esac 399c535eb59SGordon Tetlow 400deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 401c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 402c535eb59SGordon Tetlow 403deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 404deeff310SGordon Tetlow # then we need to define the locale string. 405deeff310SGordon Tetlow case "${manpage}" in 406deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 407deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 408deeff310SGordon Tetlow ;; 409deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 410deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 411deeff310SGordon Tetlow ;; 412deeff310SGordon Tetlow esac 413deeff310SGordon Tetlow 414c535eb59SGordon Tetlow # Allow language specific calls to override the default 415c535eb59SGordon Tetlow # set of utilities. 416c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 417b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 418c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 419c535eb59SGordon Tetlow done 420c535eb59SGordon Tetlow ;; 421c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 422c535eb59SGordon Tetlow EQN="$EQN -Tascii" 423c535eb59SGordon Tetlow ;; 424c535eb59SGordon Tetlow esac 425c535eb59SGordon Tetlow 426a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 427a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 428a6a3e856SRuslan Ermilov fi 429a6a3e856SRuslan Ermilov 430a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 431a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 432a0094449SRuslan Ermilov fi 433a0094449SRuslan Ermilov 434c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 435c535eb59SGordon Tetlow set -- -$MANROFFSEQ 436f555b39eSKyle Evans OPTIND=1 437c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 438c535eb59SGordon Tetlow case "${preproc_arg}" in 439c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 440487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 441c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 442c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 443b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 444c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 445c535eb59SGordon Tetlow *) usage ;; 446c535eb59SGordon Tetlow esac 447c535eb59SGordon Tetlow done 448c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 449c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 450c535eb59SGordon Tetlow else 451c535eb59SGordon Tetlow pipeline="$TBL" 452c535eb59SGordon Tetlow fi 453c535eb59SGordon Tetlow 454c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 455c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 456c535eb59SGordon Tetlow else 457a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 458c535eb59SGordon Tetlow fi 459c535eb59SGordon Tetlow 460c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 46157cd9717SGordon Tetlow decho "Command: $cattool $manpage | $pipeline" 462c535eb59SGordon Tetlow ret=0 463c535eb59SGordon Tetlow else 46457cd9717SGordon Tetlow eval "$cattool $manpage | $pipeline" 465c535eb59SGordon Tetlow ret=$? 466c535eb59SGordon Tetlow fi 467c535eb59SGordon Tetlow} 468c535eb59SGordon Tetlow 469c535eb59SGordon Tetlow# Usage: man_find_and_display page 470c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 471c535eb59SGordon Tetlowman_find_and_display() { 472c535eb59SGordon Tetlow local found_page locpath p path sect 473c535eb59SGordon Tetlow 4743d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 4753d9127f1SGordon Tetlow # the filename. 4763d9127f1SGordon Tetlow case "$1" in 4773d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 4783d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 4793d9127f1SGordon Tetlow unset use_cat 4803d9127f1SGordon Tetlow manpage="$1" 48157cd9717SGordon Tetlow setup_cattool $manpage 48257cd9717SGordon Tetlow if man_check_for_so $manpage $(dirname $manpage); then 48357cd9717SGordon Tetlow found_page=yes 4843d9127f1SGordon Tetlow man_display_page 48557cd9717SGordon Tetlow fi 4863d9127f1SGordon Tetlow return 4873d9127f1SGordon Tetlow fi 4883d9127f1SGordon Tetlow ;; 4893d9127f1SGordon Tetlow esac 4903d9127f1SGordon Tetlow 491c535eb59SGordon Tetlow IFS=: 492c535eb59SGordon Tetlow for sect in $MANSECT; do 493c535eb59SGordon Tetlow decho "Searching section $sect" 2 494c535eb59SGordon Tetlow for path in $MANPATH; do 495c535eb59SGordon Tetlow for locpath in $locpaths; do 496c535eb59SGordon Tetlow p=$path/$locpath 497c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 498c535eb59SGordon Tetlow 499c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 500c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 50157cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 502c535eb59SGordon Tetlow found_page=yes 503c535eb59SGordon Tetlow man_display_page 5041d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5051d7c660aSGordon Tetlow continue 2 5061d7c660aSGordon Tetlow else 507c535eb59SGordon Tetlow return 508c535eb59SGordon Tetlow fi 509c535eb59SGordon Tetlow fi 51057cd9717SGordon Tetlow fi 511c535eb59SGordon Tetlow 512c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 513c535eb59SGordon Tetlow # specific manpath. 514c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 51557cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 516c535eb59SGordon Tetlow found_page=yes 517c535eb59SGordon Tetlow man_display_page 5181d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5191d7c660aSGordon Tetlow continue 2 5201d7c660aSGordon Tetlow else 521c535eb59SGordon Tetlow return 522c535eb59SGordon Tetlow fi 523c535eb59SGordon Tetlow fi 52457cd9717SGordon Tetlow fi 525c535eb59SGordon Tetlow 526c535eb59SGordon Tetlow # Check plain old manpath. 527c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 52857cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 529c535eb59SGordon Tetlow found_page=yes 530c535eb59SGordon Tetlow man_display_page 5311d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5321d7c660aSGordon Tetlow continue 2 5331d7c660aSGordon Tetlow else 534c535eb59SGordon Tetlow return 535c535eb59SGordon Tetlow fi 536c535eb59SGordon Tetlow fi 53757cd9717SGordon Tetlow fi 538c535eb59SGordon Tetlow done 539c535eb59SGordon Tetlow done 540c535eb59SGordon Tetlow done 541c535eb59SGordon Tetlow unset IFS 542c535eb59SGordon Tetlow 543c535eb59SGordon Tetlow # Nothing? Well, we are done then. 544c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 545c535eb59SGordon Tetlow echo "No manual entry for $1" >&2 546c535eb59SGordon Tetlow ret=1 547c535eb59SGordon Tetlow return 548c535eb59SGordon Tetlow fi 549c535eb59SGordon Tetlow} 550c535eb59SGordon Tetlow 551c535eb59SGordon Tetlow# Usage: man_parse_args "$@" 552c535eb59SGordon Tetlow# Parses commandline options for man. 553c535eb59SGordon Tetlowman_parse_args() { 554c535eb59SGordon Tetlow local IFS cmd_arg 555c535eb59SGordon Tetlow 556f555b39eSKyle Evans OPTIND=1 5571594084fSFernando Apesteguía while getopts 'K:M:P:S:adfhkm:op:tw' cmd_arg; do 558c535eb59SGordon Tetlow case "${cmd_arg}" in 5591594084fSFernando Apesteguía K) Kflag=Kflag 5601594084fSFernando Apesteguía REGEXP=$OPTARG ;; 561c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 562a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 563c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 564c535eb59SGordon Tetlow a) aflag=aflag ;; 565c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 566c535eb59SGordon Tetlow f) fflag=fflag ;; 567c535eb59SGordon Tetlow h) man_usage 0 ;; 568c535eb59SGordon Tetlow k) kflag=kflag ;; 569c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 570c535eb59SGordon Tetlow o) oflag=oflag ;; 571c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 572c535eb59SGordon Tetlow t) tflag=tflag ;; 573c535eb59SGordon Tetlow w) wflag=wflag ;; 574c535eb59SGordon Tetlow *) man_usage ;; 575c535eb59SGordon Tetlow esac 576c535eb59SGordon Tetlow done >&2 577c535eb59SGordon Tetlow 578c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 579c535eb59SGordon Tetlow 580c535eb59SGordon Tetlow # Check the args for incompatible options. 5811594084fSFernando Apesteguía 5821594084fSFernando Apesteguía case "${Kflag}${fflag}${kflag}${tflag}${wflag}" in 5831594084fSFernando Apesteguía Kflagfflag*) echo "Incompatible options: -K and -f"; man_usage ;; 5841594084fSFernando Apesteguía Kflag*kflag*) echo "Incompatible options: -K and -k"; man_usage ;; 5851594084fSFernando Apesteguía Kflag*tflag) echo "Incompatible options: -K and -t"; man_usage ;; 586c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 587c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 588c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 589c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 590c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 591c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 592c535eb59SGordon Tetlow esac 593c535eb59SGordon Tetlow 594c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 595c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 596c535eb59SGordon Tetlow do_whatis "$@" 597c535eb59SGordon Tetlow exit 598c535eb59SGordon Tetlow fi 599c535eb59SGordon Tetlow 600c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 601c535eb59SGordon Tetlow do_apropos "$@" 602c535eb59SGordon Tetlow exit 603c535eb59SGordon Tetlow fi 604c535eb59SGordon Tetlow 605c535eb59SGordon Tetlow IFS=: 606c535eb59SGordon Tetlow for sect in $man_default_sections; do 607c535eb59SGordon Tetlow if [ "$sect" = "$1" ]; then 608c535eb59SGordon Tetlow decho "Detected manual section as first arg: $1" 609c535eb59SGordon Tetlow MANSECT="$1" 610c535eb59SGordon Tetlow shift 611c535eb59SGordon Tetlow break 612c535eb59SGordon Tetlow fi 613c535eb59SGordon Tetlow done 614c535eb59SGordon Tetlow unset IFS 615c535eb59SGordon Tetlow 616c535eb59SGordon Tetlow pages="$*" 617c535eb59SGordon Tetlow} 618c535eb59SGordon Tetlow 619c535eb59SGordon Tetlow# Usage: man_setup 620c535eb59SGordon Tetlow# Setup various trivial but essential variables. 621c535eb59SGordon Tetlowman_setup() { 622c535eb59SGordon Tetlow # Setup machine and architecture variables. 623c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 624c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 625c535eb59SGordon Tetlow MACHINE=${mflag##*:} 626c535eb59SGordon Tetlow fi 627c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 62882db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 629c535eb59SGordon Tetlow fi 630c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 63182db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 632c535eb59SGordon Tetlow fi 633c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 634c535eb59SGordon Tetlow 635c535eb59SGordon Tetlow setup_pager 636c535eb59SGordon Tetlow 637c535eb59SGordon Tetlow # Setup manual sections to search. 638c535eb59SGordon Tetlow if [ -z "$MANSECT" ]; then 639c535eb59SGordon Tetlow MANSECT=$man_default_sections 640c535eb59SGordon Tetlow fi 641c535eb59SGordon Tetlow decho "Using manual sections: $MANSECT" 642c535eb59SGordon Tetlow 643c535eb59SGordon Tetlow build_manpath 644c535eb59SGordon Tetlow man_setup_locale 645a0094449SRuslan Ermilov man_setup_width 646a0094449SRuslan Ermilov} 647a0094449SRuslan Ermilov 648a0094449SRuslan Ermilov# Usage: man_setup_width 649a0094449SRuslan Ermilov# Set up page width. 650a0094449SRuslan Ermilovman_setup_width() { 651a0094449SRuslan Ermilov local sizes 652a0094449SRuslan Ermilov 653a0094449SRuslan Ermilov unset use_width 654a0094449SRuslan Ermilov case "$MANWIDTH" in 655a0094449SRuslan Ermilov [0-9]*) 656a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 657a0094449SRuslan Ermilov use_width=$MANWIDTH 658a0094449SRuslan Ermilov fi 659a0094449SRuslan Ermilov ;; 660a0094449SRuslan Ermilov [Tt][Tt][Yy]) 661a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 662a0094449SRuslan Ermilov set -- $sizes 663a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 664a0094449SRuslan Ermilov use_width=$(($2-2)) 665a0094449SRuslan Ermilov fi 666a0094449SRuslan Ermilov fi 667a0094449SRuslan Ermilov ;; 668a0094449SRuslan Ermilov esac 669a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 670a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 671a0094449SRuslan Ermilov else 672a0094449SRuslan Ermilov decho 'Using standard page width' 673a0094449SRuslan Ermilov fi 674c535eb59SGordon Tetlow} 675c535eb59SGordon Tetlow 676c535eb59SGordon Tetlow# Usage: man_setup_locale 677c535eb59SGordon Tetlow# Setup necessary locale variables. 678c535eb59SGordon Tetlowman_setup_locale() { 679deeff310SGordon Tetlow local lang_cc 6809508f8c0SYuri Pankov local locstr 681deeff310SGordon Tetlow 682deeff310SGordon Tetlow locpaths='.' 683deeff310SGordon Tetlow man_charset='US-ASCII' 684deeff310SGordon Tetlow 685c535eb59SGordon Tetlow # Setup locale information. 686c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 687deeff310SGordon Tetlow decho 'Using non-localized manpages' 688deeff310SGordon Tetlow else 6899508f8c0SYuri Pankov # Use the locale tool to give us proper locale information 690deeff310SGordon Tetlow eval $( $LOCALE ) 691c535eb59SGordon Tetlow 6929508f8c0SYuri Pankov if [ -n "$LANG" ]; then 6939508f8c0SYuri Pankov locstr=$LANG 6949508f8c0SYuri Pankov else 6959508f8c0SYuri Pankov locstr=$LC_CTYPE 6969508f8c0SYuri Pankov fi 6979508f8c0SYuri Pankov 6989508f8c0SYuri Pankov case "$locstr" in 699deeff310SGordon Tetlow C) ;; 7009508f8c0SYuri Pankov C.UTF-8) ;; 701deeff310SGordon Tetlow POSIX) ;; 702deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 7039508f8c0SYuri Pankov lang_cc="${locstr%.*}" 7049508f8c0SYuri Pankov man_lang="${locstr%_*}" 705deeff310SGordon Tetlow man_country="${lang_cc#*_}" 7069508f8c0SYuri Pankov man_charset="${locstr#*.}" 7079508f8c0SYuri Pankov locpaths="$locstr" 708c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 709c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 710c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 711c535eb59SGordon Tetlow fi 712c535eb59SGordon Tetlow locpaths="$locpaths:." 713deeff310SGordon Tetlow ;; 714deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 715deeff310SGordon Tetlow ;; 716deeff310SGordon Tetlow esac 717c535eb59SGordon Tetlow fi 718deeff310SGordon Tetlow 719c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 720c535eb59SGordon Tetlow} 721c535eb59SGordon Tetlow 722c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 723c535eb59SGordon Tetlow# Display usage for the man utility. 724c535eb59SGordon Tetlowman_usage() { 725c535eb59SGordon Tetlow echo 'Usage:' 7261594084fSFernando Apesteguía echo ' man [-adho] [-t | -w] [-K regexp] [-M manpath] [-P pager] [-S mansect]' 727c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 728c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 729c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 730c535eb59SGordon Tetlow 731c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 732c535eb59SGordon Tetlow exit ${1:-1} 733c535eb59SGordon Tetlow} 734c535eb59SGordon Tetlow 735c535eb59SGordon Tetlow# Usage: parse_configs 736c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 737c535eb59SGordon Tetlowparse_configs() { 738c535eb59SGordon Tetlow local IFS file files 739c535eb59SGordon Tetlow 740c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 741c535eb59SGordon Tetlow return 742c535eb59SGordon Tetlow fi 743c535eb59SGordon Tetlow 744c535eb59SGordon Tetlow unset IFS 745c535eb59SGordon Tetlow 746c535eb59SGordon Tetlow # Read the global config first in case the user wants 747c535eb59SGordon Tetlow # to override config_local. 748c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 749c535eb59SGordon Tetlow parse_file "$config_global" 750c535eb59SGordon Tetlow fi 751c535eb59SGordon Tetlow 752c535eb59SGordon Tetlow # Glob the list of files to parse. 753c535eb59SGordon Tetlow set +f 754c535eb59SGordon Tetlow files=$(echo $config_local) 755c535eb59SGordon Tetlow set -f 756c535eb59SGordon Tetlow 757c535eb59SGordon Tetlow for file in $files; do 758c535eb59SGordon Tetlow if [ -r "$file" ]; then 759c535eb59SGordon Tetlow parse_file "$file" 760c535eb59SGordon Tetlow fi 761c535eb59SGordon Tetlow done 762c535eb59SGordon Tetlow 763c535eb59SGordon Tetlow parsed_configs='yes' 764c535eb59SGordon Tetlow} 765c535eb59SGordon Tetlow 766c535eb59SGordon Tetlow# Usage: parse_file file 767c535eb59SGordon Tetlow# Reads the specified config files. 768c535eb59SGordon Tetlowparse_file() { 769c535eb59SGordon Tetlow local file line tstr var 770c535eb59SGordon Tetlow 771c535eb59SGordon Tetlow file="$1" 772c535eb59SGordon Tetlow decho "Parsing config file: $file" 773c535eb59SGordon Tetlow while read line; do 774c535eb59SGordon Tetlow decho " $line" 2 775c535eb59SGordon Tetlow case "$line" in 776c535eb59SGordon Tetlow \#*) decho " Comment" 3 777c535eb59SGordon Tetlow ;; 778c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 779c535eb59SGordon Tetlow trim "${line#MANPATH}" 780c535eb59SGordon Tetlow add_to_manpath "$tstr" 781c535eb59SGordon Tetlow ;; 782c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 783c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 784c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 785c535eb59SGordon Tetlow ;; 786c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 787a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 788c535eb59SGordon Tetlow config_local="$tstr" 789c535eb59SGordon Tetlow ;; 790c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 791c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 792c535eb59SGordon Tetlow trim "${line#$var}" 793c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 794c535eb59SGordon Tetlow decho " Parsed $var" 3 795c535eb59SGordon Tetlow ;; 796c535eb59SGordon Tetlow esac 797c535eb59SGordon Tetlow done < "$file" 798c535eb59SGordon Tetlow} 799c535eb59SGordon Tetlow 800c535eb59SGordon Tetlow# Usage: search_path 801c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 802c535eb59SGordon Tetlowsearch_path() { 803c535eb59SGordon Tetlow local IFS p path 804c535eb59SGordon Tetlow 805c535eb59SGordon Tetlow decho "Searching PATH for man directories" 806c535eb59SGordon Tetlow 807c535eb59SGordon Tetlow IFS=: 808c535eb59SGordon Tetlow for path in $PATH; do 809971c1c42STijl Coosemans if add_to_manpath "$path/man"; then 810c535eb59SGordon Tetlow : 811c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 812c535eb59SGordon Tetlow : 813c535eb59SGordon Tetlow else 814c535eb59SGordon Tetlow case "$path" in 815971c1c42STijl Coosemans */bin) p="${path%/bin}/share/man" 816c535eb59SGordon Tetlow add_to_manpath "$p" 817971c1c42STijl Coosemans p="${path%/bin}/man" 81861d5f2d1SBaptiste Daroussin add_to_manpath "$p" 819c535eb59SGordon Tetlow ;; 820c535eb59SGordon Tetlow esac 821c535eb59SGordon Tetlow fi 822c535eb59SGordon Tetlow done 823c535eb59SGordon Tetlow unset IFS 824c535eb59SGordon Tetlow 825c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 826c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 827c535eb59SGordon Tetlow manpath=$man_default_path 828c535eb59SGordon Tetlow fi 829c535eb59SGordon Tetlow} 830c535eb59SGordon Tetlow 831c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 832c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 833c535eb59SGordon Tetlowsearch_whatis() { 834c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 835c535eb59SGordon Tetlow 836c535eb59SGordon Tetlow cmd="$1" 837c535eb59SGordon Tetlow shift 838c535eb59SGordon Tetlow 839c535eb59SGordon Tetlow whatis_parse_args "$@" 840c535eb59SGordon Tetlow 841c535eb59SGordon Tetlow build_manpath 842c535eb59SGordon Tetlow build_manlocales 843c535eb59SGordon Tetlow setup_pager 844c535eb59SGordon Tetlow 845c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 846c535eb59SGordon Tetlow opt="-w" 847c535eb59SGordon Tetlow fi 848c535eb59SGordon Tetlow 849c535eb59SGordon Tetlow f='whatis' 850c535eb59SGordon Tetlow 851c535eb59SGordon Tetlow IFS=: 852c535eb59SGordon Tetlow for path in $MANPATH; do 853c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 854c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 855c535eb59SGordon Tetlow continue 856c535eb59SGordon Tetlow fi 857c535eb59SGordon Tetlow 858c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 859c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 860c535eb59SGordon Tetlow wlist="$wlist $path/$f" 861c535eb59SGordon Tetlow fi 862c535eb59SGordon Tetlow 863c535eb59SGordon Tetlow for loc in $MANLOCALES; do 864c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 865c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 866c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 867c535eb59SGordon Tetlow fi 868c535eb59SGordon Tetlow done 869c535eb59SGordon Tetlow done 870c535eb59SGordon Tetlow unset IFS 871c535eb59SGordon Tetlow 872c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 873c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 874c535eb59SGordon Tetlow exit 1 875c535eb59SGordon Tetlow fi 876c535eb59SGordon Tetlow 877c535eb59SGordon Tetlow rval=0 878c535eb59SGordon Tetlow for key in $keywords; do 879c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 880c535eb59SGordon Tetlow if [ -n "$out" ]; then 881c535eb59SGordon Tetlow good="$good\\n$out" 882c535eb59SGordon Tetlow else 883c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 884c535eb59SGordon Tetlow rval=1 885c535eb59SGordon Tetlow fi 886c535eb59SGordon Tetlow done 887c535eb59SGordon Tetlow 888c535eb59SGordon Tetlow # Strip leading carriage return. 889c535eb59SGordon Tetlow good=${good#\\n} 890c535eb59SGordon Tetlow bad=${bad#\\n} 891c535eb59SGordon Tetlow 892c535eb59SGordon Tetlow if [ -n "$good" ]; then 893a6a3e856SRuslan Ermilov echo -e "$good" | $MANPAGER 894c535eb59SGordon Tetlow fi 895c535eb59SGordon Tetlow 896c535eb59SGordon Tetlow if [ -n "$bad" ]; then 89700e05e69SGordon Tetlow echo -e "$bad" >&2 898c535eb59SGordon Tetlow fi 899c535eb59SGordon Tetlow 900c535eb59SGordon Tetlow exit $rval 901c535eb59SGordon Tetlow} 902c535eb59SGordon Tetlow 90357cd9717SGordon Tetlow# Usage: setup_cattool page 90457cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 90557cd9717SGordon Tetlowsetup_cattool() { 90657cd9717SGordon Tetlow case "$1" in 90757cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 90857cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 90957cd9717SGordon Tetlow *.gz) cattool='/usr/bin/zcat' ;; 91057cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 91157cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 91257cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 91357cd9717SGordon Tetlow esac 91457cd9717SGordon Tetlow} 91557cd9717SGordon Tetlow 916c535eb59SGordon Tetlow# Usage: setup_pager 917a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 918c535eb59SGordon Tetlowsetup_pager() { 919c535eb59SGordon Tetlow # Setup pager. 920a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 921a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 922a6a3e856SRuslan Ermilov MANPAGER="less -sR" 923a6a3e856SRuslan Ermilov else 924a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 925a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 926a6a3e856SRuslan Ermilov else 92747cc9ee1SAlan Somers MANPAGER="less -s" 928c535eb59SGordon Tetlow fi 929a6a3e856SRuslan Ermilov fi 930a6a3e856SRuslan Ermilov fi 931a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 932c535eb59SGordon Tetlow} 933c535eb59SGordon Tetlow 934c535eb59SGordon Tetlow# Usage: trim string 935c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 936c535eb59SGordon Tetlowtrim() { 937c535eb59SGordon Tetlow tstr=$1 938c535eb59SGordon Tetlow while true; do 939c535eb59SGordon Tetlow case "$tstr" in 940c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 941c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 942c535eb59SGordon Tetlow *) break ;; 943c535eb59SGordon Tetlow esac 944c535eb59SGordon Tetlow done 945c535eb59SGordon Tetlow} 946c535eb59SGordon Tetlow 947c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 948c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 949c535eb59SGordon Tetlowwhatis_parse_args() { 950c535eb59SGordon Tetlow local cmd_arg 951f555b39eSKyle Evans OPTIND=1 952c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 953c535eb59SGordon Tetlow case "${cmd_arg}" in 954c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 955c535eb59SGordon Tetlow *) whatis_usage ;; 956c535eb59SGordon Tetlow esac 957c535eb59SGordon Tetlow done >&2 958c535eb59SGordon Tetlow 959c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 960c535eb59SGordon Tetlow 961c535eb59SGordon Tetlow keywords="$*" 962c535eb59SGordon Tetlow} 963c535eb59SGordon Tetlow 964c535eb59SGordon Tetlow# Usage: whatis_usage 965c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 966c535eb59SGordon Tetlowwhatis_usage() { 967c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 968c535eb59SGordon Tetlow exit 1 969c535eb59SGordon Tetlow} 970c535eb59SGordon Tetlow 971c535eb59SGordon Tetlow 972c535eb59SGordon Tetlow 973c535eb59SGordon Tetlow# Supported commands 974c535eb59SGordon Tetlowdo_apropos() { 97524ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 976772246efSBaptiste Daroussin exec apropos "$@" 977c535eb59SGordon Tetlow search_whatis apropos "$@" 978c535eb59SGordon Tetlow} 979c535eb59SGordon Tetlow 9801594084fSFernando Apesteguía# Usage: do_full_search reg_exp 9811594084fSFernando Apesteguía# Do a full search of the regular expression passed 9821594084fSFernando Apesteguía# as parameter in all man pages 9831594084fSFernando Apesteguíado_full_search() { 9841594084fSFernando Apesteguía local gflags re 9851594084fSFernando Apesteguía re=${1} 9861594084fSFernando Apesteguía 9871594084fSFernando Apesteguía # Build grep(1) flags 9881594084fSFernando Apesteguía gflags="-H" 9891594084fSFernando Apesteguía 9901594084fSFernando Apesteguía # wflag implies -l for grep(1) 9911594084fSFernando Apesteguía if [ -n "$wflag" ]; then 9921594084fSFernando Apesteguía gflags="${gflags} -l" 9931594084fSFernando Apesteguía fi 9941594084fSFernando Apesteguía 9951594084fSFernando Apesteguía gflags="${gflags} --label" 9961594084fSFernando Apesteguía 9971594084fSFernando Apesteguía set +f 9981594084fSFernando Apesteguía for mpath in $(echo "${MANPATH}" | tr : [:blank:]); do 9991594084fSFernando Apesteguía for section in $(echo "${MANSECT}" | tr : [:blank:]); do 10001594084fSFernando Apesteguía for manfile in ${mpath}/man${section}/*.${section}*; do 10011594084fSFernando Apesteguía mandoc "${manfile}" 2>/dev/null | 10021594084fSFernando Apesteguía grep -E ${gflags} "${manfile}" -e ${re} 10031594084fSFernando Apesteguía done 10041594084fSFernando Apesteguía done 10051594084fSFernando Apesteguía done 10061594084fSFernando Apesteguía set -f 10071594084fSFernando Apesteguía} 10081594084fSFernando Apesteguía 1009c535eb59SGordon Tetlowdo_man() { 1010c535eb59SGordon Tetlow man_parse_args "$@" 10111594084fSFernando Apesteguía if [ -z "$pages" -a -z "${Kflag}" ]; then 1012c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 1013c535eb59SGordon Tetlow exit 1 1014c535eb59SGordon Tetlow fi 1015c535eb59SGordon Tetlow man_setup 1016c535eb59SGordon Tetlow 10171594084fSFernando Apesteguía if [ ! -z "${Kflag}" ]; then 10181594084fSFernando Apesteguía # Short circuit because -K flag does a sufficiently 10191594084fSFernando Apesteguía # different thing like not showing the man page at all 10201594084fSFernando Apesteguía do_full_search "${REGEXP}" 10211594084fSFernando Apesteguía fi 10221594084fSFernando Apesteguía 1023c535eb59SGordon Tetlow for page in $pages; do 1024c535eb59SGordon Tetlow decho "Searching for $page" 1025c535eb59SGordon Tetlow man_find_and_display "$page" 1026c535eb59SGordon Tetlow done 1027c535eb59SGordon Tetlow 1028c535eb59SGordon Tetlow exit ${ret:-0} 1029c535eb59SGordon Tetlow} 1030c535eb59SGordon Tetlow 1031c535eb59SGordon Tetlowdo_manpath() { 1032c535eb59SGordon Tetlow manpath_parse_args "$@" 1033c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 1034c535eb59SGordon Tetlow manpath_warnings 1035c535eb59SGordon Tetlow fi 1036c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 1037c535eb59SGordon Tetlow build_manlocales 1038c535eb59SGordon Tetlow echo $MANLOCALES 1039c535eb59SGordon Tetlow else 1040c535eb59SGordon Tetlow build_manpath 1041c535eb59SGordon Tetlow echo $MANPATH 1042c535eb59SGordon Tetlow fi 1043c535eb59SGordon Tetlow exit 0 1044c535eb59SGordon Tetlow} 1045c535eb59SGordon Tetlow 1046c535eb59SGordon Tetlowdo_whatis() { 104724ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 1048772246efSBaptiste Daroussin exec whatis "$@" 1049c535eb59SGordon Tetlow search_whatis whatis "$@" 1050c535eb59SGordon Tetlow} 1051c535eb59SGordon Tetlow 1052aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 1053aeea395eSUlrich SpörleinEQN=eqn 1054a6a3e856SRuslan ErmilovNROFF='groff -S -P-h -Wall -mtty-char -man' 1055aeea395eSUlrich SpörleinPIC=pic 1056aeea395eSUlrich SpörleinREFER=refer 1057aeea395eSUlrich SpörleinTBL=tbl 10583d120968SUlrich SpörleinTROFF='groff -S -man' 1059aeea395eSUlrich SpörleinVGRIND=vgrind 1060aeea395eSUlrich Spörlein 1061deeff310SGordon TetlowLOCALE=/usr/bin/locale 1062a0094449SRuslan ErmilovSTTY=/bin/stty 106382db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1064c535eb59SGordon Tetlow 1065c535eb59SGordon Tetlowdebug=0 106673577bf0SRyan Moellerman_default_sections='1:8:2:3:3lua:n:4:5:6:7:9:l' 1067971c1c42STijl Coosemansman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man' 106857cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1069c535eb59SGordon Tetlow 1070c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1071c535eb59SGordon Tetlow 1072c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1073c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1074c535eb59SGordon Tetlow 1075c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1076c535eb59SGordon Tetlowset -f 1077c535eb59SGordon Tetlow 1078c535eb59SGordon Tetlowcase "$0" in 1079c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1080c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1081c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1082c535eb59SGordon Tetlow*) do_man "$@" ;; 1083c535eb59SGordon Tetlowesac 1084