xref: /freebsd/usr.bin/man/man.sh (revision c535eb59d10bf5555b1a5ddef7a0833a7c6a80e1)
1*c535eb59SGordon Tetlow#! /bin/sh
2*c535eb59SGordon Tetlow#
3*c535eb59SGordon Tetlow#  Copyright (c) 2010 Gordon Tetlow
4*c535eb59SGordon Tetlow#  All rights reserved.
5*c535eb59SGordon Tetlow#
6*c535eb59SGordon Tetlow#  Redistribution and use in source and binary forms, with or without
7*c535eb59SGordon Tetlow#  modification, are permitted provided that the following conditions
8*c535eb59SGordon Tetlow#  are met:
9*c535eb59SGordon Tetlow#  1. Redistributions of source code must retain the above copyright
10*c535eb59SGordon Tetlow#     notice, this list of conditions and the following disclaimer.
11*c535eb59SGordon Tetlow#  2. Redistributions in binary form must reproduce the above copyright
12*c535eb59SGordon Tetlow#     notice, this list of conditions and the following disclaimer in the
13*c535eb59SGordon Tetlow#     documentation and/or other materials provided with the distribution.
14*c535eb59SGordon Tetlow#
15*c535eb59SGordon Tetlow#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*c535eb59SGordon Tetlow#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*c535eb59SGordon Tetlow#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*c535eb59SGordon Tetlow#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*c535eb59SGordon Tetlow#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*c535eb59SGordon Tetlow#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*c535eb59SGordon Tetlow#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*c535eb59SGordon Tetlow#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*c535eb59SGordon Tetlow#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*c535eb59SGordon Tetlow#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*c535eb59SGordon Tetlow#  SUCH DAMAGE.
26*c535eb59SGordon Tetlow#
27*c535eb59SGordon Tetlow# $FreeBSD$
28*c535eb59SGordon Tetlow
29*c535eb59SGordon Tetlow# Usage: add_to_manpath path
30*c535eb59SGordon Tetlow# Adds a variable to manpath while ensuring we don't have duplicates.
31*c535eb59SGordon Tetlow# Returns true if we were able to add something. False otherwise.
32*c535eb59SGordon Tetlowadd_to_manpath() {
33*c535eb59SGordon Tetlow	case "$manpath" in
34*c535eb59SGordon Tetlow	*:$1)	decho "  Skipping duplicate manpath entry $1" 2 ;;
35*c535eb59SGordon Tetlow	$1:*)	decho "  Skipping duplicate manpath entry $1" 2 ;;
36*c535eb59SGordon Tetlow	*:$1:*)	decho "  Skipping duplicate manpath entry $1" 2 ;;
37*c535eb59SGordon Tetlow	*)	if [ -d "$1" ]; then
38*c535eb59SGordon Tetlow			decho "  Adding $1 to manpath"
39*c535eb59SGordon Tetlow			manpath="$manpath:$1"
40*c535eb59SGordon Tetlow			return 0
41*c535eb59SGordon Tetlow		fi
42*c535eb59SGordon Tetlow		;;
43*c535eb59SGordon Tetlow	esac
44*c535eb59SGordon Tetlow
45*c535eb59SGordon Tetlow	return 1
46*c535eb59SGordon Tetlow}
47*c535eb59SGordon Tetlow
48*c535eb59SGordon Tetlow# Usage: build_manlocales
49*c535eb59SGordon Tetlow# Builds a correct MANLOCALES variable.
50*c535eb59SGordon Tetlowbuild_manlocales() {
51*c535eb59SGordon Tetlow	# If the user has set manlocales, who are we to argue.
52*c535eb59SGordon Tetlow	if [ -n "$MANLOCALES" ]; then
53*c535eb59SGordon Tetlow		return
54*c535eb59SGordon Tetlow	fi
55*c535eb59SGordon Tetlow
56*c535eb59SGordon Tetlow	parse_configs
57*c535eb59SGordon Tetlow
58*c535eb59SGordon Tetlow	# Trim leading colon
59*c535eb59SGordon Tetlow	MANLOCALES=${manlocales#:}
60*c535eb59SGordon Tetlow
61*c535eb59SGordon Tetlow	decho "Available manual locales: $MANLOCALES"
62*c535eb59SGordon Tetlow}
63*c535eb59SGordon Tetlow
64*c535eb59SGordon Tetlow# Usage: build_manpath
65*c535eb59SGordon Tetlow# Builds a correct MANPATH variable.
66*c535eb59SGordon Tetlowbuild_manpath() {
67*c535eb59SGordon Tetlow	local IFS
68*c535eb59SGordon Tetlow
69*c535eb59SGordon Tetlow	# If the user has set a manpath, who are we to argue.
70*c535eb59SGordon Tetlow	if [ -n "$MANPATH" ]; then
71*c535eb59SGordon Tetlow		return
72*c535eb59SGordon Tetlow	fi
73*c535eb59SGordon Tetlow
74*c535eb59SGordon Tetlow	search_path
75*c535eb59SGordon Tetlow
76*c535eb59SGordon Tetlow	decho "Adding default manpath entries"
77*c535eb59SGordon Tetlow	IFS=:
78*c535eb59SGordon Tetlow	for path in $man_default_path; do
79*c535eb59SGordon Tetlow		add_to_manpath "$path"
80*c535eb59SGordon Tetlow	done
81*c535eb59SGordon Tetlow	unset IFS
82*c535eb59SGordon Tetlow
83*c535eb59SGordon Tetlow	parse_configs
84*c535eb59SGordon Tetlow
85*c535eb59SGordon Tetlow	# Trim leading colon
86*c535eb59SGordon Tetlow	MANPATH=${manpath#:}
87*c535eb59SGordon Tetlow
88*c535eb59SGordon Tetlow	decho "Using manual path: $MANPATH"
89*c535eb59SGordon Tetlow}
90*c535eb59SGordon Tetlow
91*c535eb59SGordon Tetlow# Usage: check_cat catglob
92*c535eb59SGordon Tetlow# Checks to see if a cat glob is available.
93*c535eb59SGordon Tetlowcheck_cat() {
94*c535eb59SGordon Tetlow	if exists "$1"; then
95*c535eb59SGordon Tetlow		use_cat=yes
96*c535eb59SGordon Tetlow		catpage=$found
97*c535eb59SGordon Tetlow		decho "    Found catpage $catpage"
98*c535eb59SGordon Tetlow		return 0
99*c535eb59SGordon Tetlow	else
100*c535eb59SGordon Tetlow		return 1
101*c535eb59SGordon Tetlow	fi
102*c535eb59SGordon Tetlow}
103*c535eb59SGordon Tetlow
104*c535eb59SGordon Tetlow# Usage: check_man manglob catglob
105*c535eb59SGordon Tetlow# Given 2 globs, figures out if the manglob is available, if so, check to
106*c535eb59SGordon Tetlow# see if the catglob is also available and up to date.
107*c535eb59SGordon Tetlowcheck_man() {
108*c535eb59SGordon Tetlow	if exists "$1"; then
109*c535eb59SGordon Tetlow		# We have a match, check for a cat page
110*c535eb59SGordon Tetlow		manpage=$found
111*c535eb59SGordon Tetlow		decho "    Found manpage $manpage"
112*c535eb59SGordon Tetlow
113*c535eb59SGordon Tetlow		if exists "$2" && is_newer $found $manpage; then
114*c535eb59SGordon Tetlow			# cat page found and is newer, use that
115*c535eb59SGordon Tetlow			use_cat=yes
116*c535eb59SGordon Tetlow			catpage=$found
117*c535eb59SGordon Tetlow			decho "    Using catpage $catpage"
118*c535eb59SGordon Tetlow		else
119*c535eb59SGordon Tetlow			# no cat page or is older
120*c535eb59SGordon Tetlow			unset use_cat
121*c535eb59SGordon Tetlow			decho "    Skipping catpage: not found or old"
122*c535eb59SGordon Tetlow		fi
123*c535eb59SGordon Tetlow		return 0
124*c535eb59SGordon Tetlow	fi
125*c535eb59SGordon Tetlow
126*c535eb59SGordon Tetlow	return 1
127*c535eb59SGordon Tetlow}
128*c535eb59SGordon Tetlow
129*c535eb59SGordon Tetlow# Usage: decho "string" [debuglevel]
130*c535eb59SGordon Tetlow# Echoes to stderr string prefaced with -- if high enough debuglevel.
131*c535eb59SGordon Tetlowdecho() {
132*c535eb59SGordon Tetlow	if [ $debug -ge ${2:-1} ]; then
133*c535eb59SGordon Tetlow		echo "-- $1" >&2
134*c535eb59SGordon Tetlow	fi
135*c535eb59SGordon Tetlow}
136*c535eb59SGordon Tetlow
137*c535eb59SGordon Tetlow# Usage: exists glob
138*c535eb59SGordon Tetlow# Returns true if glob resolves to a real file.
139*c535eb59SGordon Tetlowexists() {
140*c535eb59SGordon Tetlow	local IFS
141*c535eb59SGordon Tetlow
142*c535eb59SGordon Tetlow	# Don't accidentally inherit callers IFS (breaks perl manpages)
143*c535eb59SGordon Tetlow	unset IFS
144*c535eb59SGordon Tetlow
145*c535eb59SGordon Tetlow	# Use some globbing tricks in the shell to determine if a file
146*c535eb59SGordon Tetlow	# exists or not.
147*c535eb59SGordon Tetlow	set +f
148*c535eb59SGordon Tetlow	set -- "$1" $1
149*c535eb59SGordon Tetlow	set -f
150*c535eb59SGordon Tetlow
151*c535eb59SGordon Tetlow	if [ "$1" != "$2" -a -r "$2" ]; then
152*c535eb59SGordon Tetlow		found="$2"
153*c535eb59SGordon Tetlow		return 0
154*c535eb59SGordon Tetlow	fi
155*c535eb59SGordon Tetlow
156*c535eb59SGordon Tetlow	return 1
157*c535eb59SGordon Tetlow}
158*c535eb59SGordon Tetlow
159*c535eb59SGordon Tetlow# Usage: find_file path section subdir pagename
160*c535eb59SGordon Tetlow# Returns: true if something is matched and found.
161*c535eb59SGordon Tetlow# Search the given path/section combo for a given page.
162*c535eb59SGordon Tetlowfind_file() {
163*c535eb59SGordon Tetlow	local manroot catroot mann man0 catn cat0
164*c535eb59SGordon Tetlow
165*c535eb59SGordon Tetlow	manroot="$1/man$2"
166*c535eb59SGordon Tetlow	catroot="$1/cat$2"
167*c535eb59SGordon Tetlow	if [ -n "$3" ]; then
168*c535eb59SGordon Tetlow		manroot="$manroot/$3"
169*c535eb59SGordon Tetlow		catroot="$catroot/$3"
170*c535eb59SGordon Tetlow	fi
171*c535eb59SGordon Tetlow
172*c535eb59SGordon Tetlow	if [ ! -d "$manroot" ]; then
173*c535eb59SGordon Tetlow		return 1
174*c535eb59SGordon Tetlow	fi
175*c535eb59SGordon Tetlow	decho "  Searching directory $manroot" 2
176*c535eb59SGordon Tetlow
177*c535eb59SGordon Tetlow	mann="$manroot/$4.$2*"
178*c535eb59SGordon Tetlow	man0="$manroot/$4.0*"
179*c535eb59SGordon Tetlow	catn="$catroot/$4.$2*"
180*c535eb59SGordon Tetlow	cat0="$catroot/$4.0*"
181*c535eb59SGordon Tetlow
182*c535eb59SGordon Tetlow	# This is the behavior as seen by the original man utility.
183*c535eb59SGordon Tetlow	# Let's not change that which doesn't seem broken.
184*c535eb59SGordon Tetlow	if check_man "$mann" "$catn"; then
185*c535eb59SGordon Tetlow		return 0
186*c535eb59SGordon Tetlow	elif check_man "$man0" "$cat0"; then
187*c535eb59SGordon Tetlow		return 0
188*c535eb59SGordon Tetlow	elif check_cat "$catn"; then
189*c535eb59SGordon Tetlow		return 0
190*c535eb59SGordon Tetlow	elif check_cat "$cat0"; then
191*c535eb59SGordon Tetlow		return 0
192*c535eb59SGordon Tetlow	fi
193*c535eb59SGordon Tetlow
194*c535eb59SGordon Tetlow	return 1
195*c535eb59SGordon Tetlow}
196*c535eb59SGordon Tetlow
197*c535eb59SGordon Tetlow# Usage: is_newer file1 file2
198*c535eb59SGordon Tetlow# Returns true if file1 is newer than file2 as calculated by mtime.
199*c535eb59SGordon Tetlowis_newer() {
200*c535eb59SGordon Tetlow	if [ $(stat -f %m $1) -gt $(stat -f %m $2) ]; then
201*c535eb59SGordon Tetlow		decho "    mtime: $1 newer than $2" 3
202*c535eb59SGordon Tetlow		return 0
203*c535eb59SGordon Tetlow	else
204*c535eb59SGordon Tetlow		decho "    mtime: $1 older than $2" 3
205*c535eb59SGordon Tetlow		return 1
206*c535eb59SGordon Tetlow	fi
207*c535eb59SGordon Tetlow}
208*c535eb59SGordon Tetlow
209*c535eb59SGordon Tetlow# Usage: manpath_parse_args "$@"
210*c535eb59SGordon Tetlow# Parses commandline options for manpath.
211*c535eb59SGordon Tetlowmanpath_parse_args() {
212*c535eb59SGordon Tetlow	local cmd_arg
213*c535eb59SGordon Tetlow
214*c535eb59SGordon Tetlow	while getopts 'Ldq' cmd_arg; do
215*c535eb59SGordon Tetlow		case "${cmd_arg}" in
216*c535eb59SGordon Tetlow		L)	Lflag=Lflag ;;
217*c535eb59SGordon Tetlow		d)	debug=$(( $debug + 1 )) ;;
218*c535eb59SGordon Tetlow		q)	qflag=qflag ;;
219*c535eb59SGordon Tetlow		*)	manpath_usage ;;
220*c535eb59SGordon Tetlow		esac
221*c535eb59SGordon Tetlow	done >&2
222*c535eb59SGordon Tetlow}
223*c535eb59SGordon Tetlow
224*c535eb59SGordon Tetlow# Usage: manpath_usage
225*c535eb59SGordon Tetlow# Display usage for the manpath(1) utility.
226*c535eb59SGordon Tetlowmanpath_usage() {
227*c535eb59SGordon Tetlow	echo 'usage: manpath [-Ldq]' >&2
228*c535eb59SGordon Tetlow	exit 1
229*c535eb59SGordon Tetlow}
230*c535eb59SGordon Tetlow
231*c535eb59SGordon Tetlow# Usage: manpath_warnings
232*c535eb59SGordon Tetlow# Display some warnings to stderr.
233*c535eb59SGordon Tetlowmanpath_warnings() {
234*c535eb59SGordon Tetlow	if [ -z "$Lflag" -a -n "$MANPATH" ]; then
235*c535eb59SGordon Tetlow		echo "(Warning: MANPATH environment variable set)" >&2
236*c535eb59SGordon Tetlow	fi
237*c535eb59SGordon Tetlow
238*c535eb59SGordon Tetlow	if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then
239*c535eb59SGordon Tetlow		echo "(Warning: MANLOCALES environment variable set)" >&2
240*c535eb59SGordon Tetlow	fi
241*c535eb59SGordon Tetlow}
242*c535eb59SGordon Tetlow
243*c535eb59SGordon Tetlow# Usage: man_display_page
244*c535eb59SGordon Tetlow# Display either the manpage or catpage depending on the use_cat variable
245*c535eb59SGordon Tetlowman_display_page() {
246*c535eb59SGordon Tetlow	local EQN COL NROFF PIC TBL TROFF REFER VGRIND
247*c535eb59SGordon Tetlow	local IFS l nroff_dev pipeline preproc_arg tool
248*c535eb59SGordon Tetlow
249*c535eb59SGordon Tetlow	# We are called with IFS set to colon. This causes really weird
250*c535eb59SGordon Tetlow	# things to happen for the variables that have spaces in them.
251*c535eb59SGordon Tetlow	unset IFS
252*c535eb59SGordon Tetlow
253*c535eb59SGordon Tetlow	# If we are supposed to use a catpage and we aren't using troff(1)
254*c535eb59SGordon Tetlow	# just zcat the catpage and we are done.
255*c535eb59SGordon Tetlow	if [ -z "$tflag" -a -n "$use_cat" ]; then
256*c535eb59SGordon Tetlow		if [ -n "$wflag" ]; then
257*c535eb59SGordon Tetlow			echo "$catpage (source: $manpage)"
258*c535eb59SGordon Tetlow			ret=0
259*c535eb59SGordon Tetlow		else
260*c535eb59SGordon Tetlow			if [ $debug -gt 0 ]; then
261*c535eb59SGordon Tetlow				decho "Command: $ZCAT $catpage | $PAGER"
262*c535eb59SGordon Tetlow				ret=0
263*c535eb59SGordon Tetlow			else
264*c535eb59SGordon Tetlow				eval "$ZCAT $catpage | $PAGER"
265*c535eb59SGordon Tetlow				ret=$?
266*c535eb59SGordon Tetlow			fi
267*c535eb59SGordon Tetlow		fi
268*c535eb59SGordon Tetlow		return
269*c535eb59SGordon Tetlow	fi
270*c535eb59SGordon Tetlow
271*c535eb59SGordon Tetlow	# Okay, we are using the manpage, do we just need to output the
272*c535eb59SGordon Tetlow	# name of the manpage?
273*c535eb59SGordon Tetlow	if [ -n "$wflag" ]; then
274*c535eb59SGordon Tetlow		echo "$manpage"
275*c535eb59SGordon Tetlow		ret=0
276*c535eb59SGordon Tetlow		return
277*c535eb59SGordon Tetlow	fi
278*c535eb59SGordon Tetlow
279*c535eb59SGordon Tetlow	# So, we really do need to parse the manpage. First, figure out the
280*c535eb59SGordon Tetlow	# device flag (-T) we have to pass to eqn(1) and groff(1). Then,
281*c535eb59SGordon Tetlow	# setup the pipeline of commands based on the user's request.
282*c535eb59SGordon Tetlow
283*c535eb59SGordon Tetlow	# Apparently the locale flags are switched on where the manpage is
284*c535eb59SGordon Tetlow	# found not just the locale env variables.
285*c535eb59SGordon Tetlow	nroff_dev="ascii"
286*c535eb59SGordon Tetlow	case "X${use_locale}X${manpage}" in
287*c535eb59SGordon Tetlow	XyesX*/${man_lang}*${man_charset}/*)
288*c535eb59SGordon Tetlow		# I don't pretend to know this; I'm just copying from the
289*c535eb59SGordon Tetlow		# previous version of man(1).
290*c535eb59SGordon Tetlow		case "$man_charset" in
291*c535eb59SGordon Tetlow		KOI8-R)		nroff_dev="koi8-r" ;;
292*c535eb59SGordon Tetlow		ISO8859-1)	nroff_dev="latin1" ;;
293*c535eb59SGordon Tetlow		ISO8859-15)	nroff_dev="latin1" ;;
294*c535eb59SGordon Tetlow		UTF-8)		nroff_dev="utf8" ;;
295*c535eb59SGordon Tetlow		*)		nroff_dev="ascii" ;;
296*c535eb59SGordon Tetlow		esac
297*c535eb59SGordon Tetlow
298*c535eb59SGordon Tetlow		NROFF="$NROFF -T$nroff_dev -dlocale=$man_lang.$man_charset"
299*c535eb59SGordon Tetlow		EQN="$EQN -T$nroff_dev"
300*c535eb59SGordon Tetlow
301*c535eb59SGordon Tetlow		# Allow language specific calls to override the default
302*c535eb59SGordon Tetlow		# set of utilities.
303*c535eb59SGordon Tetlow		l=$(echo $man_lang | tr [:lower:] [:upper:])
304*c535eb59SGordon Tetlow		for tool in EQN COL NROFF PIC TBL TROFF REFER VGRIND; do
305*c535eb59SGordon Tetlow			eval "$tool=\${${tool}_$l:-\$$tool}"
306*c535eb59SGordon Tetlow		done
307*c535eb59SGordon Tetlow		;;
308*c535eb59SGordon Tetlow	*)	NROFF="$NROFF -Tascii"
309*c535eb59SGordon Tetlow		EQN="$EQN -Tascii"
310*c535eb59SGordon Tetlow		;;
311*c535eb59SGordon Tetlow	esac
312*c535eb59SGordon Tetlow
313*c535eb59SGordon Tetlow	if [ -n "$MANROFFSEQ" ]; then
314*c535eb59SGordon Tetlow		set -- -$MANROFFSEQ
315*c535eb59SGordon Tetlow		while getopts 'egprtv' preproc_arg; do
316*c535eb59SGordon Tetlow			case "${preproc_arg}" in
317*c535eb59SGordon Tetlow			e)	pipeline="$pipeline | $EQN" ;;
318*c535eb59SGordon Tetlow			g)	;; # Ignore for compatability.
319*c535eb59SGordon Tetlow			p)	pipeline="$pipeline | $PIC" ;;
320*c535eb59SGordon Tetlow			r)	pipeline="$pipeline | $REFER" ;;
321*c535eb59SGordon Tetlow			t)	pipeline="$pipeline | $TBL"; use_col=yes ;;
322*c535eb59SGordon Tetlow			v)	pipeline="$pipeline | $VGRIND" ;;
323*c535eb59SGordon Tetlow			*)	usage ;;
324*c535eb59SGordon Tetlow			esac
325*c535eb59SGordon Tetlow		done
326*c535eb59SGordon Tetlow		# Strip the leading " | " from the resulting pipeline.
327*c535eb59SGordon Tetlow		pipeline="${pipeline#" | "}"
328*c535eb59SGordon Tetlow	else
329*c535eb59SGordon Tetlow		pipeline="$TBL"
330*c535eb59SGordon Tetlow		use_col=yes
331*c535eb59SGordon Tetlow	fi
332*c535eb59SGordon Tetlow
333*c535eb59SGordon Tetlow	if [ -n "$tflag" ]; then
334*c535eb59SGordon Tetlow		pipeline="$pipeline | $TROFF"
335*c535eb59SGordon Tetlow	else
336*c535eb59SGordon Tetlow		pipeline="$pipeline | $NROFF"
337*c535eb59SGordon Tetlow
338*c535eb59SGordon Tetlow		if [ -n "$use_col" ]; then
339*c535eb59SGordon Tetlow			pipeline="$pipeline | $COL"
340*c535eb59SGordon Tetlow		fi
341*c535eb59SGordon Tetlow
342*c535eb59SGordon Tetlow		pipeline="$pipeline | $PAGER"
343*c535eb59SGordon Tetlow	fi
344*c535eb59SGordon Tetlow
345*c535eb59SGordon Tetlow	if [ $debug -gt 0 ]; then
346*c535eb59SGordon Tetlow		decho "Command: $ZCAT $manpage | $pipeline"
347*c535eb59SGordon Tetlow		ret=0
348*c535eb59SGordon Tetlow	else
349*c535eb59SGordon Tetlow		eval "$ZCAT $manpage | $pipeline"
350*c535eb59SGordon Tetlow		ret=$?
351*c535eb59SGordon Tetlow	fi
352*c535eb59SGordon Tetlow}
353*c535eb59SGordon Tetlow
354*c535eb59SGordon Tetlow# Usage: man_find_and_display page
355*c535eb59SGordon Tetlow# Search through the manpaths looking for the given page.
356*c535eb59SGordon Tetlowman_find_and_display() {
357*c535eb59SGordon Tetlow	local found_page locpath p path sect
358*c535eb59SGordon Tetlow
359*c535eb59SGordon Tetlow	IFS=:
360*c535eb59SGordon Tetlow	for sect in $MANSECT; do
361*c535eb59SGordon Tetlow		decho "Searching section $sect" 2
362*c535eb59SGordon Tetlow		for path in $MANPATH; do
363*c535eb59SGordon Tetlow			for locpath in $locpaths; do
364*c535eb59SGordon Tetlow				p=$path/$locpath
365*c535eb59SGordon Tetlow				p=${p%/.} # Rid ourselves of the trailing /.
366*c535eb59SGordon Tetlow
367*c535eb59SGordon Tetlow				# Check if there is a MACHINE specific manpath.
368*c535eb59SGordon Tetlow				if find_file $p $sect $MACHINE "$1"; then
369*c535eb59SGordon Tetlow					found_page=yes
370*c535eb59SGordon Tetlow					man_display_page
371*c535eb59SGordon Tetlow					if [ -z "$aflag" ]; then
372*c535eb59SGordon Tetlow						return
373*c535eb59SGordon Tetlow					fi
374*c535eb59SGordon Tetlow				fi
375*c535eb59SGordon Tetlow
376*c535eb59SGordon Tetlow				# Check if there is a MACHINE_ARCH
377*c535eb59SGordon Tetlow				# specific manpath.
378*c535eb59SGordon Tetlow				if find_file $p $sect $MACHINE_ARCH "$1"; then
379*c535eb59SGordon Tetlow					found_page=yes
380*c535eb59SGordon Tetlow					man_display_page
381*c535eb59SGordon Tetlow					if [ -z "$aflag" ]; then
382*c535eb59SGordon Tetlow						return
383*c535eb59SGordon Tetlow					fi
384*c535eb59SGordon Tetlow				fi
385*c535eb59SGordon Tetlow
386*c535eb59SGordon Tetlow				# Check plain old manpath.
387*c535eb59SGordon Tetlow				if find_file $p $sect '' "$1"; then
388*c535eb59SGordon Tetlow					found_page=yes
389*c535eb59SGordon Tetlow					man_display_page
390*c535eb59SGordon Tetlow					if [ -z "$aflag" ]; then
391*c535eb59SGordon Tetlow						return
392*c535eb59SGordon Tetlow					fi
393*c535eb59SGordon Tetlow				fi
394*c535eb59SGordon Tetlow			done
395*c535eb59SGordon Tetlow		done
396*c535eb59SGordon Tetlow	done
397*c535eb59SGordon Tetlow	unset IFS
398*c535eb59SGordon Tetlow
399*c535eb59SGordon Tetlow	# Nothing? Well, we are done then.
400*c535eb59SGordon Tetlow	if [ -z "$found_page" ]; then
401*c535eb59SGordon Tetlow		echo "No manual entry for $1" >&2
402*c535eb59SGordon Tetlow		ret=1
403*c535eb59SGordon Tetlow		return
404*c535eb59SGordon Tetlow	fi
405*c535eb59SGordon Tetlow}
406*c535eb59SGordon Tetlow
407*c535eb59SGordon Tetlow# Usage: man_parse_args "$@"
408*c535eb59SGordon Tetlow# Parses commandline options for man.
409*c535eb59SGordon Tetlowman_parse_args() {
410*c535eb59SGordon Tetlow	local IFS cmd_arg
411*c535eb59SGordon Tetlow
412*c535eb59SGordon Tetlow	while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do
413*c535eb59SGordon Tetlow		case "${cmd_arg}" in
414*c535eb59SGordon Tetlow		M)	MANPATH=$OPTARG ;;
415*c535eb59SGordon Tetlow		P)	PAGER=$OPTARG ;;
416*c535eb59SGordon Tetlow		S)	MANSECT=$OPTARG ;;
417*c535eb59SGordon Tetlow		a)	aflag=aflag ;;
418*c535eb59SGordon Tetlow		d)	debug=$(( $debug + 1 )) ;;
419*c535eb59SGordon Tetlow		f)	fflag=fflag ;;
420*c535eb59SGordon Tetlow		h)	man_usage 0 ;;
421*c535eb59SGordon Tetlow		k)	kflag=kflag ;;
422*c535eb59SGordon Tetlow		m)	mflag=$OPTARG ;;
423*c535eb59SGordon Tetlow		o)	oflag=oflag ;;
424*c535eb59SGordon Tetlow		p)	MANROFFSEQ=$OPTARG ;;
425*c535eb59SGordon Tetlow		t)	tflag=tflag ;;
426*c535eb59SGordon Tetlow		w)	wflag=wflag ;;
427*c535eb59SGordon Tetlow		*)	man_usage ;;
428*c535eb59SGordon Tetlow		esac
429*c535eb59SGordon Tetlow	done >&2
430*c535eb59SGordon Tetlow
431*c535eb59SGordon Tetlow	shift $(( $OPTIND - 1 ))
432*c535eb59SGordon Tetlow
433*c535eb59SGordon Tetlow	# Check the args for incompatible options.
434*c535eb59SGordon Tetlow	case "${fflag}${kflag}${tflag}${wflag}" in
435*c535eb59SGordon Tetlow	fflagkflag*)	echo "Incompatible options: -f and -k"; man_usage ;;
436*c535eb59SGordon Tetlow	fflag*tflag*)	echo "Incompatible options: -f and -t"; man_usage ;;
437*c535eb59SGordon Tetlow	fflag*wflag)	echo "Incompatible options: -f and -w"; man_usage ;;
438*c535eb59SGordon Tetlow	*kflagtflag*)	echo "Incompatible options: -k and -t"; man_usage ;;
439*c535eb59SGordon Tetlow	*kflag*wflag)	echo "Incompatible options: -k and -w"; man_usage ;;
440*c535eb59SGordon Tetlow	*tflagwflag)	echo "Incompatible options: -t and -w"; man_usage ;;
441*c535eb59SGordon Tetlow	esac
442*c535eb59SGordon Tetlow
443*c535eb59SGordon Tetlow	# Short circuit for whatis(1) and apropos(1)
444*c535eb59SGordon Tetlow	if [ -n "$fflag" ]; then
445*c535eb59SGordon Tetlow		do_whatis "$@"
446*c535eb59SGordon Tetlow		exit
447*c535eb59SGordon Tetlow	fi
448*c535eb59SGordon Tetlow
449*c535eb59SGordon Tetlow	if [ -n "$kflag" ]; then
450*c535eb59SGordon Tetlow		do_apropos "$@"
451*c535eb59SGordon Tetlow		exit
452*c535eb59SGordon Tetlow	fi
453*c535eb59SGordon Tetlow
454*c535eb59SGordon Tetlow	IFS=:
455*c535eb59SGordon Tetlow	for sect in $man_default_sections; do
456*c535eb59SGordon Tetlow		if [ "$sect" = "$1" ]; then
457*c535eb59SGordon Tetlow			decho "Detected manual section as first arg: $1"
458*c535eb59SGordon Tetlow			MANSECT="$1"
459*c535eb59SGordon Tetlow			shift
460*c535eb59SGordon Tetlow			break
461*c535eb59SGordon Tetlow		fi
462*c535eb59SGordon Tetlow	done
463*c535eb59SGordon Tetlow	unset IFS
464*c535eb59SGordon Tetlow
465*c535eb59SGordon Tetlow	pages="$*"
466*c535eb59SGordon Tetlow}
467*c535eb59SGordon Tetlow
468*c535eb59SGordon Tetlow# Usage: man_setup
469*c535eb59SGordon Tetlow# Setup various trivial but essential variables.
470*c535eb59SGordon Tetlowman_setup() {
471*c535eb59SGordon Tetlow	# Setup machine and architecture variables.
472*c535eb59SGordon Tetlow	if [ -n "$mflag" ]; then
473*c535eb59SGordon Tetlow		MACHINE_ARCH=${mflag%%:*}
474*c535eb59SGordon Tetlow		MACHINE=${mflag##*:}
475*c535eb59SGordon Tetlow	fi
476*c535eb59SGordon Tetlow	if [ -z "$MACHINE_ARCH" ]; then
477*c535eb59SGordon Tetlow		MACHINE_ARCH=$(sysctl -n hw.machine_arch)
478*c535eb59SGordon Tetlow	fi
479*c535eb59SGordon Tetlow	if [ -z "$MACHINE" ]; then
480*c535eb59SGordon Tetlow		MACHINE=$(sysctl -n hw.machine)
481*c535eb59SGordon Tetlow	fi
482*c535eb59SGordon Tetlow	decho "Using architecture: $MACHINE_ARCH:$MACHINE"
483*c535eb59SGordon Tetlow
484*c535eb59SGordon Tetlow	setup_pager
485*c535eb59SGordon Tetlow
486*c535eb59SGordon Tetlow	# Setup manual sections to search.
487*c535eb59SGordon Tetlow	if [ -z "$MANSECT" ]; then
488*c535eb59SGordon Tetlow		MANSECT=$man_default_sections
489*c535eb59SGordon Tetlow	fi
490*c535eb59SGordon Tetlow	decho "Using manual sections: $MANSECT"
491*c535eb59SGordon Tetlow
492*c535eb59SGordon Tetlow	build_manpath
493*c535eb59SGordon Tetlow	man_setup_locale
494*c535eb59SGordon Tetlow}
495*c535eb59SGordon Tetlow
496*c535eb59SGordon Tetlow# Usage: man_setup_locale
497*c535eb59SGordon Tetlow# Setup necessary locale variables.
498*c535eb59SGordon Tetlowman_setup_locale() {
499*c535eb59SGordon Tetlow	# Setup locale information.
500*c535eb59SGordon Tetlow	if [ -n "$oflag" ]; then
501*c535eb59SGordon Tetlow		decho "Using non-localized manpages"
502*c535eb59SGordon Tetlow		unset use_locale
503*c535eb59SGordon Tetlow	elif [ -n "$LC_ALL" ]; then
504*c535eb59SGordon Tetlow		parse_locale "$LC_ALL"
505*c535eb59SGordon Tetlow	elif [ -n "$LC_CTYPE" ]; then
506*c535eb59SGordon Tetlow		parse_locale "$LC_CTYPE"
507*c535eb59SGordon Tetlow	elif [ -n "$LANG" ]; then
508*c535eb59SGordon Tetlow		parse_locale "$LANG"
509*c535eb59SGordon Tetlow	fi
510*c535eb59SGordon Tetlow
511*c535eb59SGordon Tetlow	if [ -n "$use_locale" ]; then
512*c535eb59SGordon Tetlow		locpaths="${man_lang}_${man_country}.${man_charset}"
513*c535eb59SGordon Tetlow		locpaths="$locpaths:$man_lang.$man_charset"
514*c535eb59SGordon Tetlow		if [ "$man_lang" != "en" ]; then
515*c535eb59SGordon Tetlow			locpaths="$locpaths:en.$man_charset"
516*c535eb59SGordon Tetlow		fi
517*c535eb59SGordon Tetlow		locpaths="$locpaths:."
518*c535eb59SGordon Tetlow	else
519*c535eb59SGordon Tetlow		locpaths="."
520*c535eb59SGordon Tetlow	fi
521*c535eb59SGordon Tetlow	decho "Using locale paths: $locpaths"
522*c535eb59SGordon Tetlow}
523*c535eb59SGordon Tetlow
524*c535eb59SGordon Tetlow# Usage: man_usage [exitcode]
525*c535eb59SGordon Tetlow# Display usage for the man utility.
526*c535eb59SGordon Tetlowman_usage() {
527*c535eb59SGordon Tetlow	echo 'Usage:'
528*c535eb59SGordon Tetlow	echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]'
529*c535eb59SGordon Tetlow	echo '     [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]'
530*c535eb59SGordon Tetlow	echo ' man -f page [...] -- Emulates whatis(1)'
531*c535eb59SGordon Tetlow	echo ' man -k page [...] -- Emulates apropos(1)'
532*c535eb59SGordon Tetlow
533*c535eb59SGordon Tetlow	# When exit'ing with -h, it's not an error.
534*c535eb59SGordon Tetlow	exit ${1:-1}
535*c535eb59SGordon Tetlow}
536*c535eb59SGordon Tetlow
537*c535eb59SGordon Tetlow# Usage: parse_configs
538*c535eb59SGordon Tetlow# Reads the end-user adjustable config files.
539*c535eb59SGordon Tetlowparse_configs() {
540*c535eb59SGordon Tetlow	local IFS file files
541*c535eb59SGordon Tetlow
542*c535eb59SGordon Tetlow	if [ -n "$parsed_configs" ]; then
543*c535eb59SGordon Tetlow		return
544*c535eb59SGordon Tetlow	fi
545*c535eb59SGordon Tetlow
546*c535eb59SGordon Tetlow	unset IFS
547*c535eb59SGordon Tetlow
548*c535eb59SGordon Tetlow	# Read the global config first in case the user wants
549*c535eb59SGordon Tetlow	# to override config_local.
550*c535eb59SGordon Tetlow	if [ -r "$config_global" ]; then
551*c535eb59SGordon Tetlow		parse_file "$config_global"
552*c535eb59SGordon Tetlow	fi
553*c535eb59SGordon Tetlow
554*c535eb59SGordon Tetlow	# Glob the list of files to parse.
555*c535eb59SGordon Tetlow	set +f
556*c535eb59SGordon Tetlow	files=$(echo $config_local)
557*c535eb59SGordon Tetlow	set -f
558*c535eb59SGordon Tetlow
559*c535eb59SGordon Tetlow	for file in $files; do
560*c535eb59SGordon Tetlow		if [ -r "$file" ]; then
561*c535eb59SGordon Tetlow			parse_file "$file"
562*c535eb59SGordon Tetlow		fi
563*c535eb59SGordon Tetlow	done
564*c535eb59SGordon Tetlow
565*c535eb59SGordon Tetlow	parsed_configs='yes'
566*c535eb59SGordon Tetlow}
567*c535eb59SGordon Tetlow
568*c535eb59SGordon Tetlow# Usage: parse_file file
569*c535eb59SGordon Tetlow# Reads the specified config files.
570*c535eb59SGordon Tetlowparse_file() {
571*c535eb59SGordon Tetlow	local file line tstr var
572*c535eb59SGordon Tetlow
573*c535eb59SGordon Tetlow	file="$1"
574*c535eb59SGordon Tetlow	decho "Parsing config file: $file"
575*c535eb59SGordon Tetlow	while read line; do
576*c535eb59SGordon Tetlow		decho "  $line" 2
577*c535eb59SGordon Tetlow		case "$line" in
578*c535eb59SGordon Tetlow		\#*)		decho "    Comment" 3
579*c535eb59SGordon Tetlow				;;
580*c535eb59SGordon Tetlow		MANPATH*)	decho "    MANPATH" 3
581*c535eb59SGordon Tetlow				trim "${line#MANPATH}"
582*c535eb59SGordon Tetlow				add_to_manpath "$tstr"
583*c535eb59SGordon Tetlow				;;
584*c535eb59SGordon Tetlow		MANLOCALE*)	decho "    MANLOCALE" 3
585*c535eb59SGordon Tetlow				trim "${line#MANLOCALE}"
586*c535eb59SGordon Tetlow				manlocales="$manlocales:$tstr"
587*c535eb59SGordon Tetlow				;;
588*c535eb59SGordon Tetlow		MANCONFIG*)	decho "    MANCONFIG" 3
589*c535eb59SGordon Tetlow				trim "${line#MANCONF}"
590*c535eb59SGordon Tetlow				config_local="$tstr"
591*c535eb59SGordon Tetlow				;;
592*c535eb59SGordon Tetlow		# Set variables in the form of FOO_BAR
593*c535eb59SGordon Tetlow		*_*[\ \	]*)	var="${line%%[\ \	]*}"
594*c535eb59SGordon Tetlow				trim "${line#$var}"
595*c535eb59SGordon Tetlow				eval "$var=\"$tstr\""
596*c535eb59SGordon Tetlow				decho "    Parsed $var" 3
597*c535eb59SGordon Tetlow				;;
598*c535eb59SGordon Tetlow		esac
599*c535eb59SGordon Tetlow	done < "$file"
600*c535eb59SGordon Tetlow}
601*c535eb59SGordon Tetlow
602*c535eb59SGordon Tetlow# Usage: parse_locale localestring
603*c535eb59SGordon Tetlow# Setup locale variables for proper parsing.
604*c535eb59SGordon Tetlowparse_locale() {
605*c535eb59SGordon Tetlow	local lang_cc
606*c535eb59SGordon Tetlow
607*c535eb59SGordon Tetlow	case "$1" in
608*c535eb59SGordon Tetlow	C)				;;
609*c535eb59SGordon Tetlow	POSIX)				;;
610*c535eb59SGordon Tetlow	[a-z][a-z]_[A-Z][A-Z]\.*)	lang_cc="${1%.*}"
611*c535eb59SGordon Tetlow					man_lang="${1%_*}"
612*c535eb59SGordon Tetlow					man_country="${lang_cc#*_}"
613*c535eb59SGordon Tetlow					man_charset="${1#*.}"
614*c535eb59SGordon Tetlow					use_locale=yes
615*c535eb59SGordon Tetlow					return 0
616*c535eb59SGordon Tetlow					;;
617*c535eb59SGordon Tetlow	*)				echo 'Unknown locale, assuming C' >&2
618*c535eb59SGordon Tetlow					;;
619*c535eb59SGordon Tetlow	esac
620*c535eb59SGordon Tetlow
621*c535eb59SGordon Tetlow	unset use_locale
622*c535eb59SGordon Tetlow}
623*c535eb59SGordon Tetlow
624*c535eb59SGordon Tetlow# Usage: search_path
625*c535eb59SGordon Tetlow# Traverse $PATH looking for manpaths.
626*c535eb59SGordon Tetlowsearch_path() {
627*c535eb59SGordon Tetlow	local IFS p path
628*c535eb59SGordon Tetlow
629*c535eb59SGordon Tetlow	decho "Searching PATH for man directories"
630*c535eb59SGordon Tetlow
631*c535eb59SGordon Tetlow	IFS=:
632*c535eb59SGordon Tetlow	for path in $PATH; do
633*c535eb59SGordon Tetlow		# Do a little special casing since the base manpages
634*c535eb59SGordon Tetlow		# are in /usr/share/man instead of /usr/man or /man.
635*c535eb59SGordon Tetlow		case "$path" in
636*c535eb59SGordon Tetlow		/bin|/usr/bin)	add_to_manpath "/usr/share/man" ;;
637*c535eb59SGordon Tetlow		*)	if add_to_manpath "$path/man"; then
638*c535eb59SGordon Tetlow				:
639*c535eb59SGordon Tetlow			elif add_to_manpath "$path/MAN"; then
640*c535eb59SGordon Tetlow				:
641*c535eb59SGordon Tetlow			else
642*c535eb59SGordon Tetlow				case "$path" in
643*c535eb59SGordon Tetlow				*/bin)	p="${path%/bin}/man"
644*c535eb59SGordon Tetlow					add_to_manpath "$p"
645*c535eb59SGordon Tetlow					;;
646*c535eb59SGordon Tetlow				*)	;;
647*c535eb59SGordon Tetlow				esac
648*c535eb59SGordon Tetlow			fi
649*c535eb59SGordon Tetlow			;;
650*c535eb59SGordon Tetlow		esac
651*c535eb59SGordon Tetlow	done
652*c535eb59SGordon Tetlow	unset IFS
653*c535eb59SGordon Tetlow
654*c535eb59SGordon Tetlow	if [ -z "$manpath" ]; then
655*c535eb59SGordon Tetlow		decho '  Unable to find any manpaths, using default'
656*c535eb59SGordon Tetlow		manpath=$man_default_path
657*c535eb59SGordon Tetlow	fi
658*c535eb59SGordon Tetlow}
659*c535eb59SGordon Tetlow
660*c535eb59SGordon Tetlow# Usage: search_whatis cmd [arglist]
661*c535eb59SGordon Tetlow# Do the heavy lifting for apropos/whatis
662*c535eb59SGordon Tetlowsearch_whatis() {
663*c535eb59SGordon Tetlow	local IFS bad cmd f good key keywords loc opt out path rval wlist
664*c535eb59SGordon Tetlow
665*c535eb59SGordon Tetlow	cmd="$1"
666*c535eb59SGordon Tetlow	shift
667*c535eb59SGordon Tetlow
668*c535eb59SGordon Tetlow	whatis_parse_args "$@"
669*c535eb59SGordon Tetlow
670*c535eb59SGordon Tetlow	build_manpath
671*c535eb59SGordon Tetlow	build_manlocales
672*c535eb59SGordon Tetlow	setup_pager
673*c535eb59SGordon Tetlow
674*c535eb59SGordon Tetlow	if [ "$cmd" = "whatis" ]; then
675*c535eb59SGordon Tetlow		opt="-w"
676*c535eb59SGordon Tetlow	fi
677*c535eb59SGordon Tetlow
678*c535eb59SGordon Tetlow	f='whatis'
679*c535eb59SGordon Tetlow
680*c535eb59SGordon Tetlow	IFS=:
681*c535eb59SGordon Tetlow	for path in $MANPATH; do
682*c535eb59SGordon Tetlow		if [ \! -d "$path" ]; then
683*c535eb59SGordon Tetlow			decho "Skipping non-existent path: $path" 2
684*c535eb59SGordon Tetlow			continue
685*c535eb59SGordon Tetlow		fi
686*c535eb59SGordon Tetlow
687*c535eb59SGordon Tetlow		if [ -f "$path/$f" -a -r "$path/$f" ]; then
688*c535eb59SGordon Tetlow			decho "Found whatis: $path/$f"
689*c535eb59SGordon Tetlow			wlist="$wlist $path/$f"
690*c535eb59SGordon Tetlow		fi
691*c535eb59SGordon Tetlow
692*c535eb59SGordon Tetlow		for loc in $MANLOCALES; do
693*c535eb59SGordon Tetlow			if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then
694*c535eb59SGordon Tetlow				decho "Found whatis: $path/$loc/$f"
695*c535eb59SGordon Tetlow				wlist="$wlist $path/$loc/$f"
696*c535eb59SGordon Tetlow			fi
697*c535eb59SGordon Tetlow		done
698*c535eb59SGordon Tetlow	done
699*c535eb59SGordon Tetlow	unset IFS
700*c535eb59SGordon Tetlow
701*c535eb59SGordon Tetlow	if [ -z "$wlist" ]; then
702*c535eb59SGordon Tetlow		echo "$cmd: no whatis databases in $MANPATH" >&2
703*c535eb59SGordon Tetlow		exit 1
704*c535eb59SGordon Tetlow	fi
705*c535eb59SGordon Tetlow
706*c535eb59SGordon Tetlow	rval=0
707*c535eb59SGordon Tetlow	for key in $keywords; do
708*c535eb59SGordon Tetlow		out=$(grep -Ehi $opt -- "$key" $wlist)
709*c535eb59SGordon Tetlow		if [ -n "$out" ]; then
710*c535eb59SGordon Tetlow			good="$good\\n$out"
711*c535eb59SGordon Tetlow		else
712*c535eb59SGordon Tetlow			bad="$bad\\n$key: nothing appropriate"
713*c535eb59SGordon Tetlow			rval=1
714*c535eb59SGordon Tetlow		fi
715*c535eb59SGordon Tetlow	done
716*c535eb59SGordon Tetlow
717*c535eb59SGordon Tetlow	# Strip leading carriage return.
718*c535eb59SGordon Tetlow	good=${good#\\n}
719*c535eb59SGordon Tetlow	bad=${bad#\\n}
720*c535eb59SGordon Tetlow
721*c535eb59SGordon Tetlow	if [ -n "$good" ]; then
722*c535eb59SGordon Tetlow		echo -e $good | $PAGER
723*c535eb59SGordon Tetlow	fi
724*c535eb59SGordon Tetlow
725*c535eb59SGordon Tetlow	if [ -n "$bad" ]; then
726*c535eb59SGordon Tetlow		echo -e $bad >&2
727*c535eb59SGordon Tetlow	fi
728*c535eb59SGordon Tetlow
729*c535eb59SGordon Tetlow	exit $rval
730*c535eb59SGordon Tetlow}
731*c535eb59SGordon Tetlow
732*c535eb59SGordon Tetlow# Usage: setup_pager
733*c535eb59SGordon Tetlow# Correctly sets $PAGER
734*c535eb59SGordon Tetlowsetup_pager() {
735*c535eb59SGordon Tetlow	# Setup pager.
736*c535eb59SGordon Tetlow	if [ -z "$PAGER" ]; then
737*c535eb59SGordon Tetlow		PAGER="more -s"
738*c535eb59SGordon Tetlow	fi
739*c535eb59SGordon Tetlow	decho "Using pager: $PAGER"
740*c535eb59SGordon Tetlow}
741*c535eb59SGordon Tetlow
742*c535eb59SGordon Tetlow# Usage: trim string
743*c535eb59SGordon Tetlow# Trims whitespace from beginning and end of a variable
744*c535eb59SGordon Tetlowtrim() {
745*c535eb59SGordon Tetlow	tstr=$1
746*c535eb59SGordon Tetlow	while true; do
747*c535eb59SGordon Tetlow		case "$tstr" in
748*c535eb59SGordon Tetlow		[\ \	]*)	tstr="${tstr##[\ \	]}" ;;
749*c535eb59SGordon Tetlow		*[\ \	])	tstr="${tstr%%[\ \	]}" ;;
750*c535eb59SGordon Tetlow		*)		break ;;
751*c535eb59SGordon Tetlow		esac
752*c535eb59SGordon Tetlow	done
753*c535eb59SGordon Tetlow}
754*c535eb59SGordon Tetlow
755*c535eb59SGordon Tetlow# Usage: whatis_parse_args "$@"
756*c535eb59SGordon Tetlow# Parse commandline args for whatis and apropos.
757*c535eb59SGordon Tetlowwhatis_parse_args() {
758*c535eb59SGordon Tetlow	local cmd_arg
759*c535eb59SGordon Tetlow	while getopts 'd' cmd_arg; do
760*c535eb59SGordon Tetlow		case "${cmd_arg}" in
761*c535eb59SGordon Tetlow		d)	debug=$(( $debug + 1 )) ;;
762*c535eb59SGordon Tetlow		*)	whatis_usage ;;
763*c535eb59SGordon Tetlow		esac
764*c535eb59SGordon Tetlow	done >&2
765*c535eb59SGordon Tetlow
766*c535eb59SGordon Tetlow	shift $(( $OPTIND - 1 ))
767*c535eb59SGordon Tetlow
768*c535eb59SGordon Tetlow	keywords="$*"
769*c535eb59SGordon Tetlow}
770*c535eb59SGordon Tetlow
771*c535eb59SGordon Tetlow# Usage: whatis_usage
772*c535eb59SGordon Tetlow# Display usage for the whatis/apropos utility.
773*c535eb59SGordon Tetlowwhatis_usage() {
774*c535eb59SGordon Tetlow	echo "usage: $cmd [-d] keyword [...]"
775*c535eb59SGordon Tetlow	exit 1
776*c535eb59SGordon Tetlow}
777*c535eb59SGordon Tetlow
778*c535eb59SGordon Tetlow
779*c535eb59SGordon Tetlow
780*c535eb59SGordon Tetlow# Supported commands
781*c535eb59SGordon Tetlowdo_apropos() {
782*c535eb59SGordon Tetlow	search_whatis apropos "$@"
783*c535eb59SGordon Tetlow}
784*c535eb59SGordon Tetlow
785*c535eb59SGordon Tetlowdo_man() {
786*c535eb59SGordon Tetlow	man_parse_args "$@"
787*c535eb59SGordon Tetlow	if [ -z "$pages" ]; then
788*c535eb59SGordon Tetlow		echo 'What manual page do you want?' >&2
789*c535eb59SGordon Tetlow		exit 1
790*c535eb59SGordon Tetlow	fi
791*c535eb59SGordon Tetlow	man_setup
792*c535eb59SGordon Tetlow
793*c535eb59SGordon Tetlow	for page in $pages; do
794*c535eb59SGordon Tetlow		decho "Searching for $page"
795*c535eb59SGordon Tetlow		man_find_and_display "$page"
796*c535eb59SGordon Tetlow	done
797*c535eb59SGordon Tetlow
798*c535eb59SGordon Tetlow	exit ${ret:-0}
799*c535eb59SGordon Tetlow}
800*c535eb59SGordon Tetlow
801*c535eb59SGordon Tetlowdo_manpath() {
802*c535eb59SGordon Tetlow	manpath_parse_args "$@"
803*c535eb59SGordon Tetlow	if [ -z "$qflag" ]; then
804*c535eb59SGordon Tetlow		manpath_warnings
805*c535eb59SGordon Tetlow	fi
806*c535eb59SGordon Tetlow	if [ -n "$Lflag" ]; then
807*c535eb59SGordon Tetlow		build_manlocales
808*c535eb59SGordon Tetlow		echo $MANLOCALES
809*c535eb59SGordon Tetlow	else
810*c535eb59SGordon Tetlow		build_manpath
811*c535eb59SGordon Tetlow		echo $MANPATH
812*c535eb59SGordon Tetlow	fi
813*c535eb59SGordon Tetlow	exit 0
814*c535eb59SGordon Tetlow}
815*c535eb59SGordon Tetlow
816*c535eb59SGordon Tetlowdo_whatis() {
817*c535eb59SGordon Tetlow	search_whatis whatis "$@"
818*c535eb59SGordon Tetlow}
819*c535eb59SGordon Tetlow
820*c535eb59SGordon TetlowEQN=/usr/bin/eqn
821*c535eb59SGordon TetlowCOL=/usr/bin/col
822*c535eb59SGordon TetlowNROFF='/usr/bin/groff -S -Wall -mtty-char -man'
823*c535eb59SGordon TetlowPIC=/usr/bin/pic
824*c535eb59SGordon TetlowTBL=/usr/bin/tbl
825*c535eb59SGordon TetlowTROFF='/usr/bin/groff -S -man'
826*c535eb59SGordon TetlowREFER=/usr/bin/refer
827*c535eb59SGordon TetlowVGRIND=/usr/bin/vgrind
828*c535eb59SGordon TetlowZCAT='/usr/bin/zcat -f'
829*c535eb59SGordon Tetlow
830*c535eb59SGordon Tetlowdebug=0
831*c535eb59SGordon Tetlowman_default_sections='1:1aout:8:2:3:n:4:5:6:7:9:l'
832*c535eb59SGordon Tetlowman_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/man'
833*c535eb59SGordon Tetlow
834*c535eb59SGordon Tetlowconfig_global='/etc/man.conf'
835*c535eb59SGordon Tetlow
836*c535eb59SGordon Tetlow# This can be overridden via a setting in /etc/man.conf.
837*c535eb59SGordon Tetlowconfig_local='/usr/local/etc/man.d/*.conf'
838*c535eb59SGordon Tetlow
839*c535eb59SGordon Tetlow# Set noglobbing for now. I don't want spurious globbing.
840*c535eb59SGordon Tetlowset -f
841*c535eb59SGordon Tetlow
842*c535eb59SGordon Tetlowcase "$0" in
843*c535eb59SGordon Tetlow*apropos)	do_apropos "$@" ;;
844*c535eb59SGordon Tetlow*manpath)	do_manpath "$@" ;;
845*c535eb59SGordon Tetlow*whatis)	do_whatis "$@" ;;
846*c535eb59SGordon Tetlow*)		do_man "$@" ;;
847*c535eb59SGordon Tetlowesac
848