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