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