1cde00b53SSascha Wildner#! /bin/sh 2cde00b53SSascha Wildner# 3cde00b53SSascha Wildner# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4cde00b53SSascha Wildner# 5cde00b53SSascha Wildner# Copyright (c) 2010 Gordon Tetlow 6cde00b53SSascha Wildner# All rights reserved. 7cde00b53SSascha Wildner# 8cde00b53SSascha Wildner# Redistribution and use in source and binary forms, with or without 9cde00b53SSascha Wildner# modification, are permitted provided that the following conditions 10cde00b53SSascha Wildner# are met: 11cde00b53SSascha Wildner# 1. Redistributions of source code must retain the above copyright 12cde00b53SSascha Wildner# notice, this list of conditions and the following disclaimer. 13cde00b53SSascha Wildner# 2. Redistributions in binary form must reproduce the above copyright 14cde00b53SSascha Wildner# notice, this list of conditions and the following disclaimer in the 15cde00b53SSascha Wildner# documentation and/or other materials provided with the distribution. 16cde00b53SSascha Wildner# 17cde00b53SSascha Wildner# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18cde00b53SSascha Wildner# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19cde00b53SSascha Wildner# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20cde00b53SSascha Wildner# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21cde00b53SSascha Wildner# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22cde00b53SSascha Wildner# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23cde00b53SSascha Wildner# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24cde00b53SSascha Wildner# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25cde00b53SSascha Wildner# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26cde00b53SSascha Wildner# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27cde00b53SSascha Wildner# SUCH DAMAGE. 28cde00b53SSascha Wildner# 29cde00b53SSascha Wildner# $FreeBSD: head/usr.bin/man/man.sh 340128 2018-11-04 16:58:55Z yuripv $ 30cde00b53SSascha Wildner 31cde00b53SSascha Wildner# Usage: add_to_manpath path 32cde00b53SSascha Wildner# Adds a variable to manpath while ensuring we don't have duplicates. 33cde00b53SSascha Wildner# Returns true if we were able to add something. False otherwise. 34cde00b53SSascha Wildneradd_to_manpath() { 35cde00b53SSascha Wildner case "$manpath" in 36cde00b53SSascha Wildner *:$1) decho " Skipping duplicate manpath entry $1" 2 ;; 37cde00b53SSascha Wildner $1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 38cde00b53SSascha Wildner *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;; 39cde00b53SSascha Wildner *) if [ -d "$1" ]; then 40cde00b53SSascha Wildner decho " Adding $1 to manpath" 41cde00b53SSascha Wildner manpath="$manpath:$1" 42cde00b53SSascha Wildner return 0 43cde00b53SSascha Wildner fi 44cde00b53SSascha Wildner ;; 45cde00b53SSascha Wildner esac 46cde00b53SSascha Wildner 47cde00b53SSascha Wildner return 1 48cde00b53SSascha Wildner} 49cde00b53SSascha Wildner 50cde00b53SSascha Wildner# Usage: build_manlocales 51cde00b53SSascha Wildner# Builds a correct MANLOCALES variable. 52cde00b53SSascha Wildnerbuild_manlocales() { 53cde00b53SSascha Wildner # If the user has set manlocales, who are we to argue. 54cde00b53SSascha Wildner if [ -n "$MANLOCALES" ]; then 55cde00b53SSascha Wildner return 56cde00b53SSascha Wildner fi 57cde00b53SSascha Wildner 58cde00b53SSascha Wildner parse_configs 59cde00b53SSascha Wildner 60cde00b53SSascha Wildner # Trim leading colon 61cde00b53SSascha Wildner MANLOCALES=${manlocales#:} 62cde00b53SSascha Wildner 63cde00b53SSascha Wildner decho "Available manual locales: $MANLOCALES" 64cde00b53SSascha Wildner} 65cde00b53SSascha Wildner 66cde00b53SSascha Wildner# Usage: build_manpath 67cde00b53SSascha Wildner# Builds a correct MANPATH variable. 68cde00b53SSascha Wildnerbuild_manpath() { 69cde00b53SSascha Wildner local IFS 70cde00b53SSascha Wildner 71cde00b53SSascha Wildner # If the user has set a manpath, who are we to argue. 72cde00b53SSascha Wildner if [ -n "$MANPATH" ]; then 73cde00b53SSascha Wildner case "$MANPATH" in 74cde00b53SSascha Wildner *:) PREPEND_MANPATH=${MANPATH} ;; 75cde00b53SSascha Wildner :*) APPEND_MANPATH=${MANPATH} ;; 76cde00b53SSascha Wildner *::*) 77cde00b53SSascha Wildner PREPEND_MANPATH=${MANPATH%%::*} 78cde00b53SSascha Wildner APPEND_MANPATH=${MANPATH#*::} 79cde00b53SSascha Wildner ;; 80cde00b53SSascha Wildner *) return ;; 81cde00b53SSascha Wildner esac 82cde00b53SSascha Wildner fi 83cde00b53SSascha Wildner 84cde00b53SSascha Wildner if [ -n "$PREPEND_MANPATH" ]; then 85cde00b53SSascha Wildner IFS=: 86cde00b53SSascha Wildner for path in $PREPEND_MANPATH; do 87cde00b53SSascha Wildner add_to_manpath "$path" 88cde00b53SSascha Wildner done 89cde00b53SSascha Wildner unset IFS 90cde00b53SSascha Wildner fi 91cde00b53SSascha Wildner 92cde00b53SSascha Wildner search_path 93cde00b53SSascha Wildner 94cde00b53SSascha Wildner decho "Adding default manpath entries" 95cde00b53SSascha Wildner IFS=: 96cde00b53SSascha Wildner for path in $man_default_path; do 97cde00b53SSascha Wildner add_to_manpath "$path" 98cde00b53SSascha Wildner done 99cde00b53SSascha Wildner unset IFS 100cde00b53SSascha Wildner 101cde00b53SSascha Wildner parse_configs 102cde00b53SSascha Wildner 103cde00b53SSascha Wildner if [ -n "$APPEND_MANPATH" ]; then 104cde00b53SSascha Wildner IFS=: 105cde00b53SSascha Wildner for path in $APPEND_MANPATH; do 106cde00b53SSascha Wildner add_to_manpath "$path" 107cde00b53SSascha Wildner done 108cde00b53SSascha Wildner unset IFS 109cde00b53SSascha Wildner fi 110cde00b53SSascha Wildner # Trim leading colon 111cde00b53SSascha Wildner MANPATH=${manpath#:} 112cde00b53SSascha Wildner 113cde00b53SSascha Wildner decho "Using manual path: $MANPATH" 114cde00b53SSascha Wildner} 115cde00b53SSascha Wildner 116cde00b53SSascha Wildner# Usage: check_cat catglob 117cde00b53SSascha Wildner# Checks to see if a cat glob is available. 118cde00b53SSascha Wildnercheck_cat() { 119cde00b53SSascha Wildner if exists "$1"; then 120cde00b53SSascha Wildner use_cat=yes 121cde00b53SSascha Wildner catpage=$found 122cde00b53SSascha Wildner setup_cattool $catpage 123cde00b53SSascha Wildner decho " Found catpage $catpage" 124cde00b53SSascha Wildner return 0 125cde00b53SSascha Wildner else 126cde00b53SSascha Wildner return 1 127cde00b53SSascha Wildner fi 128cde00b53SSascha Wildner} 129cde00b53SSascha Wildner 130cde00b53SSascha Wildner# Usage: check_man manglob catglob 131cde00b53SSascha Wildner# Given 2 globs, figures out if the manglob is available, if so, check to 132cde00b53SSascha Wildner# see if the catglob is also available and up to date. 133cde00b53SSascha Wildnercheck_man() { 134cde00b53SSascha Wildner if exists "$1"; then 135cde00b53SSascha Wildner # We have a match, check for a cat page 136cde00b53SSascha Wildner manpage=$found 137cde00b53SSascha Wildner setup_cattool $manpage 138cde00b53SSascha Wildner decho " Found manpage $manpage" 139cde00b53SSascha Wildner 140cde00b53SSascha Wildner if [ -n "${use_width}" ]; then 141cde00b53SSascha Wildner # non-standard width 142cde00b53SSascha Wildner unset use_cat 143cde00b53SSascha Wildner decho " Skipping catpage: non-standard page width" 144cde00b53SSascha Wildner elif exists "$2" && is_newer $found $manpage; then 145cde00b53SSascha Wildner # cat page found and is newer, use that 146cde00b53SSascha Wildner use_cat=yes 147cde00b53SSascha Wildner catpage=$found 148cde00b53SSascha Wildner setup_cattool $catpage 149cde00b53SSascha Wildner decho " Using catpage $catpage" 150cde00b53SSascha Wildner else 151cde00b53SSascha Wildner # no cat page or is older 152cde00b53SSascha Wildner unset use_cat 153cde00b53SSascha Wildner decho " Skipping catpage: not found or old" 154cde00b53SSascha Wildner fi 155cde00b53SSascha Wildner return 0 156cde00b53SSascha Wildner fi 157cde00b53SSascha Wildner 158cde00b53SSascha Wildner return 1 159cde00b53SSascha Wildner} 160cde00b53SSascha Wildner 161cde00b53SSascha Wildner# Usage: decho "string" [debuglevel] 162cde00b53SSascha Wildner# Echoes to stderr string prefaced with -- if high enough debuglevel. 163cde00b53SSascha Wildnerdecho() { 164cde00b53SSascha Wildner if [ $debug -ge ${2:-1} ]; then 165cde00b53SSascha Wildner echo "-- $1" >&2 166cde00b53SSascha Wildner fi 167cde00b53SSascha Wildner} 168cde00b53SSascha Wildner 169cde00b53SSascha Wildner# Usage: exists glob 170cde00b53SSascha Wildner# Returns true if glob resolves to a real file. 171cde00b53SSascha Wildnerexists() { 172cde00b53SSascha Wildner local IFS 173cde00b53SSascha Wildner 174cde00b53SSascha Wildner # Don't accidentally inherit callers IFS (breaks perl manpages) 175cde00b53SSascha Wildner unset IFS 176cde00b53SSascha Wildner 177cde00b53SSascha Wildner # Use some globbing tricks in the shell to determine if a file 178cde00b53SSascha Wildner # exists or not. 179cde00b53SSascha Wildner set +f 180cde00b53SSascha Wildner set -- "$1" $1 181cde00b53SSascha Wildner set -f 182cde00b53SSascha Wildner 183cde00b53SSascha Wildner if [ "$1" != "$2" -a -r "$2" ]; then 184cde00b53SSascha Wildner found="$2" 185cde00b53SSascha Wildner return 0 186cde00b53SSascha Wildner fi 187cde00b53SSascha Wildner 188cde00b53SSascha Wildner return 1 189cde00b53SSascha Wildner} 190cde00b53SSascha Wildner 191cde00b53SSascha Wildner# Usage: find_file path section subdir pagename 192cde00b53SSascha Wildner# Returns: true if something is matched and found. 193cde00b53SSascha Wildner# Search the given path/section combo for a given page. 194cde00b53SSascha Wildnerfind_file() { 195cde00b53SSascha Wildner local manroot catroot mann man0 catn cat0 196cde00b53SSascha Wildner 197cde00b53SSascha Wildner manroot="$1/man$2" 198cde00b53SSascha Wildner catroot="$1/cat$2" 199cde00b53SSascha Wildner if [ -n "$3" ]; then 200cde00b53SSascha Wildner manroot="$manroot/$3" 201cde00b53SSascha Wildner catroot="$catroot/$3" 202cde00b53SSascha Wildner fi 203cde00b53SSascha Wildner 204cde00b53SSascha Wildner if [ ! -d "$manroot" -a ! -d "$catroot" ]; then 205cde00b53SSascha Wildner return 1 206cde00b53SSascha Wildner fi 207cde00b53SSascha Wildner decho " Searching directory $manroot" 2 208cde00b53SSascha Wildner 209cde00b53SSascha Wildner mann="$manroot/$4.$2*" 210cde00b53SSascha Wildner man0="$manroot/$4.0*" 211cde00b53SSascha Wildner catn="$catroot/$4.$2*" 212cde00b53SSascha Wildner cat0="$catroot/$4.0*" 213cde00b53SSascha Wildner 214cde00b53SSascha Wildner # This is the behavior as seen by the original man utility. 215cde00b53SSascha Wildner # Let's not change that which doesn't seem broken. 216cde00b53SSascha Wildner if check_man "$mann" "$catn"; then 217cde00b53SSascha Wildner return 0 218cde00b53SSascha Wildner elif check_man "$man0" "$cat0"; then 219cde00b53SSascha Wildner return 0 220cde00b53SSascha Wildner elif check_cat "$catn"; then 221cde00b53SSascha Wildner return 0 222cde00b53SSascha Wildner elif check_cat "$cat0"; then 223cde00b53SSascha Wildner return 0 224cde00b53SSascha Wildner fi 225cde00b53SSascha Wildner 226cde00b53SSascha Wildner return 1 227cde00b53SSascha Wildner} 228cde00b53SSascha Wildner 229cde00b53SSascha Wildner# Usage: is_newer file1 file2 230cde00b53SSascha Wildner# Returns true if file1 is newer than file2 as calculated by mtime. 231cde00b53SSascha Wildneris_newer() { 232cde00b53SSascha Wildner if ! [ "$1" -ot "$2" ]; then 233cde00b53SSascha Wildner decho " mtime: $1 not older than $2" 3 234cde00b53SSascha Wildner return 0 235cde00b53SSascha Wildner else 236cde00b53SSascha Wildner decho " mtime: $1 older than $2" 3 237cde00b53SSascha Wildner return 1 238cde00b53SSascha Wildner fi 239cde00b53SSascha Wildner} 240cde00b53SSascha Wildner 241cde00b53SSascha Wildner# Usage: manpath_parse_args "$@" 242cde00b53SSascha Wildner# Parses commandline options for manpath. 243cde00b53SSascha Wildnermanpath_parse_args() { 244cde00b53SSascha Wildner local cmd_arg 245cde00b53SSascha Wildner 246cde00b53SSascha Wildner while getopts 'Ldq' cmd_arg; do 247cde00b53SSascha Wildner case "${cmd_arg}" in 248cde00b53SSascha Wildner L) Lflag=Lflag ;; 249cde00b53SSascha Wildner d) debug=$(( $debug + 1 )) ;; 250cde00b53SSascha Wildner q) qflag=qflag ;; 251cde00b53SSascha Wildner *) manpath_usage ;; 252cde00b53SSascha Wildner esac 253cde00b53SSascha Wildner done >&2 254cde00b53SSascha Wildner} 255cde00b53SSascha Wildner 256cde00b53SSascha Wildner# Usage: manpath_usage 257cde00b53SSascha Wildner# Display usage for the manpath(1) utility. 258cde00b53SSascha Wildnermanpath_usage() { 259cde00b53SSascha Wildner echo 'usage: manpath [-Ldq]' >&2 260cde00b53SSascha Wildner exit 1 261cde00b53SSascha Wildner} 262cde00b53SSascha Wildner 263cde00b53SSascha Wildner# Usage: manpath_warnings 264cde00b53SSascha Wildner# Display some warnings to stderr. 265cde00b53SSascha Wildnermanpath_warnings() { 266cde00b53SSascha Wildner if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then 267cde00b53SSascha Wildner echo "(Warning: MANLOCALES environment variable set)" >&2 268cde00b53SSascha Wildner fi 269cde00b53SSascha Wildner} 270cde00b53SSascha Wildner 271cde00b53SSascha Wildner# Usage: man_check_for_so page path 272cde00b53SSascha Wildner# Returns: True if able to resolve the file, false if it ended in tears. 273cde00b53SSascha Wildner# Detects the presence of the .so directive and causes the file to be 274cde00b53SSascha Wildner# redirected to another source file. 275cde00b53SSascha Wildnerman_check_for_so() { 276cde00b53SSascha Wildner local IFS line tstr 277cde00b53SSascha Wildner 278cde00b53SSascha Wildner unset IFS 279cde00b53SSascha Wildner if [ -n "$catpage" ]; then 280cde00b53SSascha Wildner return 0 281cde00b53SSascha Wildner fi 282cde00b53SSascha Wildner 283cde00b53SSascha Wildner # We need to loop to accommodate multiple .so directives. 284cde00b53SSascha Wildner while true 285cde00b53SSascha Wildner do 286cde00b53SSascha Wildner line=$($cattool $manpage | head -1) 287cde00b53SSascha Wildner case "$line" in 288cde00b53SSascha Wildner .so*) trim "${line#.so}" 289cde00b53SSascha Wildner decho "$manpage includes $tstr" 290cde00b53SSascha Wildner # Glob and check for the file. 291cde00b53SSascha Wildner if ! check_man "$path/$tstr*" ""; then 292cde00b53SSascha Wildner decho " Unable to find $tstr" 293cde00b53SSascha Wildner return 1 294cde00b53SSascha Wildner fi 295cde00b53SSascha Wildner ;; 296cde00b53SSascha Wildner *) break ;; 297cde00b53SSascha Wildner esac 298cde00b53SSascha Wildner done 299cde00b53SSascha Wildner 300cde00b53SSascha Wildner return 0 301cde00b53SSascha Wildner} 302cde00b53SSascha Wildner 303cde00b53SSascha Wildner# Usage: man_display_page 304cde00b53SSascha Wildner# Display either the manpage or catpage depending on the use_cat variable 305cde00b53SSascha Wildnerman_display_page() { 306cde00b53SSascha Wildner local IFS pipeline testline 307cde00b53SSascha Wildner 308cde00b53SSascha Wildner # We are called with IFS set to colon. This causes really weird 309cde00b53SSascha Wildner # things to happen for the variables that have spaces in them. 310cde00b53SSascha Wildner unset IFS 311cde00b53SSascha Wildner 312cde00b53SSascha Wildner # If we are supposed to use a catpage and we aren't using troff(1) 313cde00b53SSascha Wildner # just zcat the catpage and we are done. 314cde00b53SSascha Wildner if [ -z "$tflag" -a -n "$use_cat" ]; then 315cde00b53SSascha Wildner if [ -n "$wflag" ]; then 316cde00b53SSascha Wildner echo "$catpage (source: $manpage)" 317cde00b53SSascha Wildner ret=0 318cde00b53SSascha Wildner else 319cde00b53SSascha Wildner if [ $debug -gt 0 ]; then 320cde00b53SSascha Wildner decho "Command: $cattool $catpage | $MANPAGER" 321cde00b53SSascha Wildner ret=0 322cde00b53SSascha Wildner else 323cde00b53SSascha Wildner eval "$cattool $catpage | $MANPAGER" 324cde00b53SSascha Wildner ret=$? 325cde00b53SSascha Wildner fi 326cde00b53SSascha Wildner fi 327cde00b53SSascha Wildner return 328cde00b53SSascha Wildner fi 329cde00b53SSascha Wildner 330cde00b53SSascha Wildner # Okay, we are using the manpage, do we just need to output the 331cde00b53SSascha Wildner # name of the manpage? 332cde00b53SSascha Wildner if [ -n "$wflag" ]; then 333cde00b53SSascha Wildner echo "$manpage" 334cde00b53SSascha Wildner ret=0 335cde00b53SSascha Wildner return 336cde00b53SSascha Wildner fi 337cde00b53SSascha Wildner 338cde00b53SSascha Wildner if [ -n "$use_width" ]; then 339cde00b53SSascha Wildner mandoc_args="-O width=${use_width}" 340cde00b53SSascha Wildner fi 341cde00b53SSascha Wildner testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1" 342cde00b53SSascha Wildner if [ -n "$tflag" ]; then 343cde00b53SSascha Wildner pipeline="mandoc -Tps $mandoc_args" 344cde00b53SSascha Wildner else 345cde00b53SSascha Wildner pipeline="mandoc $mandoc_args | $MANPAGER" 346cde00b53SSascha Wildner fi 347cde00b53SSascha Wildner 348cde00b53SSascha Wildner if ! eval "$cattool $manpage | $testline" ;then 349cde00b53SSascha Wildner if which -s groff; then 350cde00b53SSascha Wildner man_display_page_groff 351cde00b53SSascha Wildner else 352cde00b53SSascha Wildner echo "This manpage needs groff(1) to be rendered" >&2 353cde00b53SSascha Wildner echo "First install groff(1): " >&2 354cde00b53SSascha Wildner echo "pkg install groff " >&2 355cde00b53SSascha Wildner ret=1 356cde00b53SSascha Wildner fi 357cde00b53SSascha Wildner return 358cde00b53SSascha Wildner fi 359cde00b53SSascha Wildner 360cde00b53SSascha Wildner if [ $debug -gt 0 ]; then 361cde00b53SSascha Wildner decho "Command: $cattool $manpage | $pipeline" 362cde00b53SSascha Wildner ret=0 363cde00b53SSascha Wildner else 364cde00b53SSascha Wildner eval "$cattool $manpage | $pipeline" 365cde00b53SSascha Wildner ret=$? 366cde00b53SSascha Wildner fi 367cde00b53SSascha Wildner} 368cde00b53SSascha Wildner 369cde00b53SSascha Wildner# Usage: man_display_page_groff 370cde00b53SSascha Wildner# Display the manpage using groff 371cde00b53SSascha Wildnerman_display_page_groff() { 372cde00b53SSascha Wildner local EQN NROFF PIC TBL TROFF REFER VGRIND 373cde00b53SSascha Wildner local IFS l nroff_dev pipeline preproc_arg tool 374cde00b53SSascha Wildner 375cde00b53SSascha Wildner # So, we really do need to parse the manpage. First, figure out the 376cde00b53SSascha Wildner # device flag (-T) we have to pass to eqn(1) and groff(1). Then, 377cde00b53SSascha Wildner # setup the pipeline of commands based on the user's request. 378cde00b53SSascha Wildner 379cde00b53SSascha Wildner # If the manpage is from a particular charset, we need to setup nroff 380cde00b53SSascha Wildner # to properly output for the correct device. 381cde00b53SSascha Wildner case "${manpage}" in 382cde00b53SSascha Wildner *.${man_charset}/*) 383cde00b53SSascha Wildner # I don't pretend to know this; I'm just copying from the 384cde00b53SSascha Wildner # previous version of man(1). 385cde00b53SSascha Wildner case "$man_charset" in 386cde00b53SSascha Wildner KOI8-R) nroff_dev="koi8-r" ;; 387cde00b53SSascha Wildner ISO8859-1) nroff_dev="latin1" ;; 388cde00b53SSascha Wildner ISO8859-15) nroff_dev="latin1" ;; 389cde00b53SSascha Wildner UTF-8) nroff_dev="utf8" ;; 390cde00b53SSascha Wildner *) nroff_dev="ascii" ;; 391cde00b53SSascha Wildner esac 392cde00b53SSascha Wildner 393cde00b53SSascha Wildner NROFF="$NROFF -T$nroff_dev" 394cde00b53SSascha Wildner EQN="$EQN -T$nroff_dev" 395cde00b53SSascha Wildner 396cde00b53SSascha Wildner # Iff the manpage is from the locale and not just the charset, 397cde00b53SSascha Wildner # then we need to define the locale string. 398cde00b53SSascha Wildner case "${manpage}" in 399cde00b53SSascha Wildner */${man_lang}_${man_country}.${man_charset}/*) 400cde00b53SSascha Wildner NROFF="$NROFF -dlocale=$man_lang.$man_charset" 401cde00b53SSascha Wildner ;; 402cde00b53SSascha Wildner */${man_lang}.${man_charset}/*) 403cde00b53SSascha Wildner NROFF="$NROFF -dlocale=$man_lang.$man_charset" 404cde00b53SSascha Wildner ;; 405cde00b53SSascha Wildner esac 406cde00b53SSascha Wildner 407cde00b53SSascha Wildner # Allow language specific calls to override the default 408cde00b53SSascha Wildner # set of utilities. 409cde00b53SSascha Wildner l=$(echo $man_lang | tr [:lower:] [:upper:]) 410cde00b53SSascha Wildner for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do 411cde00b53SSascha Wildner eval "$tool=\${${tool}_$l:-\$$tool}" 412cde00b53SSascha Wildner done 413cde00b53SSascha Wildner ;; 414cde00b53SSascha Wildner *) NROFF="$NROFF -Tascii" 415cde00b53SSascha Wildner EQN="$EQN -Tascii" 416cde00b53SSascha Wildner ;; 417cde00b53SSascha Wildner esac 418cde00b53SSascha Wildner 419cde00b53SSascha Wildner if [ -z "$MANCOLOR" ]; then 420cde00b53SSascha Wildner NROFF="$NROFF -P-c" 421cde00b53SSascha Wildner fi 422cde00b53SSascha Wildner 423cde00b53SSascha Wildner if [ -n "${use_width}" ]; then 424cde00b53SSascha Wildner NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n" 425cde00b53SSascha Wildner fi 426cde00b53SSascha Wildner 427cde00b53SSascha Wildner if [ -n "$MANROFFSEQ" ]; then 428cde00b53SSascha Wildner set -- -$MANROFFSEQ 429cde00b53SSascha Wildner while getopts 'egprtv' preproc_arg; do 430cde00b53SSascha Wildner case "${preproc_arg}" in 431cde00b53SSascha Wildner e) pipeline="$pipeline | $EQN" ;; 432cde00b53SSascha Wildner g) ;; # Ignore for compatibility. 433cde00b53SSascha Wildner p) pipeline="$pipeline | $PIC" ;; 434cde00b53SSascha Wildner r) pipeline="$pipeline | $REFER" ;; 435cde00b53SSascha Wildner t) pipeline="$pipeline | $TBL" ;; 436cde00b53SSascha Wildner v) pipeline="$pipeline | $VGRIND" ;; 437cde00b53SSascha Wildner *) usage ;; 438cde00b53SSascha Wildner esac 439cde00b53SSascha Wildner done 440cde00b53SSascha Wildner # Strip the leading " | " from the resulting pipeline. 441cde00b53SSascha Wildner pipeline="${pipeline#" | "}" 442cde00b53SSascha Wildner else 443cde00b53SSascha Wildner pipeline="$TBL" 444cde00b53SSascha Wildner fi 445cde00b53SSascha Wildner 446cde00b53SSascha Wildner if [ -n "$tflag" ]; then 447cde00b53SSascha Wildner pipeline="$pipeline | $TROFF" 448cde00b53SSascha Wildner else 449cde00b53SSascha Wildner pipeline="$pipeline | $NROFF | $MANPAGER" 450cde00b53SSascha Wildner fi 451cde00b53SSascha Wildner 452cde00b53SSascha Wildner if [ $debug -gt 0 ]; then 453cde00b53SSascha Wildner decho "Command: $cattool $manpage | $pipeline" 454cde00b53SSascha Wildner ret=0 455cde00b53SSascha Wildner else 456cde00b53SSascha Wildner eval "$cattool $manpage | $pipeline" 457cde00b53SSascha Wildner ret=$? 458cde00b53SSascha Wildner fi 459cde00b53SSascha Wildner} 460cde00b53SSascha Wildner 461cde00b53SSascha Wildner# Usage: man_find_and_display page 462cde00b53SSascha Wildner# Search through the manpaths looking for the given page. 463cde00b53SSascha Wildnerman_find_and_display() { 464cde00b53SSascha Wildner local found_page locpath p path sect 465cde00b53SSascha Wildner 466cde00b53SSascha Wildner # Check to see if it's a file. But only if it has a '/' in 467cde00b53SSascha Wildner # the filename. 468cde00b53SSascha Wildner case "$1" in 469cde00b53SSascha Wildner */*) if [ -f "$1" -a -r "$1" ]; then 470cde00b53SSascha Wildner decho "Found a usable page, displaying that" 471cde00b53SSascha Wildner unset use_cat 472cde00b53SSascha Wildner manpage="$1" 473cde00b53SSascha Wildner setup_cattool $manpage 474cde00b53SSascha Wildner if man_check_for_so $manpage $(dirname $manpage); then 475cde00b53SSascha Wildner found_page=yes 476cde00b53SSascha Wildner man_display_page 477cde00b53SSascha Wildner fi 478cde00b53SSascha Wildner return 479cde00b53SSascha Wildner fi 480cde00b53SSascha Wildner ;; 481cde00b53SSascha Wildner esac 482cde00b53SSascha Wildner 483cde00b53SSascha Wildner IFS=: 484cde00b53SSascha Wildner for sect in $MANSECT; do 485cde00b53SSascha Wildner decho "Searching section $sect" 2 486cde00b53SSascha Wildner for path in $MANPATH; do 487cde00b53SSascha Wildner for locpath in $locpaths; do 488cde00b53SSascha Wildner p=$path/$locpath 489cde00b53SSascha Wildner p=${p%/.} # Rid ourselves of the trailing /. 490cde00b53SSascha Wildner 491cde00b53SSascha Wildner # Check if there is a MACHINE specific manpath. 492cde00b53SSascha Wildner if find_file $p $sect $MACHINE "$1"; then 493cde00b53SSascha Wildner if man_check_for_so $manpage $p; then 494cde00b53SSascha Wildner found_page=yes 495cde00b53SSascha Wildner man_display_page 496cde00b53SSascha Wildner if [ -n "$aflag" ]; then 497cde00b53SSascha Wildner continue 2 498cde00b53SSascha Wildner else 499cde00b53SSascha Wildner return 500cde00b53SSascha Wildner fi 501cde00b53SSascha Wildner fi 502cde00b53SSascha Wildner fi 503cde00b53SSascha Wildner 504cde00b53SSascha Wildner # Check if there is a MACHINE_ARCH 505cde00b53SSascha Wildner # specific manpath. 506cde00b53SSascha Wildner if find_file $p $sect $MACHINE_ARCH "$1"; then 507cde00b53SSascha Wildner if man_check_for_so $manpage $p; then 508cde00b53SSascha Wildner found_page=yes 509cde00b53SSascha Wildner man_display_page 510cde00b53SSascha Wildner if [ -n "$aflag" ]; then 511cde00b53SSascha Wildner continue 2 512cde00b53SSascha Wildner else 513cde00b53SSascha Wildner return 514cde00b53SSascha Wildner fi 515cde00b53SSascha Wildner fi 516cde00b53SSascha Wildner fi 517cde00b53SSascha Wildner 518cde00b53SSascha Wildner # Check plain old manpath. 519cde00b53SSascha Wildner if find_file $p $sect '' "$1"; then 520cde00b53SSascha Wildner if man_check_for_so $manpage $p; then 521cde00b53SSascha Wildner found_page=yes 522cde00b53SSascha Wildner man_display_page 523cde00b53SSascha Wildner if [ -n "$aflag" ]; then 524cde00b53SSascha Wildner continue 2 525cde00b53SSascha Wildner else 526cde00b53SSascha Wildner return 527cde00b53SSascha Wildner fi 528cde00b53SSascha Wildner fi 529cde00b53SSascha Wildner fi 530cde00b53SSascha Wildner done 531cde00b53SSascha Wildner done 532cde00b53SSascha Wildner done 533cde00b53SSascha Wildner unset IFS 534cde00b53SSascha Wildner 535cde00b53SSascha Wildner # Nothing? Well, we are done then. 536cde00b53SSascha Wildner if [ -z "$found_page" ]; then 537cde00b53SSascha Wildner echo "No manual entry for $1" >&2 538cde00b53SSascha Wildner ret=1 539cde00b53SSascha Wildner return 540cde00b53SSascha Wildner fi 541cde00b53SSascha Wildner} 542cde00b53SSascha Wildner 543cde00b53SSascha Wildner# Usage: man_parse_args "$@" 544cde00b53SSascha Wildner# Parses commandline options for man. 545cde00b53SSascha Wildnerman_parse_args() { 546cde00b53SSascha Wildner local IFS cmd_arg 547cde00b53SSascha Wildner 548cde00b53SSascha Wildner while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do 549cde00b53SSascha Wildner case "${cmd_arg}" in 550cde00b53SSascha Wildner M) MANPATH=$OPTARG ;; 551cde00b53SSascha Wildner P) MANPAGER=$OPTARG ;; 552cde00b53SSascha Wildner S) MANSECT=$OPTARG ;; 553cde00b53SSascha Wildner a) aflag=aflag ;; 554cde00b53SSascha Wildner d) debug=$(( $debug + 1 )) ;; 555cde00b53SSascha Wildner f) fflag=fflag ;; 556cde00b53SSascha Wildner h) man_usage 0 ;; 557cde00b53SSascha Wildner k) kflag=kflag ;; 558cde00b53SSascha Wildner m) mflag=$OPTARG ;; 559cde00b53SSascha Wildner o) oflag=oflag ;; 560cde00b53SSascha Wildner p) MANROFFSEQ=$OPTARG ;; 561cde00b53SSascha Wildner t) tflag=tflag ;; 562cde00b53SSascha Wildner w) wflag=wflag ;; 563cde00b53SSascha Wildner *) man_usage ;; 564cde00b53SSascha Wildner esac 565cde00b53SSascha Wildner done >&2 566cde00b53SSascha Wildner 567cde00b53SSascha Wildner shift $(( $OPTIND - 1 )) 568cde00b53SSascha Wildner 569cde00b53SSascha Wildner # Check the args for incompatible options. 570cde00b53SSascha Wildner case "${fflag}${kflag}${tflag}${wflag}" in 571cde00b53SSascha Wildner fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;; 572cde00b53SSascha Wildner fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;; 573cde00b53SSascha Wildner fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;; 574cde00b53SSascha Wildner *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;; 575cde00b53SSascha Wildner *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;; 576cde00b53SSascha Wildner *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;; 577cde00b53SSascha Wildner esac 578cde00b53SSascha Wildner 579cde00b53SSascha Wildner # Short circuit for whatis(1) and apropos(1) 580cde00b53SSascha Wildner if [ -n "$fflag" ]; then 581cde00b53SSascha Wildner do_whatis "$@" 582cde00b53SSascha Wildner exit 583cde00b53SSascha Wildner fi 584cde00b53SSascha Wildner 585cde00b53SSascha Wildner if [ -n "$kflag" ]; then 586cde00b53SSascha Wildner do_apropos "$@" 587cde00b53SSascha Wildner exit 588cde00b53SSascha Wildner fi 589cde00b53SSascha Wildner 590cde00b53SSascha Wildner IFS=: 591cde00b53SSascha Wildner for sect in $man_default_sections; do 592cde00b53SSascha Wildner if [ "$sect" = "$1" ]; then 593cde00b53SSascha Wildner decho "Detected manual section as first arg: $1" 594cde00b53SSascha Wildner MANSECT="$1" 595cde00b53SSascha Wildner shift 596cde00b53SSascha Wildner break 597cde00b53SSascha Wildner fi 598cde00b53SSascha Wildner done 599cde00b53SSascha Wildner unset IFS 600cde00b53SSascha Wildner 601cde00b53SSascha Wildner pages="$*" 602cde00b53SSascha Wildner} 603cde00b53SSascha Wildner 604cde00b53SSascha Wildner# Usage: man_setup 605cde00b53SSascha Wildner# Setup various trivial but essential variables. 606cde00b53SSascha Wildnerman_setup() { 607cde00b53SSascha Wildner # Setup machine and architecture variables. 608cde00b53SSascha Wildner if [ -n "$mflag" ]; then 609cde00b53SSascha Wildner MACHINE_ARCH=${mflag%%:*} 610cde00b53SSascha Wildner MACHINE=${mflag##*:} 611cde00b53SSascha Wildner fi 612cde00b53SSascha Wildner if [ -z "$MACHINE_ARCH" ]; then 613cde00b53SSascha Wildner MACHINE_ARCH=$($SYSCTL -n hw.machine_arch) 614cde00b53SSascha Wildner fi 615cde00b53SSascha Wildner if [ -z "$MACHINE" ]; then 616cde00b53SSascha Wildner MACHINE=$($SYSCTL -n hw.machine) 617cde00b53SSascha Wildner fi 618cde00b53SSascha Wildner decho "Using architecture: $MACHINE_ARCH:$MACHINE" 619cde00b53SSascha Wildner 620cde00b53SSascha Wildner setup_pager 621cde00b53SSascha Wildner 622cde00b53SSascha Wildner # Setup manual sections to search. 623cde00b53SSascha Wildner if [ -z "$MANSECT" ]; then 624cde00b53SSascha Wildner MANSECT=$man_default_sections 625cde00b53SSascha Wildner fi 626cde00b53SSascha Wildner decho "Using manual sections: $MANSECT" 627cde00b53SSascha Wildner 628cde00b53SSascha Wildner build_manpath 629cde00b53SSascha Wildner man_setup_locale 630cde00b53SSascha Wildner man_setup_width 631cde00b53SSascha Wildner} 632cde00b53SSascha Wildner 633cde00b53SSascha Wildner# Usage: man_setup_width 634cde00b53SSascha Wildner# Set up page width. 635cde00b53SSascha Wildnerman_setup_width() { 636cde00b53SSascha Wildner local sizes 637cde00b53SSascha Wildner 638cde00b53SSascha Wildner unset use_width 639cde00b53SSascha Wildner case "$MANWIDTH" in 640cde00b53SSascha Wildner [0-9]*) 641cde00b53SSascha Wildner if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then 642cde00b53SSascha Wildner use_width=$MANWIDTH 643cde00b53SSascha Wildner fi 644cde00b53SSascha Wildner ;; 645cde00b53SSascha Wildner [Tt][Tt][Yy]) 646cde00b53SSascha Wildner if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then 647cde00b53SSascha Wildner set -- $sizes 648cde00b53SSascha Wildner if [ $2 -gt 80 ]; then 649cde00b53SSascha Wildner use_width=$(($2-2)) 650cde00b53SSascha Wildner fi 651cde00b53SSascha Wildner fi 652cde00b53SSascha Wildner ;; 653cde00b53SSascha Wildner esac 654cde00b53SSascha Wildner if [ -n "$use_width" ]; then 655cde00b53SSascha Wildner decho "Using non-standard page width: ${use_width}" 656cde00b53SSascha Wildner else 657cde00b53SSascha Wildner decho 'Using standard page width' 658cde00b53SSascha Wildner fi 659cde00b53SSascha Wildner} 660cde00b53SSascha Wildner 661cde00b53SSascha Wildner# Usage: man_setup_locale 662cde00b53SSascha Wildner# Setup necessary locale variables. 663cde00b53SSascha Wildnerman_setup_locale() { 664cde00b53SSascha Wildner local lang_cc 665cde00b53SSascha Wildner local locstr 666cde00b53SSascha Wildner 667cde00b53SSascha Wildner locpaths='.' 668cde00b53SSascha Wildner man_charset='US-ASCII' 669cde00b53SSascha Wildner 670cde00b53SSascha Wildner # Setup locale information. 671cde00b53SSascha Wildner if [ -n "$oflag" ]; then 672cde00b53SSascha Wildner decho 'Using non-localized manpages' 673cde00b53SSascha Wildner else 674cde00b53SSascha Wildner # Use the locale tool to give us proper locale information 675cde00b53SSascha Wildner eval $( $LOCALE ) 676cde00b53SSascha Wildner 677cde00b53SSascha Wildner if [ -n "$LANG" ]; then 678cde00b53SSascha Wildner locstr=$LANG 679cde00b53SSascha Wildner else 680cde00b53SSascha Wildner locstr=$LC_CTYPE 681cde00b53SSascha Wildner fi 682cde00b53SSascha Wildner 683cde00b53SSascha Wildner case "$locstr" in 684cde00b53SSascha Wildner C) ;; 685cde00b53SSascha Wildner C.UTF-8) ;; 686cde00b53SSascha Wildner POSIX) ;; 687cde00b53SSascha Wildner [a-z][a-z]_[A-Z][A-Z]\.*) 688cde00b53SSascha Wildner lang_cc="${locstr%.*}" 689cde00b53SSascha Wildner man_lang="${locstr%_*}" 690cde00b53SSascha Wildner man_country="${lang_cc#*_}" 691cde00b53SSascha Wildner man_charset="${locstr#*.}" 692cde00b53SSascha Wildner locpaths="$locstr" 693cde00b53SSascha Wildner locpaths="$locpaths:$man_lang.$man_charset" 694cde00b53SSascha Wildner if [ "$man_lang" != "en" ]; then 695cde00b53SSascha Wildner locpaths="$locpaths:en.$man_charset" 696cde00b53SSascha Wildner fi 697cde00b53SSascha Wildner locpaths="$locpaths:." 698cde00b53SSascha Wildner ;; 699cde00b53SSascha Wildner *) echo 'Unknown locale, assuming C' >&2 700cde00b53SSascha Wildner ;; 701cde00b53SSascha Wildner esac 702cde00b53SSascha Wildner fi 703cde00b53SSascha Wildner 704cde00b53SSascha Wildner decho "Using locale paths: $locpaths" 705cde00b53SSascha Wildner} 706cde00b53SSascha Wildner 707cde00b53SSascha Wildner# Usage: man_usage [exitcode] 708cde00b53SSascha Wildner# Display usage for the man utility. 709cde00b53SSascha Wildnerman_usage() { 710cde00b53SSascha Wildner echo 'Usage:' 711cde00b53SSascha Wildner echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]' 712cde00b53SSascha Wildner echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]' 713cde00b53SSascha Wildner echo ' man -f page [...] -- Emulates whatis(1)' 714cde00b53SSascha Wildner echo ' man -k page [...] -- Emulates apropos(1)' 715cde00b53SSascha Wildner 716cde00b53SSascha Wildner # When exit'ing with -h, it's not an error. 717cde00b53SSascha Wildner exit ${1:-1} 718cde00b53SSascha Wildner} 719cde00b53SSascha Wildner 720cde00b53SSascha Wildner# Usage: parse_configs 721cde00b53SSascha Wildner# Reads the end-user adjustable config files. 722cde00b53SSascha Wildnerparse_configs() { 723cde00b53SSascha Wildner local IFS file files 724cde00b53SSascha Wildner 725cde00b53SSascha Wildner if [ -n "$parsed_configs" ]; then 726cde00b53SSascha Wildner return 727cde00b53SSascha Wildner fi 728cde00b53SSascha Wildner 729cde00b53SSascha Wildner unset IFS 730cde00b53SSascha Wildner 731cde00b53SSascha Wildner # Read the global config first in case the user wants 732cde00b53SSascha Wildner # to override config_local. 733cde00b53SSascha Wildner if [ -r "$config_global" ]; then 734cde00b53SSascha Wildner parse_file "$config_global" 735cde00b53SSascha Wildner fi 736cde00b53SSascha Wildner 737cde00b53SSascha Wildner # Glob the list of files to parse. 738cde00b53SSascha Wildner set +f 739cde00b53SSascha Wildner files=$(echo $config_local) 740cde00b53SSascha Wildner set -f 741cde00b53SSascha Wildner 742cde00b53SSascha Wildner for file in $files; do 743cde00b53SSascha Wildner if [ -r "$file" ]; then 744cde00b53SSascha Wildner parse_file "$file" 745cde00b53SSascha Wildner fi 746cde00b53SSascha Wildner done 747cde00b53SSascha Wildner 748cde00b53SSascha Wildner parsed_configs='yes' 749cde00b53SSascha Wildner} 750cde00b53SSascha Wildner 751cde00b53SSascha Wildner# Usage: parse_file file 752cde00b53SSascha Wildner# Reads the specified config files. 753cde00b53SSascha Wildnerparse_file() { 754cde00b53SSascha Wildner local file line tstr var 755cde00b53SSascha Wildner 756cde00b53SSascha Wildner file="$1" 757cde00b53SSascha Wildner decho "Parsing config file: $file" 758cde00b53SSascha Wildner while read line; do 759cde00b53SSascha Wildner decho " $line" 2 760cde00b53SSascha Wildner case "$line" in 761cde00b53SSascha Wildner \#*) decho " Comment" 3 762cde00b53SSascha Wildner ;; 763cde00b53SSascha Wildner MANPATH*) decho " MANPATH" 3 764cde00b53SSascha Wildner trim "${line#MANPATH}" 765cde00b53SSascha Wildner add_to_manpath "$tstr" 766cde00b53SSascha Wildner ;; 767cde00b53SSascha Wildner MANLOCALE*) decho " MANLOCALE" 3 768cde00b53SSascha Wildner trim "${line#MANLOCALE}" 769cde00b53SSascha Wildner manlocales="$manlocales:$tstr" 770cde00b53SSascha Wildner ;; 771cde00b53SSascha Wildner MANCONFIG*) decho " MANCONFIG" 3 772cde00b53SSascha Wildner trim "${line#MANCONFIG}" 773cde00b53SSascha Wildner config_local="$tstr" 774cde00b53SSascha Wildner ;; 775cde00b53SSascha Wildner # Set variables in the form of FOO_BAR 776cde00b53SSascha Wildner *_*[\ \ ]*) var="${line%%[\ \ ]*}" 777cde00b53SSascha Wildner trim "${line#$var}" 778cde00b53SSascha Wildner eval "$var=\"$tstr\"" 779cde00b53SSascha Wildner decho " Parsed $var" 3 780cde00b53SSascha Wildner ;; 781cde00b53SSascha Wildner esac 782cde00b53SSascha Wildner done < "$file" 783cde00b53SSascha Wildner} 784cde00b53SSascha Wildner 785cde00b53SSascha Wildner# Usage: search_path 786cde00b53SSascha Wildner# Traverse $PATH looking for manpaths. 787cde00b53SSascha Wildnersearch_path() { 788cde00b53SSascha Wildner local IFS p path 789cde00b53SSascha Wildner 790cde00b53SSascha Wildner decho "Searching PATH for man directories" 791cde00b53SSascha Wildner 792cde00b53SSascha Wildner IFS=: 793cde00b53SSascha Wildner for path in $PATH; do 794cde00b53SSascha Wildner if add_to_manpath "$path/man"; then 795cde00b53SSascha Wildner : 796cde00b53SSascha Wildner elif add_to_manpath "$path/MAN"; then 797cde00b53SSascha Wildner : 798cde00b53SSascha Wildner else 799cde00b53SSascha Wildner case "$path" in 800cde00b53SSascha Wildner */bin) p="${path%/bin}/share/man" 801cde00b53SSascha Wildner add_to_manpath "$p" 802cde00b53SSascha Wildner p="${path%/bin}/man" 803cde00b53SSascha Wildner add_to_manpath "$p" 804cde00b53SSascha Wildner ;; 805cde00b53SSascha Wildner esac 806cde00b53SSascha Wildner fi 807cde00b53SSascha Wildner done 808cde00b53SSascha Wildner unset IFS 809cde00b53SSascha Wildner 810cde00b53SSascha Wildner if [ -z "$manpath" ]; then 811cde00b53SSascha Wildner decho ' Unable to find any manpaths, using default' 812cde00b53SSascha Wildner manpath=$man_default_path 813cde00b53SSascha Wildner fi 814cde00b53SSascha Wildner} 815cde00b53SSascha Wildner 816cde00b53SSascha Wildner# Usage: search_whatis cmd [arglist] 817cde00b53SSascha Wildner# Do the heavy lifting for apropos/whatis 818cde00b53SSascha Wildnersearch_whatis() { 819cde00b53SSascha Wildner local IFS bad cmd f good key keywords loc opt out path rval wlist 820cde00b53SSascha Wildner 821cde00b53SSascha Wildner cmd="$1" 822cde00b53SSascha Wildner shift 823cde00b53SSascha Wildner 824cde00b53SSascha Wildner whatis_parse_args "$@" 825cde00b53SSascha Wildner 826cde00b53SSascha Wildner build_manpath 827cde00b53SSascha Wildner build_manlocales 828cde00b53SSascha Wildner setup_pager 829cde00b53SSascha Wildner 830cde00b53SSascha Wildner if [ "$cmd" = "whatis" ]; then 831cde00b53SSascha Wildner opt="-w" 832cde00b53SSascha Wildner fi 833cde00b53SSascha Wildner 834cde00b53SSascha Wildner f='whatis' 835cde00b53SSascha Wildner 836cde00b53SSascha Wildner IFS=: 837cde00b53SSascha Wildner for path in $MANPATH; do 838cde00b53SSascha Wildner if [ \! -d "$path" ]; then 839cde00b53SSascha Wildner decho "Skipping non-existent path: $path" 2 840cde00b53SSascha Wildner continue 841cde00b53SSascha Wildner fi 842cde00b53SSascha Wildner 843cde00b53SSascha Wildner if [ -f "$path/$f" -a -r "$path/$f" ]; then 844cde00b53SSascha Wildner decho "Found whatis: $path/$f" 845cde00b53SSascha Wildner wlist="$wlist $path/$f" 846cde00b53SSascha Wildner fi 847cde00b53SSascha Wildner 848cde00b53SSascha Wildner for loc in $MANLOCALES; do 849cde00b53SSascha Wildner if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then 850cde00b53SSascha Wildner decho "Found whatis: $path/$loc/$f" 851cde00b53SSascha Wildner wlist="$wlist $path/$loc/$f" 852cde00b53SSascha Wildner fi 853cde00b53SSascha Wildner done 854cde00b53SSascha Wildner done 855cde00b53SSascha Wildner unset IFS 856cde00b53SSascha Wildner 857cde00b53SSascha Wildner if [ -z "$wlist" ]; then 858cde00b53SSascha Wildner echo "$cmd: no whatis databases in $MANPATH" >&2 859cde00b53SSascha Wildner exit 1 860cde00b53SSascha Wildner fi 861cde00b53SSascha Wildner 862cde00b53SSascha Wildner rval=0 863cde00b53SSascha Wildner for key in $keywords; do 864cde00b53SSascha Wildner out=$(grep -Ehi $opt -- "$key" $wlist) 865cde00b53SSascha Wildner if [ -n "$out" ]; then 866cde00b53SSascha Wildner good="$good\\n$out" 867cde00b53SSascha Wildner else 868cde00b53SSascha Wildner bad="$bad\\n$key: nothing appropriate" 869cde00b53SSascha Wildner rval=1 870cde00b53SSascha Wildner fi 871cde00b53SSascha Wildner done 872cde00b53SSascha Wildner 873cde00b53SSascha Wildner # Strip leading carriage return. 874cde00b53SSascha Wildner good=${good#\\n} 875cde00b53SSascha Wildner bad=${bad#\\n} 876cde00b53SSascha Wildner 877cde00b53SSascha Wildner if [ -n "$good" ]; then 878cde00b53SSascha Wildner echo -e "$good" | $MANPAGER 879cde00b53SSascha Wildner fi 880cde00b53SSascha Wildner 881cde00b53SSascha Wildner if [ -n "$bad" ]; then 882cde00b53SSascha Wildner echo -e "$bad" >&2 883cde00b53SSascha Wildner fi 884cde00b53SSascha Wildner 885cde00b53SSascha Wildner exit $rval 886cde00b53SSascha Wildner} 887cde00b53SSascha Wildner 888cde00b53SSascha Wildner# Usage: setup_cattool page 889cde00b53SSascha Wildner# Finds an appropriate decompressor based on extension 890cde00b53SSascha Wildnersetup_cattool() { 891cde00b53SSascha Wildner case "$1" in 892cde00b53SSascha Wildner *.bz) cattool='/usr/bin/bzcat' ;; 893cde00b53SSascha Wildner *.bz2) cattool='/usr/bin/bzcat' ;; 894cde00b53SSascha Wildner *.gz) cattool='/usr/bin/zcat' ;; 895cde00b53SSascha Wildner *.lzma) cattool='/usr/bin/lzcat' ;; 896cde00b53SSascha Wildner *.xz) cattool='/usr/bin/xzcat' ;; 897cde00b53SSascha Wildner *) cattool='/usr/bin/zcat -f' ;; 898cde00b53SSascha Wildner esac 899cde00b53SSascha Wildner} 900cde00b53SSascha Wildner 901cde00b53SSascha Wildner# Usage: setup_pager 902cde00b53SSascha Wildner# Correctly sets $MANPAGER 903cde00b53SSascha Wildnersetup_pager() { 904cde00b53SSascha Wildner # Setup pager. 905cde00b53SSascha Wildner if [ -z "$MANPAGER" ]; then 906cde00b53SSascha Wildner if [ -n "$MANCOLOR" ]; then 907cde00b53SSascha Wildner MANPAGER="less -sR" 908cde00b53SSascha Wildner else 909cde00b53SSascha Wildner if [ -n "$PAGER" ]; then 910cde00b53SSascha Wildner MANPAGER="$PAGER" 911cde00b53SSascha Wildner else 912cde00b53SSascha Wildner MANPAGER="less -s" 913cde00b53SSascha Wildner fi 914cde00b53SSascha Wildner fi 915cde00b53SSascha Wildner fi 916cde00b53SSascha Wildner decho "Using pager: $MANPAGER" 917cde00b53SSascha Wildner} 918cde00b53SSascha Wildner 919cde00b53SSascha Wildner# Usage: trim string 920cde00b53SSascha Wildner# Trims whitespace from beginning and end of a variable 921cde00b53SSascha Wildnertrim() { 922cde00b53SSascha Wildner tstr=$1 923cde00b53SSascha Wildner while true; do 924cde00b53SSascha Wildner case "$tstr" in 925cde00b53SSascha Wildner [\ \ ]*) tstr="${tstr##[\ \ ]}" ;; 926cde00b53SSascha Wildner *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;; 927cde00b53SSascha Wildner *) break ;; 928cde00b53SSascha Wildner esac 929cde00b53SSascha Wildner done 930cde00b53SSascha Wildner} 931cde00b53SSascha Wildner 932cde00b53SSascha Wildner# Usage: whatis_parse_args "$@" 933cde00b53SSascha Wildner# Parse commandline args for whatis and apropos. 934cde00b53SSascha Wildnerwhatis_parse_args() { 935cde00b53SSascha Wildner local cmd_arg 936cde00b53SSascha Wildner while getopts 'd' cmd_arg; do 937cde00b53SSascha Wildner case "${cmd_arg}" in 938cde00b53SSascha Wildner d) debug=$(( $debug + 1 )) ;; 939cde00b53SSascha Wildner *) whatis_usage ;; 940cde00b53SSascha Wildner esac 941cde00b53SSascha Wildner done >&2 942cde00b53SSascha Wildner 943cde00b53SSascha Wildner shift $(( $OPTIND - 1 )) 944cde00b53SSascha Wildner 945cde00b53SSascha Wildner keywords="$*" 946cde00b53SSascha Wildner} 947cde00b53SSascha Wildner 948cde00b53SSascha Wildner# Usage: whatis_usage 949cde00b53SSascha Wildner# Display usage for the whatis/apropos utility. 950cde00b53SSascha Wildnerwhatis_usage() { 951cde00b53SSascha Wildner echo "usage: $cmd [-d] keyword [...]" 952cde00b53SSascha Wildner exit 1 953cde00b53SSascha Wildner} 954cde00b53SSascha Wildner 955cde00b53SSascha Wildner 956cde00b53SSascha Wildner 957cde00b53SSascha Wildner# Supported commands 958cde00b53SSascha Wildnerdo_apropos() { 959cde00b53SSascha Wildner [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \ 960cde00b53SSascha Wildner exec apropos "$@" 961cde00b53SSascha Wildner search_whatis apropos "$@" 962cde00b53SSascha Wildner} 963cde00b53SSascha Wildner 964cde00b53SSascha Wildnerdo_man() { 965cde00b53SSascha Wildner man_parse_args "$@" 966cde00b53SSascha Wildner if [ -z "$pages" ]; then 967cde00b53SSascha Wildner echo 'What manual page do you want?' >&2 968cde00b53SSascha Wildner exit 1 969cde00b53SSascha Wildner fi 970cde00b53SSascha Wildner man_setup 971cde00b53SSascha Wildner 972cde00b53SSascha Wildner for page in $pages; do 973cde00b53SSascha Wildner decho "Searching for $page" 974cde00b53SSascha Wildner man_find_and_display "$page" 975cde00b53SSascha Wildner done 976cde00b53SSascha Wildner 977cde00b53SSascha Wildner exit ${ret:-0} 978cde00b53SSascha Wildner} 979cde00b53SSascha Wildner 980cde00b53SSascha Wildnerdo_manpath() { 981cde00b53SSascha Wildner manpath_parse_args "$@" 982cde00b53SSascha Wildner if [ -z "$qflag" ]; then 983cde00b53SSascha Wildner manpath_warnings 984cde00b53SSascha Wildner fi 985cde00b53SSascha Wildner if [ -n "$Lflag" ]; then 986cde00b53SSascha Wildner build_manlocales 987cde00b53SSascha Wildner echo $MANLOCALES 988cde00b53SSascha Wildner else 989cde00b53SSascha Wildner build_manpath 990cde00b53SSascha Wildner echo $MANPATH 991cde00b53SSascha Wildner fi 992cde00b53SSascha Wildner exit 0 993cde00b53SSascha Wildner} 994cde00b53SSascha Wildner 995cde00b53SSascha Wildnerdo_whatis() { 996cde00b53SSascha Wildner [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \ 997cde00b53SSascha Wildner exec whatis "$@" 998cde00b53SSascha Wildner search_whatis whatis "$@" 999cde00b53SSascha Wildner} 1000cde00b53SSascha Wildner 1001cde00b53SSascha Wildner# User's PATH setting decides on the groff-suite to pick up. 1002cde00b53SSascha WildnerEQN=eqn 1003cde00b53SSascha WildnerNROFF='groff -S -P-h -Wall -mtty-char -man' 1004cde00b53SSascha WildnerPIC=pic 1005cde00b53SSascha WildnerREFER=refer 1006cde00b53SSascha WildnerTBL=tbl 1007cde00b53SSascha WildnerTROFF='groff -S -man' 1008cde00b53SSascha WildnerVGRIND=vgrind 1009cde00b53SSascha Wildner 1010cde00b53SSascha WildnerLOCALE=/usr/bin/locale 1011cde00b53SSascha WildnerSTTY=/bin/stty 1012cde00b53SSascha WildnerSYSCTL=/sbin/sysctl 1013cde00b53SSascha Wildner 1014cde00b53SSascha Wildnerdebug=0 1015cde00b53SSascha Wildnerman_default_sections='1:8:2:3:n:4:5:6:7:9:l' 1016*a3b5347fSSascha Wildnerman_default_path='/usr/share/man:/usr/local/share/man:/usr/local/man:/raven/share/man:/usr/pkg/man' 1017cde00b53SSascha Wildnercattool='/usr/bin/zcat -f' 1018cde00b53SSascha Wildner 1019cde00b53SSascha Wildnerconfig_global='/etc/man.conf' 1020cde00b53SSascha Wildner 1021cde00b53SSascha Wildner# This can be overridden via a setting in /etc/man.conf. 1022cde00b53SSascha Wildnerconfig_local='/usr/local/etc/man.d/*.conf' 1023cde00b53SSascha Wildner 1024cde00b53SSascha Wildner# Set noglobbing for now. I don't want spurious globbing. 1025cde00b53SSascha Wildnerset -f 1026cde00b53SSascha Wildner 1027cde00b53SSascha Wildnercase "$0" in 1028cde00b53SSascha Wildner*apropos) do_apropos "$@" ;; 1029cde00b53SSascha Wildner*manpath) do_manpath "$@" ;; 1030cde00b53SSascha Wildner*whatis) do_whatis "$@" ;; 1031cde00b53SSascha Wildner*) do_man "$@" ;; 1032cde00b53SSascha Wildneresac 1033