From: Jordan K. Hubbard Date: Wed, 7 Jul 1993 23:07:02 +0000 (+0000) Subject: Newer new man page reader. X-Git-Tag: FreeBSD-release/1.0~3 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/00ba3d1d219eacfe9faf19f124f491c82248a040 Newer new man page reader. --- diff --git a/gnu/usr.bin/man/COPYING b/gnu/usr.bin/man/COPYING new file mode 100644 index 0000000000..a43ea2126f --- /dev/null +++ b/gnu/usr.bin/man/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gnu/usr.bin/man/Makefile b/gnu/usr.bin/man/Makefile new file mode 100644 index 0000000000..1777b6669a --- /dev/null +++ b/gnu/usr.bin/man/Makefile @@ -0,0 +1,10 @@ +# Master Makefile for man, manpath, apropos, whatis, and makewhatis +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man 1.0 +# distribution. +# + +SUBDIR = lib man manpath apropos whatis makewhatis + +.include diff --git a/gnu/usr.bin/man/Makefile.inc b/gnu/usr.bin/man/Makefile.inc new file mode 100644 index 0000000000..b3ccb46744 --- /dev/null +++ b/gnu/usr.bin/man/Makefile.inc @@ -0,0 +1,6 @@ +BINDIR?= /usr/bin +libdir= /etc +bindir= ${BINDIR} +pager= /usr/gnu/bin/less -sC +manpath_config_file= /etc/manpath.config +troff= /usr/bin/groff -Tps -man diff --git a/gnu/usr.bin/man/README b/gnu/usr.bin/man/README new file mode 100644 index 0000000000..d8fc4d448b --- /dev/null +++ b/gnu/usr.bin/man/README @@ -0,0 +1,134 @@ +README file for man(1). + +This is a replacement for Un*x man(1), apropos(1), whatis(1), and +manpath(1). It has all kinds of neat features that other versions of +man don't, including support for multiple man page directory trees, +preformatted man pages, and troff. It is provided without any +warranty whatever. I hope you find it useful. + +This program is not a GNU product but it is distributed under the +terms of the GNU copyleft which is described in the file COPYING. + +There is a solution written in perl which is probably superior in +every way, but, like me, you may prefer this one anyway. +:-) + +If you compile with support for preformatted man pages, man(1) will +try to update the preformatted page if the man page source is newer. + +If you compile with support for troff, you can say things like +`man -t foo | psdit > foo.ps' and have fabulous printed documentation +as well. + +I have resisted the temptation to handle all the bizarre ways various +vendors have of organizing man pages. This version of man assumes +that directory trees have the structure: + + .../man + /manSect + /foo.Sect* + ... + /catSect + /foo.Sect* + ... + +where Sect is some number or string and should be listed in the set of +sections to be searched. It is not necessary to have both the cat* +and man* subdirectories, but you must have at least one. :-) + + +INSTALLATION + +1. Run configure. This will grope around your system a bit and then + ask you a number of questions. It will create a Makefile from the + file Makefile.in, and a config.h file from config.h.in. You may + have to do some fine tuning to get things to work exactly right on + your system. If you do, I'd like to know what changes you had to + make to get things working. + +2. Edit the manpath.config file. This determines the system-wide + mappings for bin directories and man page directories. + +3. Do a `make all', try it out, and then if you're happy with that, do + a `make install'. You don't need to be root to use this set of + programs. + +4. Install the whatis database(s) by running makewhatis. If you want + to keep things absolutely current, you'll need to run this whenever + you add new man pages. You might want to add an entry in your + crontab. + +BUGS + +If you find one of these, please tell me about it. If you have a fix, +that's even better. If not, I can't guarantee that I'll fix it, but I +would like to know about them. + +John Eaton +jwe@che.utexas.edu +Department of Chemical Engineering +The University of Texas at Austin +Austin, Texas 78712 + + +CHANGES + +Partial list of changes since version 1.0: + +Installation made easier (this was the intent anyway) with the +introduction of a configure script. + +Commands like `man 3f intro' handled properly when the name of the +file we want is something like .../man3/intro.3f. + +Man can now run set uid to a special user so formatted man pages don't +have to be world writable. + +Man now works with compressed (.Z) frozen (.F) and yabba (.Y) cat +files. Frozen files are compressed files using freeze/melt, some +combination of LZW and tree coding. Sources for it came out on +comp.sources.misc or alt.sources or ... a few months ago. Yabba files +are compressed using yabba/unyabba, a data compression scheme posted +to alt.sources by Dan Bernstein. + +Man now uses a more reasonable default for the search order: +1, n, l, 6, 8, 2, 3, 4, 5, 7, p, o + +Man now allows for user-definable section search order via -S or +MANSECT. + +Glob.c can work even if you don't have alloca, and works properly on +Suns with the Sun C compiler. + +There is now a way to automatically to run preprocessors like the Sun +man program. The first line of the man page indicates which +preprocessors should be run: + + If the first line is a string of the form: + + '\" X + + where X is separated from the the `"' by a single SPACE and + consists of any combination of characters in the following + list, man pipes its input to troff(1) or nroff(1) through + the corresponding preprocessors. + + e eqn(1), or neqn for nroff + g grap(1) + p pic(1) + r refer(1) + t tbl(1), and col(1V) for nroff + v vgrind(1) + +Preprocessors may also be set on the command line with -p or from the +environment with MANROFFSEQ. + +The tbl preprocessor is run by default. + +Manpath now stat()'s the directories in MANPATH to avoid including +directories that don't exist. + +The output of apropos and whatis are now piped through PAGER. + +There is a new option to show where you would find a man page +(-w option) and in what order (-w with -a). diff --git a/gnu/usr.bin/man/TODO b/gnu/usr.bin/man/TODO new file mode 100644 index 0000000000..19060adc82 --- /dev/null +++ b/gnu/usr.bin/man/TODO @@ -0,0 +1,123 @@ +Things that would be nice but aren't really necessary: + +0. Update the documentation. + +XX Come up with an easier way to install this thing. There are now + lots of options and dependent flags to set. Should I worry too + much about this? + +XX Properly handle commands like `man 3f intro' when the name of the + file we want is something like .../man3/intro.3f. The way this is + done right now seems sort of kludgey but it mostly works. See + man.c for details. + +2. Malloc everything instead of having fixed limits... Or at least + check the limits everywhere. If you're paranoid about this, make + the limits big (famous last words: really, there aren't that many + things that could go wrong :-). + +3. Try to do a little better job of memory management. There are a + lot of little temporary strings that are malloc'd and never freed. + This is probably ok for a standalone program but not so good if + you wanted to call man() from another program. + +XX Come up with a clear view of the cat directory file permissions + problem. What's a good solution, other than having man run setuid + to some special user? (Make directories writable by all, cat + files 666.) + +XX Allow a compile time option that makes man run setuid to some + other user that owns all the cat pages, so that they don't have to + be world writable. + +XX Allow man to deal with compressed (.Z) frozen (.F) and yabba (.Y) + cat files. Frozen files are compressed files using freeze/melt, + some combination of LZW and tree coding. Sources for it came out + on comp.sources.misc or alt.sources or ... a few months ago. + Yabba files are compressed using yabba/unyabba, a data compression + scheme posted to alt.sources by Dan Bernstein. + +XX Choose a more reasonable default for the search order. Perhaps + this: 1, n, l, 6, 8, 2, 3, 4, 5, 7, p, o + +XX Fix glob.c so it doesn't need alloca, and/or fix it so that it can + work on a Sun: + + #ifdef __GNUC__ + #define alloca __builtin_alloca + #else /* !__GNUC__ */ + #ifdef sparc + #include + #endif /* sparc */ + #endif /* __GNUC__ */ + +XX Add some way to automatically to run preprocessors. The Sun man + program has a convention that the first line of the man page can + indicate which preprocessors should be run. Here's an excerpt from + its man page: + + Preprocessing Manual Pages + If the first line is a string of the form: + + '\" X + + where X is separated from the the `"' by a single SPACE and + consists of any combination of characters in the following + list, man pipes its input to troff(1) or nroff(1) through + the corresponding preprocessors. + + e eqn(1), or neqn for nroff + r refer(1) + t tbl(1), and col(1V) for nroff + v vgrind(1) + + If eqn or neqn is invoked, it will automatically read the + file /usr/pub/eqnchar (see eqnchar(7)). + +XX Have manpath stat() the directories in MANPATH to avoid including + directories that don't exist. Some versions of man and whatis + complain when the directories (like /usr/new/man) don't exist. + +XX Pipe the output of apropos and whatis through a pager. + +XX I've been using your man(1) package for a while now and I ran into + a problem with the X man pages that use tbl commands. Is it + possible to configure your man(1) package to use a general command + string. For example, a user could set an environment variable: + + setenv ROFFLINE 'pic $* | tbl | nroff -man' + +13. Fix makewhatis so that it can handle stuff like this (from the + Motif 1.1 man pages): + + .TH XmRowColumn 3X "" "" "" "" + .SH NAME + .mc | + \fBXmRowColumn \(em the RowColumn widget class.\fP + .mc + .iX "XmRowColumn" + .iX "widget class" "RowColumn" + .sp 1 + .SH SYNOPSIS + +14. Consider changing the format of the awk command's printf to use + "%s" instead of the standard 20.20s to accomodate the extra long + file names used by Motif. Maybe there's a better way to handle + this? + +15. Add ability to run man on a local file + +16. Handle per-tree tmac macros + +XX Allow user-definable section search order via -S or $MANSECT. + Thus programmers can get stty(3) before stty(1). + +XX Show all the places you would find a man page (-w option) and in + what order. + +19. Support for multi-char sections like man1m/*.1m or manavs/*.avs + (can I have a section that doesn't start with a numeral?) + +20. Implement man -K for regexp apropos + +21. An option to grep through all the man pages in $MANPATH diff --git a/gnu/usr.bin/man/apropos/Makefile b/gnu/usr.bin/man/apropos/Makefile new file mode 100644 index 0000000000..892af95051 --- /dev/null +++ b/gnu/usr.bin/man/apropos/Makefile @@ -0,0 +1,26 @@ +.include "../Makefile.inc" + +all: apropos apropos.1 + +obj depend rcsfreeze all: + @echo -n + +cleandir: clean + +clean: + @rm -f apropos apropos.1 + +apropos: apropos.sh + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' \ + apropos.sh > apropos + +apropos.1: apropos.man + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \ + -e 's,%manpath_config_file%,${manpath_config_file},' \ + apropos.man > apropos.1 + +install: apropos apropos.1 + install -c -o bin -g bin -m 555 apropos /usr/bin + install -c -o bin -g bin -m 444 apropos.1 /usr/share/man/man1 diff --git a/gnu/usr.bin/man/apropos/apropos b/gnu/usr.bin/man/apropos/apropos new file mode 100644 index 0000000000..8735e5fcdd --- /dev/null +++ b/gnu/usr.bin/man/apropos/apropos @@ -0,0 +1,64 @@ +#!/bin/sh +# +# apropos -- search the whatis database for keywords. +# +# Copyright (c) 1990, 1991, John W. Eaton. +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man +# distribution. +# +# John W. Eaton +# jwe@che.utexas.edu +# Department of Chemical Engineering +# The University of Texas at Austin +# Austin, Texas 78712 + +PATH=/usr/local/bin:/bin:/usr/ucb:/usr/bin + +libdir=/etc + +if [ $# = 0 ] +then + echo "usage: `basename $0` keyword ..." + exit 1 +fi + +manpath=`/usr/bin/manpath -q | tr : '\040'` + +if [ "$manpath" = "" ] +then + echo "whatis: manpath is null" + exit 1 +fi + +if [ "$PAGER" = "" ] +then + PAGER="/usr/gnu/bin/less -sC" +fi + +while [ $1 ] +do + found=0 + for d in $manpath /usr/lib + do + if [ -f $d/whatis ] + then + grep -i "$1" $d/whatis + status=$? + if [ "$status" = "0" ] + then + found=1 + fi + fi + done + + if [ "$found" = "0" ] + then + echo "$1: nothing appropriate" + fi + + shift +done | $PAGER + +exit diff --git a/gnu/usr.bin/man/apropos/apropos.1 b/gnu/usr.bin/man/apropos/apropos.1 new file mode 100644 index 0000000000..3bb3e17d61 --- /dev/null +++ b/gnu/usr.bin/man/apropos/apropos.1 @@ -0,0 +1,27 @@ +.\" Man page for apropos +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH apropos 1 "Jan 15, 1991" +.LO 1 +.SH NAME +apropos \- search the whatis database for strings +.SH SYNOPSIS +.BI apropos +keyword ... +.SH DESCRIPTION +apropos searches a set of database files containing short descriptions +of system commands for keywords and displays the result on the +standard output. +.SH "SEE ALSO" +whatis(1), man(1). diff --git a/gnu/usr.bin/man/apropos/apropos.man b/gnu/usr.bin/man/apropos/apropos.man new file mode 100644 index 0000000000..3bb3e17d61 --- /dev/null +++ b/gnu/usr.bin/man/apropos/apropos.man @@ -0,0 +1,27 @@ +.\" Man page for apropos +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH apropos 1 "Jan 15, 1991" +.LO 1 +.SH NAME +apropos \- search the whatis database for strings +.SH SYNOPSIS +.BI apropos +keyword ... +.SH DESCRIPTION +apropos searches a set of database files containing short descriptions +of system commands for keywords and displays the result on the +standard output. +.SH "SEE ALSO" +whatis(1), man(1). diff --git a/gnu/usr.bin/man/apropos/apropos.sh b/gnu/usr.bin/man/apropos/apropos.sh new file mode 100644 index 0000000000..070b8481c1 --- /dev/null +++ b/gnu/usr.bin/man/apropos/apropos.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# apropos -- search the whatis database for keywords. +# +# Copyright (c) 1990, 1991, John W. Eaton. +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man +# distribution. +# +# John W. Eaton +# jwe@che.utexas.edu +# Department of Chemical Engineering +# The University of Texas at Austin +# Austin, Texas 78712 + +PATH=/usr/local/bin:/bin:/usr/ucb:/usr/bin + +libdir=%libdir% + +if [ $# = 0 ] +then + echo "usage: `basename $0` keyword ..." + exit 1 +fi + +manpath=`%bindir%/manpath -q | tr : '\040'` + +if [ "$manpath" = "" ] +then + echo "whatis: manpath is null" + exit 1 +fi + +if [ "$PAGER" = "" ] +then + PAGER="%pager%" +fi + +while [ $1 ] +do + found=0 + for d in $manpath /usr/lib + do + if [ -f $d/whatis ] + then + grep -i "$1" $d/whatis + status=$? + if [ "$status" = "0" ] + then + found=1 + fi + fi + done + + if [ "$found" = "0" ] + then + echo "$1: nothing appropriate" + fi + + shift +done | $PAGER + +exit diff --git a/gnu/usr.bin/man/lib/Makefile b/gnu/usr.bin/man/lib/Makefile new file mode 100644 index 0000000000..33bd40b9e0 --- /dev/null +++ b/gnu/usr.bin/man/lib/Makefile @@ -0,0 +1,10 @@ +LIB = man + +CFLAGS+= -I${.CURDIR} -DSTDC_HEADERS -DPOSIX -DHAS_TROFF -DDO_UNCOMPRESS -DALT_SYSTEMS + +SRCS = util.c gripes.c + +install: + @echo -n + +.include diff --git a/gnu/usr.bin/man/lib/config.h b/gnu/usr.bin/man/lib/config.h new file mode 100644 index 0000000000..2c231681b1 --- /dev/null +++ b/gnu/usr.bin/man/lib/config.h @@ -0,0 +1,216 @@ +/* + * config.h + * + * If you haven't read the README file, now might be a good time. + * + * This file is edited by configure, so you shouldn't have to. + * If that doesn't work, edit this file to match your site. + * + * Sorry it's so long, but there are lots of things you might want to + * customize for your site. + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +#ifdef COMPRESS +#define DO_COMPRESS +#define DO_UNCOMPRESS +#endif + +/* + * This is the size of a number of internal buffers. It should + * probably not be less than 512. + */ +#ifndef BUFSIZ +#define BUFSIZ 1024 +#endif + +/* + * This should be at least the size of the longest path. + */ +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +/* + * This is the maximum number of directories expected in the manpath. + */ +#ifndef MAXDIRS +#define MAXDIRS 64 +#endif + +/* + * This is the name of the group that owns the preformatted man pages. + * If you are running man as a setgid program, you should make sure + * that all of the preformatted man pages and the directories that + * they live in are readable and writeable and owned by this group. + */ +#ifdef SECURE_MAN_UID +#define MAN_USER "" +#endif + +/* + * It's probably best to define absolute paths to all of these. If + * you don't, you'll be depending on the user's path to be correct + * when system () is called. This can result in weird behavior that's + * hard to track down, especially after you forget how this program + * works... If you don't have some of these programs, simply define + * them to be empty strings (i.e. ""). As a minimum, you must have + * nroff installed. + */ +#ifndef APROPOS +#define APROPOS "/usr/bin/apropos" +#endif + +#ifndef WHATIS +#define WHATIS "/usr/bin/whatis" +#endif + +#ifndef PAGER +#define PAGER "/usr/gnu/bin/less -sC" +#endif + +#ifdef HAS_TROFF +#ifndef TROFF +#define TROFF "/usr/bin/groff -Tps -man" +#endif +#endif + +#ifndef NROFF +#define NROFF "/usr/bin/groff -Tascii -man" +#endif + +#ifndef EQN +#define EQN "/usr/bin/eqn -Tps" +#endif + +#ifndef NEQN +#define NEQN "/usr/bin/eqn -Tascii" +#endif + +#ifndef TBL +#define TBL "/usr/bin/tbl" +#endif + +#ifndef COL +#define COL "/usr/bin/col" +#endif + +#ifndef VGRIND +#define VGRIND "/usr/bin/vgrind" +#endif + +#ifndef REFER +#define REFER "/usr/bin/refer" +#endif + +#ifndef GRAP +#define GRAP "" +#endif + +#ifndef PIC +#define PIC "/usr/bin/pic" +#endif + +/* + * Define the absolute path to the configuration file. + */ +#ifndef MAN_MAIN + static char config_file[] = "/etc/manpath.config"; +#endif + +/* + * Define the uncompression program(s) to use for those preformatted + * pages that end in the given character. If you add extras here, you + * may need to change man.c. + */ +#ifdef DO_UNCOMPRESS +/* .F files */ +#define FCAT "" +/* .Y files */ +#define YCAT "" +/* .Z files */ +#define ZCAT "/usr/bin/zcat" +#endif + +/* + * This is the standard program to use on this system for compressing + * pages once they have been formatted, and the character to tack on + * to the end of those files. The program listed is expected to read + * from the standard input and write compressed output to the standard + * output. + */ +#ifdef DO_COMPRESS +#define COMPRESSOR "" +#define COMPRESS_EXT "" +#endif + +/* + * Define the standard manual sections. For example, if your man + * directory tree has subdirectories man1, man2, man3, mann, + * and man3foo, std_sections[] would have "1", "2", "3", "n", and + * "3foo". Directories are searched in the order they appear. Having + * extras isn't fatal, it just slows things down a bit. + * + * Note that this is just for directories to search. If you have + * files like .../man3/foobar.3Xtc, you don't need to have "3Xtc" in + * the list below -- this is handled separately, so that `man 3Xtc foobar', + * `man 3 foobar', and `man foobar' should find the file .../man3/foo.3Xtc, + * (assuming, of course, that there isn't a .../man1/foo.1 or somesuch + * that we would find first). + * + * Note that this list should be in the order that you want the + * directories to be searched. Is there a standard for this? What is + * the normal order? If anyone knows, please tell me! + */ +#ifndef MANPATH_MAIN + static char *std_sections[] = + { + "1", "n", "l", "6", "8", "2", "3", "4", "5", "7", "p", "o", NULL + }; +#endif + +/* + * Not all systems define these in stat.h. + */ +#ifndef S_IRUSR +#define S_IRUSR 00400 /* read permission: owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR 00200 /* write permission: owner */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 00040 /* read permission: group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 00020 /* write permission: group */ +#endif +#ifndef S_IROTH +#define S_IROTH 00004 /* read permission: other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 00002 /* write permission: other */ +#endif + +/* + * This is the mode used for formatted pages that we create. If you + * are using the setgid option, you should use 664. If you are not, + * you should use 666 and make the cat* directories mode 777. + */ +#ifndef CATMODE +#ifdef SECURE_MAN_UID +#define CATMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH +#else +#define CATMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH +#endif +#endif diff --git a/gnu/usr.bin/man/lib/gripes.c b/gnu/usr.bin/man/lib/gripes.c new file mode 100644 index 0000000000..76f8e703ad --- /dev/null +++ b/gnu/usr.bin/man/lib/gripes.c @@ -0,0 +1,180 @@ +/* + * gripes.c + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +#include +#include "gripes.h" + +#ifdef STDC_HEADERS +#include +#else +extern int fprintf (); +extern int fflush (); +extern int exit (); +#endif + +extern char *prognam; + +void +gripe_no_name (section) + char *section; +{ + if (section) + fprintf (stderr, "What manual page do you want from section %s?\n", + section); + else + fprintf (stderr, "What manual page do you want?\n"); + + fflush (stderr); +} + +void +gripe_reading_man_file (name) + char *name; +{ + fprintf (stderr, "Read access denied for file %s\n", name); + + fflush (stderr); +} + +void +gripe_converting_name (name, to_cat) + char *name; + int to_cat; +{ + if (to_cat) + fprintf (stderr, "Error converting %s to cat name\n", name); + else + fprintf (stderr, "Error converting %s to man name\n", name); + + fflush (stderr); + + exit (1); +} + +void +gripe_system_command (status) + int status; +{ + fprintf (stderr, "Error executing formatting or display command.\n"); + fprintf (stderr, "system command exited with status %d\n", status); + + fflush (stderr); +} + +void +gripe_not_found (name, section) + char *name, *section; +{ + if (section) + fprintf (stderr, "No entry for %s in section %s of the manual\n", + name, section); + else + fprintf (stderr, "No manual entry for %s\n", name); + + fflush (stderr); +} + +void +gripe_incompatible (s) + char *s; +{ + fprintf (stderr, "%s: incompatible options %s\n", prognam, s); + + fflush (stderr); + + exit (1); +} + +void +gripe_getting_mp_config (file) + char *file; +{ + fprintf (stderr, "%s: unable to find the file %s\n", prognam, file); + + fflush (stderr); + + exit (1); +} + +void +gripe_reading_mp_config (file) + char *file; +{ + fprintf (stderr, "%s: unable to make sense of the file %s\n", prognam, file); + + fflush (stderr); + + exit (1); +} + +void +gripe_invalid_section (section) + char *section; +{ + fprintf (stderr, "%s: invalid section (%s) selected\n", prognam, section); + + fflush (stderr); + + exit (1); +} + +void +gripe_manpath () +{ + fprintf (stderr, "%s: manpath is null\n", prognam); + + fflush (stderr); + + exit (1); +} + +void +gripe_alloc (bytes, object) + int bytes; + char *object; +{ + fprintf (stderr, "%s: can't malloc %d bytes for %s\n", + prognam, bytes, object); + + fflush (stderr); + + exit (1); +} + +void +gripe_roff_command_from_file (file) + char *file; +{ + fprintf (stderr, "Error parsing *roff command from file %s\n", file); + + fflush (stderr); +} + +void +gripe_roff_command_from_env () +{ + fprintf (stderr, "Error parsing MANROFFSEQ. Using system defaults.\n"); + + fflush (stderr); +} + +void +gripe_roff_command_from_command_line () +{ + fprintf (stderr, "Error parsing *roff command from command line.\n"); + + fflush (stderr); +} diff --git a/gnu/usr.bin/man/lib/gripes.h b/gnu/usr.bin/man/lib/gripes.h new file mode 100644 index 0000000000..e3be4a08b1 --- /dev/null +++ b/gnu/usr.bin/man/lib/gripes.h @@ -0,0 +1,30 @@ +/* + * gripes.h + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +extern void gripe_no_name (); +extern void gripe_converting_name (); +extern void gripe_system_command (); +extern void gripe_reading_man_file (); +extern void gripe_not_found (); +extern void gripe_invalid_section (); +extern void gripe_manpath (); +extern void gripe_alloc (); +extern void gripe_incompatible (); +extern void gripe_getting_mp_config (); +extern void gripe_reading_mp_config (); +extern void gripe_roff_command_from_file (); +extern void gripe_roff_command_from_env (); +extern void gripe_roff_command_from_command_line (); diff --git a/gnu/usr.bin/man/lib/gripes.po b/gnu/usr.bin/man/lib/gripes.po new file mode 100644 index 0000000000..6bfd455e59 Binary files /dev/null and b/gnu/usr.bin/man/lib/gripes.po differ diff --git a/gnu/usr.bin/man/lib/util.c b/gnu/usr.bin/man/lib/util.c new file mode 100644 index 0000000000..b0babed3c6 --- /dev/null +++ b/gnu/usr.bin/man/lib/util.c @@ -0,0 +1,150 @@ +/* + * util.c + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +#include +#include +#include +#include +#include + +#ifdef STDC_HEADERS +#include +#else +extern int fprintf (); +extern int tolower (); +#endif + +extern char *strdup (); +extern int system (); + +#include "gripes.h" + +/* + * Extract last element of a name like /foo/bar/baz. + */ +char * +mkprogname (s) + register char *s; +{ + char *t; + + t = strrchr (s, '/'); + if (t == (char *)NULL) + t = s; + else + t++; + + return strdup (t); +} + +void +downcase (s) + char *s; +{ + register char c; + while ((c = *s) != '\0') + { + if (isalpha (c)) + *s++ = tolower (c); + } +} + +/* + * Is file a newer than file b? + * + * case: + * + * a newer than b returns 1 + * a older than b returns 0 + * stat on a fails returns -1 + * stat on b fails returns -2 + * stat on a and b fails returns -3 + */ +int +is_newer (fa, fb) + register char *fa; + register char *fb; +{ + struct stat fa_sb; + struct stat fb_sb; + register int fa_stat; + register int fb_stat; + register int status = 0; + + fa_stat = stat (fa, &fa_sb); + if (fa_stat != 0) + status = 1; + + fb_stat = stat (fb, &fb_sb); + if (fb_stat != 0) + status |= 2; + + if (status != 0) + return -status; + + return (fa_sb.st_mtime > fb_sb.st_mtime); +} + +/* + * Is path a directory? + */ +int +is_directory (path) + char *path; +{ + struct stat sb; + register int status; + + status = stat (path, &sb); + + if (status != 0) + return -1; + + return ((sb.st_mode & S_IFDIR) == S_IFDIR); + +} + +/* + * Attempt a system () call. Return 1 for success and 0 for failure + * (handy for counting successes :-). + */ +int +do_system_command (command) + char *command; +{ + int status = 0; + extern int debug; + + /* + * If we're debugging, don't really execute the command -- you never + * know what might be in that mangled string :-O. + */ + if (debug) + fprintf (stderr, "\ntrying command: %s\n", command); + else + status = system (command); + + /* + * Ultrix returns 127 for failure. Is this normal? + */ + if (status == 127) + { + gripe_system_command (status); + return 0; + } + else + return 1; +} diff --git a/gnu/usr.bin/man/lib/util.po b/gnu/usr.bin/man/lib/util.po new file mode 100644 index 0000000000..37dffc26d9 Binary files /dev/null and b/gnu/usr.bin/man/lib/util.po differ diff --git a/gnu/usr.bin/man/makewhatis/Makefile b/gnu/usr.bin/man/makewhatis/Makefile new file mode 100644 index 0000000000..8c26f08c12 --- /dev/null +++ b/gnu/usr.bin/man/makewhatis/Makefile @@ -0,0 +1,17 @@ +.include "../Makefile.inc" + +all: makewhatis + +obj depend rcsfreeze all: + @echo -n + +cleandir: clean + +clean: + @rm -f makewhatis + +install: + install -c -o bin -g bin -m 444 makewhatis /usr/bin + +makewhatis: makewhatis.sh + sed -e 's/%sections%/ "1", "n", "l", "6", "8", "2", "3", "4", "5", "7", "p", "o", NULL/' makewhatis.sh > makewhatis diff --git a/gnu/usr.bin/man/makewhatis/makewhatis b/gnu/usr.bin/man/makewhatis/makewhatis new file mode 100644 index 0000000000..e6c238c2ba --- /dev/null +++ b/gnu/usr.bin/man/makewhatis/makewhatis @@ -0,0 +1,79 @@ +#!/bin/sh +# +# makewhatis -- update the whatis database in the man directories. +# +# Copyright (c) 1990, 1991, John W. Eaton. +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man +# distribution. +# +# John W. Eaton +# jwe@che.utexas.edu +# Department of Chemical Engineering +# The University of Texas at Austin +# Austin, Texas 78712 + +PATH=/bin:/usr/local/bin:/usr/ucb:/usr/bin + +if [ $# = 0 ] +then + echo "usage: makewhatis directory [...]" + exit 1 +fi + +for dir in $* +do + cd $dir + for subdir in man* + do + if [ -d $subdir ] + then + for f in `find . -name '*' -print` + do + sed -n '/^\.TH.*$/p + /^\.SH[ ]*NAME/,/^\.SH/p' $f |\ + sed -e 's/\\[ ]*\-/-/ + s/^.PP.*$// + s/\\(em// + s/\\fI// + s/\\fR//' |\ + awk 'BEGIN {insh = 0} { + if ($1 == ".TH") + sect = $3 + else if ($1 == ".SH" && insh == 1) { + if (i > 0 && name != NULL) { + namesect = sprintf("%s (%s)", name, sect) + printf("%-20.20s", namesect) + printf(" - ") + for (j = 0; j < i-1; j++) + printf("%s ", desc[j]) + printf("%s\n", desc[i-1]) + } + } else if ($1 == ".SH" && insh == 0) { + insh = 1 + count = 0 + i = 0 + } else if (insh == 1) { + count++ + if (count == 1 && NF > 2) { + start = 2 + if ($2 == "-") start = 3 + if (NF > start + 1) + for (j = start; j <= NF; j++) + desc[i++] = $j + name = $1 + } else { + for (j = 1; j <= NF; j++) + desc[i++] = $j + } + } + }' + done + cd .. + fi + done | sort | colrm 80 > $dir/whatis.db.tmp + mv $dir/whatis.db.tmp $dir/whatis +done + +exit diff --git a/gnu/usr.bin/man/makewhatis/makewhatis.sh b/gnu/usr.bin/man/makewhatis/makewhatis.sh new file mode 100644 index 0000000000..e6c238c2ba --- /dev/null +++ b/gnu/usr.bin/man/makewhatis/makewhatis.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# +# makewhatis -- update the whatis database in the man directories. +# +# Copyright (c) 1990, 1991, John W. Eaton. +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man +# distribution. +# +# John W. Eaton +# jwe@che.utexas.edu +# Department of Chemical Engineering +# The University of Texas at Austin +# Austin, Texas 78712 + +PATH=/bin:/usr/local/bin:/usr/ucb:/usr/bin + +if [ $# = 0 ] +then + echo "usage: makewhatis directory [...]" + exit 1 +fi + +for dir in $* +do + cd $dir + for subdir in man* + do + if [ -d $subdir ] + then + for f in `find . -name '*' -print` + do + sed -n '/^\.TH.*$/p + /^\.SH[ ]*NAME/,/^\.SH/p' $f |\ + sed -e 's/\\[ ]*\-/-/ + s/^.PP.*$// + s/\\(em// + s/\\fI// + s/\\fR//' |\ + awk 'BEGIN {insh = 0} { + if ($1 == ".TH") + sect = $3 + else if ($1 == ".SH" && insh == 1) { + if (i > 0 && name != NULL) { + namesect = sprintf("%s (%s)", name, sect) + printf("%-20.20s", namesect) + printf(" - ") + for (j = 0; j < i-1; j++) + printf("%s ", desc[j]) + printf("%s\n", desc[i-1]) + } + } else if ($1 == ".SH" && insh == 0) { + insh = 1 + count = 0 + i = 0 + } else if (insh == 1) { + count++ + if (count == 1 && NF > 2) { + start = 2 + if ($2 == "-") start = 3 + if (NF > start + 1) + for (j = start; j <= NF; j++) + desc[i++] = $j + name = $1 + } else { + for (j = 1; j <= NF; j++) + desc[i++] = $j + } + } + }' + done + cd .. + fi + done | sort | colrm 80 > $dir/whatis.db.tmp + mv $dir/whatis.db.tmp $dir/whatis +done + +exit diff --git a/gnu/usr.bin/man/man/Makefile b/gnu/usr.bin/man/man/Makefile new file mode 100644 index 0000000000..d116ad93ba --- /dev/null +++ b/gnu/usr.bin/man/man/Makefile @@ -0,0 +1,14 @@ +PROG= man +SRCS= man.c manpath.c glob.c +MAN1= man.1 +LDADD+= -L${.CURDIR}/../lib -lman + +CFLAGS+= -I${.CURDIR}/../lib -DSTDC_HEADERS -DPOSIX -DHAS_TROFF -DDO_UNCOMPRESS -DALT_SYSTEMS + +man.1: man.man + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \ + -e 's,%manpath_config_file%,${manpath_config_file},' \ + man.man > man.1 + +.include diff --git a/gnu/usr.bin/man/man/glob.c b/gnu/usr.bin/man/man/glob.c new file mode 100644 index 0000000000..5bfb1bf686 --- /dev/null +++ b/gnu/usr.bin/man/man/glob.c @@ -0,0 +1,680 @@ +/* File-name wildcard pattern matching for GNU. + Copyright (C) 1985, 1988, 1989, 1990, 1991 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* To whomever it may concern: I have never seen the code which most + Unix programs use to perform this function. I wrote this from scratch + based on specifications for the pattern matching. --RMS. */ + +#ifdef SHELL +#include "config.h" +#endif /* SHELL */ + +#include + +#if defined (USGr3) && !defined (DIRENT) +#define DIRENT +#endif /* USGr3 */ +#if defined (Xenix) && !defined (SYSNDIR) +#define SYSNDIR +#endif /* Xenix */ + +#if defined (POSIX) || defined (DIRENT) || defined (__GNU_LIBRARY__) +#include +#define direct dirent +#define D_NAMLEN(d) strlen((d)->d_name) +#else /* not POSIX or DIRENT or __GNU_LIBRARY__ */ +#define D_NAMLEN(d) ((d)->d_namlen) +#ifdef USG +#if defined (SYSNDIR) +#include +#else /* SYSNDIR */ +#include "ndir.h" +#endif /* not SYSNDIR */ +#else /* not USG */ +#include +#endif /* USG */ +#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */ + +#if defined (_POSIX_SOURCE) +/* Posix does not require that the d_ino field be present, and some + systems do not provide it. */ +#define REAL_DIR_ENTRY(dp) 1 +#else +#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +#endif /* _POSIX_SOURCE */ + +#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) +#include +#include +#define STDC_STRINGS +#else /* STDC_HEADERS or __GNU_LIBRARY__ */ + +#if defined (USG) +#include +#ifndef POSIX +#include +#endif /* POSIX */ +#define STDC_STRINGS +#else /* not USG */ +#ifdef NeXT +#include +#else /* NeXT */ +#include +#endif /* NeXT */ +/* Declaring bcopy causes errors on systems whose declarations are different. + If the declaration is omitted, everything works fine. */ +#endif /* not USG */ + +extern char *malloc (); +extern char *realloc (); +extern void free (); + +#ifndef NULL +#define NULL 0 +#endif +#endif /* Not STDC_HEADERS or __GNU_LIBRARY__. */ + +#ifdef STDC_STRINGS +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define index strchr +#define rindex strrchr +#endif /* STDC_STRINGS */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* Not GCC. */ +#ifdef sparc +#include +#else /* Not sparc. */ +extern char *alloca (); +#endif /* sparc. */ +#endif /* GCC. */ +#endif + +/* Nonzero if '*' and '?' do not match an initial '.' for glob_filename. */ +int noglob_dot_filenames = 1; + +static int glob_match_after_star (); + +/* Return nonzero if PATTERN has any special globbing chars in it. */ + +int +glob_pattern_p (pattern) + char *pattern; +{ + register char *p = pattern; + register char c; + int open = 0; + + while ((c = *p++) != '\0') + switch (c) + { + case '?': + case '*': + return 1; + + case '[': /* Only accept an open brace if there is a close */ + open++; /* brace to match it. Bracket expressions must be */ + continue; /* complete, according to Posix.2 */ + case ']': + if (open) + return 1; + continue; + + case '\\': + if (*p++ == '\0') + return 0; + } + + return 0; +} + + +/* Match the pattern PATTERN against the string TEXT; + return 1 if it matches, 0 otherwise. + + A match means the entire string TEXT is used up in matching. + + In the pattern string, `*' matches any sequence of characters, + `?' matches any character, [SET] matches any character in the specified set, + [!SET] matches any character not in the specified set. + + A set is composed of characters or ranges; a range looks like + character hyphen character (as in 0-9 or A-Z). + [0-9a-zA-Z_] is the set of characters allowed in C identifiers. + Any other character in the pattern must be matched exactly. + + To suppress the special syntactic significance of any of `[]*?!-\', + and match the character exactly, precede it with a `\'. + + If DOT_SPECIAL is nonzero, + `*' and `?' do not match `.' at the beginning of TEXT. */ + +int +glob_match (pattern, text, dot_special) + char *pattern, *text; + int dot_special; +{ + register char *p = pattern, *t = text; + register char c; + + while ((c = *p++) != '\0') + switch (c) + { + case '?': + if (*t == '\0' || (dot_special && t == text && *t == '.')) + return 0; + else + ++t; + break; + + case '\\': + if (*p++ != *t++) + return 0; + break; + + case '*': + if (dot_special && t == text && *t == '.') + return 0; + return glob_match_after_star (p, t); + + case '[': + { + register char c1 = *t++; + int invert; + + if (c1 == '\0') + return 0; + + invert = (*p == '!'); + + if (invert) + p++; + + c = *p++; + while (1) + { + register char cstart = c, cend = c; + + if (c == '\\') + { + cstart = *p++; + cend = cstart; + } + + if (cstart == '\0') + return 0; /* Missing ']'. */ + + c = *p++; + + if (c == '-') + { + cend = *p++; + if (cend == '\\') + cend = *p++; + if (cend == '\0') + return 0; + c = *p++; + } + if (c1 >= cstart && c1 <= cend) + goto match; + if (c == ']') + break; + } + if (!invert) + return 0; + break; + + match: + /* Skip the rest of the [...] construct that already matched. */ + while (c != ']') + { + if (c == '\0') + return 0; + c = *p++; + if (c == '\0') + return 0; + if (c == '\\') + p++; + } + if (invert) + return 0; + break; + } + + default: + if (c != *t++) + return 0; + } + + return *t == '\0'; +} + +/* Like glob_match, but match PATTERN against any final segment of TEXT. */ + +static int +glob_match_after_star (pattern, text) + char *pattern, *text; +{ + register char *p = pattern, *t = text; + register char c, c1; + + while ((c = *p++) == '?' || c == '*') + if (c == '?' && *t++ == '\0') + return 0; + + if (c == '\0') + return 1; + + if (c == '\\') + c1 = *p; + else + c1 = c; + + --p; + while (1) + { + if ((c == '[' || *t == c1) && glob_match (p, t, 0)) + return 1; + if (*t++ == '\0') + return 0; + } +} + +/* Return a vector of names of files in directory DIR + whose names match glob pattern PAT. + The names are not in any particular order. + Wildcards at the beginning of PAT do not match an initial period + if noglob_dot_filenames is nonzero. + + The vector is terminated by an element that is a null pointer. + + To free the space allocated, first free the vector's elements, + then free the vector. + + Return NULL if cannot get enough memory to hold the pointer + and the names. + + Return -1 if cannot access directory DIR. + Look in errno for more information. */ + +char ** +glob_vector (pat, dir) + char *pat; + char *dir; +{ + struct globval + { + struct globval *next; + char *name; + }; + + DIR *d; + register struct direct *dp; + struct globval *lastlink; + register struct globval *nextlink; + register char *nextname; + unsigned int count; + int lose; + register char **name_vector; + register unsigned int i; +#ifdef ALLOCA_MISSING + struct globval *templink; +#endif + + d = opendir (dir); + if (d == NULL) + return (char **) -1; + + lastlink = NULL; + count = 0; + lose = 0; + + /* Scan the directory, finding all names that match. + For each name that matches, allocate a struct globval + on the stack and store the name in it. + Chain those structs together; lastlink is the front of the chain. */ + while (1) + { +#if defined (SHELL) + /* Make globbing interruptible in the bash shell. */ + extern int interrupt_state; + + if (interrupt_state) + { + closedir (d); + lose = 1; + goto lost; + } +#endif /* SHELL */ + + dp = readdir (d); + if (dp == NULL) + break; + if (REAL_DIR_ENTRY (dp) + && glob_match (pat, dp->d_name, noglob_dot_filenames)) + { +#ifdef ALLOCA_MISSING + nextlink = (struct globval *) malloc (sizeof (struct globval)); +#else + nextlink = (struct globval *) alloca (sizeof (struct globval)); +#endif + nextlink->next = lastlink; + i = D_NAMLEN (dp) + 1; + nextname = (char *) malloc (i); + if (nextname == NULL) + { + lose = 1; + break; + } + lastlink = nextlink; + nextlink->name = nextname; + bcopy (dp->d_name, nextname, i); + count++; + } + } + closedir (d); + + if (!lose) + { + name_vector = (char **) malloc ((count + 1) * sizeof (char *)); + lose |= name_vector == NULL; + } + + /* Have we run out of memory? */ +#ifdef SHELL + lost: +#endif + if (lose) + { + /* Here free the strings we have got. */ + while (lastlink) + { + free (lastlink->name); +#ifdef ALLOCA_MISSING + templink = lastlink->next; + free ((char *) lastlink); + lastlink = templink; +#else + lastlink = lastlink->next; +#endif + } + return NULL; + } + + /* Copy the name pointers from the linked list into the vector. */ + for (i = 0; i < count; ++i) + { + name_vector[i] = lastlink->name; +#ifdef ALLOCA_MISSING + templink = lastlink->next; + free ((char *) lastlink); + lastlink = templink; +#else + lastlink = lastlink->next; +#endif + } + + name_vector[count] = NULL; + return name_vector; +} + +/* Return a new array, replacing ARRAY, which is the concatenation + of each string in ARRAY to DIR. + Return NULL if out of memory. */ + +static char ** +glob_dir_to_array (dir, array) + char *dir, **array; +{ + register unsigned int i, l; + int add_slash = 0; + char **result; + + l = strlen (dir); + if (l == 0) + return array; + + if (dir[l - 1] != '/') + add_slash++; + + for (i = 0; array[i] != NULL; i++) + ; + + result = (char **) malloc ((i + 1) * sizeof (char *)); + if (result == NULL) + return NULL; + + for (i = 0; array[i] != NULL; i++) + { + result[i] = (char *) malloc (1 + l + add_slash + strlen (array[i])); + if (result[i] == NULL) + return NULL; + strcpy (result[i], dir); + if (add_slash) + result[i][l] = '/'; + strcpy (result[i] + l + add_slash, array[i]); + } + result[i] = NULL; + + /* Free the input array. */ + for (i = 0; array[i] != NULL; i++) + free (array[i]); + free ((char *) array); + return result; +} + +/* Do globbing on PATHNAME. Return an array of pathnames that match, + marking the end of the array with a null-pointer as an element. + If no pathnames match, then the array is empty (first element is null). + If there isn't enough memory, then return NULL. + If a file system error occurs, return -1; `errno' has the error code. + + Wildcards at the beginning of PAT, or following a slash, + do not match an initial period if noglob_dot_filenames is nonzero. */ + +char ** +glob_filename (pathname) + char *pathname; +{ + char **result; + unsigned int result_size; + char *directory_name, *filename; + unsigned int directory_len; + + result = (char **) malloc (sizeof (char *)); + result_size = 1; + if (result == NULL) + return NULL; + + result[0] = NULL; + + /* Find the filename. */ + filename = rindex (pathname, '/'); + if (filename == NULL) + { + filename = pathname; + directory_name = ""; + directory_len = 0; + } + else + { + directory_len = (filename - pathname) + 1; +#ifdef ALLOCA_MISSING + directory_name = (char *) malloc (directory_len + 1); +#else + directory_name = (char *) alloca (directory_len + 1); +#endif + bcopy (pathname, directory_name, directory_len); + directory_name[directory_len] = '\0'; + ++filename; + } + + /* If directory_name contains globbing characters, then we + have to expand the previous levels. Just recurse. */ + if (glob_pattern_p (directory_name)) + { + char **directories; + register unsigned int i; + + if (directory_name[directory_len - 1] == '/') + directory_name[directory_len - 1] = '\0'; + + directories = glob_filename (directory_name); +#ifdef ALLOCA_MISSING + free ((char *) directory_name); +#endif + if (directories == NULL) + goto memory_error; + else if (directories == (char **) -1) + return (char **) -1; + else if (*directories == NULL) + { + free ((char *) directories); + return (char **) -1; + } + + /* We have successfully globbed the preceding directory name. + For each name in DIRECTORIES, call glob_vector on it and + FILENAME. Concatenate the results together. */ + for (i = 0; directories[i] != NULL; i++) + { + char **temp_results = glob_vector (filename, directories[i]); + if (temp_results == NULL) + goto memory_error; + else if (temp_results == (char **) -1) + /* This filename is probably not a directory. Ignore it. */ + ; + else + { + char **array = glob_dir_to_array (directories[i], temp_results); + register unsigned int l; + + l = 0; + while (array[l] != NULL) + ++l; + + result = (char **) realloc (result, + (result_size + l) * sizeof (char *)); + if (result == NULL) + goto memory_error; + + for (l = 0; array[l] != NULL; ++l) + result[result_size++ - 1] = array[l]; + result[result_size - 1] = NULL; + free ((char *) array); + } + } + /* Free the directories. */ + for (i = 0; directories[i] != NULL; i++) + free (directories[i]); + free ((char *) directories); + + return result; + } + + /* If there is only a directory name, return it. */ + if (*filename == '\0') + { + result = (char **) realloc ((char *) result, 2 * sizeof (char *)); + if (result != NULL) + { + result[0] = (char *) malloc (directory_len + 1); + if (result[0] == NULL) + { +#ifdef ALLOCA_MISSING + free ((char *) directory_name); +#endif + goto memory_error; + } + bcopy (directory_name, result[0], directory_len + 1); + result[1] = NULL; + } +#ifdef ALLOCA_MISSING + free ((char *) directory_name); +#endif + return result; + } + else + { + /* Otherwise, just return what glob_vector + returns appended to the directory name. */ + char **temp_results = glob_vector (filename, + (directory_len == 0 + ? "." : directory_name)); + + if (temp_results == NULL || temp_results == (char **) -1) + { +#ifdef NO_ALLOCA + free ((char *) directory_name); +#endif + return temp_results; + } + + temp_results = glob_dir_to_array (directory_name, temp_results); +#ifdef NO_ALLOCA + free ((char *) directory_name); +#endif + return temp_results; + } + + /* We get to memory error if the program has run out of memory, or + if this is the shell, and we have been interrupted. */ + memory_error: + if (result != NULL) + { + register unsigned int i; + for (i = 0; result[i] != NULL; ++i) + free (result[i]); + free ((char *) result); + } +#if defined (SHELL) + { + extern int interrupt_state; + + if (interrupt_state) + throw_to_top_level (); + } +#endif /* SHELL */ + return NULL; +} + +#ifdef TEST + +main (argc, argv) + int argc; + char **argv; +{ + char **value; + int i, optind; + + for (optind = 1; optind < argc; optind++) + { + value = glob_filename (argv[optind]); + if (value == NULL) + puts ("virtual memory exhausted"); + else if (value == (char **) -1) + perror (argv[optind]); + else + for (i = 0; value[i] != NULL; i++) + puts (value[i]); + } + exit (0); +} + +#endif /* TEST */ diff --git a/gnu/usr.bin/man/man/man.1 b/gnu/usr.bin/man/man/man.1 new file mode 100644 index 0000000000..f17aced5c2 --- /dev/null +++ b/gnu/usr.bin/man/man/man.1 @@ -0,0 +1,132 @@ +.\" Man page for man +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH man 1 "Jan 5, 1991" +.LO 1 +.SH NAME +man \- format and display the on-line manual pages +.SH SYNOPSIS +man [\-adfhktw] [\-m system] [\-p string] [\-M path] [\-P pager] +[\-S list] [section] name ... +.SH DESCRIPTION +man formats and displays the on-line manual pages. This version knows +about the MANPATH and PAGER environment variables, so you can have +your own set(s) of personal man pages and choose whatever program you +like to display the formatted pages. If section is specified, man +only looks in that section of the manual. You may also specify the +order to search the sections for entries and which preprocessors to +run on the source files via command line options or environment +variables. +.SH OPTIONS +.TP +.B \-\^M " path" +Specify an alternate manpath. By default, man uses +.B manpath +to determine the path to search. This option overrides the +.B MANPATH +environment variable. +.TP +.B \-\^P " pager" +Specify which pager to use. By default, man uses +.B /usr/local/bin/less -sC, +This option overrides the +.B PAGER +environment variable. +.TP +.B \-\^S " list" +List is a colon separated list of manual sections to search. +This option overrides the +.B MANSECT +environment variable. +.TP +.B \-\^a +By default, man will exit after displaying the first manual page it +finds. Using this option forces man to display all the manual pages +that match +.B name, +not just the first. +.TP +.B \-\^d +Don't actually display the man pages, but do print gobs of debugging +information. +.TP +.B \-\^f +Equivalent to +.B whatis. +.TP +.B \-\^h +Print a one line help message and exit. +.TP +.B \-\^k +Equivalent to +.B apropos. +.TP +.B \-\^m " system" +Specify an alternate set of man pages to search based on the system +name given. +.TP +.B \-\^p " string" +Specify the sequence of preprocessors to run before nroff or troff. +Not all installations will have a full set of preprocessors. +Some of the preprocessors and the letters used to designate them are: +eqn (e), grap (g), pic (p), tbl (t), vgrind (v), refer (r). +This option overrides the +.B MANROFFSEQ +environment variable. +.TP +.B \-\^t +Use +.B /usr/bin/groff -Tps -man +to format the manual page, passing the output to +.B stdout. +The output from +.B /usr/bin/groff -Tps -man +may need to be passed through some filter or another before being +printed. +.TP +.B \-\^w +Don't actually display the man pages, but do print the location(s) of +the files that would be formatted or displayed. +.SH ENVIRONMENT +.TP \w'MANROFFSEQ\ \ 'u +.B MANPATH +If +.B MANPATH +is set, its value is used as the path to search for manual pages. +.TP +.B MANROFFSEQ +If +.B MANROFFSEQ +is set, its value is used to determine the set of preprocessors run +before running nroff or troff. By default, pages are passed through +the table preprocessor before nroff. +.TP +.B MANSEC +If +.B MANSEC +is set, its value is used to determine which manual sections to search. +.TP +.B PAGER +If +.B PAGER +is set, its value is used as the name of the program to use to display +the man page. By default, +.B /usr/local/bin/less -sC +is used. +.SH "SEE ALSO" +apropos(1), whatis(1), manpath(1), less(1), groff(1). +.SH BUGS +The +.B \-t +option only works if a troff-like program is installed. diff --git a/gnu/usr.bin/man/man/man.c b/gnu/usr.bin/man/man/man.c new file mode 100644 index 0000000000..398368960e --- /dev/null +++ b/gnu/usr.bin/man/man/man.c @@ -0,0 +1,1382 @@ +/* + * man.c + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +#define MAN_MAIN + +#include +#include +#include +#include +#include +#include "config.h" +#include "gripes.h" +#include "version.h" + +#ifndef POSIX +#include +#else +#ifndef R_OK +#define R_OK 4 +#endif +#endif + +#ifdef SECURE_MAN_UID +extern uid_t getuid (); +extern int setuid (); +#endif + +#ifdef STDC_HEADERS +#include +#else +extern char *malloc (); +extern char *getenv (); +extern void free (); +extern int system (); +extern int strcmp (); +extern int strncmp (); +extern int exit (); +extern int fflush (); +extern int printf (); +extern int fprintf (); +extern FILE *fopen (); +extern int fclose (); +extern char *sprintf (); +#endif + +extern char *strdup (); + +extern char **glob_vector (); +extern char **glob_filename (); +extern int access (); +extern int unlink (); +extern int system (); +extern int chmod (); +extern int is_newer (); +extern int is_directory (); +extern int do_system_command (); + +char *prognam; +static char *pager; +static char *manp; +static char *manpathlist[MAXDIRS]; +static char *section; +static char *colon_sep_section_list; +static char **section_list; +static char *roff_directive; +static int apropos; +static int whatis; +static int findall; +static int print_where; + +#ifdef ALT_SYSTEMS +static int alt_system; +static char *alt_system_name; +#endif + +static int troff = 0; + +int debug; + +#ifdef HAS_TROFF +#ifdef ALT_SYSTEMS +static char args[] = "M:P:S:adfhkm:p:tw?"; +#else +static char args[] = "M:P:S:adfhkp:tw?"; +#endif +#else +#ifdef ALT_SYSTEMS +static char args[] = "M:P:S:adfhkm:p:w?"; +#else +static char args[] = "M:P:S:adfhkp:w?"; +#endif +#endif + +int +main (argc, argv) + int argc; + char **argv; +{ + int status = 0; + char *nextarg; + char *tmp; + extern int optind; + extern char *mkprogname (); + char *is_section (); + char **get_section_list (); + void man_getopt (); + void do_apropos (); + void do_whatis (); + int man (); + + prognam = mkprogname (argv[0]); + + man_getopt (argc, argv); + + if (optind == argc) + gripe_no_name ((char *)NULL); + + section_list = get_section_list (); + + if (optind == argc - 1) + { + tmp = is_section (argv[optind]); + + if (tmp != NULL) + gripe_no_name (tmp); + } + + while (optind < argc) + { + nextarg = argv[optind++]; + + /* + * See if this argument is a valid section name. If not, + * is_section returns NULL. + */ + tmp = is_section (nextarg); + + if (tmp != NULL) + { + section = tmp; + + if (debug) + fprintf (stderr, "\nsection: %s\n", section); + + continue; + } + + if (apropos) + do_apropos (nextarg); + else if (whatis) + do_whatis (nextarg); + else + { + status = man (nextarg); + + if (status == 0) + gripe_not_found (nextarg, section); + } + } + return status; +} + +void +usage () +{ + static char usage_string[1024] = "%s, version %s\n\n"; + +#ifdef HAS_TROFF +#ifdef ALT_SYSTEMS + static char s1[] = + "usage: %s [-adfhktw] [section] [-M path] [-P pager] [-S list]\n\ + [-m system] [-p string] name ...\n\n"; +#else + static char s1[] = + "usage: %s [-adfhktw] [section] [-M path] [-P pager] [-S list]\n\ + [-p string] name ...\n\n"; +#endif +#else +#ifdef ALT_SYSTEMS + static char s1[] = + "usage: %s [-adfhkw] [section] [-M path] [-P pager] [-S list]\n\ + [-m system] [-p string] name ...\n\n"; +#else + static char s1[] = + "usage: %s [-adfhkw] [section] [-M path] [-P pager] [-S list]\n\ + [-p string] name ...\n\n"; +#endif +#endif + +static char s2[] = " a : find all matching entries\n\ + d : print gobs of debugging information\n\ + f : same as whatis(1)\n\ + h : print this help message\n\ + k : same as apropos(1)\n"; + +#ifdef HAS_TROFF + static char s3[] = " t : use troff to format pages for printing\n"; +#endif + + static char s4[] = " w : print location of man page(s) that would be displayed\n\n\ + M path : set search path for manual pages to `path'\n\ + P pager : use program `pager' to display pages\n\ + S list : colon separated section list\n"; + +#ifdef ALT_SYSTEMS + static char s5[] = " m system : search for alternate system's man pages\n"; +#endif + + static char s6[] = " p string : string tells which preprocessors to run\n\ + e - [n]eqn(1) p - pic(1) t - tbl(1)\n\ + g - grap(1) r - refer(1) v - vgrind(1)\n"; + + strcat (usage_string, s1); + strcat (usage_string, s2); + +#ifdef HAS_TROFF + strcat (usage_string, s3); +#endif + + strcat (usage_string, s4); + +#ifdef ALT_SYSTEMS + strcat (usage_string, s5); +#endif + + strcat (usage_string, s6); + + fprintf (stderr, usage_string, prognam, version, prognam); + exit(1); +} + +char ** +add_dir_to_mpath_list (mp, p) + char **mp; + char *p; +{ + int status; + + status = is_directory (p); + + if (status < 0) + { + fprintf (stderr, "Warning: couldn't stat file %s!\n", p); + } + else if (status == 0) + { + fprintf (stderr, "Warning: %s isn't a directory!\n", p); + } + else if (status == 1) + { + if (debug) + fprintf (stderr, "adding %s to manpathlist\n", p); + + *mp++ = strdup (p); + } + return mp; +} + +/* + * Get options from the command line and user environment. + */ +void +man_getopt (argc, argv) + register int argc; + register char **argv; +{ + register int c; + register char *p; + register char *end; + register char **mp; + extern char *optarg; + extern int getopt (); + extern void downcase (); + extern char *manpath (); + + while ((c = getopt (argc, argv, args)) != EOF) + { + switch (c) + { + case 'M': + manp = strdup (optarg); + break; + case 'P': + pager = strdup (optarg); + break; + case 'S': + colon_sep_section_list = strdup (optarg); + break; + case 'a': + findall++; + break; + case 'd': + debug++; + break; + case 'f': + if (troff) + gripe_incompatible ("-f and -t"); + if (apropos) + gripe_incompatible ("-f and -k"); + if (print_where) + gripe_incompatible ("-f and -w"); + whatis++; + break; + case 'k': + if (troff) + gripe_incompatible ("-k and -t"); + if (whatis) + gripe_incompatible ("-k and -f"); + if (print_where) + gripe_incompatible ("-k and -w"); + apropos++; + break; +#ifdef ALT_SYSTEMS + case 'm': + alt_system++; + alt_system_name = strdup (optarg); + break; +#endif + case 'p': + roff_directive = strdup (optarg); + break; +#ifdef HAS_TROFF + case 't': + if (apropos) + gripe_incompatible ("-t and -k"); + if (whatis) + gripe_incompatible ("-t and -f"); + if (print_where) + gripe_incompatible ("-t and -w"); + troff++; + break; +#endif + case 'w': + if (apropos) + gripe_incompatible ("-w and -k"); + if (whatis) + gripe_incompatible ("-w and -f"); + if (troff) + gripe_incompatible ("-w and -t"); + print_where++; + break; + case 'h': + case '?': + default: + usage(); + break; + } + } + + if (pager == NULL || *pager == '\0') + if ((pager = getenv ("PAGER")) == NULL) + pager = strdup (PAGER); + + if (debug) + fprintf (stderr, "\nusing %s as pager\n", pager); + + if (manp == NULL) + { + if ((manp = manpath (0)) == NULL) + gripe_manpath (); + + if (debug) + fprintf (stderr, + "\nsearch path for pages determined by manpath is\n%s\n\n", + manp); + } + +#ifdef ALT_SYSTEMS + if (alt_system_name == NULL || *alt_system_name == '\0') + if ((alt_system_name = getenv ("SYSTEM")) != NULL) + alt_system_name = strdup (alt_system_name); + + if (alt_system_name != NULL && *alt_system_name != '\0') + downcase (alt_system_name); +#endif + + /* + * Expand the manpath into a list for easier handling. + */ + mp = manpathlist; + for (p = manp; ; p = end+1) + { + if ((end = strchr (p, ':')) != NULL) + *end = '\0'; + +#ifdef ALT_SYSTEMS + if (alt_system) + { + char buf[BUFSIZ]; + + if (debug) + fprintf (stderr, "Alternate system `%s' specified\n", + alt_system_name); + + strcpy (buf, p); + strcat (buf, "/"); + strcat (buf, alt_system_name); + + mp = add_dir_to_mpath_list (mp, buf); + } + else + { + mp = add_dir_to_mpath_list (mp, p); + } +#else + mp = add_dir_to_mpath_list (mp, p); +#endif + if (end == NULL) + break; + + *end = ':'; + } + *mp = NULL; +} + +/* + * Check to see if the argument is a valid section number. If the + * first character of name is a numeral, or the name matches one of + * the sections listed in section_list, we'll assume that it's a section. + * The list of sections in config.h simply allows us to specify oddly + * named directories like .../man3f. Yuk. + */ +char * +is_section (name) + register char *name; +{ + register char **vs; + + for (vs = section_list; *vs != NULL; vs++) + if ((strcmp (*vs, name) == NULL) || (isdigit (name[0]))) + return strdup (name); + + return NULL; +} + +/* + * Handle the apropos option. Cheat by using another program. + */ +void +do_apropos (name) + register char *name; +{ + register int len; + register char *command; + + len = strlen (APROPOS) + strlen (name) + 2; + + if ((command = (char *) malloc(len)) == NULL) + gripe_alloc (len, "command"); + + sprintf (command, "%s %s", APROPOS, name); + + (void) do_system_command (command); + + free (command); +} + +/* + * Handle the whatis option. Cheat by using another program. + */ +void +do_whatis (name) + register char *name; +{ + register int len; + register char *command; + + len = strlen (WHATIS) + strlen (name) + 2; + + if ((command = (char *) malloc(len)) == NULL) + gripe_alloc (len, "command"); + + sprintf (command, "%s %s", WHATIS, name); + + (void) do_system_command (command); + + free (command); +} + +/* + * Change a name of the form ...man/man1/name.1 to ...man/cat1/name.1 + * or a name of the form ...man/cat1/name.1 to ...man/man1/name.1 + */ +char * +convert_name (name, to_cat) + register char *name; + register int to_cat; +{ + register char *to_name; + register char *t1; + register char *t2 = NULL; + +#ifdef DO_COMPRESS + if (to_cat) + { + int len = strlen (name) + 3; + to_name = (char *) malloc (len); + if (to_name == NULL) + gripe_alloc (len, "to_name"); + strcpy (to_name, name); + strcat (to_name, ".Z"); + } + else + to_name = strdup (name); +#else + to_name = strdup (name); +#endif + + t1 = strrchr (to_name, '/'); + if (t1 != NULL) + { + *t1 = NULL; + t2 = strrchr (to_name, '/'); + *t1 = '/'; + } + + if (t2 == NULL) + gripe_converting_name (name, to_cat); + + if (to_cat) + { + *(++t2) = 'c'; + *(t2+2) = 't'; + } + else + { + *(++t2) = 'm'; + *(t2+2) = 'n'; + } + + if (debug) + fprintf (stderr, "to_name in convert_name () is: %s\n", to_name); + + return to_name; +} + +/* + * Try to find the man page corresponding to the given name. The + * reason we do this with globbing is because some systems have man + * page directories named man3 which contain files with names like + * XtPopup.3Xt. Rather than requiring that this program know about + * all those possible names, we simply try to match things like + * .../man[sect]/name[sect]*. This is *much* easier. + * + * Note that globbing is only done when the section is unspecified. + */ +char ** +glob_for_file (path, section, name, cat) + register char *path; + register char *section; + register char *name; + register int cat; +{ + char pathname[BUFSIZ]; + char **gf; + + if (cat) + sprintf (pathname, "%s/cat%s/%s.%s*", path, section, name, section); + else + sprintf (pathname, "%s/man%s/%s.%s*", path, section, name, section); + + if (debug) + fprintf (stderr, "globbing %s\n", pathname); + + gf = glob_filename (pathname); + + if ((gf == (char **) -1 || *gf == NULL) && isdigit (*section)) + { + if (cat) + sprintf (pathname, "%s/cat%s/%s.%c*", path, section, name, *section); + else + sprintf (pathname, "%s/man%s/%s.%c*", path, section, name, *section); + + gf = glob_filename (pathname); + } + return gf; +} + +/* + * Return an un-globbed name in the same form as if we were doing + * globbing. + */ +char ** +make_name (path, section, name, cat) + register char *path; + register char *section; + register char *name; + register int cat; +{ + register int i = 0; + static char *names[3]; + char buf[BUFSIZ]; + + if (cat) + sprintf (buf, "%s/cat%s/%s.%s", path, section, name, section); + else + sprintf (buf, "%s/man%s/%s.%s", path, section, name, section); + + if (access (buf, R_OK) == 0) + names[i++] = strdup (buf); + + /* + * If we're given a section that looks like `3f', we may want to try + * file names like .../man3/foo.3f as well. This seems a bit + * kludgey to me, but what the hey... + */ + if (section[1] != '\0') + { + if (cat) + sprintf (buf, "%s/cat%c/%s.%s", path, section[0], name, section); + else + sprintf (buf, "%s/man%c/%s.%s", path, section[0], name, section); + + if (access (buf, R_OK) == 0) + names[i++] = strdup (buf); + } + + names[i] = NULL; + + return &names[0]; +} + +#ifdef DO_UNCOMPRESS +char * +get_expander (file) + char *file; +{ + char *expander = NULL; + int len = strlen (file); + + if (file[len - 2] == '.') + { + switch (file[len - 1]) + { +#ifdef FCAT + case 'F': + if (strcmp (FCAT, "") != 0) + expander = strdup (FCAT); + break; +#endif +#ifdef YCAT + case 'Y': + if (strcmp (YCAT, "") != 0) + expander = strdup (YCAT); + break; +#endif +#ifdef ZCAT + case 'Z': + if (strcmp (ZCAT, "") != 0) + expander = strdup (ZCAT); + break; +#endif + default: + break; + } + } + return expander; +} +#endif + +/* + * Simply display the preformatted page. + */ +int +display_cat_file (file) + register char *file; +{ + register int found; + char command[BUFSIZ]; + + found = 0; + + if (access (file, R_OK) == 0) + { +#ifdef DO_UNCOMPRESS + char *expander = get_expander (file); + + if (expander != NULL) + sprintf (command, "%s %s | %s", expander, file, pager); + else + sprintf (command, "%s %s", pager, file); +#else + sprintf (command, "%s %s", pager, file); +#endif + + found = do_system_command (command); + } + return found; +} + +/* + * Try to find the ultimate source file. If the first line of the + * current file is not of the form + * + * .so man3/printf.3s + * + * the input file name is returned. + */ +char * +ultimate_source (name, path) + char *name; + char *path; +{ + FILE *fp; + char buf[BUFSIZ]; + char ult[BUFSIZ]; + char *beg; + char *end; + + strcpy (ult, name); + strcpy (buf, name); + + next: + + if ((fp = fopen (ult, "r")) == NULL) + return buf; + + if (fgets (buf, BUFSIZ, fp) == NULL) + return ult; + + if (strlen (buf) < 5) + return ult; + + beg = buf; + if (*beg++ == '.' && *beg++ == 's' && *beg++ == 'o') + { + while ((*beg == ' ' || *beg == '\t') && *beg != '\0') + beg++; + + end = beg; + while (*end != ' ' && *end != '\t' && *end != '\n' && *end != '\0') + end++; + + *end = '\0'; + + strcpy (ult, path); + strcat (ult, "/"); + strcat (ult, beg); + + strcpy (buf, ult); + + goto next; + } + + if (debug) + fprintf (stderr, "found ultimate source file %s\n", ult); + + return ult; +} + +void +add_directive (first, d, file, buf) + int *first; + char *d; + char *file; + char *buf; +{ + if (strcmp (d, "") != 0) + { + if (*first) + { + *first = 0; + strcpy (buf, d); + strcat (buf, " "); + strcat (buf, file); + } + else + { + strcat (buf, " | "); + strcat (buf, d); + } + } +} + +int +parse_roff_directive (cp, file, buf) + char *cp; + char *file; + char *buf; +{ + char c; + int first = 1; + int tbl_found = 0; + + while ((c = *cp++) != '\0') + { + switch (c) + { + case 'e': + + if (debug) + fprintf (stderr, "found eqn(1) directive\n"); + + if (troff) + add_directive (&first, EQN, file, buf); + else + add_directive (&first, NEQN, file, buf); + + break; + + case 'g': + + if (debug) + fprintf (stderr, "found grap(1) directive\n"); + + add_directive (&first, GRAP, file, buf); + + break; + + case 'p': + + if (debug) + fprintf (stderr, "found pic(1) directive\n"); + + add_directive (&first, PIC, file, buf); + + break; + + case 't': + + if (debug) + fprintf (stderr, "found tbl(1) directive\n"); + + tbl_found++; + add_directive (&first, TBL, file, buf); + break; + + case 'v': + + if (debug) + fprintf (stderr, "found vgrind(1) directive\n"); + + add_directive (&first, VGRIND, file, buf); + break; + + case 'r': + + if (debug) + fprintf (stderr, "found refer(1) directive\n"); + + add_directive (&first, REFER, file, buf); + break; + + case ' ': + case '\t': + case '\n': + + goto done; + + default: + + return -1; + } + } + + done: + + if (first) + return 1; + +#ifdef HAS_TROFF + if (troff) + { + strcat (buf, " | "); + strcat (buf, TROFF); + } + else +#endif + { + strcat (buf, " | "); + strcat (buf, NROFF); + } + + if (tbl_found && !troff && strcmp (COL, "") != 0) + { + strcat (buf, " | "); + strcat (buf, COL); + } + + return 0; +} + +char * +make_roff_command (file) + char *file; +{ + FILE *fp; + char line [BUFSIZ]; + static char buf [BUFSIZ]; + int status; + char *cp; + + if (roff_directive != NULL) + { + if (debug) + fprintf (stderr, "parsing directive from command line\n"); + + status = parse_roff_directive (roff_directive, file, buf); + + if (status == 0) + return buf; + + if (status == -1) + gripe_roff_command_from_command_line (file); + } + + if ((fp = fopen (file, "r")) != NULL) + { + cp = &line[0]; + fgets (line, 100, fp); + if (*cp++ == '\'' && *cp++ == '\\' && *cp++ == '"' && *cp++ == ' ') + { + if (debug) + fprintf (stderr, "parsing directive from file\n"); + + status = parse_roff_directive (cp, file, buf); + + fclose (fp); + + if (status == 0) + return buf; + + if (status == -1) + gripe_roff_command_from_file (file); + } + } + else + { + /* + * Is there really any point in continuing to look for + * preprocessor options if we can't even read the man page source? + */ + gripe_reading_man_file (file); + return NULL; + } + + if ((cp = getenv ("MANROFFSEQ")) != NULL) + { + if (debug) + fprintf (stderr, "parsing directive from environment\n"); + + status = parse_roff_directive (cp, file, buf); + + if (status == 0) + return buf; + + if (status == -1) + gripe_roff_command_from_env (); + } + + if (debug) + fprintf (stderr, "using default preprocessor sequence\n"); + +#ifdef HAS_TROFF + if (troff) + { + if (strcmp (TBL, "") != 0) + { + strcpy (buf, TBL); + strcat (buf, " "); + strcat (buf, file); + strcat (buf, " | "); + strcat (buf, TROFF); + } + else + { + strcpy (buf, TROFF); + strcat (buf, " "); + strcat (buf, file); + } + } + else +#endif + { + if (strcmp (TBL, "") != 0) + { + strcpy (buf, TBL); + strcat (buf, " "); + strcat (buf, file); + strcat (buf, " | "); + strcat (buf, NROFF); + } + else + { + strcpy (buf, NROFF); + strcat (buf, " "); + strcat (buf, file); + } + + if (strcmp (COL, "") != 0) + { + strcat (buf, " | "); + strcat (buf, COL); + } + } + return buf; +} + +/* + * Try to format the man page and create a new formatted file. Return + * 1 for success and 0 for failure. + */ +int +make_cat_file (path, man_file, cat_file) + register char *path; + register char *man_file; + register char *cat_file; +{ + int status; + int mode; + FILE *fp; + char *roff_command; + char command[BUFSIZ]; + + if ((fp = fopen (cat_file, "w")) != NULL) + { + fclose (fp); + unlink (cat_file); + + roff_command = make_roff_command (man_file, 0); + if (roff_command == NULL) + return 0; + else +#ifdef DO_COMPRESS + sprintf (command, "(cd %s ; %s | %s > %s)", path, + roff_command, COMPRESSOR, cat_file); +#else + sprintf (command, "(cd %s ; %s > %s)", path, + roff_command, cat_file); +#endif + /* + * Don't let the user interrupt the system () call and screw up + * the formmatted man page if we're not done yet. + */ + signal (SIGINT, SIG_IGN); + + fprintf (stderr, "Formatting page, please wait...\n"); + + status = do_system_command (command); + + if (status == 1) + { + mode = CATMODE; + chmod (cat_file, mode); + + if (debug) + fprintf (stderr, "mode of %s is now %o\n", cat_file, mode); + } + + signal (SIGINT, SIG_DFL); + + return 1; + } + else + { + if (debug) + fprintf (stderr, "Couldn't open %s for writing.\n", cat_file); + + return 0; + } +} + +/* + * Try to format the man page source and save it, then display it. If + * that's not possible, try to format the man page source and display + * it directly. + * + * Note that we've already been handed the name of the ultimate source + * file at this point. + */ +int +format_and_display (path, man_file, cat_file) + register char *path; + register char *man_file; + register char *cat_file; +{ + int status; + register int found; + char *roff_command; + char command[BUFSIZ]; + + found = 0; + + if (access (man_file, R_OK) != 0) + return 0; + + if (troff) + { + roff_command = make_roff_command (man_file, 1); + if (roff_command == NULL) + return 0; + else + sprintf (command, "(cd %s ; %s)", path, roff_command); + + found = do_system_command (command); + } + else + { + status = is_newer (man_file, cat_file); + if (debug) + fprintf (stderr, "status from is_newer() = %d\n"); + + if (status == 1 || status == -2) + { + /* + * Cat file is out of date. Try to format and save it. + */ + if (print_where) + { + printf ("%s\n", man_file); + found++; + } + else + { + found = make_cat_file (path, man_file, cat_file); +#ifdef SECURE_MAN_UID + if (!found) + { + /* + * Try again as real user. Note that for private + * man pages, we won't even get this far unless the + * effective user can read the real user's man page + * source. Also, if we are trying to find all the + * man pages, this will probably make it impossible + * to make cat files in the system directories if + * the real user's man directories are searched + * first, because there's no way to undo this (is + * there?). Yikes, am I missing something obvious? + */ + setuid (getuid ()); + + found = make_cat_file (path, man_file, cat_file); + } +#endif + if (found) + { + /* + * Creating the cat file worked. Now just display it. + */ + (void) display_cat_file (cat_file); + } + else + { + /* + * Couldn't create cat file. Just format it and + * display it through the pager. + */ + roff_command = make_roff_command (man_file, 0); + if (roff_command == NULL) + return 0; + else + sprintf (command, "(cd %s ; %s | %s)", path, + roff_command, pager); + + found = do_system_command (command); + } + } + } + else if (access (cat_file, R_OK) == 0) + { + /* + * Formatting not necessary. Cat file is newer than source + * file, or source file is not present but cat file is. + */ + if (print_where) + { + printf ("%s (source: %s)\n", cat_file, man_file); + found++; + } + else + { + found = display_cat_file (cat_file); + } + } + } + return found; +} + +/* + * See if the preformatted man page or the source exists in the given + * section. + */ +int +try_section (path, section, name, glob) + register char *path; + register char *section; + register char *name; + register int glob; +{ + register int found = 0; + register int to_cat; + register int cat; + register char **names; + register char **np; + + if (debug) + { + if (glob) + fprintf (stderr, "trying section %s with globbing\n", section); + else + fprintf (stderr, "trying section %s without globbing\n", section); + } + +#ifndef NROFF_MISSING + /* + * Look for man page source files. + */ + cat = 0; + if (glob) + names = glob_for_file (path, section, name, cat); + else + names = make_name (path, section, name, cat); + + if (names == (char **) -1 || *names == NULL) + /* + * No files match. See if there's a preformatted page around that + * we can display. + */ +#endif /* NROFF_MISSING */ + { + if (!troff) + { + cat = 1; + if (glob) + names = glob_for_file (path, section, name, cat); + else + names = make_name (path, section, name, cat); + + if (names != (char **) -1 && *names != NULL) + { + for (np = names; *np != NULL; np++) + { + if (print_where) + { + printf ("%s\n", *np); + found++; + } + else + { + found += display_cat_file (*np); + } + } + } + } + } +#ifndef NROFF_MISSING + else + { + for (np = names; *np != NULL; np++) + { + register char *cat_file = NULL; + register char *man_file; + + man_file = ultimate_source (*np, path); + + if (!troff) + { + to_cat = 1; + + cat_file = convert_name (man_file, to_cat); + + if (debug) + fprintf (stderr, "will try to write %s if needed\n", cat_file); + } + + found += format_and_display (path, man_file, cat_file); + } + } +#endif /* NROFF_MISSING */ + return found; +} + +/* + * Search for manual pages. + * + * If preformatted manual pages are supported, look for the formatted + * file first, then the man page source file. If they both exist and + * the man page source file is newer, or only the source file exists, + * try to reformat it and write the results in the cat directory. If + * it is not possible to write the cat file, simply format and display + * the man file. + * + * If preformatted pages are not supported, or the troff option is + * being used, only look for the man page source file. + * + */ +int +man (name) + char *name; +{ + register int found; + register int glob; + register char **mp; + register char **sp; + + found = 0; + + fflush (stdout); + if (section != NULL) + { + for (mp = manpathlist; *mp != NULL; mp++) + { + if (debug) + fprintf (stderr, "\nsearching in %s\n", *mp); + + glob = 0; + + found += try_section (*mp, section, name, glob); + + if (found && !findall) /* i.e. only do this section... */ + return found; + } + } + else + { + for (sp = section_list; *sp != NULL; sp++) + { + for (mp = manpathlist; *mp != NULL; mp++) + { + if (debug) + fprintf (stderr, "\nsearching in %s\n", *mp); + + glob = 1; + + found += try_section (*mp, *sp, name, glob); + + if (found && !findall) /* i.e. only do this section... */ + return found; + } + } + } + return found; +} + +char ** +get_section_list () +{ + int i; + char *p; + char *end; + static char *tmp_section_list[100]; + + if (colon_sep_section_list == NULL) + { + if ((p = getenv ("MANSECT")) == NULL) + { + return std_sections; + } + else + { + colon_sep_section_list = strdup (p); + } + } + + i = 0; + for (p = colon_sep_section_list; ; p = end+1) + { + if ((end = strchr (p, ':')) != NULL) + *end = '\0'; + + tmp_section_list[i++] = strdup (p); + + if (end == NULL) + break; + } + + tmp_section_list [i] = NULL; + return tmp_section_list; +} diff --git a/gnu/usr.bin/man/man/man.man b/gnu/usr.bin/man/man/man.man new file mode 100644 index 0000000000..2c034feee0 --- /dev/null +++ b/gnu/usr.bin/man/man/man.man @@ -0,0 +1,132 @@ +.\" Man page for man +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH man 1 "Jan 5, 1991" +.LO 1 +.SH NAME +man \- format and display the on-line manual pages +.SH SYNOPSIS +man [\-adfhktw] [\-m system] [\-p string] [\-M path] [\-P pager] +[\-S list] [section] name ... +.SH DESCRIPTION +man formats and displays the on-line manual pages. This version knows +about the MANPATH and PAGER environment variables, so you can have +your own set(s) of personal man pages and choose whatever program you +like to display the formatted pages. If section is specified, man +only looks in that section of the manual. You may also specify the +order to search the sections for entries and which preprocessors to +run on the source files via command line options or environment +variables. +.SH OPTIONS +.TP +.B \-\^M " path" +Specify an alternate manpath. By default, man uses +.B manpath +to determine the path to search. This option overrides the +.B MANPATH +environment variable. +.TP +.B \-\^P " pager" +Specify which pager to use. By default, man uses +.B %pager%, +This option overrides the +.B PAGER +environment variable. +.TP +.B \-\^S " list" +List is a colon separated list of manual sections to search. +This option overrides the +.B MANSECT +environment variable. +.TP +.B \-\^a +By default, man will exit after displaying the first manual page it +finds. Using this option forces man to display all the manual pages +that match +.B name, +not just the first. +.TP +.B \-\^d +Don't actually display the man pages, but do print gobs of debugging +information. +.TP +.B \-\^f +Equivalent to +.B whatis. +.TP +.B \-\^h +Print a one line help message and exit. +.TP +.B \-\^k +Equivalent to +.B apropos. +.TP +.B \-\^m " system" +Specify an alternate set of man pages to search based on the system +name given. +.TP +.B \-\^p " string" +Specify the sequence of preprocessors to run before nroff or troff. +Not all installations will have a full set of preprocessors. +Some of the preprocessors and the letters used to designate them are: +eqn (e), grap (g), pic (p), tbl (t), vgrind (v), refer (r). +This option overrides the +.B MANROFFSEQ +environment variable. +.TP +.B \-\^t +Use +.B %troff% +to format the manual page, passing the output to +.B stdout. +The output from +.B %troff% +may need to be passed through some filter or another before being +printed. +.TP +.B \-\^w +Don't actually display the man pages, but do print the location(s) of +the files that would be formatted or displayed. +.SH ENVIRONMENT +.TP \w'MANROFFSEQ\ \ 'u +.B MANPATH +If +.B MANPATH +is set, its value is used as the path to search for manual pages. +.TP +.B MANROFFSEQ +If +.B MANROFFSEQ +is set, its value is used to determine the set of preprocessors run +before running nroff or troff. By default, pages are passed through +the table preprocessor before nroff. +.TP +.B MANSEC +If +.B MANSEC +is set, its value is used to determine which manual sections to search. +.TP +.B PAGER +If +.B PAGER +is set, its value is used as the name of the program to use to display +the man page. By default, +.B %pager% +is used. +.SH "SEE ALSO" +apropos(1), whatis(1), manpath(1), less(1), groff(1). +.SH BUGS +The +.B \-t +option only works if a troff-like program is installed. diff --git a/gnu/usr.bin/man/man/manpath.c b/gnu/usr.bin/man/man/manpath.c new file mode 100644 index 0000000000..ccf7a55684 --- /dev/null +++ b/gnu/usr.bin/man/man/manpath.c @@ -0,0 +1,520 @@ +/* + * manpath.c + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +#define MANPATH_MAIN + +#include +#include +#include +#include +#include "config.h" +#include "manpath.h" +#include "gripes.h" + +#ifdef STDC_HEADERS +#include +#else +extern int fprintf (); +extern int strcmp (); +extern int strncmp (); +extern char *memcpy (); +extern char *getenv(); +extern char *malloc(); +extern void free (); +extern int exit (); +#endif + +extern char *strdup (); +extern int is_directory (); + +#ifndef MAIN +extern int debug; +#endif + +#ifdef MAIN + +#ifndef STDC_HEADERS +extern char *strcpy (); +extern int fflush (); +#endif + +char *prognam; +int debug; + +/* + * Examine user's PATH and print a reasonable MANPATH. + */ +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + int quiet; + char *mp; + extern int getopt (); + extern char *mkprogname (); + void usage (); + char *manpath (); + + quiet = 1; + + prognam = mkprogname (argv[0]); + + while ((c = getopt (argc, argv, "dhq?")) != EOF) + { + switch (c) + { + case 'd': + debug++; + break; + case 'q': + quiet = 0; + break; + case '?': + case 'h': + default: + usage(); + break; + } + } + + mp = manpath (quiet); + + fprintf (stdout, "%s\n", mp); + fflush (stdout); + + return 0; +} + +void +usage () +{ + fprintf (stderr, "usage: %s [-q]\n", prognam); + exit (1); +} +#endif /* MAIN */ + +/* + * If the environment variable MANPATH is set, return it. + * If the environment variable PATH is set and has a nonzero length, + * try to determine the corresponding manpath, otherwise, return the + * default manpath. + * + * The manpath.config file is used to map system wide /bin directories + * to top level man page directories. + * + * For directories which are in the user's path but not in the + * manpath.config file, see if there is a subdirectory `man' or `MAN'. + * If so, add that directory to the path. Example: user has + * $HOME/bin in his path and the directory $HOME/bin/man exists -- the + * directory $HOME/bin/man will be added to the manpath. + */ +char * +manpath (perrs) + register int perrs; +{ + register int len; + register char *manpathlist; + register char *path; + int get_dirlist (); + char *def_path (); + char *get_manpath (); + + if (get_dirlist ()) + gripe_reading_mp_config (); + + if ((manpathlist = getenv ("MANPATH")) != NULL) + /* + * This must be it. + */ + { + if (perrs) + fprintf (stderr, "(Warning: MANPATH environment variable set)\n"); + return strdup (manpathlist); + } + else if ((path = getenv ("PATH")) == NULL) + /* + * Things aren't going to work well, but hey... + */ + { + if (perrs) + fprintf (stderr, "Warning: path not set\n"); + return def_path (perrs); + } + else + { + if ((len = strlen (path)) == 0) + /* + * Things aren't going to work well here either... + */ + { + if (perrs) + fprintf (stderr, "Warning: path set but has zero length\n"); + return def_path (perrs); + } + return get_manpath (perrs, path); + } +} + +/* + * Get the list of bin directories and the corresponding man + * directories from the manpath.config file. + * + * This is ugly. + */ +int +get_dirlist () +{ + int i; + char *bp; + char *p; + char buf[BUFSIZ]; + DIRLIST *dlp = list; + FILE *config; + + if ((config = fopen (config_file, "r")) == NULL) + gripe_getting_mp_config (config_file); + + while ((bp = fgets (buf, BUFSIZ, config)) != NULL) + { + while (*bp && (*bp == ' ' || *bp == '\t')) + bp++; + + if (*bp == '#' || *bp == '\n') + continue; + + if (!strncmp ("MANBIN", bp, 6)) + continue; + + if (!strncmp ("MANDATORY_MANPATH", bp, 17)) + { + if ((p = strchr (bp, ' ')) == NULL) + if ((p = strchr (bp, '\t')) == NULL) + return -1; + + bp = p; + + dlp->mandatory = 1; + + while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t')) + bp++; + + i = 0; + while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t') + dlp->mandir[i++] = *bp++; + dlp->mandir[i] = '\0'; + + if (debug) + fprintf (stderr, "found mandatory man directory %s\n", + dlp->mandir); + } + else if (!strncmp ("MANPATH_MAP", bp, 11)) + { + if ((p = strchr (bp, ' ')) == NULL) + if ((p = strchr (bp, '\t')) == NULL) + return -1; + + bp = p; + + dlp->mandatory = 0; + + while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t')) + bp++; + + i = 0; + while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t') + dlp->bin[i++] = *bp++; + dlp->bin[i] = '\0'; + + while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t')) + bp++; + + i = 0; + while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t') + dlp->mandir[i++] = *bp++; + dlp->mandir[i] = '\0'; + + if (debug) + fprintf (stderr, "found manpath map %s --> %s\n", + dlp->bin, dlp->mandir); + } + else + { + gripe_reading_mp_config (); + } + dlp++; + } + + dlp->bin[0] = '\0'; + dlp->mandir[0] = '\0'; + dlp->mandatory = 0; + + return 0; +} + +/* + * Construct the default manpath. This picks up mandatory manpaths + * only. + */ +char * +def_path (perrs) + int perrs; +{ + register int len; + register char *manpathlist, *p; + register DIRLIST *dlp; + + len = 0; + dlp = list; + while (dlp->mandatory != 0) + { + len += strlen (dlp->mandir) + 1; + dlp++; + } + + manpathlist = (char *) malloc (len); + if (manpathlist == NULL) + gripe_alloc (len, "manpathlist"); + + *manpathlist = '\0'; + + dlp = list; + p = manpathlist; + while (dlp->mandatory != 0) + { + int status; + char *path = dlp->mandir; + + status = is_directory(path); + + if (status < 0 && perrs) + { + fprintf (stderr, "Warning: couldn't stat file %s!\n", path); + } + else if (status == 0 && perrs) + { + fprintf (stderr, "Warning: standard directory %s doesn't exist!\n", + path); + } + else if (status == 1) + { + len = strlen (path); + memcpy (p, path, len); + p += len; + *p++ = ':'; + dlp++; + } + } + + p[-1] = '\0'; + + return manpathlist; +} + +/* + * For each directory in the user's path, see if it is one of the + * directories listed in the manpath.config file. If so, and it is + * not already in the manpath, add it. If the directory is not listed + * in the manpath.config file, see if there is a subdirectory `man' or + * `MAN'. If so, and it is not already in the manpath, add it. + * Example: user has $HOME/bin in his path and the directory + * $HOME/bin/man exists -- the directory $HOME/bin/man will be added + * to the manpath. + */ +char * +get_manpath (perrs, path) + register int perrs; + register char *path; +{ + register int len; + register char *tmppath; + register char *t; + register char *p; + register char **lp; + register char *end; + register char *manpathlist; + register DIRLIST *dlp; + void add_dir_to_list (); + char *has_subdirs (); + + tmppath = strdup (path); + + for (p = tmppath; ; p = end+1) + { + if (end = strchr(p, ':')) + *end = '\0'; + + if (debug) + fprintf (stderr, "\npath directory %s ", p); + + /* + * The directory we're working on is in the config file. + * If we haven't added it to the list yet, do. + */ + for (dlp = list; dlp->mandir[0] != '\0'; dlp++) + if (dlp->bin[0] != '\0' && !strcmp (p, dlp->bin)) + { + if (debug) + fprintf (stderr, "is in the config file\n"); + + add_dir_to_list (tmplist, dlp->mandir, perrs); + goto found; + } + + /* + * The directory we're working on isn't in the config file. See + * if it has man or MAN subdirectories. If so, and it hasn't + * been added to the list, do. + */ + if (debug) + fprintf (stderr, "is not in the config file\n"); + + t = has_subdirs (p); + if (t != NULL) + { + if (debug) + fprintf (stderr, "but it does have a man or MAN subdirectory\n"); + + add_dir_to_list (tmplist, t, perrs); + free (t); + } + else + { + if (debug) + fprintf (stderr, "and doesn't have man or MAN subdirectories\n"); + } + + found: + + if (!end) + break; + } + + if (debug) + fprintf (stderr, "\nadding mandatory man directories\n\n"); + + dlp = list; + while (dlp->mandatory != 0) + { + add_dir_to_list (tmplist, dlp->mandir, perrs); + dlp++; + } + + len = 0; + lp = tmplist; + while (*lp != NULL) + { + len += strlen (*lp) + 1; + lp++; + } + + manpathlist = (char *) malloc (len); + if (manpathlist == NULL) + gripe_alloc (len, "manpathlist"); + + *manpathlist = '\0'; + + lp = tmplist; + p = manpathlist; + while (*lp != NULL) + { + len = strlen (*lp); + memcpy (p, *lp, len); + p += len; + *p++ = ':'; + lp++; + } + + p[-1] = '\0'; + + return manpathlist; +} + +/* + * Add a directory to the manpath list if it isn't already there. + */ +void +add_dir_to_list (lp, dir, perrs) + char **lp; + char *dir; + int perrs; +{ + extern char *strdup (); + int status; + + while (*lp != NULL) + { + if (!strcmp (*lp, dir)) + { + if (debug) + fprintf (stderr, "%s is already in the manpath\n", dir); + return; + } + lp++; + } + /* + * Not found -- add it. + */ + status = is_directory(dir); + + if (status < 0 && perrs) + { + fprintf (stderr, "Warning: couldn't stat file %s!\n", dir); + } + else if (status == 0 && perrs) + { + fprintf (stderr, "Warning: %s isn't a directory!\n", dir); + } + else if (status == 1) + { + if (debug) + fprintf (stderr, "adding %s to manpath\n", dir); + + *lp = strdup (dir); + } +} + +/* + * Check to see if the current directory has man or MAN + * subdirectories. + */ +char * +has_subdirs (p) + register char *p; +{ + int len; + register char *t; + + len = strlen (p); + + t = (char *) malloc ((unsigned) len + 5); + if (t == NULL) + gripe_alloc (len+5, "p\n"); + + memcpy (t, p, len); + strcpy (t + len, "/man"); + + if (is_directory (t) == 1) + return t; + + strcpy (t + len, "/MAN"); + + if (is_directory (t) == 1) + return t; + + return NULL; +} diff --git a/gnu/usr.bin/man/man/manpath.h b/gnu/usr.bin/man/man/manpath.h new file mode 100644 index 0000000000..a61761f676 --- /dev/null +++ b/gnu/usr.bin/man/man/manpath.h @@ -0,0 +1,26 @@ +/* + * manpath.h + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +typedef struct +{ + char mandir[MAXPATHLEN]; + char bin[MAXPATHLEN]; + int mandatory; +} DIRLIST; + +DIRLIST list[MAXDIRS]; + +char *tmplist[MAXDIRS]; diff --git a/gnu/usr.bin/man/man/ndir.h b/gnu/usr.bin/man/man/ndir.h new file mode 100644 index 0000000000..438d5c20a1 --- /dev/null +++ b/gnu/usr.bin/man/man/ndir.h @@ -0,0 +1,51 @@ +/* + -- definitions for 4.2BSD-compatible directory access + + last edit: 09-Jul-1983 D A Gwyn +*/ + +#ifdef VMS +#ifndef FAB$C_BID +#include +#endif +#ifndef NAM$C_BID +#include +#endif +#ifndef RMS$_SUC +#include +#endif +#include "dir.h" +#endif /* VMS */ + +#define DIRBLKSIZ 512 /* size of directory block */ +#ifdef VMS +#define MAXNAMLEN (DIR$S_NAME + 7) /* 80 plus room for version #. */ +#define MAXFULLSPEC NAM$C_MAXRSS /* Maximum full spec */ +#else +#define MAXNAMLEN 15 /* maximum filename length */ +#endif /* VMS */ + /* NOTE: MAXNAMLEN must be one less than a multiple of 4 */ + +struct direct /* data from readdir() */ + { + long d_ino; /* inode number of entry */ + unsigned short d_reclen; /* length of this record */ + unsigned short d_namlen; /* length of string in d_name */ + char d_name[MAXNAMLEN+1]; /* name of file */ + }; + +typedef struct + { + int dd_fd; /* file descriptor */ + int dd_loc; /* offset in block */ + int dd_size; /* amount of valid data */ + char dd_buf[DIRBLKSIZ]; /* directory block */ + } DIR; /* stream data from opendir() */ + +extern DIR *opendir(); +extern struct direct *readdir(); +extern long telldir(); +extern void seekdir(); +extern void closedir(); + +#define rewinddir( dirp ) seekdir( dirp, 0L ) diff --git a/gnu/usr.bin/man/man/strdup.c b/gnu/usr.bin/man/man/strdup.c new file mode 100644 index 0000000000..4e5af07257 --- /dev/null +++ b/gnu/usr.bin/man/man/strdup.c @@ -0,0 +1,39 @@ +/* strdup.c -- return a newly allocated copy of a string + Copyright (C) 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef STDC_HEADERS +#include +#include +#else +char *malloc (); +char *strcpy (); +#endif + +/* Return a newly allocated copy of STR, + or 0 if out of memory. */ + +char * +strdup (str) + char *str; +{ + char *newstr; + + newstr = (char *) malloc (strlen (str) + 1); + if (newstr) + strcpy (newstr, str); + return newstr; +} diff --git a/gnu/usr.bin/man/man/version.h b/gnu/usr.bin/man/man/version.h new file mode 100644 index 0000000000..4d9eb636a8 --- /dev/null +++ b/gnu/usr.bin/man/man/version.h @@ -0,0 +1,17 @@ +/* + * version.h + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +static char version[] = "1.1"; diff --git a/gnu/usr.bin/man/manpath/Makefile b/gnu/usr.bin/man/manpath/Makefile new file mode 100644 index 0000000000..81897ab3ab --- /dev/null +++ b/gnu/usr.bin/man/manpath/Makefile @@ -0,0 +1,14 @@ +PROG= manpath +MAN1= manpath.1 +SRCS= manpath.c +LDADD+= -L${.CURDIR}/../lib -lman + +CFLAGS+= -I${.CURDIR}/../lib -DMAIN -DSTDC_HEADERS -DPOSIX -DHAS_TROFF -DDO_UNCOMPRESS -DALT_SYSTEMS + +manpath.1: manpath.man + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \ + -e 's,%manpath_config_file%,${manpath_config_file},' \ + manpath.man > manpath.1 + +.include diff --git a/gnu/usr.bin/man/manpath/manpath b/gnu/usr.bin/man/manpath/manpath new file mode 100644 index 0000000000..049d5b9b31 Binary files /dev/null and b/gnu/usr.bin/man/manpath/manpath differ diff --git a/gnu/usr.bin/man/manpath/manpath.1 b/gnu/usr.bin/man/manpath/manpath.1 new file mode 100644 index 0000000000..7883ce9956 --- /dev/null +++ b/gnu/usr.bin/man/manpath/manpath.1 @@ -0,0 +1,56 @@ +.\" Man page for manpath +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH manpath 1 "Jan 5, 1991" +.LO 1 +.SH NAME +manpath \- determine user's search path for man pages +.SH SYNOPSIS +manpath [\-q] +.SH DESCRIPTION +manpath tries to determine the user's manpath from a set of system +defaults and the user's +.B PATH , +echoing the result to the standard output. Warnings and errors are +written to the standard error. +If a directory in the user's path is not listed in the manpath.config +file, manpath looks for the subdirectories man or MAN. If they exist, +they are added to the search path. +.PP +manpath is used by +.B man +to determine the search path, so user's normally don't need to set the +.B MANPATH +environment variable directly. +.SH OPTIONS +.TP +.B \-\^q +Operate quietly. Only echo the final manpath. +.SH ENVIRONMENT +.TP \w'MANPATH\ \ 'u +.B MANPATH +If +.B MANPATH +is set, +.B manpath +echoes its value on the standard output and issues a warning on the +standard error. +.SH FILES +.TP \w'/etc/manpath.config'u+2n +.BI /etc/manpath.config +System configuration file. +.SH "SEE ALSO" +apropos(1), whatis(1), man(1). +.SH BUGS +None known. diff --git a/gnu/usr.bin/man/manpath/manpath.c b/gnu/usr.bin/man/manpath/manpath.c new file mode 100644 index 0000000000..ccf7a55684 --- /dev/null +++ b/gnu/usr.bin/man/manpath/manpath.c @@ -0,0 +1,520 @@ +/* + * manpath.c + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +#define MANPATH_MAIN + +#include +#include +#include +#include +#include "config.h" +#include "manpath.h" +#include "gripes.h" + +#ifdef STDC_HEADERS +#include +#else +extern int fprintf (); +extern int strcmp (); +extern int strncmp (); +extern char *memcpy (); +extern char *getenv(); +extern char *malloc(); +extern void free (); +extern int exit (); +#endif + +extern char *strdup (); +extern int is_directory (); + +#ifndef MAIN +extern int debug; +#endif + +#ifdef MAIN + +#ifndef STDC_HEADERS +extern char *strcpy (); +extern int fflush (); +#endif + +char *prognam; +int debug; + +/* + * Examine user's PATH and print a reasonable MANPATH. + */ +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + int quiet; + char *mp; + extern int getopt (); + extern char *mkprogname (); + void usage (); + char *manpath (); + + quiet = 1; + + prognam = mkprogname (argv[0]); + + while ((c = getopt (argc, argv, "dhq?")) != EOF) + { + switch (c) + { + case 'd': + debug++; + break; + case 'q': + quiet = 0; + break; + case '?': + case 'h': + default: + usage(); + break; + } + } + + mp = manpath (quiet); + + fprintf (stdout, "%s\n", mp); + fflush (stdout); + + return 0; +} + +void +usage () +{ + fprintf (stderr, "usage: %s [-q]\n", prognam); + exit (1); +} +#endif /* MAIN */ + +/* + * If the environment variable MANPATH is set, return it. + * If the environment variable PATH is set and has a nonzero length, + * try to determine the corresponding manpath, otherwise, return the + * default manpath. + * + * The manpath.config file is used to map system wide /bin directories + * to top level man page directories. + * + * For directories which are in the user's path but not in the + * manpath.config file, see if there is a subdirectory `man' or `MAN'. + * If so, add that directory to the path. Example: user has + * $HOME/bin in his path and the directory $HOME/bin/man exists -- the + * directory $HOME/bin/man will be added to the manpath. + */ +char * +manpath (perrs) + register int perrs; +{ + register int len; + register char *manpathlist; + register char *path; + int get_dirlist (); + char *def_path (); + char *get_manpath (); + + if (get_dirlist ()) + gripe_reading_mp_config (); + + if ((manpathlist = getenv ("MANPATH")) != NULL) + /* + * This must be it. + */ + { + if (perrs) + fprintf (stderr, "(Warning: MANPATH environment variable set)\n"); + return strdup (manpathlist); + } + else if ((path = getenv ("PATH")) == NULL) + /* + * Things aren't going to work well, but hey... + */ + { + if (perrs) + fprintf (stderr, "Warning: path not set\n"); + return def_path (perrs); + } + else + { + if ((len = strlen (path)) == 0) + /* + * Things aren't going to work well here either... + */ + { + if (perrs) + fprintf (stderr, "Warning: path set but has zero length\n"); + return def_path (perrs); + } + return get_manpath (perrs, path); + } +} + +/* + * Get the list of bin directories and the corresponding man + * directories from the manpath.config file. + * + * This is ugly. + */ +int +get_dirlist () +{ + int i; + char *bp; + char *p; + char buf[BUFSIZ]; + DIRLIST *dlp = list; + FILE *config; + + if ((config = fopen (config_file, "r")) == NULL) + gripe_getting_mp_config (config_file); + + while ((bp = fgets (buf, BUFSIZ, config)) != NULL) + { + while (*bp && (*bp == ' ' || *bp == '\t')) + bp++; + + if (*bp == '#' || *bp == '\n') + continue; + + if (!strncmp ("MANBIN", bp, 6)) + continue; + + if (!strncmp ("MANDATORY_MANPATH", bp, 17)) + { + if ((p = strchr (bp, ' ')) == NULL) + if ((p = strchr (bp, '\t')) == NULL) + return -1; + + bp = p; + + dlp->mandatory = 1; + + while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t')) + bp++; + + i = 0; + while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t') + dlp->mandir[i++] = *bp++; + dlp->mandir[i] = '\0'; + + if (debug) + fprintf (stderr, "found mandatory man directory %s\n", + dlp->mandir); + } + else if (!strncmp ("MANPATH_MAP", bp, 11)) + { + if ((p = strchr (bp, ' ')) == NULL) + if ((p = strchr (bp, '\t')) == NULL) + return -1; + + bp = p; + + dlp->mandatory = 0; + + while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t')) + bp++; + + i = 0; + while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t') + dlp->bin[i++] = *bp++; + dlp->bin[i] = '\0'; + + while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t')) + bp++; + + i = 0; + while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t') + dlp->mandir[i++] = *bp++; + dlp->mandir[i] = '\0'; + + if (debug) + fprintf (stderr, "found manpath map %s --> %s\n", + dlp->bin, dlp->mandir); + } + else + { + gripe_reading_mp_config (); + } + dlp++; + } + + dlp->bin[0] = '\0'; + dlp->mandir[0] = '\0'; + dlp->mandatory = 0; + + return 0; +} + +/* + * Construct the default manpath. This picks up mandatory manpaths + * only. + */ +char * +def_path (perrs) + int perrs; +{ + register int len; + register char *manpathlist, *p; + register DIRLIST *dlp; + + len = 0; + dlp = list; + while (dlp->mandatory != 0) + { + len += strlen (dlp->mandir) + 1; + dlp++; + } + + manpathlist = (char *) malloc (len); + if (manpathlist == NULL) + gripe_alloc (len, "manpathlist"); + + *manpathlist = '\0'; + + dlp = list; + p = manpathlist; + while (dlp->mandatory != 0) + { + int status; + char *path = dlp->mandir; + + status = is_directory(path); + + if (status < 0 && perrs) + { + fprintf (stderr, "Warning: couldn't stat file %s!\n", path); + } + else if (status == 0 && perrs) + { + fprintf (stderr, "Warning: standard directory %s doesn't exist!\n", + path); + } + else if (status == 1) + { + len = strlen (path); + memcpy (p, path, len); + p += len; + *p++ = ':'; + dlp++; + } + } + + p[-1] = '\0'; + + return manpathlist; +} + +/* + * For each directory in the user's path, see if it is one of the + * directories listed in the manpath.config file. If so, and it is + * not already in the manpath, add it. If the directory is not listed + * in the manpath.config file, see if there is a subdirectory `man' or + * `MAN'. If so, and it is not already in the manpath, add it. + * Example: user has $HOME/bin in his path and the directory + * $HOME/bin/man exists -- the directory $HOME/bin/man will be added + * to the manpath. + */ +char * +get_manpath (perrs, path) + register int perrs; + register char *path; +{ + register int len; + register char *tmppath; + register char *t; + register char *p; + register char **lp; + register char *end; + register char *manpathlist; + register DIRLIST *dlp; + void add_dir_to_list (); + char *has_subdirs (); + + tmppath = strdup (path); + + for (p = tmppath; ; p = end+1) + { + if (end = strchr(p, ':')) + *end = '\0'; + + if (debug) + fprintf (stderr, "\npath directory %s ", p); + + /* + * The directory we're working on is in the config file. + * If we haven't added it to the list yet, do. + */ + for (dlp = list; dlp->mandir[0] != '\0'; dlp++) + if (dlp->bin[0] != '\0' && !strcmp (p, dlp->bin)) + { + if (debug) + fprintf (stderr, "is in the config file\n"); + + add_dir_to_list (tmplist, dlp->mandir, perrs); + goto found; + } + + /* + * The directory we're working on isn't in the config file. See + * if it has man or MAN subdirectories. If so, and it hasn't + * been added to the list, do. + */ + if (debug) + fprintf (stderr, "is not in the config file\n"); + + t = has_subdirs (p); + if (t != NULL) + { + if (debug) + fprintf (stderr, "but it does have a man or MAN subdirectory\n"); + + add_dir_to_list (tmplist, t, perrs); + free (t); + } + else + { + if (debug) + fprintf (stderr, "and doesn't have man or MAN subdirectories\n"); + } + + found: + + if (!end) + break; + } + + if (debug) + fprintf (stderr, "\nadding mandatory man directories\n\n"); + + dlp = list; + while (dlp->mandatory != 0) + { + add_dir_to_list (tmplist, dlp->mandir, perrs); + dlp++; + } + + len = 0; + lp = tmplist; + while (*lp != NULL) + { + len += strlen (*lp) + 1; + lp++; + } + + manpathlist = (char *) malloc (len); + if (manpathlist == NULL) + gripe_alloc (len, "manpathlist"); + + *manpathlist = '\0'; + + lp = tmplist; + p = manpathlist; + while (*lp != NULL) + { + len = strlen (*lp); + memcpy (p, *lp, len); + p += len; + *p++ = ':'; + lp++; + } + + p[-1] = '\0'; + + return manpathlist; +} + +/* + * Add a directory to the manpath list if it isn't already there. + */ +void +add_dir_to_list (lp, dir, perrs) + char **lp; + char *dir; + int perrs; +{ + extern char *strdup (); + int status; + + while (*lp != NULL) + { + if (!strcmp (*lp, dir)) + { + if (debug) + fprintf (stderr, "%s is already in the manpath\n", dir); + return; + } + lp++; + } + /* + * Not found -- add it. + */ + status = is_directory(dir); + + if (status < 0 && perrs) + { + fprintf (stderr, "Warning: couldn't stat file %s!\n", dir); + } + else if (status == 0 && perrs) + { + fprintf (stderr, "Warning: %s isn't a directory!\n", dir); + } + else if (status == 1) + { + if (debug) + fprintf (stderr, "adding %s to manpath\n", dir); + + *lp = strdup (dir); + } +} + +/* + * Check to see if the current directory has man or MAN + * subdirectories. + */ +char * +has_subdirs (p) + register char *p; +{ + int len; + register char *t; + + len = strlen (p); + + t = (char *) malloc ((unsigned) len + 5); + if (t == NULL) + gripe_alloc (len+5, "p\n"); + + memcpy (t, p, len); + strcpy (t + len, "/man"); + + if (is_directory (t) == 1) + return t; + + strcpy (t + len, "/MAN"); + + if (is_directory (t) == 1) + return t; + + return NULL; +} diff --git a/gnu/usr.bin/man/manpath/manpath.config b/gnu/usr.bin/man/manpath/manpath.config new file mode 100644 index 0000000000..b9c1171ae3 --- /dev/null +++ b/gnu/usr.bin/man/manpath/manpath.config @@ -0,0 +1,30 @@ +# manpath.config +# +# This file is read by manpath to configure the mandatory manpath, to +# map each path element to a manpath element and to determine where the +# "man" binary lives. The format is: +# +# MANBIN pathname +# MANDATORY_MANPATH manpath_element +# MANPATH_MAP path_element manpath_element +# +# MANBIN is optional +# +#MANBIN /usr/local/bin/man +# +# every automatically generated MANPATH includes these fields +# +MANDATORY_MANPATH /usr/share/man +MANDATORY_MANPATH /usr/local/man +MANDATORY_MANPATH /usr/X386/man +MANDATORY_MANPATH /usr/gnu/man +# +# set up PATH to MANPATH mapping +# +MANPATH_MAP /bin /usr/share/man +MANPATH_MAP /usr/bin /usr/share/man +MANPATH_MAP /usr/ucb /usr/share/man +MANPATH_MAP /usr/local/mh /usr/local/mh/man +MANPATH_MAP /usr/local/bin /usr/local/man +MANPATH_MAP /usr/gnu /usr/gnu/man +MANPATH_MAP /usr/X386 /usr/X386/man diff --git a/gnu/usr.bin/man/manpath/manpath.h b/gnu/usr.bin/man/manpath/manpath.h new file mode 100644 index 0000000000..a61761f676 --- /dev/null +++ b/gnu/usr.bin/man/manpath/manpath.h @@ -0,0 +1,26 @@ +/* + * manpath.h + * + * Copyright (c) 1990, 1991, John W. Eaton. + * + * You may distribute under the terms of the GNU General Public + * License as specified in the file COPYING that comes with the man + * distribution. + * + * John W. Eaton + * jwe@che.utexas.edu + * Department of Chemical Engineering + * The University of Texas at Austin + * Austin, Texas 78712 + */ + +typedef struct +{ + char mandir[MAXPATHLEN]; + char bin[MAXPATHLEN]; + int mandatory; +} DIRLIST; + +DIRLIST list[MAXDIRS]; + +char *tmplist[MAXDIRS]; diff --git a/gnu/usr.bin/man/manpath/manpath.man b/gnu/usr.bin/man/manpath/manpath.man new file mode 100644 index 0000000000..921232474e --- /dev/null +++ b/gnu/usr.bin/man/manpath/manpath.man @@ -0,0 +1,56 @@ +.\" Man page for manpath +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH manpath 1 "Jan 5, 1991" +.LO 1 +.SH NAME +manpath \- determine user's search path for man pages +.SH SYNOPSIS +manpath [\-q] +.SH DESCRIPTION +manpath tries to determine the user's manpath from a set of system +defaults and the user's +.B PATH , +echoing the result to the standard output. Warnings and errors are +written to the standard error. +If a directory in the user's path is not listed in the manpath.config +file, manpath looks for the subdirectories man or MAN. If they exist, +they are added to the search path. +.PP +manpath is used by +.B man +to determine the search path, so user's normally don't need to set the +.B MANPATH +environment variable directly. +.SH OPTIONS +.TP +.B \-\^q +Operate quietly. Only echo the final manpath. +.SH ENVIRONMENT +.TP \w'MANPATH\ \ 'u +.B MANPATH +If +.B MANPATH +is set, +.B manpath +echoes its value on the standard output and issues a warning on the +standard error. +.SH FILES +.TP \w'%manpath_config_file%'u+2n +.BI %manpath_config_file% +System configuration file. +.SH "SEE ALSO" +apropos(1), whatis(1), man(1). +.SH BUGS +None known. diff --git a/gnu/usr.bin/man/whatis/Makefile b/gnu/usr.bin/man/whatis/Makefile new file mode 100644 index 0000000000..1e9c1c187d --- /dev/null +++ b/gnu/usr.bin/man/whatis/Makefile @@ -0,0 +1,26 @@ +.include "../Makefile.inc" + +all: whatis whatis.1 + +obj depend rcsfreeze all: + @echo -n + +cleandir: clean + +clean: + @rm -f whatis whatis.1 + +whatis: whatis.sh + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' \ + whatis.sh > whatis + +whatis.1: whatis.man + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \ + -e 's,%manpath_config_file%,${manpath_config_file},' \ + whatis.man > whatis.1 + +install: whatis whatis.1 + install -c -o bin -g bin -m 555 whatis /usr/bin + install -c -o bin -g bin -m 444 whatis.1 /usr/share/man/man1 diff --git a/gnu/usr.bin/man/whatis/whatis b/gnu/usr.bin/man/whatis/whatis new file mode 100644 index 0000000000..e8cae0a12a --- /dev/null +++ b/gnu/usr.bin/man/whatis/whatis @@ -0,0 +1,66 @@ +#!/bin/sh +# +# whatis -- search the whatis database for keywords. Like apropos, +# but match only commands (as whole words). +# +# Copyright (c) 1990, 1991, John W. Eaton. +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man +# distribution. +# +# John W. Eaton +# jwe@che.utexas.edu +# Department of Chemical Engineering +# The University of Texas at Austin +# Austin, Texas 78712 + +PATH=/usr/local/bin:/bin:/usr/ucb:/usr/bin + +libdir=/etc + +if [ $# = 0 ] +then + echo "usage: `basename $0` name ..." + exit 1 +fi + +manpath=`/usr/bin/manpath -q | tr : '\040'` + +if [ "$manpath" = "" ] +then + echo "whatis: manpath is null" + exit 1 +fi + +if [ "$PAGER" = "" ] +then + PAGER="/usr/gnu/bin/less -sC" +fi + +while [ $1 ] +do + found=0 + for d in $manpath /usr/lib + do + if [ -f $d/whatis ] + then + grep -iw "^$1" $d/whatis + status=$? + if [ "$status" = "0" ] + then + found=1 + export found; + fi + fi + done + + if [ "$found" = "0" ] + then + echo "$1: nothing appropriate" + fi + + shift +done | $PAGER + +exit diff --git a/gnu/usr.bin/man/whatis/whatis.1 b/gnu/usr.bin/man/whatis/whatis.1 new file mode 100644 index 0000000000..9e5528d62b --- /dev/null +++ b/gnu/usr.bin/man/whatis/whatis.1 @@ -0,0 +1,27 @@ +.\" Man page for whatis +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH whatis 1 "Jan 5, 1991" +.LO 1 +.SH NAME +whatis \- search the whatis database for complete words. +.SH SYNOPSIS +.BI whatis +keyword ... +.SH DESCRIPTION +whatis searches a set of database files containing short descriptions +of system commands for keywords and displays the result on the +standard output. Only complete word matches are displayed. +.SH "SEE ALSO" +apropos(1), man(1). diff --git a/gnu/usr.bin/man/whatis/whatis.man b/gnu/usr.bin/man/whatis/whatis.man new file mode 100644 index 0000000000..9e5528d62b --- /dev/null +++ b/gnu/usr.bin/man/whatis/whatis.man @@ -0,0 +1,27 @@ +.\" Man page for whatis +.\" +.\" Copyright (c) 1990, 1991, John W. Eaton. +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.\" +.\" John W. Eaton +.\" jwe@che.utexas.edu +.\" Department of Chemical Engineering +.\" The University of Texas at Austin +.\" Austin, Texas 78712 +.\" +.TH whatis 1 "Jan 5, 1991" +.LO 1 +.SH NAME +whatis \- search the whatis database for complete words. +.SH SYNOPSIS +.BI whatis +keyword ... +.SH DESCRIPTION +whatis searches a set of database files containing short descriptions +of system commands for keywords and displays the result on the +standard output. Only complete word matches are displayed. +.SH "SEE ALSO" +apropos(1), man(1). diff --git a/gnu/usr.bin/man/whatis/whatis.sh b/gnu/usr.bin/man/whatis/whatis.sh new file mode 100644 index 0000000000..34abaaaa5d --- /dev/null +++ b/gnu/usr.bin/man/whatis/whatis.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# whatis -- search the whatis database for keywords. Like apropos, +# but match only commands (as whole words). +# +# Copyright (c) 1990, 1991, John W. Eaton. +# +# You may distribute under the terms of the GNU General Public +# License as specified in the README file that comes with the man +# distribution. +# +# John W. Eaton +# jwe@che.utexas.edu +# Department of Chemical Engineering +# The University of Texas at Austin +# Austin, Texas 78712 + +PATH=/usr/local/bin:/bin:/usr/ucb:/usr/bin + +libdir=%libdir% + +if [ $# = 0 ] +then + echo "usage: `basename $0` name ..." + exit 1 +fi + +manpath=`%bindir%/manpath -q | tr : '\040'` + +if [ "$manpath" = "" ] +then + echo "whatis: manpath is null" + exit 1 +fi + +if [ "$PAGER" = "" ] +then + PAGER="%pager%" +fi + +while [ $1 ] +do + found=0 + for d in $manpath /usr/lib + do + if [ -f $d/whatis ] + then + grep -iw "^$1" $d/whatis + status=$? + if [ "$status" = "0" ] + then + found=1 + export found; + fi + fi + done + + if [ "$found" = "0" ] + then + echo "$1: nothing appropriate" + fi + + shift +done | $PAGER + +exit