Newer new man page reader.
authorJordan K. Hubbard <jkh@FreeBSD.org>
Wed, 7 Jul 1993 23:07:02 +0000 (23:07 +0000)
committerJordan K. Hubbard <jkh@FreeBSD.org>
Wed, 7 Jul 1993 23:07:02 +0000 (23:07 +0000)
42 files changed:
gnu/usr.bin/man/COPYING [new file with mode: 0644]
gnu/usr.bin/man/Makefile [new file with mode: 0644]
gnu/usr.bin/man/Makefile.inc [new file with mode: 0644]
gnu/usr.bin/man/README [new file with mode: 0644]
gnu/usr.bin/man/TODO [new file with mode: 0644]
gnu/usr.bin/man/apropos/Makefile [new file with mode: 0644]
gnu/usr.bin/man/apropos/apropos [new file with mode: 0644]
gnu/usr.bin/man/apropos/apropos.1 [new file with mode: 0644]
gnu/usr.bin/man/apropos/apropos.man [new file with mode: 0644]
gnu/usr.bin/man/apropos/apropos.sh [new file with mode: 0644]
gnu/usr.bin/man/lib/Makefile [new file with mode: 0644]
gnu/usr.bin/man/lib/config.h [new file with mode: 0644]
gnu/usr.bin/man/lib/gripes.c [new file with mode: 0644]
gnu/usr.bin/man/lib/gripes.h [new file with mode: 0644]
gnu/usr.bin/man/lib/gripes.po [new file with mode: 0644]
gnu/usr.bin/man/lib/util.c [new file with mode: 0644]
gnu/usr.bin/man/lib/util.po [new file with mode: 0644]
gnu/usr.bin/man/makewhatis/Makefile [new file with mode: 0644]
gnu/usr.bin/man/makewhatis/makewhatis [new file with mode: 0644]
gnu/usr.bin/man/makewhatis/makewhatis.sh [new file with mode: 0644]
gnu/usr.bin/man/man/Makefile [new file with mode: 0644]
gnu/usr.bin/man/man/glob.c [new file with mode: 0644]
gnu/usr.bin/man/man/man.1 [new file with mode: 0644]
gnu/usr.bin/man/man/man.c [new file with mode: 0644]
gnu/usr.bin/man/man/man.man [new file with mode: 0644]
gnu/usr.bin/man/man/manpath.c [new file with mode: 0644]
gnu/usr.bin/man/man/manpath.h [new file with mode: 0644]
gnu/usr.bin/man/man/ndir.h [new file with mode: 0644]
gnu/usr.bin/man/man/strdup.c [new file with mode: 0644]
gnu/usr.bin/man/man/version.h [new file with mode: 0644]
gnu/usr.bin/man/manpath/Makefile [new file with mode: 0644]
gnu/usr.bin/man/manpath/manpath [new file with mode: 0644]
gnu/usr.bin/man/manpath/manpath.1 [new file with mode: 0644]
gnu/usr.bin/man/manpath/manpath.c [new file with mode: 0644]
gnu/usr.bin/man/manpath/manpath.config [new file with mode: 0644]
gnu/usr.bin/man/manpath/manpath.h [new file with mode: 0644]
gnu/usr.bin/man/manpath/manpath.man [new file with mode: 0644]
gnu/usr.bin/man/whatis/Makefile [new file with mode: 0644]
gnu/usr.bin/man/whatis/whatis [new file with mode: 0644]
gnu/usr.bin/man/whatis/whatis.1 [new file with mode: 0644]
gnu/usr.bin/man/whatis/whatis.man [new file with mode: 0644]
gnu/usr.bin/man/whatis/whatis.sh [new file with mode: 0644]

diff --git a/gnu/usr.bin/man/COPYING b/gnu/usr.bin/man/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+       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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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.
+
+  <signature of Ty Coon>, 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 (file)
index 0000000..1777b66
--- /dev/null
@@ -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 <bsd.subdir.mk>
diff --git a/gnu/usr.bin/man/Makefile.inc b/gnu/usr.bin/man/Makefile.inc
new file mode 100644 (file)
index 0000000..b3ccb46
--- /dev/null
@@ -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 (file)
index 0000000..d8fc4d4
--- /dev/null
@@ -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 (file)
index 0000000..19060ad
--- /dev/null
@@ -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 <alloca.h>
+        #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 (file)
index 0000000..892af95
--- /dev/null
@@ -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 (file)
index 0000000..8735e5f
--- /dev/null
@@ -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 (file)
index 0000000..3bb3e17
--- /dev/null
@@ -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 (file)
index 0000000..3bb3e17
--- /dev/null
@@ -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 (file)
index 0000000..070b848
--- /dev/null
@@ -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 (file)
index 0000000..33bd40b
--- /dev/null
@@ -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 <bsd.lib.mk>
diff --git a/gnu/usr.bin/man/lib/config.h b/gnu/usr.bin/man/lib/config.h
new file mode 100644 (file)
index 0000000..2c23168
--- /dev/null
@@ -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 (file)
index 0000000..76f8e70
--- /dev/null
@@ -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 <stdio.h>
+#include "gripes.h"
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#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 (file)
index 0000000..e3be4a0
--- /dev/null
@@ -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 (file)
index 0000000..6bfd455
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 (file)
index 0000000..b0babed
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#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 (file)
index 0000000..37dffc2
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 (file)
index 0000000..8c26f08
--- /dev/null
@@ -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 (file)
index 0000000..e6c238c
--- /dev/null
@@ -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 (file)
index 0000000..e6c238c
--- /dev/null
@@ -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 (file)
index 0000000..d116ad9
--- /dev/null
@@ -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 <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/man/glob.c b/gnu/usr.bin/man/man/glob.c
new file mode 100644 (file)
index 0000000..5bfb1bf
--- /dev/null
@@ -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.  */
+\f
+/* 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 <sys/types.h>
+
+#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 <dirent.h>
+#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 <sys/ndir.h>
+#else /* SYSNDIR */
+#include "ndir.h"
+#endif /* not SYSNDIR */
+#else /* not USG */
+#include <sys/dir.h>
+#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 <stdlib.h>
+#include <string.h>
+#define STDC_STRINGS
+#else /* STDC_HEADERS or __GNU_LIBRARY__ */
+
+#if defined (USG)
+#include <string.h>
+#ifndef POSIX
+#include <memory.h>
+#endif /* POSIX */
+#define STDC_STRINGS
+#else /* not USG */
+#ifdef NeXT
+#include <string.h>
+#else /* NeXT */
+#include <strings.h>
+#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 <alloca.h>
+#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 ();
+\f
+/* 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;
+}
+\f
+
+/* 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';
+}
+\f
+/* 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;
+    }
+}
+\f
+/* 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;
+}
+\f
+/* 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;
+}
+\f
+/* 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;
+}
+\f
+#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 (file)
index 0000000..f17aced
--- /dev/null
@@ -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 (file)
index 0000000..3983689
--- /dev/null
@@ -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 <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/file.h>
+#include <signal.h>
+#include "config.h"
+#include "gripes.h"
+#include "version.h"
+
+#ifndef POSIX
+#include <unistd.h>
+#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 <stdlib.h>
+#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 (file)
index 0000000..2c034fe
--- /dev/null
@@ -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 (file)
index 0000000..ccf7a55
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "manpath.h"
+#include "gripes.h"
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#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 (file)
index 0000000..a61761f
--- /dev/null
@@ -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 (file)
index 0000000..438d5c2
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+       <dir.h> -- definitions for 4.2BSD-compatible directory access
+
+       last edit:      09-Jul-1983     D A Gwyn
+*/
+
+#ifdef VMS
+#ifndef FAB$C_BID
+#include <fab.h>
+#endif
+#ifndef NAM$C_BID
+#include <nam.h>
+#endif
+#ifndef RMS$_SUC
+#include <rmsdef.h>
+#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 (file)
index 0000000..4e5af07
--- /dev/null
@@ -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 <string.h>
+#include <stdlib.h>
+#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 (file)
index 0000000..4d9eb63
--- /dev/null
@@ -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 (file)
index 0000000..81897ab
--- /dev/null
@@ -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 <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/manpath/manpath b/gnu/usr.bin/man/manpath/manpath
new file mode 100644 (file)
index 0000000..049d5b9
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 (file)
index 0000000..7883ce9
--- /dev/null
@@ -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 (file)
index 0000000..ccf7a55
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "manpath.h"
+#include "gripes.h"
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#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 (file)
index 0000000..b9c1171
--- /dev/null
@@ -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 (file)
index 0000000..a61761f
--- /dev/null
@@ -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 (file)
index 0000000..9212324
--- /dev/null
@@ -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 (file)
index 0000000..1e9c1c1
--- /dev/null
@@ -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 (file)
index 0000000..e8cae0a
--- /dev/null
@@ -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 (file)
index 0000000..9e5528d
--- /dev/null
@@ -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 (file)
index 0000000..9e5528d
--- /dev/null
@@ -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 (file)
index 0000000..34abaaa
--- /dev/null
@@ -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