1c535eb59SGordon Tetlow#! /bin/sh 2c535eb59SGordon Tetlow# 34d846d26SWarner Losh# SPDX-License-Identifier: BSD-2-Clause 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 30433c5a8aSWolfram Schneider# Rendering a manual page is fast. Even a manual page several 100k in size 31433c5a8aSWolfram Schneider# takes less than a CPU second. If it takes much longer, it is very likely 32433c5a8aSWolfram Schneider# that a tool like mandoc(1) is running in an infinite loop. In this case 33433c5a8aSWolfram Schneider# it is better to terminate it. 34433c5a8aSWolfram Schneiderulimit -t 20 35433c5a8aSWolfram Schneider 36c535eb59SGordon Tetlow# Usage: add_to_manpath path 37c535eb59SGordon Tetlow# Adds a variable to manpath while ensuring we don't have duplicates. 38c535eb59SGordon Tetlow# Returns true if we were able to add something. False otherwise. 39c535eb59SGordon Tetlowadd_to_manpath() { 40c535eb59SGordon Tetlow case "$manpath" in 41c535eb59SGordon Tetlow *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 42c535eb59SGordon Tetlow $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 43c535eb59SGordon Tetlow *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 44c535eb59SGordon Tetlow *) if [ -d "$1" ]; then 45c535eb59SGordon Tetlow decho " Adding $1 to manpath" 46c535eb59SGordon Tetlow manpath="$manpath:$1" 47c535eb59SGordon Tetlow return 0 48c535eb59SGordon Tetlow fi 49c535eb59SGordon Tetlow ;; 50c535eb59SGordon Tetlow esac 51c535eb59SGordon Tetlow 52c535eb59SGordon Tetlow return 1 53c535eb59SGordon Tetlow} 54c535eb59SGordon Tetlow 55c535eb59SGordon Tetlow# Usage: build_manlocales 56c535eb59SGordon Tetlow# Builds a correct MANLOCALES variable. 57c535eb59SGordon Tetlowbuild_manlocales() { 58c535eb59SGordon Tetlow # If the user has set manlocales, who are we to argue. 59c535eb59SGordon Tetlow if [ -n "$MANLOCALES" ]; then 60c535eb59SGordon Tetlow return 61c535eb59SGordon Tetlow fi 62c535eb59SGordon Tetlow 63c535eb59SGordon Tetlow parse_configs 64c535eb59SGordon Tetlow 65c535eb59SGordon Tetlow # Trim leading colon 66c535eb59SGordon Tetlow MANLOCALES=${manlocales#:} 67c535eb59SGordon Tetlow 68c535eb59SGordon Tetlow decho "Available manual locales: $MANLOCALES" 69c535eb59SGordon Tetlow} 70c535eb59SGordon Tetlow 718edb6fb5SMohamed Akram# Usage: build_mansect 728edb6fb5SMohamed Akram# Builds a correct MANSECT variable. 738edb6fb5SMohamed Akrambuild_mansect() { 748edb6fb5SMohamed Akram # If the user has set mansect, who are we to argue. 758edb6fb5SMohamed Akram if [ -n "$MANSECT" ]; then 768edb6fb5SMohamed Akram return 778edb6fb5SMohamed Akram fi 788edb6fb5SMohamed Akram 798edb6fb5SMohamed Akram parse_configs 808edb6fb5SMohamed Akram 818edb6fb5SMohamed Akram # Trim leading colon 828edb6fb5SMohamed Akram MANSECT=${mansect#:} 838edb6fb5SMohamed Akram 848edb6fb5SMohamed Akram if [ -z "$MANSECT" ]; then 858edb6fb5SMohamed Akram MANSECT=$man_default_sections 868edb6fb5SMohamed Akram fi 878edb6fb5SMohamed Akram decho "Using manual sections: $MANSECT" 888edb6fb5SMohamed Akram} 898edb6fb5SMohamed Akram 90c535eb59SGordon Tetlow# Usage: build_manpath 91c535eb59SGordon Tetlow# Builds a correct MANPATH variable. 92c535eb59SGordon Tetlowbuild_manpath() { 93c535eb59SGordon Tetlow local IFS 94c535eb59SGordon Tetlow 95c535eb59SGordon Tetlow # If the user has set a manpath, who are we to argue. 96c535eb59SGordon Tetlow if [ -n "$MANPATH" ]; then 97b2394e73SBaptiste Daroussin case "$MANPATH" in 98b2394e73SBaptiste Daroussin *:) PREPEND_MANPATH=${MANPATH} ;; 99b2394e73SBaptiste Daroussin :*) APPEND_MANPATH=${MANPATH} ;; 100b2394e73SBaptiste Daroussin *::*) 101b2394e73SBaptiste Daroussin PREPEND_MANPATH=${MANPATH%%::*} 102b2394e73SBaptiste Daroussin APPEND_MANPATH=${MANPATH#*::} 103b2394e73SBaptiste Daroussin ;; 104b2394e73SBaptiste Daroussin *) return ;; 105b2394e73SBaptiste Daroussin esac 106b2394e73SBaptiste Daroussin fi 107b2394e73SBaptiste Daroussin 108b2394e73SBaptiste Daroussin if [ -n "$PREPEND_MANPATH" ]; then 109b2394e73SBaptiste Daroussin IFS=: 110b2394e73SBaptiste Daroussin for path in $PREPEND_MANPATH; do 111b2394e73SBaptiste Daroussin add_to_manpath "$path" 112b2394e73SBaptiste Daroussin done 113b2394e73SBaptiste Daroussin unset IFS 114c535eb59SGordon Tetlow fi 115c535eb59SGordon Tetlow 116c535eb59SGordon Tetlow search_path 117c535eb59SGordon Tetlow 118c535eb59SGordon Tetlow decho "Adding default manpath entries" 119c535eb59SGordon Tetlow IFS=: 120c535eb59SGordon Tetlow for path in $man_default_path; do 121c535eb59SGordon Tetlow add_to_manpath "$path" 122c535eb59SGordon Tetlow done 123c535eb59SGordon Tetlow unset IFS 124c535eb59SGordon Tetlow 125c535eb59SGordon Tetlow parse_configs 126c535eb59SGordon Tetlow 127b2394e73SBaptiste Daroussin if [ -n "$APPEND_MANPATH" ]; then 128b2394e73SBaptiste Daroussin IFS=: 129b2394e73SBaptiste Daroussin for path in $APPEND_MANPATH; do 130b2394e73SBaptiste Daroussin add_to_manpath "$path" 131b2394e73SBaptiste Daroussin done 132b2394e73SBaptiste Daroussin unset IFS 133b2394e73SBaptiste Daroussin fi 134c535eb59SGordon Tetlow # Trim leading colon 135c535eb59SGordon Tetlow MANPATH=${manpath#:} 136c535eb59SGordon Tetlow 137c535eb59SGordon Tetlow decho "Using manual path: $MANPATH" 138c535eb59SGordon Tetlow} 139c535eb59SGordon Tetlow 140c535eb59SGordon Tetlow# Usage: check_cat catglob 141c535eb59SGordon Tetlow# Checks to see if a cat glob is available. 142c535eb59SGordon Tetlowcheck_cat() { 143c535eb59SGordon Tetlow if exists "$1"; then 144c535eb59SGordon Tetlow use_cat=yes 145c535eb59SGordon Tetlow catpage=$found 146c4368d03SWolfram Schneider setup_cattool "$catpage" 147c4368d03SWolfram Schneider decho " Found catpage \"$catpage\"" 148c535eb59SGordon Tetlow return 0 149c535eb59SGordon Tetlow else 150c535eb59SGordon Tetlow return 1 151c535eb59SGordon Tetlow fi 152c535eb59SGordon Tetlow} 153c535eb59SGordon Tetlow 154c535eb59SGordon Tetlow# Usage: check_man manglob catglob 155c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to 156c535eb59SGordon Tetlow# see if the catglob is also available and up to date. 157c535eb59SGordon Tetlowcheck_man() { 158c535eb59SGordon Tetlow if exists "$1"; then 159c535eb59SGordon Tetlow # We have a match, check for a cat page 160c535eb59SGordon Tetlow manpage=$found 16178948070SWolfram Schneider setup_cattool "$manpage" 16278948070SWolfram Schneider decho " Found manpage \"$manpage\"" 163c535eb59SGordon Tetlow 164a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 165a0094449SRuslan Ermilov # non-standard width 166a0094449SRuslan Ermilov unset use_cat 167a0094449SRuslan Ermilov decho " Skipping catpage: non-standard page width" 16878948070SWolfram Schneider elif exists "$2" && is_newer $found "$manpage"; then 169c535eb59SGordon Tetlow # cat page found and is newer, use that 170c535eb59SGordon Tetlow use_cat=yes 171c535eb59SGordon Tetlow catpage=$found 172c4368d03SWolfram Schneider setup_cattool "$catpage" 173c4368d03SWolfram Schneider decho " Using catpage \"$catpage\"" 174c535eb59SGordon Tetlow else 175c535eb59SGordon Tetlow # no cat page or is older 176c535eb59SGordon Tetlow unset use_cat 177c535eb59SGordon Tetlow decho " Skipping catpage: not found or old" 178c535eb59SGordon Tetlow fi 179c535eb59SGordon Tetlow return 0 180c535eb59SGordon Tetlow fi 181c535eb59SGordon Tetlow 182c535eb59SGordon Tetlow return 1 183c535eb59SGordon Tetlow} 184c535eb59SGordon Tetlow 185c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel] 186c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel. 187c535eb59SGordon Tetlowdecho() { 188c535eb59SGordon Tetlow if [ $debug -ge ${2:-1} ]; then 189c535eb59SGordon Tetlow echo "-- $1" >&2 190c535eb59SGordon Tetlow fi 191c535eb59SGordon Tetlow} 192c535eb59SGordon Tetlow 193c535eb59SGordon Tetlow# Usage: exists glob 194e3c7b76fSWolfram Schneider# 195e3c7b76fSWolfram Schneider# Returns true if glob resolves to a real file and store the first 196e3c7b76fSWolfram Schneider# found filename in the variable $found 197c535eb59SGordon Tetlowexists() { 198c535eb59SGordon Tetlow local IFS 199c535eb59SGordon Tetlow 200c535eb59SGordon Tetlow # Don't accidentally inherit callers IFS (breaks perl manpages) 201c535eb59SGordon Tetlow unset IFS 202c535eb59SGordon Tetlow 203c535eb59SGordon Tetlow # Use some globbing tricks in the shell to determine if a file 204c535eb59SGordon Tetlow # exists or not. 205c535eb59SGordon Tetlow set +f 206e3c7b76fSWolfram Schneider for file in "$1"* 207e3c7b76fSWolfram Schneider do 208e3c7b76fSWolfram Schneider if [ -r "$file" ]; then 209e3c7b76fSWolfram Schneider found="$file" 210c535eb59SGordon Tetlow set -f 211c535eb59SGordon Tetlow return 0 212c535eb59SGordon Tetlow fi 213e3c7b76fSWolfram Schneider done 214e3c7b76fSWolfram Schneider set -f 215c535eb59SGordon Tetlow 216c535eb59SGordon Tetlow return 1 217c535eb59SGordon Tetlow} 218c535eb59SGordon Tetlow 219c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename 220c535eb59SGordon Tetlow# Returns: true if something is matched and found. 221c535eb59SGordon Tetlow# Search the given path/section combo for a given page. 222c535eb59SGordon Tetlowfind_file() { 223c535eb59SGordon Tetlow local manroot catroot mann man0 catn cat0 224c535eb59SGordon Tetlow 225c535eb59SGordon Tetlow manroot="$1/man$2" 226c535eb59SGordon Tetlow catroot="$1/cat$2" 227c535eb59SGordon Tetlow if [ -n "$3" ]; then 228c535eb59SGordon Tetlow manroot="$manroot/$3" 229c535eb59SGordon Tetlow catroot="$catroot/$3" 230c535eb59SGordon Tetlow fi 231c535eb59SGordon Tetlow 232625490e8SBaptiste Daroussin if [ ! -d "$manroot" -a ! -d "$catroot" ]; then 233c535eb59SGordon Tetlow return 1 234c535eb59SGordon Tetlow fi 235c535eb59SGordon Tetlow decho " Searching directory $manroot" 2 236c535eb59SGordon Tetlow 237e3c7b76fSWolfram Schneider mann="$manroot/$4.$2" 238e3c7b76fSWolfram Schneider man0="$manroot/$4.0" 239e3c7b76fSWolfram Schneider catn="$catroot/$4.$2" 240e3c7b76fSWolfram Schneider cat0="$catroot/$4.0" 241c535eb59SGordon Tetlow 242c535eb59SGordon Tetlow # This is the behavior as seen by the original man utility. 243c535eb59SGordon Tetlow # Let's not change that which doesn't seem broken. 244c535eb59SGordon Tetlow if check_man "$mann" "$catn"; then 245c535eb59SGordon Tetlow return 0 246c535eb59SGordon Tetlow elif check_man "$man0" "$cat0"; then 247c535eb59SGordon Tetlow return 0 248c535eb59SGordon Tetlow elif check_cat "$catn"; then 249c535eb59SGordon Tetlow return 0 250c535eb59SGordon Tetlow elif check_cat "$cat0"; then 251c535eb59SGordon Tetlow return 0 252c535eb59SGordon Tetlow fi 253c535eb59SGordon Tetlow 254c535eb59SGordon Tetlow return 1 255c535eb59SGordon Tetlow} 256c535eb59SGordon Tetlow 257c535eb59SGordon Tetlow# Usage: is_newer file1 file2 258c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime. 259c535eb59SGordon Tetlowis_newer() { 2609b61837aSUlrich Spörlein if ! [ "$1" -ot "$2" ]; then 2619b61837aSUlrich Spörlein decho " mtime: $1 not older than $2" 3 262c535eb59SGordon Tetlow return 0 263c535eb59SGordon Tetlow else 264c535eb59SGordon Tetlow decho " mtime: $1 older than $2" 3 265c535eb59SGordon Tetlow return 1 266c535eb59SGordon Tetlow fi 267c535eb59SGordon Tetlow} 268c535eb59SGordon Tetlow 269c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@" 270c535eb59SGordon Tetlow# Parses commandline options for manpath. 271c535eb59SGordon Tetlowmanpath_parse_args() { 272c535eb59SGordon Tetlow local cmd_arg 273c535eb59SGordon Tetlow 274f555b39eSKyle Evans OPTIND=1 275c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 276c535eb59SGordon Tetlow case "${cmd_arg}" in 277c535eb59SGordon Tetlow L) Lflag=Lflag ;; 278c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 279c535eb59SGordon Tetlow q) qflag=qflag ;; 280c535eb59SGordon Tetlow *) manpath_usage ;; 281c535eb59SGordon Tetlow esac 282c535eb59SGordon Tetlow done >&2 283c535eb59SGordon Tetlow} 284c535eb59SGordon Tetlow 285c535eb59SGordon Tetlow# Usage: manpath_usage 286c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 287c535eb59SGordon Tetlowmanpath_usage() { 288c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 289c535eb59SGordon Tetlow exit 1 290c535eb59SGordon Tetlow} 291c535eb59SGordon Tetlow 292c535eb59SGordon Tetlow# Usage: manpath_warnings 293c535eb59SGordon Tetlow# Display some warnings to stderr. 294c535eb59SGordon Tetlowmanpath_warnings() { 295c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 296c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 297c535eb59SGordon Tetlow fi 298c535eb59SGordon Tetlow} 299c535eb59SGordon Tetlow 30057cd9717SGordon Tetlow# Usage: man_check_for_so page path 30157cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 30257cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 30357cd9717SGordon Tetlow# redirected to another source file. 30457cd9717SGordon Tetlowman_check_for_so() { 30557cd9717SGordon Tetlow local IFS line tstr 30657cd9717SGordon Tetlow 30757cd9717SGordon Tetlow unset IFS 308d9405a92SBaptiste Daroussin if [ -n "$catpage" ]; then 309d9405a92SBaptiste Daroussin return 0 310d9405a92SBaptiste Daroussin fi 31157cd9717SGordon Tetlow 31257cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 31357cd9717SGordon Tetlow while true 31457cd9717SGordon Tetlow do 315ec13a838SMohamed Akram line=$($cattool "$manpage" | head -n1) 31657cd9717SGordon Tetlow case "$line" in 31757cd9717SGordon Tetlow .so*) trim "${line#.so}" 31857cd9717SGordon Tetlow decho "$manpage includes $tstr" 31957cd9717SGordon Tetlow # Glob and check for the file. 320e3c7b76fSWolfram Schneider if ! check_man "$path/$tstr" ""; then 32157cd9717SGordon Tetlow decho " Unable to find $tstr" 32257cd9717SGordon Tetlow return 1 32357cd9717SGordon Tetlow fi 32457cd9717SGordon Tetlow ;; 32557cd9717SGordon Tetlow *) break ;; 32657cd9717SGordon Tetlow esac 32757cd9717SGordon Tetlow done 32857cd9717SGordon Tetlow 32957cd9717SGordon Tetlow return 0 33057cd9717SGordon Tetlow} 33157cd9717SGordon Tetlow 332b43edc06SBaptiste Daroussin# Usage: man_display_page 333b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 334c535eb59SGordon Tetlowman_display_page() { 3351fb816daSBaptiste Daroussin local IFS pipeline testline 336c535eb59SGordon Tetlow 337c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 338c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 339c535eb59SGordon Tetlow unset IFS 340c535eb59SGordon Tetlow 341c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 342c535eb59SGordon Tetlow # just zcat the catpage and we are done. 343c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 344c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 34578948070SWolfram Schneider echo "$catpage (source: \"$manpage\")" 346c535eb59SGordon Tetlow ret=0 347c535eb59SGordon Tetlow else 348c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 349c4368d03SWolfram Schneider decho "Command: $cattool \"$catpage\" | $MANPAGER" 350c535eb59SGordon Tetlow ret=0 351c535eb59SGordon Tetlow else 352*b8a484ecSWolfram Schneider $cattool "$catpage" | $MANPAGER 353c535eb59SGordon Tetlow ret=$? 354c535eb59SGordon Tetlow fi 355c535eb59SGordon Tetlow fi 356c535eb59SGordon Tetlow return 357c535eb59SGordon Tetlow fi 358c535eb59SGordon Tetlow 359c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 360c535eb59SGordon Tetlow # name of the manpage? 361c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 362c535eb59SGordon Tetlow echo "$manpage" 363c535eb59SGordon Tetlow ret=0 364c535eb59SGordon Tetlow return 365c535eb59SGordon Tetlow fi 366c535eb59SGordon Tetlow 367d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 368d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 369d433cf9aSBaptiste Daroussin fi 370451c2becSBaptiste Daroussin testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 371449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 372449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 373449a792dSBaptiste Daroussin else 374d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 375449a792dSBaptiste Daroussin fi 376d6096801SBaptiste Daroussin 377*b8a484ecSWolfram Schneider if ! $cattool "$manpage" | eval "$testline"; then 378f17575acSBaptiste Daroussin if which -s groff; then 379d6096801SBaptiste Daroussin man_display_page_groff 380d6096801SBaptiste Daroussin else 381d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 382d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 383d6096801SBaptiste Daroussin echo "pkg install groff " >&2 384d6096801SBaptiste Daroussin ret=1 385d6096801SBaptiste Daroussin fi 386d6096801SBaptiste Daroussin return 387d6096801SBaptiste Daroussin fi 388d6096801SBaptiste Daroussin 389d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 390*b8a484ecSWolfram Schneider decho "Command: $cattool \"$manpage\" | eval \"$pipeline\"" 391d6096801SBaptiste Daroussin ret=0 392d6096801SBaptiste Daroussin else 393*b8a484ecSWolfram Schneider $cattool "$manpage" | eval "$pipeline" 394d6096801SBaptiste Daroussin ret=$? 395d6096801SBaptiste Daroussin fi 396d6096801SBaptiste Daroussin} 397d6096801SBaptiste Daroussin 398b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 399b43edc06SBaptiste Daroussin# Display the manpage using groff 400d6096801SBaptiste Daroussinman_display_page_groff() { 401d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 402d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 403d6096801SBaptiste Daroussin 404c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 405c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 406c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 407c535eb59SGordon Tetlow 408deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 409deeff310SGordon Tetlow # to properly output for the correct device. 410deeff310SGordon Tetlow case "${manpage}" in 411deeff310SGordon Tetlow *.${man_charset}/*) 412c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 413c535eb59SGordon Tetlow # previous version of man(1). 414c535eb59SGordon Tetlow case "$man_charset" in 415c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 416c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 417c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 418c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 419c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 420c535eb59SGordon Tetlow esac 421c535eb59SGordon Tetlow 422deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 423c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 424c535eb59SGordon Tetlow 425deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 426deeff310SGordon Tetlow # then we need to define the locale string. 427deeff310SGordon Tetlow case "${manpage}" in 428deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 429deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 430deeff310SGordon Tetlow ;; 431deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 432deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 433deeff310SGordon Tetlow ;; 434deeff310SGordon Tetlow esac 435deeff310SGordon Tetlow 436c535eb59SGordon Tetlow # Allow language specific calls to override the default 437c535eb59SGordon Tetlow # set of utilities. 438c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 439b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 440c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 441c535eb59SGordon Tetlow done 442c535eb59SGordon Tetlow ;; 443c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 444c535eb59SGordon Tetlow EQN="$EQN -Tascii" 445c535eb59SGordon Tetlow ;; 446c535eb59SGordon Tetlow esac 447c535eb59SGordon Tetlow 448a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 449a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 450a6a3e856SRuslan Ermilov fi 451a6a3e856SRuslan Ermilov 452a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 453a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 454a0094449SRuslan Ermilov fi 455a0094449SRuslan Ermilov 456c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 457c535eb59SGordon Tetlow set -- -$MANROFFSEQ 458f555b39eSKyle Evans OPTIND=1 459c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 460c535eb59SGordon Tetlow case "${preproc_arg}" in 461c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 462487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 463c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 464c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 465b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 466c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 467c535eb59SGordon Tetlow *) usage ;; 468c535eb59SGordon Tetlow esac 469c535eb59SGordon Tetlow done 470c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 471c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 472c535eb59SGordon Tetlow else 473c535eb59SGordon Tetlow pipeline="$TBL" 474c535eb59SGordon Tetlow fi 475c535eb59SGordon Tetlow 476c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 477c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 478c535eb59SGordon Tetlow else 479a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 480c535eb59SGordon Tetlow fi 481c535eb59SGordon Tetlow 482c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 483*b8a484ecSWolfram Schneider decho "Command: $cattool \"$manpage\" | eval \"$pipeline\"" 484c535eb59SGordon Tetlow ret=0 485c535eb59SGordon Tetlow else 486*b8a484ecSWolfram Schneider $cattool "$manpage" | eval "$pipeline" 487c535eb59SGordon Tetlow ret=$? 488c535eb59SGordon Tetlow fi 489c535eb59SGordon Tetlow} 490c535eb59SGordon Tetlow 491c535eb59SGordon Tetlow# Usage: man_find_and_display page 492c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 493c535eb59SGordon Tetlowman_find_and_display() { 494c535eb59SGordon Tetlow local found_page locpath p path sect 495c535eb59SGordon Tetlow 4963d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 4973d9127f1SGordon Tetlow # the filename. 4983d9127f1SGordon Tetlow case "$1" in 4993d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 5003d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 5013d9127f1SGordon Tetlow unset use_cat 5023d9127f1SGordon Tetlow manpage="$1" 50378948070SWolfram Schneider setup_cattool "$manpage" 50478948070SWolfram Schneider if man_check_for_so "$manpage" "$(dirname \"$manpage"")"; then 50557cd9717SGordon Tetlow found_page=yes 5063d9127f1SGordon Tetlow man_display_page 50757cd9717SGordon Tetlow fi 5083d9127f1SGordon Tetlow return 5093d9127f1SGordon Tetlow fi 5103d9127f1SGordon Tetlow ;; 5113d9127f1SGordon Tetlow esac 5123d9127f1SGordon Tetlow 513c535eb59SGordon Tetlow IFS=: 514c535eb59SGordon Tetlow for sect in $MANSECT; do 515c535eb59SGordon Tetlow decho "Searching section $sect" 2 516c535eb59SGordon Tetlow for path in $MANPATH; do 517c535eb59SGordon Tetlow for locpath in $locpaths; do 518c535eb59SGordon Tetlow p=$path/$locpath 519c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 520c535eb59SGordon Tetlow 521c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 522c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 52378948070SWolfram Schneider if man_check_for_so "$manpage" $p; then 524c535eb59SGordon Tetlow found_page=yes 525c535eb59SGordon Tetlow man_display_page 5261d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5271d7c660aSGordon Tetlow continue 2 5281d7c660aSGordon Tetlow else 529c535eb59SGordon Tetlow return 530c535eb59SGordon Tetlow fi 531c535eb59SGordon Tetlow fi 53257cd9717SGordon Tetlow fi 533c535eb59SGordon Tetlow 534c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 535c535eb59SGordon Tetlow # specific manpath. 536c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 53778948070SWolfram Schneider if man_check_for_so "$manpage" $p; then 538c535eb59SGordon Tetlow found_page=yes 539c535eb59SGordon Tetlow man_display_page 5401d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5411d7c660aSGordon Tetlow continue 2 5421d7c660aSGordon Tetlow else 543c535eb59SGordon Tetlow return 544c535eb59SGordon Tetlow fi 545c535eb59SGordon Tetlow fi 54657cd9717SGordon Tetlow fi 547c535eb59SGordon Tetlow 548c535eb59SGordon Tetlow # Check plain old manpath. 549c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 55078948070SWolfram Schneider if man_check_for_so "$manpage" $p; then 551c535eb59SGordon Tetlow found_page=yes 552c535eb59SGordon Tetlow man_display_page 5531d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5541d7c660aSGordon Tetlow continue 2 5551d7c660aSGordon Tetlow else 556c535eb59SGordon Tetlow return 557c535eb59SGordon Tetlow fi 558c535eb59SGordon Tetlow fi 55957cd9717SGordon Tetlow fi 560c535eb59SGordon Tetlow done 561c535eb59SGordon Tetlow done 562c535eb59SGordon Tetlow done 563c535eb59SGordon Tetlow unset IFS 564c535eb59SGordon Tetlow 565c535eb59SGordon Tetlow # Nothing? Well, we are done then. 566c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 56778948070SWolfram Schneider echo "No manual entry for \"$1\"" >&2 568c535eb59SGordon Tetlow ret=1 569c535eb59SGordon Tetlow return 570c535eb59SGordon Tetlow fi 571c535eb59SGordon Tetlow} 572c535eb59SGordon Tetlow 5738edb6fb5SMohamed Akram# Usage: man_parse_opts "$@" 574c535eb59SGordon Tetlow# Parses commandline options for man. 5758edb6fb5SMohamed Akramman_parse_opts() { 5768edb6fb5SMohamed Akram local cmd_arg 577c535eb59SGordon Tetlow 578f555b39eSKyle Evans OPTIND=1 5791594084fSFernando Apesteguía while getopts 'K:M:P:S:adfhkm:op:tw' cmd_arg; do 580c535eb59SGordon Tetlow case "${cmd_arg}" in 5811594084fSFernando Apesteguía K) Kflag=Kflag 5821594084fSFernando Apesteguía REGEXP=$OPTARG ;; 583c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 584a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 585c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 586c535eb59SGordon Tetlow a) aflag=aflag ;; 587c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 588c535eb59SGordon Tetlow f) fflag=fflag ;; 589c535eb59SGordon Tetlow h) man_usage 0 ;; 590c535eb59SGordon Tetlow k) kflag=kflag ;; 591c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 592c535eb59SGordon Tetlow o) oflag=oflag ;; 593c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 594c535eb59SGordon Tetlow t) tflag=tflag ;; 595c535eb59SGordon Tetlow w) wflag=wflag ;; 596c535eb59SGordon Tetlow *) man_usage ;; 597c535eb59SGordon Tetlow esac 598c535eb59SGordon Tetlow done >&2 599c535eb59SGordon Tetlow 600c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 601c535eb59SGordon Tetlow 602c535eb59SGordon Tetlow # Check the args for incompatible options. 6031594084fSFernando Apesteguía 6041594084fSFernando Apesteguía case "${Kflag}${fflag}${kflag}${tflag}${wflag}" in 6051594084fSFernando Apesteguía Kflagfflag*) echo "Incompatible options: -K and -f"; man_usage ;; 6061594084fSFernando Apesteguía Kflag*kflag*) echo "Incompatible options: -K and -k"; man_usage ;; 6071594084fSFernando Apesteguía Kflag*tflag) echo "Incompatible options: -K and -t"; man_usage ;; 608c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 609c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 610c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 611c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 612c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 613c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 614c535eb59SGordon Tetlow esac 615c535eb59SGordon Tetlow 616c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 617c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 618c535eb59SGordon Tetlow do_whatis "$@" 619c535eb59SGordon Tetlow exit 620c535eb59SGordon Tetlow fi 621c535eb59SGordon Tetlow 622c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 623c535eb59SGordon Tetlow do_apropos "$@" 624c535eb59SGordon Tetlow exit 625c535eb59SGordon Tetlow fi 626c535eb59SGordon Tetlow} 627c535eb59SGordon Tetlow 628c535eb59SGordon Tetlow# Usage: man_setup 629c535eb59SGordon Tetlow# Setup various trivial but essential variables. 630c535eb59SGordon Tetlowman_setup() { 631c535eb59SGordon Tetlow # Setup machine and architecture variables. 632c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 633c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 634c535eb59SGordon Tetlow MACHINE=${mflag##*:} 635c535eb59SGordon Tetlow fi 636c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 63782db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 638c535eb59SGordon Tetlow fi 639c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 64082db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 641c535eb59SGordon Tetlow fi 642c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 643c535eb59SGordon Tetlow 644c535eb59SGordon Tetlow setup_pager 645c535eb59SGordon Tetlow build_manpath 6468edb6fb5SMohamed Akram build_mansect 647c535eb59SGordon Tetlow man_setup_locale 648a0094449SRuslan Ermilov man_setup_width 649a0094449SRuslan Ermilov} 650a0094449SRuslan Ermilov 651a0094449SRuslan Ermilov# Usage: man_setup_width 652a0094449SRuslan Ermilov# Set up page width. 653a0094449SRuslan Ermilovman_setup_width() { 654a0094449SRuslan Ermilov local sizes 655a0094449SRuslan Ermilov 656a0094449SRuslan Ermilov unset use_width 657a0094449SRuslan Ermilov case "$MANWIDTH" in 658a0094449SRuslan Ermilov [0-9]*) 659a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 660a0094449SRuslan Ermilov use_width=$MANWIDTH 661a0094449SRuslan Ermilov fi 662a0094449SRuslan Ermilov ;; 663a0094449SRuslan Ermilov [Tt][Tt][Yy]) 664a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 665a0094449SRuslan Ermilov set -- $sizes 666a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 667a0094449SRuslan Ermilov use_width=$(($2-2)) 668a0094449SRuslan Ermilov fi 669a0094449SRuslan Ermilov fi 670a0094449SRuslan Ermilov ;; 671a0094449SRuslan Ermilov esac 672a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 673a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 674a0094449SRuslan Ermilov else 675a0094449SRuslan Ermilov decho 'Using standard page width' 676a0094449SRuslan Ermilov fi 677c535eb59SGordon Tetlow} 678c535eb59SGordon Tetlow 679c535eb59SGordon Tetlow# Usage: man_setup_locale 680c535eb59SGordon Tetlow# Setup necessary locale variables. 681c535eb59SGordon Tetlowman_setup_locale() { 682deeff310SGordon Tetlow local lang_cc 6839508f8c0SYuri Pankov local locstr 684deeff310SGordon Tetlow 685deeff310SGordon Tetlow locpaths='.' 686deeff310SGordon Tetlow man_charset='US-ASCII' 687deeff310SGordon Tetlow 688c535eb59SGordon Tetlow # Setup locale information. 689c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 690deeff310SGordon Tetlow decho 'Using non-localized manpages' 691deeff310SGordon Tetlow else 6929508f8c0SYuri Pankov # Use the locale tool to give us proper locale information 693deeff310SGordon Tetlow eval $( $LOCALE ) 694c535eb59SGordon Tetlow 6959508f8c0SYuri Pankov if [ -n "$LANG" ]; then 6969508f8c0SYuri Pankov locstr=$LANG 6979508f8c0SYuri Pankov else 6989508f8c0SYuri Pankov locstr=$LC_CTYPE 6999508f8c0SYuri Pankov fi 7009508f8c0SYuri Pankov 7019508f8c0SYuri Pankov case "$locstr" in 702deeff310SGordon Tetlow C) ;; 7039508f8c0SYuri Pankov C.UTF-8) ;; 704deeff310SGordon Tetlow POSIX) ;; 705deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 7069508f8c0SYuri Pankov lang_cc="${locstr%.*}" 7079508f8c0SYuri Pankov man_lang="${locstr%_*}" 708deeff310SGordon Tetlow man_country="${lang_cc#*_}" 7099508f8c0SYuri Pankov man_charset="${locstr#*.}" 7109508f8c0SYuri Pankov locpaths="$locstr" 711c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 712c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 713c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 714c535eb59SGordon Tetlow fi 715c535eb59SGordon Tetlow locpaths="$locpaths:." 716deeff310SGordon Tetlow ;; 717deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 718deeff310SGordon Tetlow ;; 719deeff310SGordon Tetlow esac 720c535eb59SGordon Tetlow fi 721deeff310SGordon Tetlow 722c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 723c535eb59SGordon Tetlow} 724c535eb59SGordon Tetlow 725c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 726c535eb59SGordon Tetlow# Display usage for the man utility. 727c535eb59SGordon Tetlowman_usage() { 728c535eb59SGordon Tetlow echo 'Usage:' 7291594084fSFernando Apesteguía echo ' man [-adho] [-t | -w] [-K regexp] [-M manpath] [-P pager] [-S mansect]' 730c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 731c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 732c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 733c535eb59SGordon Tetlow 734c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 735c535eb59SGordon Tetlow exit ${1:-1} 736c535eb59SGordon Tetlow} 737c535eb59SGordon Tetlow 738c535eb59SGordon Tetlow# Usage: parse_configs 739c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 740c535eb59SGordon Tetlowparse_configs() { 741c535eb59SGordon Tetlow local IFS file files 742c535eb59SGordon Tetlow 743c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 744c535eb59SGordon Tetlow return 745c535eb59SGordon Tetlow fi 746c535eb59SGordon Tetlow 747c535eb59SGordon Tetlow unset IFS 748c535eb59SGordon Tetlow 749c535eb59SGordon Tetlow # Read the global config first in case the user wants 750c535eb59SGordon Tetlow # to override config_local. 751c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 752c535eb59SGordon Tetlow parse_file "$config_global" 753c535eb59SGordon Tetlow fi 754c535eb59SGordon Tetlow 755c535eb59SGordon Tetlow # Glob the list of files to parse. 756c535eb59SGordon Tetlow set +f 757c535eb59SGordon Tetlow files=$(echo $config_local) 758c535eb59SGordon Tetlow set -f 759c535eb59SGordon Tetlow 760c535eb59SGordon Tetlow for file in $files; do 761c535eb59SGordon Tetlow if [ -r "$file" ]; then 762c535eb59SGordon Tetlow parse_file "$file" 763c535eb59SGordon Tetlow fi 764c535eb59SGordon Tetlow done 765c535eb59SGordon Tetlow 766c535eb59SGordon Tetlow parsed_configs='yes' 767c535eb59SGordon Tetlow} 768c535eb59SGordon Tetlow 769c535eb59SGordon Tetlow# Usage: parse_file file 770c535eb59SGordon Tetlow# Reads the specified config files. 771c535eb59SGordon Tetlowparse_file() { 772c535eb59SGordon Tetlow local file line tstr var 773c535eb59SGordon Tetlow 774c535eb59SGordon Tetlow file="$1" 775c535eb59SGordon Tetlow decho "Parsing config file: $file" 776c535eb59SGordon Tetlow while read line; do 777c535eb59SGordon Tetlow decho " $line" 2 778c535eb59SGordon Tetlow case "$line" in 779c535eb59SGordon Tetlow \#*) decho " Comment" 3 780c535eb59SGordon Tetlow ;; 781c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 782c535eb59SGordon Tetlow trim "${line#MANPATH}" 783c535eb59SGordon Tetlow add_to_manpath "$tstr" 784c535eb59SGordon Tetlow ;; 785c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 786c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 787c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 788c535eb59SGordon Tetlow ;; 789c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 790a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 791c535eb59SGordon Tetlow config_local="$tstr" 792c535eb59SGordon Tetlow ;; 7938edb6fb5SMohamed Akram MANSECT*) decho " MANSECT" 3 7948edb6fb5SMohamed Akram trim "${line#MANSECT}" 7958edb6fb5SMohamed Akram mansect="$mansect:$tstr" 7968edb6fb5SMohamed Akram ;; 797c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 798c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 799c535eb59SGordon Tetlow trim "${line#$var}" 800c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 801c535eb59SGordon Tetlow decho " Parsed $var" 3 802c535eb59SGordon Tetlow ;; 803c535eb59SGordon Tetlow esac 804c535eb59SGordon Tetlow done < "$file" 805c535eb59SGordon Tetlow} 806c535eb59SGordon Tetlow 807c535eb59SGordon Tetlow# Usage: search_path 808c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 809c535eb59SGordon Tetlowsearch_path() { 810c535eb59SGordon Tetlow local IFS p path 811c535eb59SGordon Tetlow 812c535eb59SGordon Tetlow decho "Searching PATH for man directories" 813c535eb59SGordon Tetlow 814c535eb59SGordon Tetlow IFS=: 815c535eb59SGordon Tetlow for path in $PATH; do 816971c1c42STijl Coosemans if add_to_manpath "$path/man"; then 817c535eb59SGordon Tetlow : 818c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 819c535eb59SGordon Tetlow : 820c535eb59SGordon Tetlow else 821c535eb59SGordon Tetlow case "$path" in 822971c1c42STijl Coosemans */bin) p="${path%/bin}/share/man" 823c535eb59SGordon Tetlow add_to_manpath "$p" 824971c1c42STijl Coosemans p="${path%/bin}/man" 82561d5f2d1SBaptiste Daroussin add_to_manpath "$p" 826c535eb59SGordon Tetlow ;; 827c535eb59SGordon Tetlow esac 828c535eb59SGordon Tetlow fi 829c535eb59SGordon Tetlow done 830c535eb59SGordon Tetlow unset IFS 831c535eb59SGordon Tetlow 832c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 833c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 834c535eb59SGordon Tetlow manpath=$man_default_path 835c535eb59SGordon Tetlow fi 836c535eb59SGordon Tetlow} 837c535eb59SGordon Tetlow 838c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 839c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 840c535eb59SGordon Tetlowsearch_whatis() { 841c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 842c535eb59SGordon Tetlow 843c535eb59SGordon Tetlow cmd="$1" 844c535eb59SGordon Tetlow shift 845c535eb59SGordon Tetlow 846c535eb59SGordon Tetlow whatis_parse_args "$@" 847c535eb59SGordon Tetlow 848c535eb59SGordon Tetlow build_manpath 849c535eb59SGordon Tetlow build_manlocales 850c535eb59SGordon Tetlow setup_pager 851c535eb59SGordon Tetlow 852c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 853c535eb59SGordon Tetlow opt="-w" 854c535eb59SGordon Tetlow fi 855c535eb59SGordon Tetlow 856c535eb59SGordon Tetlow f='whatis' 857c535eb59SGordon Tetlow 858c535eb59SGordon Tetlow IFS=: 859c535eb59SGordon Tetlow for path in $MANPATH; do 860c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 861c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 862c535eb59SGordon Tetlow continue 863c535eb59SGordon Tetlow fi 864c535eb59SGordon Tetlow 865c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 866c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 867c535eb59SGordon Tetlow wlist="$wlist $path/$f" 868c535eb59SGordon Tetlow fi 869c535eb59SGordon Tetlow 870c535eb59SGordon Tetlow for loc in $MANLOCALES; do 871c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 872c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 873c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 874c535eb59SGordon Tetlow fi 875c535eb59SGordon Tetlow done 876c535eb59SGordon Tetlow done 877c535eb59SGordon Tetlow unset IFS 878c535eb59SGordon Tetlow 879c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 880c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 881c535eb59SGordon Tetlow exit 1 882c535eb59SGordon Tetlow fi 883c535eb59SGordon Tetlow 884c535eb59SGordon Tetlow rval=0 885c535eb59SGordon Tetlow for key in $keywords; do 886c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 887c535eb59SGordon Tetlow if [ -n "$out" ]; then 888c535eb59SGordon Tetlow good="$good\\n$out" 889c535eb59SGordon Tetlow else 890c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 891c535eb59SGordon Tetlow rval=1 892c535eb59SGordon Tetlow fi 893c535eb59SGordon Tetlow done 894c535eb59SGordon Tetlow 895c535eb59SGordon Tetlow # Strip leading carriage return. 896c535eb59SGordon Tetlow good=${good#\\n} 897c535eb59SGordon Tetlow bad=${bad#\\n} 898c535eb59SGordon Tetlow 899c535eb59SGordon Tetlow if [ -n "$good" ]; then 900ec13a838SMohamed Akram printf '%b\n' "$good" | $MANPAGER 901c535eb59SGordon Tetlow fi 902c535eb59SGordon Tetlow 903c535eb59SGordon Tetlow if [ -n "$bad" ]; then 904ec13a838SMohamed Akram printf '%b\n' "$bad" >&2 905c535eb59SGordon Tetlow fi 906c535eb59SGordon Tetlow 907c535eb59SGordon Tetlow exit $rval 908c535eb59SGordon Tetlow} 909c535eb59SGordon Tetlow 91057cd9717SGordon Tetlow# Usage: setup_cattool page 91157cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 91257cd9717SGordon Tetlowsetup_cattool() { 91357cd9717SGordon Tetlow case "$1" in 91457cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 91557cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 916b35ea9baSMohamed Akram *.gz) cattool='/usr/bin/gzcat' ;; 91757cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 91857cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 919c8abb673SCameron Katri *.zst) cattool='/usr/bin/zstdcat' ;; 92057cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 92157cd9717SGordon Tetlow esac 92257cd9717SGordon Tetlow} 92357cd9717SGordon Tetlow 924c535eb59SGordon Tetlow# Usage: setup_pager 925a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 926c535eb59SGordon Tetlowsetup_pager() { 927c535eb59SGordon Tetlow # Setup pager. 928a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 929a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 930a6a3e856SRuslan Ermilov MANPAGER="less -sR" 931a6a3e856SRuslan Ermilov else 932a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 933a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 934a6a3e856SRuslan Ermilov else 93547cc9ee1SAlan Somers MANPAGER="less -s" 936c535eb59SGordon Tetlow fi 937a6a3e856SRuslan Ermilov fi 938a6a3e856SRuslan Ermilov fi 939a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 940c535eb59SGordon Tetlow} 941c535eb59SGordon Tetlow 942c535eb59SGordon Tetlow# Usage: trim string 943c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 944c535eb59SGordon Tetlowtrim() { 945c535eb59SGordon Tetlow tstr=$1 946c535eb59SGordon Tetlow while true; do 947c535eb59SGordon Tetlow case "$tstr" in 948c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 949c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 950c535eb59SGordon Tetlow *) break ;; 951c535eb59SGordon Tetlow esac 952c535eb59SGordon Tetlow done 953c535eb59SGordon Tetlow} 954c535eb59SGordon Tetlow 955c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 956c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 957c535eb59SGordon Tetlowwhatis_parse_args() { 958c535eb59SGordon Tetlow local cmd_arg 959f555b39eSKyle Evans OPTIND=1 960c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 961c535eb59SGordon Tetlow case "${cmd_arg}" in 962c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 963c535eb59SGordon Tetlow *) whatis_usage ;; 964c535eb59SGordon Tetlow esac 965c535eb59SGordon Tetlow done >&2 966c535eb59SGordon Tetlow 967c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 968c535eb59SGordon Tetlow 969c535eb59SGordon Tetlow keywords="$*" 970c535eb59SGordon Tetlow} 971c535eb59SGordon Tetlow 972c535eb59SGordon Tetlow# Usage: whatis_usage 973c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 974c535eb59SGordon Tetlowwhatis_usage() { 975c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 976c535eb59SGordon Tetlow exit 1 977c535eb59SGordon Tetlow} 978c535eb59SGordon Tetlow 979c535eb59SGordon Tetlow 980c535eb59SGordon Tetlow 981c535eb59SGordon Tetlow# Supported commands 982c535eb59SGordon Tetlowdo_apropos() { 98324ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 984772246efSBaptiste Daroussin exec apropos "$@" 985c535eb59SGordon Tetlow search_whatis apropos "$@" 986c535eb59SGordon Tetlow} 987c535eb59SGordon Tetlow 9881594084fSFernando Apesteguía# Usage: do_full_search reg_exp 9891594084fSFernando Apesteguía# Do a full search of the regular expression passed 9901594084fSFernando Apesteguía# as parameter in all man pages 9911594084fSFernando Apesteguíado_full_search() { 9921594084fSFernando Apesteguía local gflags re 9931594084fSFernando Apesteguía re=${1} 9941594084fSFernando Apesteguía 9951594084fSFernando Apesteguía # Build grep(1) flags 9961594084fSFernando Apesteguía gflags="-H" 9971594084fSFernando Apesteguía 9981594084fSFernando Apesteguía # wflag implies -l for grep(1) 9991594084fSFernando Apesteguía if [ -n "$wflag" ]; then 10001594084fSFernando Apesteguía gflags="${gflags} -l" 10011594084fSFernando Apesteguía fi 10021594084fSFernando Apesteguía 10031594084fSFernando Apesteguía gflags="${gflags} --label" 10041594084fSFernando Apesteguía 10051594084fSFernando Apesteguía set +f 10068a5c836bSEd Maste for mpath in $(echo "${MANPATH}" | tr : '[:blank:]'); do 10078a5c836bSEd Maste for section in $(echo "${MANSECT}" | tr : '[:blank:]'); do 10081594084fSFernando Apesteguía for manfile in ${mpath}/man${section}/*.${section}*; do 10091594084fSFernando Apesteguía mandoc "${manfile}" 2>/dev/null | 10108a5c836bSEd Maste grep -E ${gflags} "${manfile}" -e "${re}" 10111594084fSFernando Apesteguía done 10121594084fSFernando Apesteguía done 10131594084fSFernando Apesteguía done 10141594084fSFernando Apesteguía set -f 10151594084fSFernando Apesteguía} 10161594084fSFernando Apesteguía 1017c535eb59SGordon Tetlowdo_man() { 10188edb6fb5SMohamed Akram local IFS 10198edb6fb5SMohamed Akram 10208edb6fb5SMohamed Akram man_parse_opts "$@" 10218edb6fb5SMohamed Akram man_setup 10228edb6fb5SMohamed Akram 10238edb6fb5SMohamed Akram shift $(( $OPTIND - 1 )) 10248edb6fb5SMohamed Akram IFS=: 10258edb6fb5SMohamed Akram for sect in $MANSECT; do 10268edb6fb5SMohamed Akram if [ "$sect" = "$1" ]; then 10278edb6fb5SMohamed Akram decho "Detected manual section as first arg: $1" 10288edb6fb5SMohamed Akram MANSECT="$1" 10298edb6fb5SMohamed Akram shift 10308edb6fb5SMohamed Akram break 10318edb6fb5SMohamed Akram fi 10328edb6fb5SMohamed Akram done 10338edb6fb5SMohamed Akram unset IFS 10348edb6fb5SMohamed Akram pages="$*" 10358edb6fb5SMohamed Akram 10361594084fSFernando Apesteguía if [ -z "$pages" -a -z "${Kflag}" ]; then 1037c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 1038c535eb59SGordon Tetlow exit 1 1039c535eb59SGordon Tetlow fi 1040c535eb59SGordon Tetlow 10411594084fSFernando Apesteguía if [ ! -z "${Kflag}" ]; then 10421594084fSFernando Apesteguía # Short circuit because -K flag does a sufficiently 10431594084fSFernando Apesteguía # different thing like not showing the man page at all 10441594084fSFernando Apesteguía do_full_search "${REGEXP}" 10451594084fSFernando Apesteguía fi 10461594084fSFernando Apesteguía 10471e82d882SWolfram Schneider for page in "$@"; do 104878948070SWolfram Schneider decho "Searching for \"$page\"" 1049c535eb59SGordon Tetlow man_find_and_display "$page" 1050c535eb59SGordon Tetlow done 1051c535eb59SGordon Tetlow 1052c535eb59SGordon Tetlow exit ${ret:-0} 1053c535eb59SGordon Tetlow} 1054c535eb59SGordon Tetlow 1055c535eb59SGordon Tetlowdo_manpath() { 1056c535eb59SGordon Tetlow manpath_parse_args "$@" 1057c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 1058c535eb59SGordon Tetlow manpath_warnings 1059c535eb59SGordon Tetlow fi 1060c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 1061c535eb59SGordon Tetlow build_manlocales 1062c535eb59SGordon Tetlow echo $MANLOCALES 1063c535eb59SGordon Tetlow else 1064c535eb59SGordon Tetlow build_manpath 1065c535eb59SGordon Tetlow echo $MANPATH 1066c535eb59SGordon Tetlow fi 1067c535eb59SGordon Tetlow exit 0 1068c535eb59SGordon Tetlow} 1069c535eb59SGordon Tetlow 1070c535eb59SGordon Tetlowdo_whatis() { 107124ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 1072772246efSBaptiste Daroussin exec whatis "$@" 1073c535eb59SGordon Tetlow search_whatis whatis "$@" 1074c535eb59SGordon Tetlow} 1075c535eb59SGordon Tetlow 1076aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 1077aeea395eSUlrich SpörleinEQN=eqn 1078035f7c9aSWolfram SchneiderNROFF='groff -S -P-h -Wall -mtty-char -mandoc' 1079aeea395eSUlrich SpörleinPIC=pic 1080aeea395eSUlrich SpörleinREFER=refer 1081aeea395eSUlrich SpörleinTBL=tbl 1082035f7c9aSWolfram SchneiderTROFF='groff -S -mandoc' 1083aeea395eSUlrich SpörleinVGRIND=vgrind 1084aeea395eSUlrich Spörlein 1085deeff310SGordon TetlowLOCALE=/usr/bin/locale 1086a0094449SRuslan ErmilovSTTY=/bin/stty 108782db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1088c535eb59SGordon Tetlow 1089c535eb59SGordon Tetlowdebug=0 109073577bf0SRyan Moellerman_default_sections='1:8:2:3:3lua:n:4:5:6:7:9:l' 1091971c1c42STijl Coosemansman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man' 109257cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1093c535eb59SGordon Tetlow 1094c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1095c535eb59SGordon Tetlow 1096c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1097c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1098c535eb59SGordon Tetlow 1099c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1100c535eb59SGordon Tetlowset -f 1101c535eb59SGordon Tetlow 1102c535eb59SGordon Tetlowcase "$0" in 1103c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1104c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1105c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1106c535eb59SGordon Tetlow*) do_man "$@" ;; 1107c535eb59SGordon Tetlowesac 1108