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