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 3614a5c106SWolfram Schneider# do not ignore the exit status of roff tools 3714a5c106SWolfram Schneiderset -o pipefail 3814a5c106SWolfram Schneider 3914a5c106SWolfram Schneider# ignore SIGPIPE exits because pagers may exit before reading all their input. 4014a5c106SWolfram Schneidertrap '' SIGPIPE 4114a5c106SWolfram Schneider 42c535eb59SGordon Tetlow# Usage: add_to_manpath path 43c535eb59SGordon Tetlow# Adds a variable to manpath while ensuring we don't have duplicates. 44c535eb59SGordon Tetlow# Returns true if we were able to add something. False otherwise. 45c535eb59SGordon Tetlowadd_to_manpath() { 46c535eb59SGordon Tetlow case "$manpath" in 47c535eb59SGordon Tetlow *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 48c535eb59SGordon Tetlow $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 49c535eb59SGordon Tetlow *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 50c535eb59SGordon Tetlow *) if [ -d "$1" ]; then 51c535eb59SGordon Tetlow decho " Adding $1 to manpath" 52c535eb59SGordon Tetlow manpath="$manpath:$1" 53c535eb59SGordon Tetlow return 0 54c535eb59SGordon Tetlow fi 55c535eb59SGordon Tetlow ;; 56c535eb59SGordon Tetlow esac 57c535eb59SGordon Tetlow 58c535eb59SGordon Tetlow return 1 59c535eb59SGordon Tetlow} 60c535eb59SGordon Tetlow 61c535eb59SGordon Tetlow# Usage: build_manlocales 62c535eb59SGordon Tetlow# Builds a correct MANLOCALES variable. 63c535eb59SGordon Tetlowbuild_manlocales() { 64c535eb59SGordon Tetlow # If the user has set manlocales, who are we to argue. 65c535eb59SGordon Tetlow if [ -n "$MANLOCALES" ]; then 66c535eb59SGordon Tetlow return 67c535eb59SGordon Tetlow fi 68c535eb59SGordon Tetlow 69c535eb59SGordon Tetlow parse_configs 70c535eb59SGordon Tetlow 71c535eb59SGordon Tetlow # Trim leading colon 72c535eb59SGordon Tetlow MANLOCALES=${manlocales#:} 73c535eb59SGordon Tetlow 74c535eb59SGordon Tetlow decho "Available manual locales: $MANLOCALES" 75c535eb59SGordon Tetlow} 76c535eb59SGordon Tetlow 778edb6fb5SMohamed Akram# Usage: build_mansect 788edb6fb5SMohamed Akram# Builds a correct MANSECT variable. 798edb6fb5SMohamed Akrambuild_mansect() { 808edb6fb5SMohamed Akram # If the user has set mansect, who are we to argue. 818edb6fb5SMohamed Akram if [ -n "$MANSECT" ]; then 828edb6fb5SMohamed Akram return 838edb6fb5SMohamed Akram fi 848edb6fb5SMohamed Akram 858edb6fb5SMohamed Akram parse_configs 868edb6fb5SMohamed Akram 878edb6fb5SMohamed Akram # Trim leading colon 888edb6fb5SMohamed Akram MANSECT=${mansect#:} 898edb6fb5SMohamed Akram 908edb6fb5SMohamed Akram if [ -z "$MANSECT" ]; then 918edb6fb5SMohamed Akram MANSECT=$man_default_sections 928edb6fb5SMohamed Akram fi 938edb6fb5SMohamed Akram decho "Using manual sections: $MANSECT" 948edb6fb5SMohamed Akram} 958edb6fb5SMohamed Akram 96c535eb59SGordon Tetlow# Usage: build_manpath 97c535eb59SGordon Tetlow# Builds a correct MANPATH variable. 98c535eb59SGordon Tetlowbuild_manpath() { 99c535eb59SGordon Tetlow local IFS 100c535eb59SGordon Tetlow 101c535eb59SGordon Tetlow # If the user has set a manpath, who are we to argue. 102c535eb59SGordon Tetlow if [ -n "$MANPATH" ]; then 103b2394e73SBaptiste Daroussin case "$MANPATH" in 104b2394e73SBaptiste Daroussin *:) PREPEND_MANPATH=${MANPATH} ;; 105b2394e73SBaptiste Daroussin :*) APPEND_MANPATH=${MANPATH} ;; 106b2394e73SBaptiste Daroussin *::*) 107b2394e73SBaptiste Daroussin PREPEND_MANPATH=${MANPATH%%::*} 108b2394e73SBaptiste Daroussin APPEND_MANPATH=${MANPATH#*::} 109b2394e73SBaptiste Daroussin ;; 110b2394e73SBaptiste Daroussin *) return ;; 111b2394e73SBaptiste Daroussin esac 112b2394e73SBaptiste Daroussin fi 113b2394e73SBaptiste Daroussin 114b2394e73SBaptiste Daroussin if [ -n "$PREPEND_MANPATH" ]; then 115b2394e73SBaptiste Daroussin IFS=: 116b2394e73SBaptiste Daroussin for path in $PREPEND_MANPATH; do 117b2394e73SBaptiste Daroussin add_to_manpath "$path" 118b2394e73SBaptiste Daroussin done 119b2394e73SBaptiste Daroussin unset IFS 120c535eb59SGordon Tetlow fi 121c535eb59SGordon Tetlow 122c535eb59SGordon Tetlow search_path 123c535eb59SGordon Tetlow 124c535eb59SGordon Tetlow decho "Adding default manpath entries" 125c535eb59SGordon Tetlow IFS=: 126c535eb59SGordon Tetlow for path in $man_default_path; do 127c535eb59SGordon Tetlow add_to_manpath "$path" 128c535eb59SGordon Tetlow done 129c535eb59SGordon Tetlow unset IFS 130c535eb59SGordon Tetlow 131c535eb59SGordon Tetlow parse_configs 132c535eb59SGordon Tetlow 133b2394e73SBaptiste Daroussin if [ -n "$APPEND_MANPATH" ]; then 134b2394e73SBaptiste Daroussin IFS=: 135b2394e73SBaptiste Daroussin for path in $APPEND_MANPATH; do 136b2394e73SBaptiste Daroussin add_to_manpath "$path" 137b2394e73SBaptiste Daroussin done 138b2394e73SBaptiste Daroussin unset IFS 139b2394e73SBaptiste Daroussin fi 140c535eb59SGordon Tetlow # Trim leading colon 141c535eb59SGordon Tetlow MANPATH=${manpath#:} 142c535eb59SGordon Tetlow 143c535eb59SGordon Tetlow decho "Using manual path: $MANPATH" 144c535eb59SGordon Tetlow} 145c535eb59SGordon Tetlow 146c535eb59SGordon Tetlow# Usage: check_cat catglob 147c535eb59SGordon Tetlow# Checks to see if a cat glob is available. 148c535eb59SGordon Tetlowcheck_cat() { 149c535eb59SGordon Tetlow if exists "$1"; then 150c535eb59SGordon Tetlow use_cat=yes 151c535eb59SGordon Tetlow catpage=$found 152c4368d03SWolfram Schneider setup_cattool "$catpage" 153c4368d03SWolfram Schneider decho " Found catpage \"$catpage\"" 154c535eb59SGordon Tetlow return 0 155c535eb59SGordon Tetlow else 156c535eb59SGordon Tetlow return 1 157c535eb59SGordon Tetlow fi 158c535eb59SGordon Tetlow} 159c535eb59SGordon Tetlow 160c535eb59SGordon Tetlow# Usage: check_man manglob catglob 161c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to 162c535eb59SGordon Tetlow# see if the catglob is also available and up to date. 163c535eb59SGordon Tetlowcheck_man() { 164c535eb59SGordon Tetlow if exists "$1"; then 165c535eb59SGordon Tetlow # We have a match, check for a cat page 166c535eb59SGordon Tetlow manpage=$found 16778948070SWolfram Schneider setup_cattool "$manpage" 16878948070SWolfram Schneider decho " Found manpage \"$manpage\"" 169c535eb59SGordon Tetlow 170a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 171a0094449SRuslan Ermilov # non-standard width 172a0094449SRuslan Ermilov unset use_cat 173a0094449SRuslan Ermilov decho " Skipping catpage: non-standard page width" 17478948070SWolfram Schneider elif exists "$2" && is_newer $found "$manpage"; then 175c535eb59SGordon Tetlow # cat page found and is newer, use that 176c535eb59SGordon Tetlow use_cat=yes 177c535eb59SGordon Tetlow catpage=$found 178c4368d03SWolfram Schneider setup_cattool "$catpage" 179c4368d03SWolfram Schneider decho " Using catpage \"$catpage\"" 180c535eb59SGordon Tetlow else 181c535eb59SGordon Tetlow # no cat page or is older 182c535eb59SGordon Tetlow unset use_cat 183c535eb59SGordon Tetlow decho " Skipping catpage: not found or old" 184c535eb59SGordon Tetlow fi 185c535eb59SGordon Tetlow return 0 186c535eb59SGordon Tetlow fi 187c535eb59SGordon Tetlow 188c535eb59SGordon Tetlow return 1 189c535eb59SGordon Tetlow} 190c535eb59SGordon Tetlow 191c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel] 192c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel. 193c535eb59SGordon Tetlowdecho() { 194c535eb59SGordon Tetlow if [ $debug -ge ${2:-1} ]; then 195c535eb59SGordon Tetlow echo "-- $1" >&2 196c535eb59SGordon Tetlow fi 197c535eb59SGordon Tetlow} 198c535eb59SGordon Tetlow 199c535eb59SGordon Tetlow# Usage: exists glob 200e3c7b76fSWolfram Schneider# 201e3c7b76fSWolfram Schneider# Returns true if glob resolves to a real file and store the first 202e3c7b76fSWolfram Schneider# found filename in the variable $found 203c535eb59SGordon Tetlowexists() { 204*37be4197SWolfram Schneider if [ -z "$1" ]; then 205*37be4197SWolfram Schneider return 1 206*37be4197SWolfram Schneider fi 207*37be4197SWolfram Schneider 208c535eb59SGordon Tetlow local IFS 209c535eb59SGordon Tetlow 210c535eb59SGordon Tetlow # Don't accidentally inherit callers IFS (breaks perl manpages) 211c535eb59SGordon Tetlow unset IFS 212c535eb59SGordon Tetlow 213c535eb59SGordon Tetlow # Use some globbing tricks in the shell to determine if a file 214c535eb59SGordon Tetlow # exists or not. 215c535eb59SGordon Tetlow set +f 216e3c7b76fSWolfram Schneider for file in "$1"* 217e3c7b76fSWolfram Schneider do 218e3c7b76fSWolfram Schneider if [ -r "$file" ]; then 219e3c7b76fSWolfram Schneider found="$file" 220c535eb59SGordon Tetlow set -f 221c535eb59SGordon Tetlow return 0 222c535eb59SGordon Tetlow fi 223e3c7b76fSWolfram Schneider done 224e3c7b76fSWolfram Schneider set -f 225c535eb59SGordon Tetlow 226c535eb59SGordon Tetlow return 1 227c535eb59SGordon Tetlow} 228c535eb59SGordon Tetlow 229c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename 230c535eb59SGordon Tetlow# Returns: true if something is matched and found. 231c535eb59SGordon Tetlow# Search the given path/section combo for a given page. 232c535eb59SGordon Tetlowfind_file() { 233c535eb59SGordon Tetlow local manroot catroot mann man0 catn cat0 234c535eb59SGordon Tetlow 235c535eb59SGordon Tetlow manroot="$1/man$2" 236c535eb59SGordon Tetlow catroot="$1/cat$2" 237c535eb59SGordon Tetlow if [ -n "$3" ]; then 238c535eb59SGordon Tetlow manroot="$manroot/$3" 239c535eb59SGordon Tetlow catroot="$catroot/$3" 240c535eb59SGordon Tetlow fi 241c535eb59SGordon Tetlow 242625490e8SBaptiste Daroussin if [ ! -d "$manroot" -a ! -d "$catroot" ]; then 243c535eb59SGordon Tetlow return 1 244c535eb59SGordon Tetlow fi 245c535eb59SGordon Tetlow decho " Searching directory $manroot" 2 246c535eb59SGordon Tetlow 247e3c7b76fSWolfram Schneider mann="$manroot/$4.$2" 248e3c7b76fSWolfram Schneider man0="$manroot/$4.0" 249e3c7b76fSWolfram Schneider catn="$catroot/$4.$2" 250e3c7b76fSWolfram Schneider cat0="$catroot/$4.0" 251c535eb59SGordon Tetlow 252c535eb59SGordon Tetlow # This is the behavior as seen by the original man utility. 253c535eb59SGordon Tetlow # Let's not change that which doesn't seem broken. 254c535eb59SGordon Tetlow if check_man "$mann" "$catn"; then 255c535eb59SGordon Tetlow return 0 256c535eb59SGordon Tetlow elif check_man "$man0" "$cat0"; then 257c535eb59SGordon Tetlow return 0 258c535eb59SGordon Tetlow elif check_cat "$catn"; then 259c535eb59SGordon Tetlow return 0 260c535eb59SGordon Tetlow elif check_cat "$cat0"; then 261c535eb59SGordon Tetlow return 0 262c535eb59SGordon Tetlow fi 263c535eb59SGordon Tetlow 264c535eb59SGordon Tetlow return 1 265c535eb59SGordon Tetlow} 266c535eb59SGordon Tetlow 267c535eb59SGordon Tetlow# Usage: is_newer file1 file2 268c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime. 269c535eb59SGordon Tetlowis_newer() { 2709b61837aSUlrich Spörlein if ! [ "$1" -ot "$2" ]; then 2719b61837aSUlrich Spörlein decho " mtime: $1 not older than $2" 3 272c535eb59SGordon Tetlow return 0 273c535eb59SGordon Tetlow else 274c535eb59SGordon Tetlow decho " mtime: $1 older than $2" 3 275c535eb59SGordon Tetlow return 1 276c535eb59SGordon Tetlow fi 277c535eb59SGordon Tetlow} 278c535eb59SGordon Tetlow 279c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@" 280c535eb59SGordon Tetlow# Parses commandline options for manpath. 281c535eb59SGordon Tetlowmanpath_parse_args() { 282c535eb59SGordon Tetlow local cmd_arg 283c535eb59SGordon Tetlow 284f555b39eSKyle Evans OPTIND=1 285c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 286c535eb59SGordon Tetlow case "${cmd_arg}" in 287c535eb59SGordon Tetlow L) Lflag=Lflag ;; 288c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 289c535eb59SGordon Tetlow q) qflag=qflag ;; 290c535eb59SGordon Tetlow *) manpath_usage ;; 291c535eb59SGordon Tetlow esac 292c535eb59SGordon Tetlow done >&2 293c535eb59SGordon Tetlow} 294c535eb59SGordon Tetlow 295c535eb59SGordon Tetlow# Usage: manpath_usage 296c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 297c535eb59SGordon Tetlowmanpath_usage() { 298c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 299c535eb59SGordon Tetlow exit 1 300c535eb59SGordon Tetlow} 301c535eb59SGordon Tetlow 302c535eb59SGordon Tetlow# Usage: manpath_warnings 303c535eb59SGordon Tetlow# Display some warnings to stderr. 304c535eb59SGordon Tetlowmanpath_warnings() { 305c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 306c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 307c535eb59SGordon Tetlow fi 308c535eb59SGordon Tetlow} 309c535eb59SGordon Tetlow 310e85a6f8dSMohamed Akram# Usage: man_check_for_so path 31157cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 31257cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 31357cd9717SGordon Tetlow# redirected to another source file. 31457cd9717SGordon Tetlowman_check_for_so() { 31557cd9717SGordon Tetlow local IFS line tstr 31657cd9717SGordon Tetlow 31757cd9717SGordon Tetlow unset IFS 318d9405a92SBaptiste Daroussin if [ -n "$catpage" ]; then 319d9405a92SBaptiste Daroussin return 0 320d9405a92SBaptiste Daroussin fi 32157cd9717SGordon Tetlow 32257cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 32357cd9717SGordon Tetlow while true 32457cd9717SGordon Tetlow do 32514a5c106SWolfram Schneider line=$($cattool "$manpage" 2>/dev/null | head -n1) 32657cd9717SGordon Tetlow case "$line" in 32757cd9717SGordon Tetlow .so*) trim "${line#.so}" 32857cd9717SGordon Tetlow decho "$manpage includes $tstr" 32957cd9717SGordon Tetlow # Glob and check for the file. 330e85a6f8dSMohamed Akram if ! check_man "$1/$tstr" ""; then 33157cd9717SGordon Tetlow decho " Unable to find $tstr" 33257cd9717SGordon Tetlow return 1 33357cd9717SGordon Tetlow fi 33457cd9717SGordon Tetlow ;; 33557cd9717SGordon Tetlow *) break ;; 33657cd9717SGordon Tetlow esac 33757cd9717SGordon Tetlow done 33857cd9717SGordon Tetlow 33957cd9717SGordon Tetlow return 0 34057cd9717SGordon Tetlow} 34157cd9717SGordon Tetlow 342b43edc06SBaptiste Daroussin# Usage: man_display_page 343b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 344c535eb59SGordon Tetlowman_display_page() { 3451fb816daSBaptiste Daroussin local IFS pipeline testline 346c535eb59SGordon Tetlow 347c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 348c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 349c535eb59SGordon Tetlow unset IFS 350c535eb59SGordon Tetlow 351c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 352c535eb59SGordon Tetlow # just zcat the catpage and we are done. 353c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 354c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 35578948070SWolfram Schneider echo "$catpage (source: \"$manpage\")" 356c535eb59SGordon Tetlow ret=0 357c535eb59SGordon Tetlow else 358c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 359c4368d03SWolfram Schneider decho "Command: $cattool \"$catpage\" | $MANPAGER" 360c535eb59SGordon Tetlow ret=0 361c535eb59SGordon Tetlow else 362b8a484ecSWolfram Schneider $cattool "$catpage" | $MANPAGER 363c535eb59SGordon Tetlow ret=$? 364c535eb59SGordon Tetlow fi 365c535eb59SGordon Tetlow fi 366c535eb59SGordon Tetlow return 367c535eb59SGordon Tetlow fi 368c535eb59SGordon Tetlow 369c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 370c535eb59SGordon Tetlow # name of the manpage? 371c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 372c535eb59SGordon Tetlow echo "$manpage" 373c535eb59SGordon Tetlow ret=0 374c535eb59SGordon Tetlow return 375c535eb59SGordon Tetlow fi 376c535eb59SGordon Tetlow 377d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 378d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 379d433cf9aSBaptiste Daroussin fi 380451c2becSBaptiste Daroussin testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 381449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 382449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 383449a792dSBaptiste Daroussin else 384d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 385449a792dSBaptiste Daroussin fi 386d6096801SBaptiste Daroussin 387b8a484ecSWolfram Schneider if ! $cattool "$manpage" | eval "$testline"; then 388f17575acSBaptiste Daroussin if which -s groff; then 389d6096801SBaptiste Daroussin man_display_page_groff 390d6096801SBaptiste Daroussin else 391d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 392d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 393d6096801SBaptiste Daroussin echo "pkg install groff " >&2 394d6096801SBaptiste Daroussin ret=1 395d6096801SBaptiste Daroussin fi 396d6096801SBaptiste Daroussin return 397d6096801SBaptiste Daroussin fi 398d6096801SBaptiste Daroussin 399d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 400b8a484ecSWolfram Schneider decho "Command: $cattool \"$manpage\" | eval \"$pipeline\"" 401d6096801SBaptiste Daroussin ret=0 402d6096801SBaptiste Daroussin else 403b8a484ecSWolfram Schneider $cattool "$manpage" | eval "$pipeline" 404d6096801SBaptiste Daroussin ret=$? 405d6096801SBaptiste Daroussin fi 406d6096801SBaptiste Daroussin} 407d6096801SBaptiste Daroussin 408b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 409b43edc06SBaptiste Daroussin# Display the manpage using groff 410d6096801SBaptiste Daroussinman_display_page_groff() { 411d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 412d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 413d6096801SBaptiste Daroussin 414c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 415c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 416c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 417c535eb59SGordon Tetlow 418deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 419deeff310SGordon Tetlow # to properly output for the correct device. 420deeff310SGordon Tetlow case "${manpage}" in 421deeff310SGordon Tetlow *.${man_charset}/*) 422c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 423c535eb59SGordon Tetlow # previous version of man(1). 424c535eb59SGordon Tetlow case "$man_charset" in 425c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 426c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 427c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 428c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 429c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 430c535eb59SGordon Tetlow esac 431c535eb59SGordon Tetlow 432deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 433c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 434c535eb59SGordon Tetlow 435deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 436deeff310SGordon Tetlow # then we need to define the locale string. 437deeff310SGordon Tetlow case "${manpage}" in 438deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 439deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 440deeff310SGordon Tetlow ;; 441deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 442deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 443deeff310SGordon Tetlow ;; 444deeff310SGordon Tetlow esac 445deeff310SGordon Tetlow 446c535eb59SGordon Tetlow # Allow language specific calls to override the default 447c535eb59SGordon Tetlow # set of utilities. 448c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 449b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 450c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 451c535eb59SGordon Tetlow done 452c535eb59SGordon Tetlow ;; 453c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 454c535eb59SGordon Tetlow EQN="$EQN -Tascii" 455c535eb59SGordon Tetlow ;; 456c535eb59SGordon Tetlow esac 457c535eb59SGordon Tetlow 458a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 459a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 460a6a3e856SRuslan Ermilov fi 461a6a3e856SRuslan Ermilov 462a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 463a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 464a0094449SRuslan Ermilov fi 465a0094449SRuslan Ermilov 466c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 467c535eb59SGordon Tetlow set -- -$MANROFFSEQ 468f555b39eSKyle Evans OPTIND=1 469c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 470c535eb59SGordon Tetlow case "${preproc_arg}" in 471c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 472487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 473c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 474c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 475b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 476c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 477c535eb59SGordon Tetlow *) usage ;; 478c535eb59SGordon Tetlow esac 479c535eb59SGordon Tetlow done 480c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 481c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 482c535eb59SGordon Tetlow else 483c535eb59SGordon Tetlow pipeline="$TBL" 484c535eb59SGordon Tetlow fi 485c535eb59SGordon Tetlow 486c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 487c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 488c535eb59SGordon Tetlow else 489a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 490c535eb59SGordon Tetlow fi 491c535eb59SGordon Tetlow 492c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 493b8a484ecSWolfram Schneider decho "Command: $cattool \"$manpage\" | eval \"$pipeline\"" 494c535eb59SGordon Tetlow ret=0 495c535eb59SGordon Tetlow else 496b8a484ecSWolfram Schneider $cattool "$manpage" | eval "$pipeline" 497c535eb59SGordon Tetlow ret=$? 498c535eb59SGordon Tetlow fi 499c535eb59SGordon Tetlow} 500c535eb59SGordon Tetlow 501c535eb59SGordon Tetlow# Usage: man_find_and_display page 502c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 503c535eb59SGordon Tetlowman_find_and_display() { 504c535eb59SGordon Tetlow local found_page locpath p path sect 505c535eb59SGordon Tetlow 5063d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 5073d9127f1SGordon Tetlow # the filename. 5083d9127f1SGordon Tetlow case "$1" in 5093d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 5103d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 5113d9127f1SGordon Tetlow unset use_cat 5123d9127f1SGordon Tetlow manpage="$1" 51378948070SWolfram Schneider setup_cattool "$manpage" 514e85a6f8dSMohamed Akram p=$(cd "$(dirname "$manpage")" && pwd) 515e85a6f8dSMohamed Akram case "$(basename "$p")" in 516e85a6f8dSMohamed Akram man*|cat*) p=$p/.. ;; 517e85a6f8dSMohamed Akram *) p=$p/../.. ;; 518e85a6f8dSMohamed Akram esac 519e85a6f8dSMohamed Akram if man_check_for_so "$p"; then 52057cd9717SGordon Tetlow found_page=yes 5213d9127f1SGordon Tetlow man_display_page 52257cd9717SGordon Tetlow fi 5233d9127f1SGordon Tetlow return 5243d9127f1SGordon Tetlow fi 5253d9127f1SGordon Tetlow ;; 5263d9127f1SGordon Tetlow esac 5273d9127f1SGordon Tetlow 528c535eb59SGordon Tetlow IFS=: 529c535eb59SGordon Tetlow for sect in $MANSECT; do 530c535eb59SGordon Tetlow decho "Searching section $sect" 2 531c535eb59SGordon Tetlow for path in $MANPATH; do 532c535eb59SGordon Tetlow for locpath in $locpaths; do 533c535eb59SGordon Tetlow p=$path/$locpath 534c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 535c535eb59SGordon Tetlow 536c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 537c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 538e85a6f8dSMohamed Akram if man_check_for_so $p; then 539c535eb59SGordon Tetlow found_page=yes 540c535eb59SGordon Tetlow man_display_page 5411d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5421d7c660aSGordon Tetlow continue 2 5431d7c660aSGordon Tetlow else 544c535eb59SGordon Tetlow return 545c535eb59SGordon Tetlow fi 546c535eb59SGordon Tetlow fi 54757cd9717SGordon Tetlow fi 548c535eb59SGordon Tetlow 549c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 550c535eb59SGordon Tetlow # specific manpath. 551c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 552e85a6f8dSMohamed Akram if man_check_for_so $p; then 553c535eb59SGordon Tetlow found_page=yes 554c535eb59SGordon Tetlow man_display_page 5551d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5561d7c660aSGordon Tetlow continue 2 5571d7c660aSGordon Tetlow else 558c535eb59SGordon Tetlow return 559c535eb59SGordon Tetlow fi 560c535eb59SGordon Tetlow fi 56157cd9717SGordon Tetlow fi 562c535eb59SGordon Tetlow 563c535eb59SGordon Tetlow # Check plain old manpath. 564c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 565e85a6f8dSMohamed Akram if man_check_for_so $p; then 566c535eb59SGordon Tetlow found_page=yes 567c535eb59SGordon Tetlow man_display_page 5681d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5691d7c660aSGordon Tetlow continue 2 5701d7c660aSGordon Tetlow else 571c535eb59SGordon Tetlow return 572c535eb59SGordon Tetlow fi 573c535eb59SGordon Tetlow fi 57457cd9717SGordon Tetlow fi 575c535eb59SGordon Tetlow done 576c535eb59SGordon Tetlow done 577c535eb59SGordon Tetlow done 578c535eb59SGordon Tetlow unset IFS 579c535eb59SGordon Tetlow 580c535eb59SGordon Tetlow # Nothing? Well, we are done then. 581c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 58278948070SWolfram Schneider echo "No manual entry for \"$1\"" >&2 583c535eb59SGordon Tetlow ret=1 584c535eb59SGordon Tetlow return 585c535eb59SGordon Tetlow fi 586c535eb59SGordon Tetlow} 587c535eb59SGordon Tetlow 5888edb6fb5SMohamed Akram# Usage: man_parse_opts "$@" 589c535eb59SGordon Tetlow# Parses commandline options for man. 5908edb6fb5SMohamed Akramman_parse_opts() { 5918edb6fb5SMohamed Akram local cmd_arg 592c535eb59SGordon Tetlow 593f555b39eSKyle Evans OPTIND=1 5941594084fSFernando Apesteguía while getopts 'K:M:P:S:adfhkm:op:tw' cmd_arg; do 595c535eb59SGordon Tetlow case "${cmd_arg}" in 5961594084fSFernando Apesteguía K) Kflag=Kflag 5971594084fSFernando Apesteguía REGEXP=$OPTARG ;; 598c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 599a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 600c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 601c535eb59SGordon Tetlow a) aflag=aflag ;; 602c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 603c535eb59SGordon Tetlow f) fflag=fflag ;; 604c535eb59SGordon Tetlow h) man_usage 0 ;; 605c535eb59SGordon Tetlow k) kflag=kflag ;; 606c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 607c535eb59SGordon Tetlow o) oflag=oflag ;; 608c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 609c535eb59SGordon Tetlow t) tflag=tflag ;; 610c535eb59SGordon Tetlow w) wflag=wflag ;; 611c535eb59SGordon Tetlow *) man_usage ;; 612c535eb59SGordon Tetlow esac 613c535eb59SGordon Tetlow done >&2 614c535eb59SGordon Tetlow 615c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 616c535eb59SGordon Tetlow 617c535eb59SGordon Tetlow # Check the args for incompatible options. 6181594084fSFernando Apesteguía 6191594084fSFernando Apesteguía case "${Kflag}${fflag}${kflag}${tflag}${wflag}" in 6201594084fSFernando Apesteguía Kflagfflag*) echo "Incompatible options: -K and -f"; man_usage ;; 6211594084fSFernando Apesteguía Kflag*kflag*) echo "Incompatible options: -K and -k"; man_usage ;; 6221594084fSFernando Apesteguía Kflag*tflag) echo "Incompatible options: -K and -t"; man_usage ;; 623c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 624c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 625c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 626c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 627c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 628c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 629c535eb59SGordon Tetlow esac 630c535eb59SGordon Tetlow 631c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 632c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 633c535eb59SGordon Tetlow do_whatis "$@" 634c535eb59SGordon Tetlow exit 635c535eb59SGordon Tetlow fi 636c535eb59SGordon Tetlow 637c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 638c535eb59SGordon Tetlow do_apropos "$@" 639c535eb59SGordon Tetlow exit 640c535eb59SGordon Tetlow fi 641c535eb59SGordon Tetlow} 642c535eb59SGordon Tetlow 643c535eb59SGordon Tetlow# Usage: man_setup 644c535eb59SGordon Tetlow# Setup various trivial but essential variables. 645c535eb59SGordon Tetlowman_setup() { 646c535eb59SGordon Tetlow # Setup machine and architecture variables. 647c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 648c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 649c535eb59SGordon Tetlow MACHINE=${mflag##*:} 650c535eb59SGordon Tetlow fi 651c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 65282db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 653c535eb59SGordon Tetlow fi 654c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 65582db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 656c535eb59SGordon Tetlow fi 657c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 658c535eb59SGordon Tetlow 659c535eb59SGordon Tetlow setup_pager 660c535eb59SGordon Tetlow build_manpath 6618edb6fb5SMohamed Akram build_mansect 662c535eb59SGordon Tetlow man_setup_locale 663a0094449SRuslan Ermilov man_setup_width 664a0094449SRuslan Ermilov} 665a0094449SRuslan Ermilov 666a0094449SRuslan Ermilov# Usage: man_setup_width 667a0094449SRuslan Ermilov# Set up page width. 668a0094449SRuslan Ermilovman_setup_width() { 669a0094449SRuslan Ermilov local sizes 670a0094449SRuslan Ermilov 671a0094449SRuslan Ermilov unset use_width 672a0094449SRuslan Ermilov case "$MANWIDTH" in 673a0094449SRuslan Ermilov [0-9]*) 674a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 675a0094449SRuslan Ermilov use_width=$MANWIDTH 676a0094449SRuslan Ermilov fi 677a0094449SRuslan Ermilov ;; 678a0094449SRuslan Ermilov [Tt][Tt][Yy]) 679a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 680a0094449SRuslan Ermilov set -- $sizes 681a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 682a0094449SRuslan Ermilov use_width=$(($2-2)) 683a0094449SRuslan Ermilov fi 684a0094449SRuslan Ermilov fi 685a0094449SRuslan Ermilov ;; 686a0094449SRuslan Ermilov esac 687a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 688a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 689a0094449SRuslan Ermilov else 690a0094449SRuslan Ermilov decho 'Using standard page width' 691a0094449SRuslan Ermilov fi 692c535eb59SGordon Tetlow} 693c535eb59SGordon Tetlow 694c535eb59SGordon Tetlow# Usage: man_setup_locale 695c535eb59SGordon Tetlow# Setup necessary locale variables. 696c535eb59SGordon Tetlowman_setup_locale() { 697deeff310SGordon Tetlow local lang_cc 6989508f8c0SYuri Pankov local locstr 699deeff310SGordon Tetlow 700deeff310SGordon Tetlow locpaths='.' 701deeff310SGordon Tetlow man_charset='US-ASCII' 702deeff310SGordon Tetlow 703c535eb59SGordon Tetlow # Setup locale information. 704c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 705deeff310SGordon Tetlow decho 'Using non-localized manpages' 706deeff310SGordon Tetlow else 7079508f8c0SYuri Pankov # Use the locale tool to give us proper locale information 708deeff310SGordon Tetlow eval $( $LOCALE ) 709c535eb59SGordon Tetlow 7109508f8c0SYuri Pankov if [ -n "$LANG" ]; then 7119508f8c0SYuri Pankov locstr=$LANG 7129508f8c0SYuri Pankov else 7139508f8c0SYuri Pankov locstr=$LC_CTYPE 7149508f8c0SYuri Pankov fi 7159508f8c0SYuri Pankov 7169508f8c0SYuri Pankov case "$locstr" in 717deeff310SGordon Tetlow C) ;; 7189508f8c0SYuri Pankov C.UTF-8) ;; 719deeff310SGordon Tetlow POSIX) ;; 720deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 7219508f8c0SYuri Pankov lang_cc="${locstr%.*}" 7229508f8c0SYuri Pankov man_lang="${locstr%_*}" 723deeff310SGordon Tetlow man_country="${lang_cc#*_}" 7249508f8c0SYuri Pankov man_charset="${locstr#*.}" 7259508f8c0SYuri Pankov locpaths="$locstr" 726c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 727c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 728c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 729c535eb59SGordon Tetlow fi 730c535eb59SGordon Tetlow locpaths="$locpaths:." 731deeff310SGordon Tetlow ;; 732deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 733deeff310SGordon Tetlow ;; 734deeff310SGordon Tetlow esac 735c535eb59SGordon Tetlow fi 736deeff310SGordon Tetlow 737c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 738c535eb59SGordon Tetlow} 739c535eb59SGordon Tetlow 740c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 741c535eb59SGordon Tetlow# Display usage for the man utility. 742c535eb59SGordon Tetlowman_usage() { 743c535eb59SGordon Tetlow echo 'Usage:' 7441594084fSFernando Apesteguía echo ' man [-adho] [-t | -w] [-K regexp] [-M manpath] [-P pager] [-S mansect]' 745c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 746c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 747c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 748c535eb59SGordon Tetlow 749c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 750c535eb59SGordon Tetlow exit ${1:-1} 751c535eb59SGordon Tetlow} 752c535eb59SGordon Tetlow 753c535eb59SGordon Tetlow# Usage: parse_configs 754c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 755c535eb59SGordon Tetlowparse_configs() { 756c535eb59SGordon Tetlow local IFS file files 757c535eb59SGordon Tetlow 758c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 759c535eb59SGordon Tetlow return 760c535eb59SGordon Tetlow fi 761c535eb59SGordon Tetlow 762c535eb59SGordon Tetlow unset IFS 763c535eb59SGordon Tetlow 764c535eb59SGordon Tetlow # Read the global config first in case the user wants 765c535eb59SGordon Tetlow # to override config_local. 766c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 767c535eb59SGordon Tetlow parse_file "$config_global" 768c535eb59SGordon Tetlow fi 769c535eb59SGordon Tetlow 770c535eb59SGordon Tetlow # Glob the list of files to parse. 771c535eb59SGordon Tetlow set +f 772c535eb59SGordon Tetlow files=$(echo $config_local) 773c535eb59SGordon Tetlow set -f 774c535eb59SGordon Tetlow 775c535eb59SGordon Tetlow for file in $files; do 776c535eb59SGordon Tetlow if [ -r "$file" ]; then 777c535eb59SGordon Tetlow parse_file "$file" 778c535eb59SGordon Tetlow fi 779c535eb59SGordon Tetlow done 780c535eb59SGordon Tetlow 781c535eb59SGordon Tetlow parsed_configs='yes' 782c535eb59SGordon Tetlow} 783c535eb59SGordon Tetlow 784c535eb59SGordon Tetlow# Usage: parse_file file 785c535eb59SGordon Tetlow# Reads the specified config files. 786c535eb59SGordon Tetlowparse_file() { 787c535eb59SGordon Tetlow local file line tstr var 788c535eb59SGordon Tetlow 789c535eb59SGordon Tetlow file="$1" 790c535eb59SGordon Tetlow decho "Parsing config file: $file" 791c535eb59SGordon Tetlow while read line; do 792c535eb59SGordon Tetlow decho " $line" 2 793c535eb59SGordon Tetlow case "$line" in 794c535eb59SGordon Tetlow \#*) decho " Comment" 3 795c535eb59SGordon Tetlow ;; 796c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 797c535eb59SGordon Tetlow trim "${line#MANPATH}" 798c535eb59SGordon Tetlow add_to_manpath "$tstr" 799c535eb59SGordon Tetlow ;; 800c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 801c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 802c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 803c535eb59SGordon Tetlow ;; 804c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 805a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 806c535eb59SGordon Tetlow config_local="$tstr" 807c535eb59SGordon Tetlow ;; 8088edb6fb5SMohamed Akram MANSECT*) decho " MANSECT" 3 8098edb6fb5SMohamed Akram trim "${line#MANSECT}" 8108edb6fb5SMohamed Akram mansect="$mansect:$tstr" 8118edb6fb5SMohamed Akram ;; 812c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 813c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 814c535eb59SGordon Tetlow trim "${line#$var}" 815c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 816c535eb59SGordon Tetlow decho " Parsed $var" 3 817c535eb59SGordon Tetlow ;; 818c535eb59SGordon Tetlow esac 819c535eb59SGordon Tetlow done < "$file" 820c535eb59SGordon Tetlow} 821c535eb59SGordon Tetlow 822c535eb59SGordon Tetlow# Usage: search_path 823c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 824c535eb59SGordon Tetlowsearch_path() { 825c535eb59SGordon Tetlow local IFS p path 826c535eb59SGordon Tetlow 827c535eb59SGordon Tetlow decho "Searching PATH for man directories" 828c535eb59SGordon Tetlow 829c535eb59SGordon Tetlow IFS=: 830c535eb59SGordon Tetlow for path in $PATH; do 831971c1c42STijl Coosemans if add_to_manpath "$path/man"; then 832c535eb59SGordon Tetlow : 833c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 834c535eb59SGordon Tetlow : 835c535eb59SGordon Tetlow else 836c535eb59SGordon Tetlow case "$path" in 837971c1c42STijl Coosemans */bin) p="${path%/bin}/share/man" 838c535eb59SGordon Tetlow add_to_manpath "$p" 839971c1c42STijl Coosemans p="${path%/bin}/man" 84061d5f2d1SBaptiste Daroussin add_to_manpath "$p" 841c535eb59SGordon Tetlow ;; 842c535eb59SGordon Tetlow esac 843c535eb59SGordon Tetlow fi 844c535eb59SGordon Tetlow done 845c535eb59SGordon Tetlow unset IFS 846c535eb59SGordon Tetlow 847c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 848c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 849c535eb59SGordon Tetlow manpath=$man_default_path 850c535eb59SGordon Tetlow fi 851c535eb59SGordon Tetlow} 852c535eb59SGordon Tetlow 853c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 854c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 855c535eb59SGordon Tetlowsearch_whatis() { 856c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 857c535eb59SGordon Tetlow 858c535eb59SGordon Tetlow cmd="$1" 859c535eb59SGordon Tetlow shift 860c535eb59SGordon Tetlow 861c535eb59SGordon Tetlow whatis_parse_args "$@" 862c535eb59SGordon Tetlow 863c535eb59SGordon Tetlow build_manpath 864c535eb59SGordon Tetlow build_manlocales 865c535eb59SGordon Tetlow setup_pager 866c535eb59SGordon Tetlow 867c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 868c535eb59SGordon Tetlow opt="-w" 869c535eb59SGordon Tetlow fi 870c535eb59SGordon Tetlow 871c535eb59SGordon Tetlow f='whatis' 872c535eb59SGordon Tetlow 873c535eb59SGordon Tetlow IFS=: 874c535eb59SGordon Tetlow for path in $MANPATH; do 875c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 876c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 877c535eb59SGordon Tetlow continue 878c535eb59SGordon Tetlow fi 879c535eb59SGordon Tetlow 880c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 881c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 882c535eb59SGordon Tetlow wlist="$wlist $path/$f" 883c535eb59SGordon Tetlow fi 884c535eb59SGordon Tetlow 885c535eb59SGordon Tetlow for loc in $MANLOCALES; do 886c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 887c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 888c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 889c535eb59SGordon Tetlow fi 890c535eb59SGordon Tetlow done 891c535eb59SGordon Tetlow done 892c535eb59SGordon Tetlow unset IFS 893c535eb59SGordon Tetlow 894c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 895c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 896c535eb59SGordon Tetlow exit 1 897c535eb59SGordon Tetlow fi 898c535eb59SGordon Tetlow 899c535eb59SGordon Tetlow rval=0 900c535eb59SGordon Tetlow for key in $keywords; do 901c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 902c535eb59SGordon Tetlow if [ -n "$out" ]; then 903c535eb59SGordon Tetlow good="$good\\n$out" 904c535eb59SGordon Tetlow else 905c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 906c535eb59SGordon Tetlow rval=1 907c535eb59SGordon Tetlow fi 908c535eb59SGordon Tetlow done 909c535eb59SGordon Tetlow 910c535eb59SGordon Tetlow # Strip leading carriage return. 911c535eb59SGordon Tetlow good=${good#\\n} 912c535eb59SGordon Tetlow bad=${bad#\\n} 913c535eb59SGordon Tetlow 914c535eb59SGordon Tetlow if [ -n "$good" ]; then 915ec13a838SMohamed Akram printf '%b\n' "$good" | $MANPAGER 916c535eb59SGordon Tetlow fi 917c535eb59SGordon Tetlow 918c535eb59SGordon Tetlow if [ -n "$bad" ]; then 919ec13a838SMohamed Akram printf '%b\n' "$bad" >&2 920c535eb59SGordon Tetlow fi 921c535eb59SGordon Tetlow 922c535eb59SGordon Tetlow exit $rval 923c535eb59SGordon Tetlow} 924c535eb59SGordon Tetlow 92557cd9717SGordon Tetlow# Usage: setup_cattool page 92657cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 92757cd9717SGordon Tetlowsetup_cattool() { 92857cd9717SGordon Tetlow case "$1" in 92957cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 93057cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 931b35ea9baSMohamed Akram *.gz) cattool='/usr/bin/gzcat' ;; 93257cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 93357cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 934c8abb673SCameron Katri *.zst) cattool='/usr/bin/zstdcat' ;; 93557cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 93657cd9717SGordon Tetlow esac 93757cd9717SGordon Tetlow} 93857cd9717SGordon Tetlow 939c535eb59SGordon Tetlow# Usage: setup_pager 940a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 941c535eb59SGordon Tetlowsetup_pager() { 942c535eb59SGordon Tetlow # Setup pager. 943a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 944a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 945a6a3e856SRuslan Ermilov MANPAGER="less -sR" 946a6a3e856SRuslan Ermilov else 947a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 948a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 949a6a3e856SRuslan Ermilov else 95047cc9ee1SAlan Somers MANPAGER="less -s" 951c535eb59SGordon Tetlow fi 952a6a3e856SRuslan Ermilov fi 953a6a3e856SRuslan Ermilov fi 954a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 955c535eb59SGordon Tetlow} 956c535eb59SGordon Tetlow 957c535eb59SGordon Tetlow# Usage: trim string 958c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 959c535eb59SGordon Tetlowtrim() { 960c535eb59SGordon Tetlow tstr=$1 961c535eb59SGordon Tetlow while true; do 962c535eb59SGordon Tetlow case "$tstr" in 963c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 964c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 965c535eb59SGordon Tetlow *) break ;; 966c535eb59SGordon Tetlow esac 967c535eb59SGordon Tetlow done 968c535eb59SGordon Tetlow} 969c535eb59SGordon Tetlow 970c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 971c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 972c535eb59SGordon Tetlowwhatis_parse_args() { 973c535eb59SGordon Tetlow local cmd_arg 974f555b39eSKyle Evans OPTIND=1 975c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 976c535eb59SGordon Tetlow case "${cmd_arg}" in 977c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 978c535eb59SGordon Tetlow *) whatis_usage ;; 979c535eb59SGordon Tetlow esac 980c535eb59SGordon Tetlow done >&2 981c535eb59SGordon Tetlow 982c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 983c535eb59SGordon Tetlow 984c535eb59SGordon Tetlow keywords="$*" 985c535eb59SGordon Tetlow} 986c535eb59SGordon Tetlow 987c535eb59SGordon Tetlow# Usage: whatis_usage 988c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 989c535eb59SGordon Tetlowwhatis_usage() { 990c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 991c535eb59SGordon Tetlow exit 1 992c535eb59SGordon Tetlow} 993c535eb59SGordon Tetlow 994c535eb59SGordon Tetlow 995c535eb59SGordon Tetlow 996c535eb59SGordon Tetlow# Supported commands 997c535eb59SGordon Tetlowdo_apropos() { 99824ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 999772246efSBaptiste Daroussin exec apropos "$@" 1000c535eb59SGordon Tetlow search_whatis apropos "$@" 1001c535eb59SGordon Tetlow} 1002c535eb59SGordon Tetlow 10031594084fSFernando Apesteguía# Usage: do_full_search reg_exp 10041594084fSFernando Apesteguía# Do a full search of the regular expression passed 10051594084fSFernando Apesteguía# as parameter in all man pages 10061594084fSFernando Apesteguíado_full_search() { 10071594084fSFernando Apesteguía local gflags re 10081594084fSFernando Apesteguía re=${1} 10091594084fSFernando Apesteguía 10101594084fSFernando Apesteguía # Build grep(1) flags 10111594084fSFernando Apesteguía gflags="-H" 10121594084fSFernando Apesteguía 10131594084fSFernando Apesteguía # wflag implies -l for grep(1) 10141594084fSFernando Apesteguía if [ -n "$wflag" ]; then 10151594084fSFernando Apesteguía gflags="${gflags} -l" 10161594084fSFernando Apesteguía fi 10171594084fSFernando Apesteguía 10181594084fSFernando Apesteguía gflags="${gflags} --label" 10191594084fSFernando Apesteguía 10201594084fSFernando Apesteguía set +f 10218a5c836bSEd Maste for mpath in $(echo "${MANPATH}" | tr : '[:blank:]'); do 10228a5c836bSEd Maste for section in $(echo "${MANSECT}" | tr : '[:blank:]'); do 10231594084fSFernando Apesteguía for manfile in ${mpath}/man${section}/*.${section}*; do 10241594084fSFernando Apesteguía mandoc "${manfile}" 2>/dev/null | 10258a5c836bSEd Maste grep -E ${gflags} "${manfile}" -e "${re}" 10261594084fSFernando Apesteguía done 10271594084fSFernando Apesteguía done 10281594084fSFernando Apesteguía done 10291594084fSFernando Apesteguía set -f 10301594084fSFernando Apesteguía} 10311594084fSFernando Apesteguía 1032c535eb59SGordon Tetlowdo_man() { 10338edb6fb5SMohamed Akram local IFS 10348edb6fb5SMohamed Akram 10358edb6fb5SMohamed Akram man_parse_opts "$@" 10368edb6fb5SMohamed Akram man_setup 10378edb6fb5SMohamed Akram 10388edb6fb5SMohamed Akram shift $(( $OPTIND - 1 )) 10398edb6fb5SMohamed Akram IFS=: 10408edb6fb5SMohamed Akram for sect in $MANSECT; do 10418edb6fb5SMohamed Akram if [ "$sect" = "$1" ]; then 10428edb6fb5SMohamed Akram decho "Detected manual section as first arg: $1" 10438edb6fb5SMohamed Akram MANSECT="$1" 10448edb6fb5SMohamed Akram shift 10458edb6fb5SMohamed Akram break 10468edb6fb5SMohamed Akram fi 10478edb6fb5SMohamed Akram done 10488edb6fb5SMohamed Akram unset IFS 10498edb6fb5SMohamed Akram pages="$*" 10508edb6fb5SMohamed Akram 10511594084fSFernando Apesteguía if [ -z "$pages" -a -z "${Kflag}" ]; then 1052c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 1053c535eb59SGordon Tetlow exit 1 1054c535eb59SGordon Tetlow fi 1055c535eb59SGordon Tetlow 10561594084fSFernando Apesteguía if [ ! -z "${Kflag}" ]; then 10571594084fSFernando Apesteguía # Short circuit because -K flag does a sufficiently 10581594084fSFernando Apesteguía # different thing like not showing the man page at all 10591594084fSFernando Apesteguía do_full_search "${REGEXP}" 10601594084fSFernando Apesteguía fi 10611594084fSFernando Apesteguía 10621e82d882SWolfram Schneider for page in "$@"; do 106378948070SWolfram Schneider decho "Searching for \"$page\"" 1064c535eb59SGordon Tetlow man_find_and_display "$page" 1065c535eb59SGordon Tetlow done 1066c535eb59SGordon Tetlow 1067c535eb59SGordon Tetlow exit ${ret:-0} 1068c535eb59SGordon Tetlow} 1069c535eb59SGordon Tetlow 1070c535eb59SGordon Tetlowdo_manpath() { 1071c535eb59SGordon Tetlow manpath_parse_args "$@" 1072c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 1073c535eb59SGordon Tetlow manpath_warnings 1074c535eb59SGordon Tetlow fi 1075c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 1076c535eb59SGordon Tetlow build_manlocales 1077c535eb59SGordon Tetlow echo $MANLOCALES 1078c535eb59SGordon Tetlow else 1079c535eb59SGordon Tetlow build_manpath 1080c535eb59SGordon Tetlow echo $MANPATH 1081c535eb59SGordon Tetlow fi 1082c535eb59SGordon Tetlow exit 0 1083c535eb59SGordon Tetlow} 1084c535eb59SGordon Tetlow 1085c535eb59SGordon Tetlowdo_whatis() { 108624ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 1087772246efSBaptiste Daroussin exec whatis "$@" 1088c535eb59SGordon Tetlow search_whatis whatis "$@" 1089c535eb59SGordon Tetlow} 1090c535eb59SGordon Tetlow 1091aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 1092aeea395eSUlrich SpörleinEQN=eqn 1093035f7c9aSWolfram SchneiderNROFF='groff -S -P-h -Wall -mtty-char -mandoc' 1094aeea395eSUlrich SpörleinPIC=pic 1095aeea395eSUlrich SpörleinREFER=refer 1096aeea395eSUlrich SpörleinTBL=tbl 1097035f7c9aSWolfram SchneiderTROFF='groff -S -mandoc' 1098aeea395eSUlrich SpörleinVGRIND=vgrind 1099aeea395eSUlrich Spörlein 1100deeff310SGordon TetlowLOCALE=/usr/bin/locale 1101a0094449SRuslan ErmilovSTTY=/bin/stty 110282db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1103c535eb59SGordon Tetlow 1104c535eb59SGordon Tetlowdebug=0 110573577bf0SRyan Moellerman_default_sections='1:8:2:3:3lua:n:4:5:6:7:9:l' 1106971c1c42STijl Coosemansman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man' 110757cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1108c535eb59SGordon Tetlow 1109c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1110c535eb59SGordon Tetlow 1111c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1112c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1113c535eb59SGordon Tetlow 1114c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1115c535eb59SGordon Tetlowset -f 1116c535eb59SGordon Tetlow 1117c535eb59SGordon Tetlowcase "$0" in 1118c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1119c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1120c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1121c535eb59SGordon Tetlow*) do_man "$@" ;; 1122c535eb59SGordon Tetlowesac 1123