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# $FreeBSD$ 30c535eb59SGordon Tetlow 31433c5a8aSWolfram Schneider# Rendering a manual page is fast. Even a manual page several 100k in size 32433c5a8aSWolfram Schneider# takes less than a CPU second. If it takes much longer, it is very likely 33433c5a8aSWolfram Schneider# that a tool like mandoc(1) is running in an infinite loop. In this case 34433c5a8aSWolfram Schneider# it is better to terminate it. 35433c5a8aSWolfram Schneiderulimit -t 20 36433c5a8aSWolfram Schneider 37c535eb59SGordon Tetlow# Usage: add_to_manpath path 38c535eb59SGordon Tetlow# Adds a variable to manpath while ensuring we don't have duplicates. 39c535eb59SGordon Tetlow# Returns true if we were able to add something. False otherwise. 40c535eb59SGordon Tetlowadd_to_manpath() { 41c535eb59SGordon Tetlow case "$manpath" in 42c535eb59SGordon Tetlow *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 43c535eb59SGordon Tetlow $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 44c535eb59SGordon Tetlow *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 45c535eb59SGordon Tetlow *) if [ -d "$1" ]; then 46c535eb59SGordon Tetlow decho " Adding $1 to manpath" 47c535eb59SGordon Tetlow manpath="$manpath:$1" 48c535eb59SGordon Tetlow return 0 49c535eb59SGordon Tetlow fi 50c535eb59SGordon Tetlow ;; 51c535eb59SGordon Tetlow esac 52c535eb59SGordon Tetlow 53c535eb59SGordon Tetlow return 1 54c535eb59SGordon Tetlow} 55c535eb59SGordon Tetlow 56c535eb59SGordon Tetlow# Usage: build_manlocales 57c535eb59SGordon Tetlow# Builds a correct MANLOCALES variable. 58c535eb59SGordon Tetlowbuild_manlocales() { 59c535eb59SGordon Tetlow # If the user has set manlocales, who are we to argue. 60c535eb59SGordon Tetlow if [ -n "$MANLOCALES" ]; then 61c535eb59SGordon Tetlow return 62c535eb59SGordon Tetlow fi 63c535eb59SGordon Tetlow 64c535eb59SGordon Tetlow parse_configs 65c535eb59SGordon Tetlow 66c535eb59SGordon Tetlow # Trim leading colon 67c535eb59SGordon Tetlow MANLOCALES=${manlocales#:} 68c535eb59SGordon Tetlow 69c535eb59SGordon Tetlow decho "Available manual locales: $MANLOCALES" 70c535eb59SGordon Tetlow} 71c535eb59SGordon Tetlow 72*8edb6fb5SMohamed Akram# Usage: build_mansect 73*8edb6fb5SMohamed Akram# Builds a correct MANSECT variable. 74*8edb6fb5SMohamed Akrambuild_mansect() { 75*8edb6fb5SMohamed Akram # If the user has set mansect, who are we to argue. 76*8edb6fb5SMohamed Akram if [ -n "$MANSECT" ]; then 77*8edb6fb5SMohamed Akram return 78*8edb6fb5SMohamed Akram fi 79*8edb6fb5SMohamed Akram 80*8edb6fb5SMohamed Akram parse_configs 81*8edb6fb5SMohamed Akram 82*8edb6fb5SMohamed Akram # Trim leading colon 83*8edb6fb5SMohamed Akram MANSECT=${mansect#:} 84*8edb6fb5SMohamed Akram 85*8edb6fb5SMohamed Akram if [ -z "$MANSECT" ]; then 86*8edb6fb5SMohamed Akram MANSECT=$man_default_sections 87*8edb6fb5SMohamed Akram fi 88*8edb6fb5SMohamed Akram decho "Using manual sections: $MANSECT" 89*8edb6fb5SMohamed Akram} 90*8edb6fb5SMohamed Akram 91c535eb59SGordon Tetlow# Usage: build_manpath 92c535eb59SGordon Tetlow# Builds a correct MANPATH variable. 93c535eb59SGordon Tetlowbuild_manpath() { 94c535eb59SGordon Tetlow local IFS 95c535eb59SGordon Tetlow 96c535eb59SGordon Tetlow # If the user has set a manpath, who are we to argue. 97c535eb59SGordon Tetlow if [ -n "$MANPATH" ]; then 98b2394e73SBaptiste Daroussin case "$MANPATH" in 99b2394e73SBaptiste Daroussin *:) PREPEND_MANPATH=${MANPATH} ;; 100b2394e73SBaptiste Daroussin :*) APPEND_MANPATH=${MANPATH} ;; 101b2394e73SBaptiste Daroussin *::*) 102b2394e73SBaptiste Daroussin PREPEND_MANPATH=${MANPATH%%::*} 103b2394e73SBaptiste Daroussin APPEND_MANPATH=${MANPATH#*::} 104b2394e73SBaptiste Daroussin ;; 105b2394e73SBaptiste Daroussin *) return ;; 106b2394e73SBaptiste Daroussin esac 107b2394e73SBaptiste Daroussin fi 108b2394e73SBaptiste Daroussin 109b2394e73SBaptiste Daroussin if [ -n "$PREPEND_MANPATH" ]; then 110b2394e73SBaptiste Daroussin IFS=: 111b2394e73SBaptiste Daroussin for path in $PREPEND_MANPATH; do 112b2394e73SBaptiste Daroussin add_to_manpath "$path" 113b2394e73SBaptiste Daroussin done 114b2394e73SBaptiste Daroussin unset IFS 115c535eb59SGordon Tetlow fi 116c535eb59SGordon Tetlow 117c535eb59SGordon Tetlow search_path 118c535eb59SGordon Tetlow 119c535eb59SGordon Tetlow decho "Adding default manpath entries" 120c535eb59SGordon Tetlow IFS=: 121c535eb59SGordon Tetlow for path in $man_default_path; do 122c535eb59SGordon Tetlow add_to_manpath "$path" 123c535eb59SGordon Tetlow done 124c535eb59SGordon Tetlow unset IFS 125c535eb59SGordon Tetlow 126c535eb59SGordon Tetlow parse_configs 127c535eb59SGordon Tetlow 128b2394e73SBaptiste Daroussin if [ -n "$APPEND_MANPATH" ]; then 129b2394e73SBaptiste Daroussin IFS=: 130b2394e73SBaptiste Daroussin for path in $APPEND_MANPATH; do 131b2394e73SBaptiste Daroussin add_to_manpath "$path" 132b2394e73SBaptiste Daroussin done 133b2394e73SBaptiste Daroussin unset IFS 134b2394e73SBaptiste Daroussin fi 135c535eb59SGordon Tetlow # Trim leading colon 136c535eb59SGordon Tetlow MANPATH=${manpath#:} 137c535eb59SGordon Tetlow 138c535eb59SGordon Tetlow decho "Using manual path: $MANPATH" 139c535eb59SGordon Tetlow} 140c535eb59SGordon Tetlow 141c535eb59SGordon Tetlow# Usage: check_cat catglob 142c535eb59SGordon Tetlow# Checks to see if a cat glob is available. 143c535eb59SGordon Tetlowcheck_cat() { 144c535eb59SGordon Tetlow if exists "$1"; then 145c535eb59SGordon Tetlow use_cat=yes 146c535eb59SGordon Tetlow catpage=$found 14757cd9717SGordon Tetlow setup_cattool $catpage 148c535eb59SGordon Tetlow decho " Found catpage $catpage" 149c535eb59SGordon Tetlow return 0 150c535eb59SGordon Tetlow else 151c535eb59SGordon Tetlow return 1 152c535eb59SGordon Tetlow fi 153c535eb59SGordon Tetlow} 154c535eb59SGordon Tetlow 155c535eb59SGordon Tetlow# Usage: check_man manglob catglob 156c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to 157c535eb59SGordon Tetlow# see if the catglob is also available and up to date. 158c535eb59SGordon Tetlowcheck_man() { 159c535eb59SGordon Tetlow if exists "$1"; then 160c535eb59SGordon Tetlow # We have a match, check for a cat page 161c535eb59SGordon Tetlow manpage=$found 16257cd9717SGordon Tetlow setup_cattool $manpage 163c535eb59SGordon Tetlow decho " Found manpage $manpage" 164c535eb59SGordon Tetlow 165a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 166a0094449SRuslan Ermilov # non-standard width 167a0094449SRuslan Ermilov unset use_cat 168a0094449SRuslan Ermilov decho " Skipping catpage: non-standard page width" 169a0094449SRuslan Ermilov elif exists "$2" && is_newer $found $manpage; then 170c535eb59SGordon Tetlow # cat page found and is newer, use that 171c535eb59SGordon Tetlow use_cat=yes 172c535eb59SGordon Tetlow catpage=$found 17357cd9717SGordon Tetlow setup_cattool $catpage 174c535eb59SGordon Tetlow decho " Using catpage $catpage" 175c535eb59SGordon Tetlow else 176c535eb59SGordon Tetlow # no cat page or is older 177c535eb59SGordon Tetlow unset use_cat 178c535eb59SGordon Tetlow decho " Skipping catpage: not found or old" 179c535eb59SGordon Tetlow fi 180c535eb59SGordon Tetlow return 0 181c535eb59SGordon Tetlow fi 182c535eb59SGordon Tetlow 183c535eb59SGordon Tetlow return 1 184c535eb59SGordon Tetlow} 185c535eb59SGordon Tetlow 186c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel] 187c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel. 188c535eb59SGordon Tetlowdecho() { 189c535eb59SGordon Tetlow if [ $debug -ge ${2:-1} ]; then 190c535eb59SGordon Tetlow echo "-- $1" >&2 191c535eb59SGordon Tetlow fi 192c535eb59SGordon Tetlow} 193c535eb59SGordon Tetlow 194c535eb59SGordon Tetlow# Usage: exists glob 195c535eb59SGordon Tetlow# Returns true if glob resolves to a real file. 196c535eb59SGordon Tetlowexists() { 197c535eb59SGordon Tetlow local IFS 198c535eb59SGordon Tetlow 199c535eb59SGordon Tetlow # Don't accidentally inherit callers IFS (breaks perl manpages) 200c535eb59SGordon Tetlow unset IFS 201c535eb59SGordon Tetlow 202c535eb59SGordon Tetlow # Use some globbing tricks in the shell to determine if a file 203c535eb59SGordon Tetlow # exists or not. 204c535eb59SGordon Tetlow set +f 205c535eb59SGordon Tetlow set -- "$1" $1 206c535eb59SGordon Tetlow set -f 207c535eb59SGordon Tetlow 208c535eb59SGordon Tetlow if [ "$1" != "$2" -a -r "$2" ]; then 209c535eb59SGordon Tetlow found="$2" 210c535eb59SGordon Tetlow return 0 211c535eb59SGordon Tetlow fi 212c535eb59SGordon Tetlow 213c535eb59SGordon Tetlow return 1 214c535eb59SGordon Tetlow} 215c535eb59SGordon Tetlow 216c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename 217c535eb59SGordon Tetlow# Returns: true if something is matched and found. 218c535eb59SGordon Tetlow# Search the given path/section combo for a given page. 219c535eb59SGordon Tetlowfind_file() { 220c535eb59SGordon Tetlow local manroot catroot mann man0 catn cat0 221c535eb59SGordon Tetlow 222c535eb59SGordon Tetlow manroot="$1/man$2" 223c535eb59SGordon Tetlow catroot="$1/cat$2" 224c535eb59SGordon Tetlow if [ -n "$3" ]; then 225c535eb59SGordon Tetlow manroot="$manroot/$3" 226c535eb59SGordon Tetlow catroot="$catroot/$3" 227c535eb59SGordon Tetlow fi 228c535eb59SGordon Tetlow 229625490e8SBaptiste Daroussin if [ ! -d "$manroot" -a ! -d "$catroot" ]; then 230c535eb59SGordon Tetlow return 1 231c535eb59SGordon Tetlow fi 232c535eb59SGordon Tetlow decho " Searching directory $manroot" 2 233c535eb59SGordon Tetlow 234c535eb59SGordon Tetlow mann="$manroot/$4.$2*" 235c535eb59SGordon Tetlow man0="$manroot/$4.0*" 236c535eb59SGordon Tetlow catn="$catroot/$4.$2*" 237c535eb59SGordon Tetlow cat0="$catroot/$4.0*" 238c535eb59SGordon Tetlow 239c535eb59SGordon Tetlow # This is the behavior as seen by the original man utility. 240c535eb59SGordon Tetlow # Let's not change that which doesn't seem broken. 241c535eb59SGordon Tetlow if check_man "$mann" "$catn"; then 242c535eb59SGordon Tetlow return 0 243c535eb59SGordon Tetlow elif check_man "$man0" "$cat0"; then 244c535eb59SGordon Tetlow return 0 245c535eb59SGordon Tetlow elif check_cat "$catn"; then 246c535eb59SGordon Tetlow return 0 247c535eb59SGordon Tetlow elif check_cat "$cat0"; then 248c535eb59SGordon Tetlow return 0 249c535eb59SGordon Tetlow fi 250c535eb59SGordon Tetlow 251c535eb59SGordon Tetlow return 1 252c535eb59SGordon Tetlow} 253c535eb59SGordon Tetlow 254c535eb59SGordon Tetlow# Usage: is_newer file1 file2 255c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime. 256c535eb59SGordon Tetlowis_newer() { 2579b61837aSUlrich Spörlein if ! [ "$1" -ot "$2" ]; then 2589b61837aSUlrich Spörlein decho " mtime: $1 not older than $2" 3 259c535eb59SGordon Tetlow return 0 260c535eb59SGordon Tetlow else 261c535eb59SGordon Tetlow decho " mtime: $1 older than $2" 3 262c535eb59SGordon Tetlow return 1 263c535eb59SGordon Tetlow fi 264c535eb59SGordon Tetlow} 265c535eb59SGordon Tetlow 266c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@" 267c535eb59SGordon Tetlow# Parses commandline options for manpath. 268c535eb59SGordon Tetlowmanpath_parse_args() { 269c535eb59SGordon Tetlow local cmd_arg 270c535eb59SGordon Tetlow 271f555b39eSKyle Evans OPTIND=1 272c535eb59SGordon Tetlow while getopts 'Ldq' cmd_arg; do 273c535eb59SGordon Tetlow case "${cmd_arg}" in 274c535eb59SGordon Tetlow L) Lflag=Lflag ;; 275c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 276c535eb59SGordon Tetlow q) qflag=qflag ;; 277c535eb59SGordon Tetlow *) manpath_usage ;; 278c535eb59SGordon Tetlow esac 279c535eb59SGordon Tetlow done >&2 280c535eb59SGordon Tetlow} 281c535eb59SGordon Tetlow 282c535eb59SGordon Tetlow# Usage: manpath_usage 283c535eb59SGordon Tetlow# Display usage for the manpath(1) utility. 284c535eb59SGordon Tetlowmanpath_usage() { 285c535eb59SGordon Tetlow echo 'usage: manpath [-Ldq]' >&2 286c535eb59SGordon Tetlow exit 1 287c535eb59SGordon Tetlow} 288c535eb59SGordon Tetlow 289c535eb59SGordon Tetlow# Usage: manpath_warnings 290c535eb59SGordon Tetlow# Display some warnings to stderr. 291c535eb59SGordon Tetlowmanpath_warnings() { 292c535eb59SGordon Tetlow if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 293c535eb59SGordon Tetlow echo "(Warning: MANLOCALES environment variable set)" >&2 294c535eb59SGordon Tetlow fi 295c535eb59SGordon Tetlow} 296c535eb59SGordon Tetlow 29757cd9717SGordon Tetlow# Usage: man_check_for_so page path 29857cd9717SGordon Tetlow# Returns: True if able to resolve the file, false if it ended in tears. 29957cd9717SGordon Tetlow# Detects the presence of the .so directive and causes the file to be 30057cd9717SGordon Tetlow# redirected to another source file. 30157cd9717SGordon Tetlowman_check_for_so() { 30257cd9717SGordon Tetlow local IFS line tstr 30357cd9717SGordon Tetlow 30457cd9717SGordon Tetlow unset IFS 305d9405a92SBaptiste Daroussin if [ -n "$catpage" ]; then 306d9405a92SBaptiste Daroussin return 0 307d9405a92SBaptiste Daroussin fi 30857cd9717SGordon Tetlow 30957cd9717SGordon Tetlow # We need to loop to accommodate multiple .so directives. 31057cd9717SGordon Tetlow while true 31157cd9717SGordon Tetlow do 31257cd9717SGordon Tetlow line=$($cattool $manpage | head -1) 31357cd9717SGordon Tetlow case "$line" in 31457cd9717SGordon Tetlow .so*) trim "${line#.so}" 31557cd9717SGordon Tetlow decho "$manpage includes $tstr" 31657cd9717SGordon Tetlow # Glob and check for the file. 31757cd9717SGordon Tetlow if ! check_man "$path/$tstr*" ""; then 31857cd9717SGordon Tetlow decho " Unable to find $tstr" 31957cd9717SGordon Tetlow return 1 32057cd9717SGordon Tetlow fi 32157cd9717SGordon Tetlow ;; 32257cd9717SGordon Tetlow *) break ;; 32357cd9717SGordon Tetlow esac 32457cd9717SGordon Tetlow done 32557cd9717SGordon Tetlow 32657cd9717SGordon Tetlow return 0 32757cd9717SGordon Tetlow} 32857cd9717SGordon Tetlow 329b43edc06SBaptiste Daroussin# Usage: man_display_page 330b43edc06SBaptiste Daroussin# Display either the manpage or catpage depending on the use_cat variable 331c535eb59SGordon Tetlowman_display_page() { 3321fb816daSBaptiste Daroussin local IFS pipeline testline 333c535eb59SGordon Tetlow 334c535eb59SGordon Tetlow # We are called with IFS set to colon. This causes really weird 335c535eb59SGordon Tetlow # things to happen for the variables that have spaces in them. 336c535eb59SGordon Tetlow unset IFS 337c535eb59SGordon Tetlow 338c535eb59SGordon Tetlow # If we are supposed to use a catpage and we aren't using troff(1) 339c535eb59SGordon Tetlow # just zcat the catpage and we are done. 340c535eb59SGordon Tetlow if [ -z "$tflag" -a -n "$use_cat" ]; then 341c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 342c535eb59SGordon Tetlow echo "$catpage (source: $manpage)" 343c535eb59SGordon Tetlow ret=0 344c535eb59SGordon Tetlow else 345c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 346a6a3e856SRuslan Ermilov decho "Command: $cattool $catpage | $MANPAGER" 347c535eb59SGordon Tetlow ret=0 348c535eb59SGordon Tetlow else 349a6a3e856SRuslan Ermilov eval "$cattool $catpage | $MANPAGER" 350c535eb59SGordon Tetlow ret=$? 351c535eb59SGordon Tetlow fi 352c535eb59SGordon Tetlow fi 353c535eb59SGordon Tetlow return 354c535eb59SGordon Tetlow fi 355c535eb59SGordon Tetlow 356c535eb59SGordon Tetlow # Okay, we are using the manpage, do we just need to output the 357c535eb59SGordon Tetlow # name of the manpage? 358c535eb59SGordon Tetlow if [ -n "$wflag" ]; then 359c535eb59SGordon Tetlow echo "$manpage" 360c535eb59SGordon Tetlow ret=0 361c535eb59SGordon Tetlow return 362c535eb59SGordon Tetlow fi 363c535eb59SGordon Tetlow 364d433cf9aSBaptiste Daroussin if [ -n "$use_width" ]; then 365d433cf9aSBaptiste Daroussin mandoc_args="-O width=${use_width}" 366d433cf9aSBaptiste Daroussin fi 367451c2becSBaptiste Daroussin testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 368449a792dSBaptiste Daroussin if [ -n "$tflag" ]; then 369449a792dSBaptiste Daroussin pipeline="mandoc -Tps $mandoc_args" 370449a792dSBaptiste Daroussin else 371d433cf9aSBaptiste Daroussin pipeline="mandoc $mandoc_args | $MANPAGER" 372449a792dSBaptiste Daroussin fi 373d6096801SBaptiste Daroussin 374d6096801SBaptiste Daroussin if ! eval "$cattool $manpage | $testline" ;then 375f17575acSBaptiste Daroussin if which -s groff; then 376d6096801SBaptiste Daroussin man_display_page_groff 377d6096801SBaptiste Daroussin else 378d6096801SBaptiste Daroussin echo "This manpage needs groff(1) to be rendered" >&2 379d6096801SBaptiste Daroussin echo "First install groff(1): " >&2 380d6096801SBaptiste Daroussin echo "pkg install groff " >&2 381d6096801SBaptiste Daroussin ret=1 382d6096801SBaptiste Daroussin fi 383d6096801SBaptiste Daroussin return 384d6096801SBaptiste Daroussin fi 385d6096801SBaptiste Daroussin 386d6096801SBaptiste Daroussin if [ $debug -gt 0 ]; then 387d6096801SBaptiste Daroussin decho "Command: $cattool $manpage | $pipeline" 388d6096801SBaptiste Daroussin ret=0 389d6096801SBaptiste Daroussin else 390d6096801SBaptiste Daroussin eval "$cattool $manpage | $pipeline" 391d6096801SBaptiste Daroussin ret=$? 392d6096801SBaptiste Daroussin fi 393d6096801SBaptiste Daroussin} 394d6096801SBaptiste Daroussin 395b43edc06SBaptiste Daroussin# Usage: man_display_page_groff 396b43edc06SBaptiste Daroussin# Display the manpage using groff 397d6096801SBaptiste Daroussinman_display_page_groff() { 398d6096801SBaptiste Daroussin local EQN NROFF PIC TBL TROFF REFER VGRIND 399d6096801SBaptiste Daroussin local IFS l nroff_dev pipeline preproc_arg tool 400d6096801SBaptiste Daroussin 401c535eb59SGordon Tetlow # So, we really do need to parse the manpage. First, figure out the 402c535eb59SGordon Tetlow # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 403c535eb59SGordon Tetlow # setup the pipeline of commands based on the user's request. 404c535eb59SGordon Tetlow 405deeff310SGordon Tetlow # If the manpage is from a particular charset, we need to setup nroff 406deeff310SGordon Tetlow # to properly output for the correct device. 407deeff310SGordon Tetlow case "${manpage}" in 408deeff310SGordon Tetlow *.${man_charset}/*) 409c535eb59SGordon Tetlow # I don't pretend to know this; I'm just copying from the 410c535eb59SGordon Tetlow # previous version of man(1). 411c535eb59SGordon Tetlow case "$man_charset" in 412c535eb59SGordon Tetlow KOI8-R) nroff_dev="koi8-r" ;; 413c535eb59SGordon Tetlow ISO8859-1) nroff_dev="latin1" ;; 414c535eb59SGordon Tetlow ISO8859-15) nroff_dev="latin1" ;; 415c535eb59SGordon Tetlow UTF-8) nroff_dev="utf8" ;; 416c535eb59SGordon Tetlow *) nroff_dev="ascii" ;; 417c535eb59SGordon Tetlow esac 418c535eb59SGordon Tetlow 419deeff310SGordon Tetlow NROFF="$NROFF -T$nroff_dev" 420c535eb59SGordon Tetlow EQN="$EQN -T$nroff_dev" 421c535eb59SGordon Tetlow 422deeff310SGordon Tetlow # Iff the manpage is from the locale and not just the charset, 423deeff310SGordon Tetlow # then we need to define the locale string. 424deeff310SGordon Tetlow case "${manpage}" in 425deeff310SGordon Tetlow */${man_lang}_${man_country}.${man_charset}/*) 426deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 427deeff310SGordon Tetlow ;; 428deeff310SGordon Tetlow */${man_lang}.${man_charset}/*) 429deeff310SGordon Tetlow NROFF="$NROFF -dlocale=$man_lang.$man_charset" 430deeff310SGordon Tetlow ;; 431deeff310SGordon Tetlow esac 432deeff310SGordon Tetlow 433c535eb59SGordon Tetlow # Allow language specific calls to override the default 434c535eb59SGordon Tetlow # set of utilities. 435c535eb59SGordon Tetlow l=$(echo $man_lang | tr [:lower:] [:upper:]) 436b70e2025SRuslan Ermilov for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 437c535eb59SGordon Tetlow eval "$tool=\${${tool}_$l:-\$$tool}" 438c535eb59SGordon Tetlow done 439c535eb59SGordon Tetlow ;; 440c535eb59SGordon Tetlow *) NROFF="$NROFF -Tascii" 441c535eb59SGordon Tetlow EQN="$EQN -Tascii" 442c535eb59SGordon Tetlow ;; 443c535eb59SGordon Tetlow esac 444c535eb59SGordon Tetlow 445a6a3e856SRuslan Ermilov if [ -z "$MANCOLOR" ]; then 446a6a3e856SRuslan Ermilov NROFF="$NROFF -P-c" 447a6a3e856SRuslan Ermilov fi 448a6a3e856SRuslan Ermilov 449a0094449SRuslan Ermilov if [ -n "${use_width}" ]; then 450a0094449SRuslan Ermilov NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 451a0094449SRuslan Ermilov fi 452a0094449SRuslan Ermilov 453c535eb59SGordon Tetlow if [ -n "$MANROFFSEQ" ]; then 454c535eb59SGordon Tetlow set -- -$MANROFFSEQ 455f555b39eSKyle Evans OPTIND=1 456c535eb59SGordon Tetlow while getopts 'egprtv' preproc_arg; do 457c535eb59SGordon Tetlow case "${preproc_arg}" in 458c535eb59SGordon Tetlow e) pipeline="$pipeline | $EQN" ;; 459487ac9acSUlrich Spörlein g) ;; # Ignore for compatibility. 460c535eb59SGordon Tetlow p) pipeline="$pipeline | $PIC" ;; 461c535eb59SGordon Tetlow r) pipeline="$pipeline | $REFER" ;; 462b70e2025SRuslan Ermilov t) pipeline="$pipeline | $TBL" ;; 463c535eb59SGordon Tetlow v) pipeline="$pipeline | $VGRIND" ;; 464c535eb59SGordon Tetlow *) usage ;; 465c535eb59SGordon Tetlow esac 466c535eb59SGordon Tetlow done 467c535eb59SGordon Tetlow # Strip the leading " | " from the resulting pipeline. 468c535eb59SGordon Tetlow pipeline="${pipeline#" | "}" 469c535eb59SGordon Tetlow else 470c535eb59SGordon Tetlow pipeline="$TBL" 471c535eb59SGordon Tetlow fi 472c535eb59SGordon Tetlow 473c535eb59SGordon Tetlow if [ -n "$tflag" ]; then 474c535eb59SGordon Tetlow pipeline="$pipeline | $TROFF" 475c535eb59SGordon Tetlow else 476a6a3e856SRuslan Ermilov pipeline="$pipeline | $NROFF | $MANPAGER" 477c535eb59SGordon Tetlow fi 478c535eb59SGordon Tetlow 479c535eb59SGordon Tetlow if [ $debug -gt 0 ]; then 48057cd9717SGordon Tetlow decho "Command: $cattool $manpage | $pipeline" 481c535eb59SGordon Tetlow ret=0 482c535eb59SGordon Tetlow else 48357cd9717SGordon Tetlow eval "$cattool $manpage | $pipeline" 484c535eb59SGordon Tetlow ret=$? 485c535eb59SGordon Tetlow fi 486c535eb59SGordon Tetlow} 487c535eb59SGordon Tetlow 488c535eb59SGordon Tetlow# Usage: man_find_and_display page 489c535eb59SGordon Tetlow# Search through the manpaths looking for the given page. 490c535eb59SGordon Tetlowman_find_and_display() { 491c535eb59SGordon Tetlow local found_page locpath p path sect 492c535eb59SGordon Tetlow 4933d9127f1SGordon Tetlow # Check to see if it's a file. But only if it has a '/' in 4943d9127f1SGordon Tetlow # the filename. 4953d9127f1SGordon Tetlow case "$1" in 4963d9127f1SGordon Tetlow */*) if [ -f "$1" -a -r "$1" ]; then 4973d9127f1SGordon Tetlow decho "Found a usable page, displaying that" 4983d9127f1SGordon Tetlow unset use_cat 4993d9127f1SGordon Tetlow manpage="$1" 50057cd9717SGordon Tetlow setup_cattool $manpage 50157cd9717SGordon Tetlow if man_check_for_so $manpage $(dirname $manpage); then 50257cd9717SGordon Tetlow found_page=yes 5033d9127f1SGordon Tetlow man_display_page 50457cd9717SGordon Tetlow fi 5053d9127f1SGordon Tetlow return 5063d9127f1SGordon Tetlow fi 5073d9127f1SGordon Tetlow ;; 5083d9127f1SGordon Tetlow esac 5093d9127f1SGordon Tetlow 510c535eb59SGordon Tetlow IFS=: 511c535eb59SGordon Tetlow for sect in $MANSECT; do 512c535eb59SGordon Tetlow decho "Searching section $sect" 2 513c535eb59SGordon Tetlow for path in $MANPATH; do 514c535eb59SGordon Tetlow for locpath in $locpaths; do 515c535eb59SGordon Tetlow p=$path/$locpath 516c535eb59SGordon Tetlow p=${p%/.} # Rid ourselves of the trailing /. 517c535eb59SGordon Tetlow 518c535eb59SGordon Tetlow # Check if there is a MACHINE specific manpath. 519c535eb59SGordon Tetlow if find_file $p $sect $MACHINE "$1"; then 52057cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 521c535eb59SGordon Tetlow found_page=yes 522c535eb59SGordon Tetlow man_display_page 5231d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5241d7c660aSGordon Tetlow continue 2 5251d7c660aSGordon Tetlow else 526c535eb59SGordon Tetlow return 527c535eb59SGordon Tetlow fi 528c535eb59SGordon Tetlow fi 52957cd9717SGordon Tetlow fi 530c535eb59SGordon Tetlow 531c535eb59SGordon Tetlow # Check if there is a MACHINE_ARCH 532c535eb59SGordon Tetlow # specific manpath. 533c535eb59SGordon Tetlow if find_file $p $sect $MACHINE_ARCH "$1"; then 53457cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 535c535eb59SGordon Tetlow found_page=yes 536c535eb59SGordon Tetlow man_display_page 5371d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5381d7c660aSGordon Tetlow continue 2 5391d7c660aSGordon Tetlow else 540c535eb59SGordon Tetlow return 541c535eb59SGordon Tetlow fi 542c535eb59SGordon Tetlow fi 54357cd9717SGordon Tetlow fi 544c535eb59SGordon Tetlow 545c535eb59SGordon Tetlow # Check plain old manpath. 546c535eb59SGordon Tetlow if find_file $p $sect '' "$1"; then 54757cd9717SGordon Tetlow if man_check_for_so $manpage $p; then 548c535eb59SGordon Tetlow found_page=yes 549c535eb59SGordon Tetlow man_display_page 5501d7c660aSGordon Tetlow if [ -n "$aflag" ]; then 5511d7c660aSGordon Tetlow continue 2 5521d7c660aSGordon Tetlow else 553c535eb59SGordon Tetlow return 554c535eb59SGordon Tetlow fi 555c535eb59SGordon Tetlow fi 55657cd9717SGordon Tetlow fi 557c535eb59SGordon Tetlow done 558c535eb59SGordon Tetlow done 559c535eb59SGordon Tetlow done 560c535eb59SGordon Tetlow unset IFS 561c535eb59SGordon Tetlow 562c535eb59SGordon Tetlow # Nothing? Well, we are done then. 563c535eb59SGordon Tetlow if [ -z "$found_page" ]; then 564c535eb59SGordon Tetlow echo "No manual entry for $1" >&2 565c535eb59SGordon Tetlow ret=1 566c535eb59SGordon Tetlow return 567c535eb59SGordon Tetlow fi 568c535eb59SGordon Tetlow} 569c535eb59SGordon Tetlow 570*8edb6fb5SMohamed Akram# Usage: man_parse_opts "$@" 571c535eb59SGordon Tetlow# Parses commandline options for man. 572*8edb6fb5SMohamed Akramman_parse_opts() { 573*8edb6fb5SMohamed Akram local cmd_arg 574c535eb59SGordon Tetlow 575f555b39eSKyle Evans OPTIND=1 5761594084fSFernando Apesteguía while getopts 'K:M:P:S:adfhkm:op:tw' cmd_arg; do 577c535eb59SGordon Tetlow case "${cmd_arg}" in 5781594084fSFernando Apesteguía K) Kflag=Kflag 5791594084fSFernando Apesteguía REGEXP=$OPTARG ;; 580c535eb59SGordon Tetlow M) MANPATH=$OPTARG ;; 581a6a3e856SRuslan Ermilov P) MANPAGER=$OPTARG ;; 582c535eb59SGordon Tetlow S) MANSECT=$OPTARG ;; 583c535eb59SGordon Tetlow a) aflag=aflag ;; 584c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 585c535eb59SGordon Tetlow f) fflag=fflag ;; 586c535eb59SGordon Tetlow h) man_usage 0 ;; 587c535eb59SGordon Tetlow k) kflag=kflag ;; 588c535eb59SGordon Tetlow m) mflag=$OPTARG ;; 589c535eb59SGordon Tetlow o) oflag=oflag ;; 590c535eb59SGordon Tetlow p) MANROFFSEQ=$OPTARG ;; 591c535eb59SGordon Tetlow t) tflag=tflag ;; 592c535eb59SGordon Tetlow w) wflag=wflag ;; 593c535eb59SGordon Tetlow *) man_usage ;; 594c535eb59SGordon Tetlow esac 595c535eb59SGordon Tetlow done >&2 596c535eb59SGordon Tetlow 597c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 598c535eb59SGordon Tetlow 599c535eb59SGordon Tetlow # Check the args for incompatible options. 6001594084fSFernando Apesteguía 6011594084fSFernando Apesteguía case "${Kflag}${fflag}${kflag}${tflag}${wflag}" in 6021594084fSFernando Apesteguía Kflagfflag*) echo "Incompatible options: -K and -f"; man_usage ;; 6031594084fSFernando Apesteguía Kflag*kflag*) echo "Incompatible options: -K and -k"; man_usage ;; 6041594084fSFernando Apesteguía Kflag*tflag) echo "Incompatible options: -K and -t"; man_usage ;; 605c535eb59SGordon Tetlow fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 606c535eb59SGordon Tetlow fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 607c535eb59SGordon Tetlow fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 608c535eb59SGordon Tetlow *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 609c535eb59SGordon Tetlow *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 610c535eb59SGordon Tetlow *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 611c535eb59SGordon Tetlow esac 612c535eb59SGordon Tetlow 613c535eb59SGordon Tetlow # Short circuit for whatis(1) and apropos(1) 614c535eb59SGordon Tetlow if [ -n "$fflag" ]; then 615c535eb59SGordon Tetlow do_whatis "$@" 616c535eb59SGordon Tetlow exit 617c535eb59SGordon Tetlow fi 618c535eb59SGordon Tetlow 619c535eb59SGordon Tetlow if [ -n "$kflag" ]; then 620c535eb59SGordon Tetlow do_apropos "$@" 621c535eb59SGordon Tetlow exit 622c535eb59SGordon Tetlow fi 623c535eb59SGordon Tetlow} 624c535eb59SGordon Tetlow 625c535eb59SGordon Tetlow# Usage: man_setup 626c535eb59SGordon Tetlow# Setup various trivial but essential variables. 627c535eb59SGordon Tetlowman_setup() { 628c535eb59SGordon Tetlow # Setup machine and architecture variables. 629c535eb59SGordon Tetlow if [ -n "$mflag" ]; then 630c535eb59SGordon Tetlow MACHINE_ARCH=${mflag%%:*} 631c535eb59SGordon Tetlow MACHINE=${mflag##*:} 632c535eb59SGordon Tetlow fi 633c535eb59SGordon Tetlow if [ -z "$MACHINE_ARCH" ]; then 63482db8a5eSGordon Tetlow MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 635c535eb59SGordon Tetlow fi 636c535eb59SGordon Tetlow if [ -z "$MACHINE" ]; then 63782db8a5eSGordon Tetlow MACHINE=$($SYSCTL -n hw.machine) 638c535eb59SGordon Tetlow fi 639c535eb59SGordon Tetlow decho "Using architecture: $MACHINE_ARCH:$MACHINE" 640c535eb59SGordon Tetlow 641c535eb59SGordon Tetlow setup_pager 642c535eb59SGordon Tetlow build_manpath 643*8edb6fb5SMohamed Akram build_mansect 644c535eb59SGordon Tetlow man_setup_locale 645a0094449SRuslan Ermilov man_setup_width 646a0094449SRuslan Ermilov} 647a0094449SRuslan Ermilov 648a0094449SRuslan Ermilov# Usage: man_setup_width 649a0094449SRuslan Ermilov# Set up page width. 650a0094449SRuslan Ermilovman_setup_width() { 651a0094449SRuslan Ermilov local sizes 652a0094449SRuslan Ermilov 653a0094449SRuslan Ermilov unset use_width 654a0094449SRuslan Ermilov case "$MANWIDTH" in 655a0094449SRuslan Ermilov [0-9]*) 656a0094449SRuslan Ermilov if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 657a0094449SRuslan Ermilov use_width=$MANWIDTH 658a0094449SRuslan Ermilov fi 659a0094449SRuslan Ermilov ;; 660a0094449SRuslan Ermilov [Tt][Tt][Yy]) 661a0094449SRuslan Ermilov if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 662a0094449SRuslan Ermilov set -- $sizes 663a0094449SRuslan Ermilov if [ $2 -gt 80 ]; then 664a0094449SRuslan Ermilov use_width=$(($2-2)) 665a0094449SRuslan Ermilov fi 666a0094449SRuslan Ermilov fi 667a0094449SRuslan Ermilov ;; 668a0094449SRuslan Ermilov esac 669a0094449SRuslan Ermilov if [ -n "$use_width" ]; then 670a0094449SRuslan Ermilov decho "Using non-standard page width: ${use_width}" 671a0094449SRuslan Ermilov else 672a0094449SRuslan Ermilov decho 'Using standard page width' 673a0094449SRuslan Ermilov fi 674c535eb59SGordon Tetlow} 675c535eb59SGordon Tetlow 676c535eb59SGordon Tetlow# Usage: man_setup_locale 677c535eb59SGordon Tetlow# Setup necessary locale variables. 678c535eb59SGordon Tetlowman_setup_locale() { 679deeff310SGordon Tetlow local lang_cc 6809508f8c0SYuri Pankov local locstr 681deeff310SGordon Tetlow 682deeff310SGordon Tetlow locpaths='.' 683deeff310SGordon Tetlow man_charset='US-ASCII' 684deeff310SGordon Tetlow 685c535eb59SGordon Tetlow # Setup locale information. 686c535eb59SGordon Tetlow if [ -n "$oflag" ]; then 687deeff310SGordon Tetlow decho 'Using non-localized manpages' 688deeff310SGordon Tetlow else 6899508f8c0SYuri Pankov # Use the locale tool to give us proper locale information 690deeff310SGordon Tetlow eval $( $LOCALE ) 691c535eb59SGordon Tetlow 6929508f8c0SYuri Pankov if [ -n "$LANG" ]; then 6939508f8c0SYuri Pankov locstr=$LANG 6949508f8c0SYuri Pankov else 6959508f8c0SYuri Pankov locstr=$LC_CTYPE 6969508f8c0SYuri Pankov fi 6979508f8c0SYuri Pankov 6989508f8c0SYuri Pankov case "$locstr" in 699deeff310SGordon Tetlow C) ;; 7009508f8c0SYuri Pankov C.UTF-8) ;; 701deeff310SGordon Tetlow POSIX) ;; 702deeff310SGordon Tetlow [a-z][a-z]_[A-Z][A-Z]\.*) 7039508f8c0SYuri Pankov lang_cc="${locstr%.*}" 7049508f8c0SYuri Pankov man_lang="${locstr%_*}" 705deeff310SGordon Tetlow man_country="${lang_cc#*_}" 7069508f8c0SYuri Pankov man_charset="${locstr#*.}" 7079508f8c0SYuri Pankov locpaths="$locstr" 708c535eb59SGordon Tetlow locpaths="$locpaths:$man_lang.$man_charset" 709c535eb59SGordon Tetlow if [ "$man_lang" != "en" ]; then 710c535eb59SGordon Tetlow locpaths="$locpaths:en.$man_charset" 711c535eb59SGordon Tetlow fi 712c535eb59SGordon Tetlow locpaths="$locpaths:." 713deeff310SGordon Tetlow ;; 714deeff310SGordon Tetlow *) echo 'Unknown locale, assuming C' >&2 715deeff310SGordon Tetlow ;; 716deeff310SGordon Tetlow esac 717c535eb59SGordon Tetlow fi 718deeff310SGordon Tetlow 719c535eb59SGordon Tetlow decho "Using locale paths: $locpaths" 720c535eb59SGordon Tetlow} 721c535eb59SGordon Tetlow 722c535eb59SGordon Tetlow# Usage: man_usage [exitcode] 723c535eb59SGordon Tetlow# Display usage for the man utility. 724c535eb59SGordon Tetlowman_usage() { 725c535eb59SGordon Tetlow echo 'Usage:' 7261594084fSFernando Apesteguía echo ' man [-adho] [-t | -w] [-K regexp] [-M manpath] [-P pager] [-S mansect]' 727c535eb59SGordon Tetlow echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 728c535eb59SGordon Tetlow echo ' man -f page [...] -- Emulates whatis(1)' 729c535eb59SGordon Tetlow echo ' man -k page [...] -- Emulates apropos(1)' 730c535eb59SGordon Tetlow 731c535eb59SGordon Tetlow # When exit'ing with -h, it's not an error. 732c535eb59SGordon Tetlow exit ${1:-1} 733c535eb59SGordon Tetlow} 734c535eb59SGordon Tetlow 735c535eb59SGordon Tetlow# Usage: parse_configs 736c535eb59SGordon Tetlow# Reads the end-user adjustable config files. 737c535eb59SGordon Tetlowparse_configs() { 738c535eb59SGordon Tetlow local IFS file files 739c535eb59SGordon Tetlow 740c535eb59SGordon Tetlow if [ -n "$parsed_configs" ]; then 741c535eb59SGordon Tetlow return 742c535eb59SGordon Tetlow fi 743c535eb59SGordon Tetlow 744c535eb59SGordon Tetlow unset IFS 745c535eb59SGordon Tetlow 746c535eb59SGordon Tetlow # Read the global config first in case the user wants 747c535eb59SGordon Tetlow # to override config_local. 748c535eb59SGordon Tetlow if [ -r "$config_global" ]; then 749c535eb59SGordon Tetlow parse_file "$config_global" 750c535eb59SGordon Tetlow fi 751c535eb59SGordon Tetlow 752c535eb59SGordon Tetlow # Glob the list of files to parse. 753c535eb59SGordon Tetlow set +f 754c535eb59SGordon Tetlow files=$(echo $config_local) 755c535eb59SGordon Tetlow set -f 756c535eb59SGordon Tetlow 757c535eb59SGordon Tetlow for file in $files; do 758c535eb59SGordon Tetlow if [ -r "$file" ]; then 759c535eb59SGordon Tetlow parse_file "$file" 760c535eb59SGordon Tetlow fi 761c535eb59SGordon Tetlow done 762c535eb59SGordon Tetlow 763c535eb59SGordon Tetlow parsed_configs='yes' 764c535eb59SGordon Tetlow} 765c535eb59SGordon Tetlow 766c535eb59SGordon Tetlow# Usage: parse_file file 767c535eb59SGordon Tetlow# Reads the specified config files. 768c535eb59SGordon Tetlowparse_file() { 769c535eb59SGordon Tetlow local file line tstr var 770c535eb59SGordon Tetlow 771c535eb59SGordon Tetlow file="$1" 772c535eb59SGordon Tetlow decho "Parsing config file: $file" 773c535eb59SGordon Tetlow while read line; do 774c535eb59SGordon Tetlow decho " $line" 2 775c535eb59SGordon Tetlow case "$line" in 776c535eb59SGordon Tetlow \#*) decho " Comment" 3 777c535eb59SGordon Tetlow ;; 778c535eb59SGordon Tetlow MANPATH*) decho " MANPATH" 3 779c535eb59SGordon Tetlow trim "${line#MANPATH}" 780c535eb59SGordon Tetlow add_to_manpath "$tstr" 781c535eb59SGordon Tetlow ;; 782c535eb59SGordon Tetlow MANLOCALE*) decho " MANLOCALE" 3 783c535eb59SGordon Tetlow trim "${line#MANLOCALE}" 784c535eb59SGordon Tetlow manlocales="$manlocales:$tstr" 785c535eb59SGordon Tetlow ;; 786c535eb59SGordon Tetlow MANCONFIG*) decho " MANCONFIG" 3 787a1528c80SRuslan Ermilov trim "${line#MANCONFIG}" 788c535eb59SGordon Tetlow config_local="$tstr" 789c535eb59SGordon Tetlow ;; 790*8edb6fb5SMohamed Akram MANSECT*) decho " MANSECT" 3 791*8edb6fb5SMohamed Akram trim "${line#MANSECT}" 792*8edb6fb5SMohamed Akram mansect="$mansect:$tstr" 793*8edb6fb5SMohamed Akram ;; 794c535eb59SGordon Tetlow # Set variables in the form of FOO_BAR 795c535eb59SGordon Tetlow *_*[\ \ ]*) var="${line%%[\ \ ]*}" 796c535eb59SGordon Tetlow trim "${line#$var}" 797c535eb59SGordon Tetlow eval "$var=\"$tstr\"" 798c535eb59SGordon Tetlow decho " Parsed $var" 3 799c535eb59SGordon Tetlow ;; 800c535eb59SGordon Tetlow esac 801c535eb59SGordon Tetlow done < "$file" 802c535eb59SGordon Tetlow} 803c535eb59SGordon Tetlow 804c535eb59SGordon Tetlow# Usage: search_path 805c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths. 806c535eb59SGordon Tetlowsearch_path() { 807c535eb59SGordon Tetlow local IFS p path 808c535eb59SGordon Tetlow 809c535eb59SGordon Tetlow decho "Searching PATH for man directories" 810c535eb59SGordon Tetlow 811c535eb59SGordon Tetlow IFS=: 812c535eb59SGordon Tetlow for path in $PATH; do 813971c1c42STijl Coosemans if add_to_manpath "$path/man"; then 814c535eb59SGordon Tetlow : 815c535eb59SGordon Tetlow elif add_to_manpath "$path/MAN"; then 816c535eb59SGordon Tetlow : 817c535eb59SGordon Tetlow else 818c535eb59SGordon Tetlow case "$path" in 819971c1c42STijl Coosemans */bin) p="${path%/bin}/share/man" 820c535eb59SGordon Tetlow add_to_manpath "$p" 821971c1c42STijl Coosemans p="${path%/bin}/man" 82261d5f2d1SBaptiste Daroussin add_to_manpath "$p" 823c535eb59SGordon Tetlow ;; 824c535eb59SGordon Tetlow esac 825c535eb59SGordon Tetlow fi 826c535eb59SGordon Tetlow done 827c535eb59SGordon Tetlow unset IFS 828c535eb59SGordon Tetlow 829c535eb59SGordon Tetlow if [ -z "$manpath" ]; then 830c535eb59SGordon Tetlow decho ' Unable to find any manpaths, using default' 831c535eb59SGordon Tetlow manpath=$man_default_path 832c535eb59SGordon Tetlow fi 833c535eb59SGordon Tetlow} 834c535eb59SGordon Tetlow 835c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist] 836c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis 837c535eb59SGordon Tetlowsearch_whatis() { 838c535eb59SGordon Tetlow local IFS bad cmd f good key keywords loc opt out path rval wlist 839c535eb59SGordon Tetlow 840c535eb59SGordon Tetlow cmd="$1" 841c535eb59SGordon Tetlow shift 842c535eb59SGordon Tetlow 843c535eb59SGordon Tetlow whatis_parse_args "$@" 844c535eb59SGordon Tetlow 845c535eb59SGordon Tetlow build_manpath 846c535eb59SGordon Tetlow build_manlocales 847c535eb59SGordon Tetlow setup_pager 848c535eb59SGordon Tetlow 849c535eb59SGordon Tetlow if [ "$cmd" = "whatis" ]; then 850c535eb59SGordon Tetlow opt="-w" 851c535eb59SGordon Tetlow fi 852c535eb59SGordon Tetlow 853c535eb59SGordon Tetlow f='whatis' 854c535eb59SGordon Tetlow 855c535eb59SGordon Tetlow IFS=: 856c535eb59SGordon Tetlow for path in $MANPATH; do 857c535eb59SGordon Tetlow if [ \! -d "$path" ]; then 858c535eb59SGordon Tetlow decho "Skipping non-existent path: $path" 2 859c535eb59SGordon Tetlow continue 860c535eb59SGordon Tetlow fi 861c535eb59SGordon Tetlow 862c535eb59SGordon Tetlow if [ -f "$path/$f" -a -r "$path/$f" ]; then 863c535eb59SGordon Tetlow decho "Found whatis: $path/$f" 864c535eb59SGordon Tetlow wlist="$wlist $path/$f" 865c535eb59SGordon Tetlow fi 866c535eb59SGordon Tetlow 867c535eb59SGordon Tetlow for loc in $MANLOCALES; do 868c535eb59SGordon Tetlow if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 869c535eb59SGordon Tetlow decho "Found whatis: $path/$loc/$f" 870c535eb59SGordon Tetlow wlist="$wlist $path/$loc/$f" 871c535eb59SGordon Tetlow fi 872c535eb59SGordon Tetlow done 873c535eb59SGordon Tetlow done 874c535eb59SGordon Tetlow unset IFS 875c535eb59SGordon Tetlow 876c535eb59SGordon Tetlow if [ -z "$wlist" ]; then 877c535eb59SGordon Tetlow echo "$cmd: no whatis databases in $MANPATH" >&2 878c535eb59SGordon Tetlow exit 1 879c535eb59SGordon Tetlow fi 880c535eb59SGordon Tetlow 881c535eb59SGordon Tetlow rval=0 882c535eb59SGordon Tetlow for key in $keywords; do 883c535eb59SGordon Tetlow out=$(grep -Ehi $opt -- "$key" $wlist) 884c535eb59SGordon Tetlow if [ -n "$out" ]; then 885c535eb59SGordon Tetlow good="$good\\n$out" 886c535eb59SGordon Tetlow else 887c535eb59SGordon Tetlow bad="$bad\\n$key: nothing appropriate" 888c535eb59SGordon Tetlow rval=1 889c535eb59SGordon Tetlow fi 890c535eb59SGordon Tetlow done 891c535eb59SGordon Tetlow 892c535eb59SGordon Tetlow # Strip leading carriage return. 893c535eb59SGordon Tetlow good=${good#\\n} 894c535eb59SGordon Tetlow bad=${bad#\\n} 895c535eb59SGordon Tetlow 896c535eb59SGordon Tetlow if [ -n "$good" ]; then 897a6a3e856SRuslan Ermilov echo -e "$good" | $MANPAGER 898c535eb59SGordon Tetlow fi 899c535eb59SGordon Tetlow 900c535eb59SGordon Tetlow if [ -n "$bad" ]; then 90100e05e69SGordon Tetlow echo -e "$bad" >&2 902c535eb59SGordon Tetlow fi 903c535eb59SGordon Tetlow 904c535eb59SGordon Tetlow exit $rval 905c535eb59SGordon Tetlow} 906c535eb59SGordon Tetlow 90757cd9717SGordon Tetlow# Usage: setup_cattool page 90857cd9717SGordon Tetlow# Finds an appropriate decompressor based on extension 90957cd9717SGordon Tetlowsetup_cattool() { 91057cd9717SGordon Tetlow case "$1" in 91157cd9717SGordon Tetlow *.bz) cattool='/usr/bin/bzcat' ;; 91257cd9717SGordon Tetlow *.bz2) cattool='/usr/bin/bzcat' ;; 91357cd9717SGordon Tetlow *.gz) cattool='/usr/bin/zcat' ;; 91457cd9717SGordon Tetlow *.lzma) cattool='/usr/bin/lzcat' ;; 91557cd9717SGordon Tetlow *.xz) cattool='/usr/bin/xzcat' ;; 916c8abb673SCameron Katri *.zst) cattool='/usr/bin/zstdcat' ;; 91757cd9717SGordon Tetlow *) cattool='/usr/bin/zcat -f' ;; 91857cd9717SGordon Tetlow esac 91957cd9717SGordon Tetlow} 92057cd9717SGordon Tetlow 921c535eb59SGordon Tetlow# Usage: setup_pager 922a6a3e856SRuslan Ermilov# Correctly sets $MANPAGER 923c535eb59SGordon Tetlowsetup_pager() { 924c535eb59SGordon Tetlow # Setup pager. 925a6a3e856SRuslan Ermilov if [ -z "$MANPAGER" ]; then 926a6a3e856SRuslan Ermilov if [ -n "$MANCOLOR" ]; then 927a6a3e856SRuslan Ermilov MANPAGER="less -sR" 928a6a3e856SRuslan Ermilov else 929a6a3e856SRuslan Ermilov if [ -n "$PAGER" ]; then 930a6a3e856SRuslan Ermilov MANPAGER="$PAGER" 931a6a3e856SRuslan Ermilov else 93247cc9ee1SAlan Somers MANPAGER="less -s" 933c535eb59SGordon Tetlow fi 934a6a3e856SRuslan Ermilov fi 935a6a3e856SRuslan Ermilov fi 936a6a3e856SRuslan Ermilov decho "Using pager: $MANPAGER" 937c535eb59SGordon Tetlow} 938c535eb59SGordon Tetlow 939c535eb59SGordon Tetlow# Usage: trim string 940c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable 941c535eb59SGordon Tetlowtrim() { 942c535eb59SGordon Tetlow tstr=$1 943c535eb59SGordon Tetlow while true; do 944c535eb59SGordon Tetlow case "$tstr" in 945c535eb59SGordon Tetlow [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 946c535eb59SGordon Tetlow *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 947c535eb59SGordon Tetlow *) break ;; 948c535eb59SGordon Tetlow esac 949c535eb59SGordon Tetlow done 950c535eb59SGordon Tetlow} 951c535eb59SGordon Tetlow 952c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@" 953c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos. 954c535eb59SGordon Tetlowwhatis_parse_args() { 955c535eb59SGordon Tetlow local cmd_arg 956f555b39eSKyle Evans OPTIND=1 957c535eb59SGordon Tetlow while getopts 'd' cmd_arg; do 958c535eb59SGordon Tetlow case "${cmd_arg}" in 959c535eb59SGordon Tetlow d) debug=$(( $debug + 1 )) ;; 960c535eb59SGordon Tetlow *) whatis_usage ;; 961c535eb59SGordon Tetlow esac 962c535eb59SGordon Tetlow done >&2 963c535eb59SGordon Tetlow 964c535eb59SGordon Tetlow shift $(( $OPTIND - 1 )) 965c535eb59SGordon Tetlow 966c535eb59SGordon Tetlow keywords="$*" 967c535eb59SGordon Tetlow} 968c535eb59SGordon Tetlow 969c535eb59SGordon Tetlow# Usage: whatis_usage 970c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility. 971c535eb59SGordon Tetlowwhatis_usage() { 972c535eb59SGordon Tetlow echo "usage: $cmd [-d] keyword [...]" 973c535eb59SGordon Tetlow exit 1 974c535eb59SGordon Tetlow} 975c535eb59SGordon Tetlow 976c535eb59SGordon Tetlow 977c535eb59SGordon Tetlow 978c535eb59SGordon Tetlow# Supported commands 979c535eb59SGordon Tetlowdo_apropos() { 98024ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 981772246efSBaptiste Daroussin exec apropos "$@" 982c535eb59SGordon Tetlow search_whatis apropos "$@" 983c535eb59SGordon Tetlow} 984c535eb59SGordon Tetlow 9851594084fSFernando Apesteguía# Usage: do_full_search reg_exp 9861594084fSFernando Apesteguía# Do a full search of the regular expression passed 9871594084fSFernando Apesteguía# as parameter in all man pages 9881594084fSFernando Apesteguíado_full_search() { 9891594084fSFernando Apesteguía local gflags re 9901594084fSFernando Apesteguía re=${1} 9911594084fSFernando Apesteguía 9921594084fSFernando Apesteguía # Build grep(1) flags 9931594084fSFernando Apesteguía gflags="-H" 9941594084fSFernando Apesteguía 9951594084fSFernando Apesteguía # wflag implies -l for grep(1) 9961594084fSFernando Apesteguía if [ -n "$wflag" ]; then 9971594084fSFernando Apesteguía gflags="${gflags} -l" 9981594084fSFernando Apesteguía fi 9991594084fSFernando Apesteguía 10001594084fSFernando Apesteguía gflags="${gflags} --label" 10011594084fSFernando Apesteguía 10021594084fSFernando Apesteguía set +f 10031594084fSFernando Apesteguía for mpath in $(echo "${MANPATH}" | tr : [:blank:]); do 10041594084fSFernando Apesteguía for section in $(echo "${MANSECT}" | tr : [:blank:]); do 10051594084fSFernando Apesteguía for manfile in ${mpath}/man${section}/*.${section}*; do 10061594084fSFernando Apesteguía mandoc "${manfile}" 2>/dev/null | 10071594084fSFernando Apesteguía grep -E ${gflags} "${manfile}" -e ${re} 10081594084fSFernando Apesteguía done 10091594084fSFernando Apesteguía done 10101594084fSFernando Apesteguía done 10111594084fSFernando Apesteguía set -f 10121594084fSFernando Apesteguía} 10131594084fSFernando Apesteguía 1014c535eb59SGordon Tetlowdo_man() { 1015*8edb6fb5SMohamed Akram local IFS 1016*8edb6fb5SMohamed Akram 1017*8edb6fb5SMohamed Akram man_parse_opts "$@" 1018*8edb6fb5SMohamed Akram man_setup 1019*8edb6fb5SMohamed Akram 1020*8edb6fb5SMohamed Akram shift $(( $OPTIND - 1 )) 1021*8edb6fb5SMohamed Akram IFS=: 1022*8edb6fb5SMohamed Akram for sect in $MANSECT; do 1023*8edb6fb5SMohamed Akram if [ "$sect" = "$1" ]; then 1024*8edb6fb5SMohamed Akram decho "Detected manual section as first arg: $1" 1025*8edb6fb5SMohamed Akram MANSECT="$1" 1026*8edb6fb5SMohamed Akram shift 1027*8edb6fb5SMohamed Akram break 1028*8edb6fb5SMohamed Akram fi 1029*8edb6fb5SMohamed Akram done 1030*8edb6fb5SMohamed Akram unset IFS 1031*8edb6fb5SMohamed Akram pages="$*" 1032*8edb6fb5SMohamed Akram 10331594084fSFernando Apesteguía if [ -z "$pages" -a -z "${Kflag}" ]; then 1034c535eb59SGordon Tetlow echo 'What manual page do you want?' >&2 1035c535eb59SGordon Tetlow exit 1 1036c535eb59SGordon Tetlow fi 1037c535eb59SGordon Tetlow 10381594084fSFernando Apesteguía if [ ! -z "${Kflag}" ]; then 10391594084fSFernando Apesteguía # Short circuit because -K flag does a sufficiently 10401594084fSFernando Apesteguía # different thing like not showing the man page at all 10411594084fSFernando Apesteguía do_full_search "${REGEXP}" 10421594084fSFernando Apesteguía fi 10431594084fSFernando Apesteguía 1044c535eb59SGordon Tetlow for page in $pages; do 1045c535eb59SGordon Tetlow decho "Searching for $page" 1046c535eb59SGordon Tetlow man_find_and_display "$page" 1047c535eb59SGordon Tetlow done 1048c535eb59SGordon Tetlow 1049c535eb59SGordon Tetlow exit ${ret:-0} 1050c535eb59SGordon Tetlow} 1051c535eb59SGordon Tetlow 1052c535eb59SGordon Tetlowdo_manpath() { 1053c535eb59SGordon Tetlow manpath_parse_args "$@" 1054c535eb59SGordon Tetlow if [ -z "$qflag" ]; then 1055c535eb59SGordon Tetlow manpath_warnings 1056c535eb59SGordon Tetlow fi 1057c535eb59SGordon Tetlow if [ -n "$Lflag" ]; then 1058c535eb59SGordon Tetlow build_manlocales 1059c535eb59SGordon Tetlow echo $MANLOCALES 1060c535eb59SGordon Tetlow else 1061c535eb59SGordon Tetlow build_manpath 1062c535eb59SGordon Tetlow echo $MANPATH 1063c535eb59SGordon Tetlow fi 1064c535eb59SGordon Tetlow exit 0 1065c535eb59SGordon Tetlow} 1066c535eb59SGordon Tetlow 1067c535eb59SGordon Tetlowdo_whatis() { 106824ef7420SBaptiste Daroussin [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 1069772246efSBaptiste Daroussin exec whatis "$@" 1070c535eb59SGordon Tetlow search_whatis whatis "$@" 1071c535eb59SGordon Tetlow} 1072c535eb59SGordon Tetlow 1073aeea395eSUlrich Spörlein# User's PATH setting decides on the groff-suite to pick up. 1074aeea395eSUlrich SpörleinEQN=eqn 1075a6a3e856SRuslan ErmilovNROFF='groff -S -P-h -Wall -mtty-char -man' 1076aeea395eSUlrich SpörleinPIC=pic 1077aeea395eSUlrich SpörleinREFER=refer 1078aeea395eSUlrich SpörleinTBL=tbl 10793d120968SUlrich SpörleinTROFF='groff -S -man' 1080aeea395eSUlrich SpörleinVGRIND=vgrind 1081aeea395eSUlrich Spörlein 1082deeff310SGordon TetlowLOCALE=/usr/bin/locale 1083a0094449SRuslan ErmilovSTTY=/bin/stty 108482db8a5eSGordon TetlowSYSCTL=/sbin/sysctl 1085c535eb59SGordon Tetlow 1086c535eb59SGordon Tetlowdebug=0 108773577bf0SRyan Moellerman_default_sections='1:8:2:3:3lua:n:4:5:6:7:9:l' 1088971c1c42STijl Coosemansman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man' 108957cd9717SGordon Tetlowcattool='/usr/bin/zcat -f' 1090c535eb59SGordon Tetlow 1091c535eb59SGordon Tetlowconfig_global='/etc/man.conf' 1092c535eb59SGordon Tetlow 1093c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf. 1094c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf' 1095c535eb59SGordon Tetlow 1096c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing. 1097c535eb59SGordon Tetlowset -f 1098c535eb59SGordon Tetlow 1099c535eb59SGordon Tetlowcase "$0" in 1100c535eb59SGordon Tetlow*apropos) do_apropos "$@" ;; 1101c535eb59SGordon Tetlow*manpath) do_manpath "$@" ;; 1102c535eb59SGordon Tetlow*whatis) do_whatis "$@" ;; 1103c535eb59SGordon Tetlow*) do_man "$@" ;; 1104c535eb59SGordon Tetlowesac 1105