summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Paolo Lovergine <frankie@debian.org>2022-08-04 08:39:48 -0700
committerFrancesco Paolo Lovergine <frankie@debian.org>2022-08-04 08:39:48 -0700
commitd770aa46ca6ed8f4b8f22550fc9aaa70aca2e336 (patch)
tree25a07034aa9abe12c15e13e73aa52b9cfc5ad437
Import ypserv_4.2.orig.tar.gz
[dgit import orig ypserv_4.2.orig.tar.gz]
-rw-r--r--.gitignore69
-rw-r--r--AUTHORS2
-rw-r--r--COPYING339
-rw-r--r--ChangeLog1144
-rw-r--r--INSTALL231
-rw-r--r--Makefile.am15
-rw-r--r--NEWS281
-rw-r--r--README20
-rw-r--r--THANKS20
-rw-r--r--TODO9
-rw-r--r--acinclude.m430
-rw-r--r--aclocal.m41431
-rwxr-xr-xautogen.sh7
-rw-r--r--conf_post.h10
-rw-r--r--configure.ac328
-rwxr-xr-xdepcomp436
-rw-r--r--etc/Makefile.am19
-rw-r--r--etc/README5
-rw-r--r--etc/locale12
-rw-r--r--etc/netgroup22
-rw-r--r--etc/netgroup.558
-rw-r--r--etc/netgroup.5.xml90
-rw-r--r--etc/netmasks14
-rw-r--r--etc/securenets17
-rw-r--r--etc/timezone13
-rw-r--r--etc/ypserv.conf46
-rw-r--r--etc/ypserv.conf.5173
-rw-r--r--etc/ypserv.conf.5.xml205
-rwxr-xr-xinstall-sh251
-rw-r--r--lib/Makefile.am33
-rw-r--r--lib/access.c312
-rw-r--r--lib/access.h42
-rw-r--r--lib/log_msg.c47
-rw-r--r--lib/log_msg.h9
-rw-r--r--lib/pidfile.c91
-rw-r--r--lib/pidfile.h35
-rw-r--r--lib/securenets.c359
-rw-r--r--lib/securenets.test20
-rw-r--r--lib/test-securenets.c89
-rw-r--r--lib/test-ypserv_conf.c33
-rw-r--r--lib/test/ypserv.conf47
-rw-r--r--lib/yp.h170
-rw-r--r--lib/yp_db.c532
-rw-r--r--lib/yp_db.h64
-rw-r--r--lib/ypproc_all_2.c34
-rw-r--r--lib/ypproc_match_2.c34
-rw-r--r--lib/ypserv_conf.c656
-rw-r--r--lib/ypserv_conf.h52
-rw-r--r--lib/ypxfrd.h111
-rw-r--r--lib/ypxfrd.x170
-rw-r--r--lib/ypxfrd_xdr.c110
-rw-r--r--m4/japhar_grep_cflags.m415
-rw-r--r--m4/jh_path_xml_catalog.m454
-rw-r--r--makedbm/Makefile.am31
-rw-r--r--makedbm/makedbm.8109
-rw-r--r--makedbm/makedbm.8.xml161
-rw-r--r--makedbm/makedbm.c758
-rw-r--r--mknetid/Makefile.am34
-rw-r--r--mknetid/mknetid.8111
-rw-r--r--mknetid/mknetid.8.xml158
-rw-r--r--mknetid/mknetid.c316
-rw-r--r--mknetid/mknetid.h28
-rw-r--r--mknetid/netid_hash.c266
-rw-r--r--revnetgroup/Makefile.am33
-rw-r--r--revnetgroup/getnetgrent.c272
-rw-r--r--revnetgroup/hash.c291
-rw-r--r--revnetgroup/hash.h41
-rw-r--r--revnetgroup/revnetgroup.8.xml117
-rw-r--r--revnetgroup/revnetgroup.c349
-rw-r--r--rpc.yppasswdd/Makefile.am35
-rw-r--r--rpc.yppasswdd/rpc.yppasswdd.8.xml265
-rw-r--r--rpc.yppasswdd/update.c1072
-rw-r--r--rpc.yppasswdd/yppasswd.x71
-rw-r--r--rpc.yppasswdd/yppasswd_xdr.c37
-rw-r--r--rpc.yppasswdd/yppasswdd.81
-rw-r--r--rpc.yppasswdd/yppasswdd.c566
-rw-r--r--rpc.yppasswdd/yppwd_local.h46
-rw-r--r--rpc.ypxfrd/Makefile.am33
-rw-r--r--rpc.ypxfrd/rpc.ypxfrd.8.xml181
-rw-r--r--rpc.ypxfrd/ypxfrd.81
-rw-r--r--rpc.ypxfrd/ypxfrd.c474
-rw-r--r--rpc.ypxfrd/ypxfrd_server.c223
-rw-r--r--rpc.ypxfrd/ypxfrd_svc.c111
-rw-r--r--scripts/Makefile.am29
-rw-r--r--scripts/create_printcap.in36
-rw-r--r--scripts/match_printcap.in34
-rw-r--r--scripts/pwupdate.8.xml72
-rw-r--r--scripts/pwupdate.in88
-rw-r--r--scripts/ypMakefile.in474
-rw-r--r--scripts/ypinit.8.xml115
-rw-r--r--scripts/ypinit.in185
-rw-r--r--scripts/ypxfr_1perday.in14
-rw-r--r--scripts/ypxfr_1perhour.in14
-rw-r--r--scripts/ypxfr_2perday.in15
-rw-r--r--yphelper/Makefile.am32
-rw-r--r--yphelper/yphelper.8.xml84
-rw-r--r--yphelper/yphelper.c654
-rw-r--r--yppush/Makefile.am32
-rw-r--r--yppush/yppush.8.xml170
-rw-r--r--yppush/yppush.c922
-rw-r--r--ypserv/Makefile.am29
-rw-r--r--ypserv/reg_slp.c301
-rw-r--r--ypserv/reg_slp.h25
-rw-r--r--ypserv/server.c1544
-rw-r--r--ypserv/ypserv.8.xml223
-rw-r--r--ypserv/ypserv.c601
-rw-r--r--ypserv/ypserv_xdr.c111
-rw-r--r--ypxfr/Makefile.am32
-rw-r--r--ypxfr/ypxfr.8.xml225
-rw-r--r--ypxfr/ypxfr.c1011
-rw-r--r--ypxfr/ypxfr.h7
-rw-r--r--ypxfr/ypxfr_clnt.c49
-rw-r--r--ypxfr/ypxfr_xdr.c124
113 files changed, 21859 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e08a675
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,69 @@
+# http://www.gnu.org/software/automake
+
+Makefile.in
+
+# http://www.gnu.org/software/autoconf
+
+/autom4te.cache
+/aclocal.m4
+/compile
+/configure
+/depcomp
+/install-sh
+/missing
+/stamp-h1
+
+# files generated by configure
+.deps
+.libs
+Makefile
+config.h
+config.h.in
+libnsl.pc
+*.o
+*.lo
+*.la
+*.a
+*~
+*.rej
+*.orig
+core
+config.log
+config.status
+libnsl-*.tar.bz2
+libnsl-*.tar.gz
+libtool
+po/POTFILES
+po/stamp-po
+po/remove-potcdate.sed
+
+# tar archive
+ypserv-*.tar.*
+*.8
+
+# some binaries
+lib/test-securenets
+makedbm/makedbm
+mknetid/mknetid
+revnetgroup/revnetgroup
+rpc.yppasswdd/rpc.yppasswdd
+rpc.ypxfrd/rpc.ypxfrd
+scripts/create_printcap
+scripts/match_printcap
+scripts/pwupdate
+scripts/ypMakefile
+scripts/ypinit
+scripts/ypxfr_1perday
+scripts/ypxfr_1perhour
+scripts/ypxfr_2perday
+yphelper/yphelper
+yppush/yppush
+ypserv/ypserv
+ypxfr/ypxfr
+lib/test-securenets.log
+lib/test-securenets.trs
+lib/test-suite.log
+lib/test-ypserv_conf
+lib/test-ypserv_conf.log
+lib/test-ypserv_conf.trs
+test-driver
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..5a76cf9
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+ypserv was originally written by Peter Eriksson <pen@lysator.liu.se>.
+Maintainer since version 0.18 and author of ypserv v2 is Thorsten Kukuk.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ 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) <year> <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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..4bcc11e
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1144 @@
+2016-04-05 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 4.0
+
+ * ypxfr/ypxfr.c (ypxfrd_transfer): Replace getrpcport with
+ code using TIRPC
+ * configure.ac: check for rpc_getaddr
+
+2016-03-14 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * makedbm/Makefile.am: Link makedbm against libtirpc
+
+ * lib/Makefile.am: run test-securenets and test-ypserv_conf
+ as test case
+ * lib/access.c: Finish port for IPv6, make useable for test suite.
+ * lib/access.h: Adjust prototype
+ * lib/securenets.c: Make useable for testsuite
+
+2016-03-04 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * etc/ypserv.conf.5.xml: Document that the rules are ignored for
+ IPv6.
+ * etc/ypserv.conf: Likewise.
+
+2016-03-02 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * lib/yp_db.c (_db_open): Remove dead code.
+
+ * lib/securenets.c (dump_securenets): Print error messge,
+ if there is an unknown family.
+
+ * rpc.yppasswdd/yppasswdd.c (main): Check if we could
+ register at least one protocol, else abort.
+
+2016-02-26 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * ypserv/ypserv.c (main): Check if we could register at least
+ one protocol, else abort.
+
+ * scripts/ypMakefile.in (netid.byname): Don't rebuild map
+ on every make call if /etc/netid is missing.
+
+2016-02-26 Matt Dainty <matt@bodgit-n-scarper.com>
+
+ * scripts/ypinit.in: Don't double-prefix awk variables.
+
+2016-02-17 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * lib/Makefile.am: Replace libnis with libnsl.
+ * makedbm/Makefile.am: Likewise.
+ * mknetid/Makefile.am: Likewise.
+ * revnetgroup/Makefile.am: Likewise.
+ * rpc.yppasswdd/Makefile.am: Likewise.
+ * rpc.ypxfrd/Makefile.am: Likewise.
+ * yphelper/Makefile.am: Likewise.
+ * yppush/Makefile.am: Likewise.
+ * ypserv/Makefile.am: Likewise.
+ * ypxfr/Makefile.am: Likewise.
+
+ * ypserv/ypserv.c (ypprog_2): Add YPPROC_NEWXFR.
+ * lib/yp.h: Likewise.
+ * yppush/yppush.c: Try YPPROC_NEWXFR first.
+ * ypserv/server.c: Implement ypproc_newxfr support.
+
+2015-04-14 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.7
+
+ * yppush/yppush.c: Register callback function correct for IPv4 and
+ IPv6, enable --port option again.
+
+ * ypxfr/ypxfr.c (main): In debug case log remote parameters.
+
+2015-04-13 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.6
+
+ * yppush/yppush.c: register callback for IPv6, too.
+
+2015-03-31 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.5
+
+ * rpc.yppasswdd/update.c: Remove pmap_clnt.h header include.
+ * rpc.ypxfrd/ypxfrd_svc.c: Likewise.
+ * rpc.ypxfrd/ypxfrd.c: Replace pmap_* functions with svc_unreg.
+
+ * yppush/yppush.c: Replace svc_unregister with svc_unreg.
+
+2015-03-30 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.4
+
+ * yppush/yppush.c (yppush_foreach): Use svc_reg instead
+ of svc_register.
+
+2015-03-13 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.3
+
+ * ypserv/server.c: Adjust debug output for IP with port to avoid
+ misinterpretions with IPv6.
+
+ * yppush/yppush.c (yppush_foreach): Call clnt_create().
+
+2015-01-15 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * rpc.yppasswdd/yppasswdd.c (main): Fix -v/--version
+ option handling.
+
+2014-12-12 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.2.1
+
+ * ypserv/ypserv.8.xml: Enhance securenet documentation
+ with new IPv6 and network/netmask features.
+
+2014-12-11 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * etc/securenets (host): Fix catch all allow all rule for IPv6.
+
+2014-12-02 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.2
+
+ * lib/access.c (is_valid): Free nconf.
+
+2014-12-01 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.1
+
+ * revnetgroup/Makefile.am (DEFS): Replace hardcoded /var/yp value.
+ * rpc.ypxfrd/ypxfrd.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+
+ * ypserv/server.c (ypproc_xfr_2_svc): initialize nconf.
+ * ypserv/ypserv.c (main): Don't set RPC_SVC_CONNMAXREC_SET.
+ * ypserv/ypserv_xdr.c: Remove unused define XDRMAXRECORD.
+
+2014-11-14 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * scripts/Makefile.am (varypdir): Replace hardcoded value with
+ configure option.
+
+2014-11-05 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 3.0
+
+ * rpc.yppasswdd/yppasswdd.c: Port to TI-RPC.
+ * rpc.ypxfrd/ypxfrd.c: Likewise.
+
+2014-11-04 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * rpc.yppasswdd/yppasswd_xdr.c: Use header file from libnis.
+
+ * rpc.yppasswdd/update.c: Adjust for TI-RPC.
+
+2014-10-31 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * ypxfr/ypxfr_xdr.c: Remove duplicate/unused functions.
+
+ * ypxfr/ypxfr.c: Convert to TI-RPC/IPv6 enablement.
+ * yppush/yppush.c: Likewise.
+ * ypserv/ypserv.c: Likewise.
+ * rpc.ypxfrd/ypxfrd_server.c: Likewise.
+
+2014-10-30 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * lib/securenets.c: Implement IPv6 support.
+
+ * ypserv/server.c: Convert to TI-RPC/IPv6 enablement.
+ * ypserv/ypserv_xdr.c: Adjust for new yp_prot.h.
+
+ * lib/ypserv_conf.c: Remove compat header include.
+
+ * lib/compat.c: Removed.
+ * lib/compat.h: Removed.
+
+2014-03-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.32.1
+
+ * configure.ac: Adjust sd_notify check for systemd >= 209.
+
+2014-01-04 Thorsten Kukuk <kukuk@suse.de>
+
+ * yphelper/yphelper.c: fix command name.
+ * yphelper/yphelper.8.xml: fix command name.
+
+2013-11-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.32
+
+ * ypserv/ypserv.c: Remove sig_hup, ignore SIG_HUP.
+ * ypserv/ypserv.8.xml: Remove SIG HUP section.
+ * lib/yp_db.c: fix return value for tcbdbopen in error case.
+ Patch by Edgar Hoch, RHBZ#1004110
+
+ * scripts/ypMakefile.in: Read MINUID/MINGID from /etc/login.defs
+ Patch by Honza Horak, RHBZ#1004090
+
+2013-10-07 Thorsten Kukuk <kukuk@suse.de>
+
+ * yppush/yppush.8.xml: Fix typo (reported by
+ Masatake YAMATO <yamato@redhat.com>).
+
+2013-07-22 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Use int instead
+ of c because of fgetc/EOF.
+
+2013-04-11 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.31
+
+ * rpc.yppasswdd/Makefile.am: Fix link order.
+
+2013-04-10 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.30
+
+ * lib/yp_db.c: fixes for Tokyo Cabinet.
+ * makedbm/makedbm.c: Likewise.
+ * yphelper/yphelper.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+ * lib/pidfile.c: Close pidfile file descriptor on exit.
+ * configure.in: Add AC_USE_SYSTEM_EXTENSIONS.
+
+2013-04-09 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: check for systemd header/library.
+ * lib/access.c: implement systemd notification.
+ * lib/access.h: Likewise.
+ * lib/Makefile.am: Likewise.
+ * rpc.yppasswdd/Makefile.am: Likewise.
+ * rpc.yppasswdd/yppasswdd.c: Likewise.
+ * rpc.ypxfrd/Makefile.am: Likewise.
+ * rpc.ypxfrd/ypxfrd.c: Likewise.
+ * ypserv/Makefile.am: Likewise.
+ * ypserv/ypserv.c: Likewise.
+
+2012-08-30 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.29
+
+ * rpc.yppasswdd/yppasswdd.c: Fix memory leak [bnc#777833].
+ * rpc.ypxfrd/ypxfrd_svc.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ Based on patch from Honza Horak <hhorak@redhat.com>.
+
+2012-05-30 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.28
+
+ * mknetid/mknetid.c (main): Handle empty group lines and broken
+ group entries more graceful.
+ Patch from Stefan Sydow <stsydow@cs.tu-berlin.de>.
+
+ * configure.in: Add support for tokyocabinet.
+ * lib/yp.h: Likewise.
+ * lib/yp_db.c: Likewise.
+ * lib/yp_db.h: Likewise.
+ * lib/ypxfrd.h: Likewise.
+ * lib/ypxfrd.x: Likewise.
+ * makedbm/makedbm.c: Likewise.
+ * rpc.ypxfrd/ypxfrd_server.c: Likewise.
+ * yphelper/yphelper.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+
+ * rpc.yppasswdd/update.c: check crypt() ret value for
+ NULL pointer, add support for passwd.adjunct.
+
+ * rpc.yppasswdd/yppasswdd.c: check port value.
+ * rpc.ypxfrd/ypxfrd.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypserv/ypserv.: Likewise.
+
+ * scripts/ypinit.in: check for empty domainname.
+
+ Based on patches from Honza Horak <hhorak@redhat.com>.
+
+2012-01-27 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.27
+
+ * configure.in: Check for qdbm.
+ * conf_post.h: New file.
+ * lib/yp_db.c: Include header for qdbm.
+ * lib/yp_db.h: Likewise.
+ * makedbm/makedbm.c: Likewise.
+ * rpc.ypxfrd/ypxfrd_server.c: Likewise.
+ * yphelper/yphelper.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+
+ * rpc.yppasswdd/update.c: Fix remove_password,
+ check for correct return values.
+
+ * scripts/ypMakefile.in: Add YPPUSH_ARGS variable.
+ * yppush/yppush.8.xml: Document to edit /var/yp/Makefile.
+
+ Based on patches from Honza Horak <hhorak@redhat.com>.
+
+2011-08-31 Thorsten Kukuk <kukuk@suse.de>
+
+ * Update FSF address.
+ Patch by Honza Horak <hhorak@redhat.com>.
+
+2011-06-22 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.26
+
+ * ypserv/server.c (ypproc_xfr_2_svc): Ignore -4 as error,
+ create better (debug) logs.
+
+2011-06-16 Thorsten Kukuk <kukuk@suse.de>
+
+ * mknetid/mknetid.c (main): Fix group parsing [bnc#700248].
+ Patch from Anders Johansson.
+
+2011-04-29 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.25
+
+ * yphelper/yphelper.c (is_master): Fix memory leak.
+ * rpc.yppasswdd/yppasswdd.c (main): Check if we could open
+ /dev/null.
+ * ypserv/ypserv.c (main): Likewise.
+ * rpc.yppasswdd/update.c (update_files): Close all files.
+ * revnetgroup/getnetgrent.c: Return if malloc fails.
+ * makedbm/makedbm.c (create_file): Close file if not stdin.
+ * lib/yp_db.c (_db_open): Document not implemented cache size.
+ * lib/pidfile.c (create_pidfile): Exit if we cannot create
+ pid file.
+ Based on patches from Honza Horak <hhorak@redhat.com>.
+
+2010-10-29 Thorsten Kukuk <kukuk@suse.de>
+
+ * rpc.yppasswdd/update.c (remove_password): Remove password
+ for logging.
+
+2010-09-24 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.24
+
+ * rpc.yppasswdd/update.c (external_update_pipe): Use correct
+ gecos variable. Reported by Mark Riley.
+
+2010-09-20 Thorsten Kukuk <kukuk@suse.de>
+
+ * rpc.yppasswdd/update.c (external_update_pipe): Make logbuf
+ a new parameter, fix usage of parentmsg.
+ Bugs reported by Mark Riley.
+
+2010-02-23 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.23
+
+ * lib/Makefile.am: Add pidfile.c, pidfile.h
+ * lib/pidfile.c: New.
+ * lib/pidfile.h: New.
+ * rpc.yppasswdd/yppasswdd.c: Use create_pidfile().
+ * rpc.ypxfrd/ypxfrd.c: Likewise.
+ * ypserv/ypserv.c: Likewise.
+ Patch from Karel Klic <kklic@redhat.com>.
+
+2010-01-27 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.22
+
+ * ypserv/ypserv.8.xml: Code cleanup, document problems with SIGHUP.
+
+ * ypserv/server.c (ypproc_xfr_2_svc): Remove wrong ypdb_close
+ call. Reported by Karel Klic <kklic@redhat.com>.
+
+2009-06-12 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.21
+
+2009-05-19 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.c (main): Free transp (fix memory leak)
+
+2009-05-12 Thorsten Kukuk <kukuk@suse.de>
+
+ * yphelper/yphelper.8.xml: New.
+ * yphelper/yphelper.8: Regenerated from xml source.
+ * yphelper/Makefile.am: Add rules for xml.
+
+2009-05-07 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/access.c (is_valid): Don't print message for non-existing
+ maps.
+
+ * mknetid/mknetid.c (main): Check for NULL pointers before
+ calling insert_user().
+ Reported by Mark Brown <broonie@sirena.org.uk>
+
+ * mknetid/netid_hash.c: Remove second xstrtok implementation.
+
+ * mknetid/mknetid.h: Add xstrtok prototype.
+
+2009-04-15 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.c (ypprog_2): If decoding fails, try
+ to free the already allocated memory.
+
+2009-04-02 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.20
+
+ * ypserv/ypserv.8.xml: New file.
+ * ypserv/ypserv.8: Regenerated from xml source.
+ * ypserv/Makefile.am: Add rules for xml.
+
+ * ypxfr/ypxfr.8.xml: New file.
+ * ypxfr/ypxfr.8: Regenerated from xml source.
+ * ypxfr/Makefile.am: Add rules for xml.
+
+ * yppush/yppush.8.xml: New file.
+ * yppush/yppush.8: Regenerated from xml source.
+ * yppush/Makefile.am: Add rules for xml.
+
+ * lib/yp_db.c: Add some sanity checks.
+
+ * rpc.ypxfrd/ypxfrd_server.c (ypxfrd_getmap_1_svc): Fix debug message.
+
+ * lib/access.c (is_valid): New return value if map does not exist.
+ * ypserv/server.c: handle new return value of is_valid().
+
+2008-04-15 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Only warn about
+ missing SLP support if it is enabled in ypserv.conf.
+
+2007-10-01 Thorsten Kukuk <kukuk@suse.de>
+
+ * rpc.ypxfrd/rpc.ypxfrd.8.xml: New file.
+ * rpc.ypxfrd/rpc.ypxfrd.8: Regenerated from xml source.
+ * rpc.ypxfrd/Makefile.am: Add rules for xml.
+
+2007-09-26 Thorsten Kukuk <kukuk@suse.de>
+
+ * revnetgroup/revnetgroup.8.xml: New file.
+ * revnetgroup/revnetgroup.8: Regenerated from xml source.
+ * revnetgroup/Makefile.am: Add rules for xml.
+
+2006-08-02 Thorsten Kukuk <kukuk@suse.de>
+
+ * makedbm/makedbm.8.xml: New file.
+ * makedbm/makedbm.8: Regenerated from xml source.
+ * makedbm/Makefile.am: Add rules for xml.
+
+ * mknetid/mknetid.8.xml: New file.
+ * mknetid/mknetid.8: Regenerated from xml source.
+ * mknetid/Makefile.am: Add rules for xml.
+
+ * rpc.yppasswdd/rpc.yppasswdd.8.xml: New file.
+ * rpc.yppasswdd/rpc.yppasswdd.8: Regenerated from xml source.
+ * rpc.yppasswdd/Makefile.am: Add rules for xml.
+
+2006-04-07 Thorsten Kukuk <kukuk@suse.de>
+
+ * etc/ypserv.conf.5.xml: New file.
+ * etc/ypserv.conf.5: Regenerated from xml source.
+
+2006-04-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * etc/netgroup.5.xml: New file.
+ * etc/netgroup.5: Regenerated from xml source.
+ * etc/Makefile.am: Add rules for xml.
+ * configure.in: Check for xml tools.
+
+2006-01-10 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * release version 2.19
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Don't ignore return value
+ of fgets().
+ * lib/securenets.c (load_securenets): Likewise.
+ * revnetgroup/revnetgroup.c (main): Likewise.
+
+ * ypserv/ypserv.c (main): Don't ignore return value of dup().
+ * ypserv/server.c (ypproc_xfr_2_svc): Likewise.
+ * rpc.ypxfrd/ypxfrd.c (main): Likewise.
+
+ * makedbm/makedbm.c (create_file): Don't ignore return value of
+ getline().
+
+ * rpc.yppasswdd/update.c (update_files): Don't ignore return values
+ of unlink() and chown().
+
+ * rpc.yppasswdd/yppasswdd.c (main): Don't ignore return values of
+ chdir() and dup().
+
+ * ypserv/reg_slp.c (register_slp): Check if hostname is resolveable.
+
+ * configure.in: Make -pie usage configureable.
+ Based on patch by Urs Thuermann <urs@isnogud.escape.de>.
+
+2005-09-02 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypxfr/ypxfr.c (ypxfr): Clear response structures before usage.
+
+2005-07-20 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.18
+
+ * rpc.yppasswdd/update.c (external_update_env): Remove obsolete code.
+ (external_update_pipe): Don't use buffer of fixed length.
+
+ * lib/log_msg.c (log_msg): Use vsnprintf.
+
+2005-05-31 Thorsten Kukuk <kukuk@suse.de>
+
+ * release vesion 2.17
+
+ * lib/securenets.c (load_securenets): Fix debug output.
+
+ * ypserv/server.c: Handle return value of 0 correct for is_valid().
+
+2005-05-19 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.16
+
+ * rpc.yppasswdd/yppasswdd.c (sig_child): Restore errno.
+ * rpc.ypxfrd/ypxfrd.c (sig_child): Likewise.
+ * yppush/yppush.c (sig_child): Likewise.
+ Based on patch from Mark Brown <broonie@sirena.org.uk>
+
+ * lib/compat.c (svc_getcaller): Fix return value.
+ * revnetgroup/revnetgroup.c (insert_netgroup): Make static.
+ * rpc.yppasswdd/yppasswd_xdr.c: Cast uid_t/gid_t to int.
+ * rpc.ypxfrd/ypxfrd.c: Fix includes, use int on HPUX for
+ getpeername.
+ * rpc.ypxfrd/ypxfrd_server.c: Fix includes.
+ * yphelper/yphelper.c: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypserv/ypserv.c: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+ Patch from Petter Reinholdtsen <petter.reinholdtsen@usit.uio.no>
+
+2005-04-07 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.15
+
+ * configure.in: Check for -fpie/-pie support.
+ * lib/Makefile: Compile with -fpie if supported.
+ * rpc.yppasswdd/Makefile.am: Likewise.
+ * rpc.ypxfrd/Makefile.am: Likewise.
+ * yppush/Makefile.am: Likewise.
+ * ypserv/Makefile.am: Likewise.
+
+ * yphelper/yphelper.c: Fix gcc4 warning.
+
+2005-03-23 Thorsten Kukuk <kukuk@suse.de>
+
+ * makedbm/makedbm.c (dump_file): Use a TAB as seperator
+ between key and data.
+
+2004-09-03 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.14
+
+ * lib/compat.c (svc_getcaller): Use log_msg instead of
+ fprintf. Patch from Petter Reinholdtsen <pere@hungry.com>.
+
+ * ypserv/reg_slp.c: Support systems without asprintf.
+ Based on patch from Petter Reinholdtsen <pere@hungry.com>.
+
+ * ypserv/ypserv.c (create_pidfile): Don't continue in
+ function if we cannot create pid file.
+
+ * ypserv/reg_slp.c (register_slp): Use signal() instead
+ of sigaction().
+
+ * configure.in: Check for asprintf
+
+2004-08-10 Mark Brown <broonie@sirena.org.uk>
+
+ * ypxfr/ypxfr_clnt.c (ypproc_master_2): memset() the response
+ structure before calling clnt_call().
+ (ypproc_order_2): Likewise.
+ * ypxfr/ypxfr_xdr.c (ypproc_all_2): Likewise.
+
+2004-07-19 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypxfr/ypxfr.c (ypxfr): Don't free xdr_ypresp_val,
+ if no data was send.
+ Reported by Artur Niederstebruch <artur@sgi.com>.
+
+2004-04-14 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.13
+
+ * etc/ypserv.conf.5 (slp): Document slp: domain option.
+
+ * ypserv/slp_reg.c: If slp: domain option is set, create attr
+ with all supported domain names.
+
+ * lib/yp_db.c (ypdb_open): Fix memory leak if the cache is too small
+ and the map does not exist. Reported by Feng Qin <fengqin@uiuc.edu>.
+
+ * rpc.ypxfrd/ypxfrd_svc.c: Reformat.
+
+ * scripts/ypMakefile.in (services.byservicename): Add aliases
+ as key with /proto, too. Patch from Jakub Jelinek <jakub@redhat.com>.
+
+2004-04-01 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.12.2
+
+ * lib/ypserv.conf: Add slp_timeout.
+ * lib/ypserv_conf.h: Add slp_timeout prototype.
+ * lib/ypserv_conf.c: Add slp_timeout support.
+ * ypserv/reg_slp.c: Set alarm handler to re-register service.
+
+2004-04-01 Jakub Jelinek <jakub@redhat.com>
+
+ * scripts/ypMakefile.in (services.byservicename): Add main
+ key with /proto and fix but which would trim any digits from
+ protocol name.
+
+2004-02-14 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.12.1
+
+ * ypserv/reg_slp.c (register_slp): Change SLP URL to ypserv.
+
+2004-02-13 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.12
+
+ * yppush/yppush.c (yppushproc_xfrresp_1_svc): Fix compiler
+ warnings.
+
+ * ypserv/reg_slp.c: Don't set dummy domain attributes.
+
+2004-02-07 Michael Gernoth <simigern@stud.uni-erlangen.de>
+
+ * ypserv/server.c: Return NOMAP error if access forbidden.
+
+2004-01-12 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.11
+
+ * ypxfr/ypxfr.c (main): Abort if no domainname is set.
+ (Reported by Jens Laas <jens.laas@data.slu.se>)
+
+ * yppush/yppush.c: Add support for fixed port
+ (Patch from Tony Kew <tonykew@ccr.buffalo.edu>)
+
+2004-01-09 Thorsten Kukuk <kukuk@suse.de>
+
+ * yppush/yppush.c (yppushproc_xfrresp_1_svc): Remove wrong
+ memcpy.
+
+ * ypxfr/Makefile.am (DEFS): Define YPMAPDIR
+ (Reported by Damien Touraine <webmyster@addoc.u-psud.fr>)
+
+2003-11-24 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Check for SLP presence.
+
+ * ypserv/ypserv.c (main): Register/deregister at SLP server
+ only if we have SLP support and if it is enabled in ypserv.conf.
+
+ * lib/ypserv_conf.h: Add prototype for slp_flag.
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Use strcasecmp for option
+ parsing, add slp option.
+
+2003-11-19 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/reg_slp.c: New, register ypserv at SLP server.
+ * ypserv/reg_slp.h: New.
+
+ * ypserv/ypserv.c (main): Call register_slp().
+
+2003-10-22 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.10
+
+ * makedbm/makedbm.c (create_file): If there are spaces before
+ a tab, remove this spaces, too.
+
+ * ypserv/ypserv.c: Save/restore errno in signal handler.
+
+2003-08-15 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.c (main): Use signal instead of sigaction.
+
+ * ypserv/server.c (ypproc_all_2_svc): Use _exit instead of exit.
+
+2003-08-12 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.c: Add own svc_run implentation based on select,
+ but prefer glibc one.
+
+2003-07-30 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/server.c: Kill counting of running childs.
+
+2003-06-27 Thorsten Kukuk <kukuk@suse.de>
+
+ * yppush/yppush.8.in: Fix typo.
+ * yppush/yppush.c: Fix error message.
+
+2003-06-26 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.9
+
+ * configure.in: Bump version number to 2.9, remove -Werror.
+ Remove duplicate getrpcport check.
+
+ * scripts/ypxfr_1perday.in: Add variable which contains maps
+ to update.
+ * scripts/ypxfr_1perhour.in: Likewise.
+ * scripts/ypxfr_2perday.in: Likewise.
+
+ * scripts/ypMakefile.in: Apply fix for multiline mail aliases
+ from Jonathan Gowland <jgowland@genaware.com>.
+
+2003-06-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * Add more portability changes from
+ Petter Reinholdtsen <pere@hungry.com>
+
+2003-06-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypxfr/ypxfr_clnt.c (ypproc_master_2): New function.
+
+ * ypxfr/ypxfr.c (ypxfr): Get official name of master host from
+ master itself.
+
+2003-06-05 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Check for availability of more functions.
+ * rpc.ypxfrd/ypxfrd.h: Removed.
+ * acinclude.m4: Add portability changes from
+ Petter Reinholdtsen <pere@hungry.com>
+ * lib/Makefile.am: Likewise.
+ * lib/yp.h: Likewise.
+ * lib/yp_db.c: Likewise.
+ * lib/ypserv_conf.c: Likewise.
+ * lib/ypxfrd.h: Likewise.
+ * makedbm/Makefile.am: Likewise.
+ * makedbm/makedbm.c: Likewise.
+ * mknetid/Makefile.am: Likewise.
+ * mknetid/mknetid.c: Likewise.
+ * revnetgroup/Makefile.am: Likewise.
+ * revnetgroup/hash.c: Likewise.
+ * revnetgroup/revnetgroup.c: Likewise.
+ * rpc.yppasswdd/Makefile.am: Likewise.
+ * rpc.yppasswdd/update.c: Likewise.
+ * rpc.yppasswdd/yppasswdd.c: Likewise.
+ * rpc.ypxfrd/Makefile.am: Likewise.
+ * rpc.ypxfrd/ypxfrd.c: Likewise.
+ * rpc.ypxfrd/ypxfrd.h: Likewise.
+ * rpc.ypxfrd/ypxfrd_svc.c: Likewise.
+ * yphelper/Makefile.am: Likewise.
+ * yphelper/yphelper.c: Likewise.
+ * yppush/Makefile.am: Likewise.
+ * yppush/yppush.c: Likewise.
+ * ypserv/Makefile.am: Likewise.
+ * ypserv/server.c: Likewise.
+ * ypserv/ypserv.c: Likewise.
+ * ypxfr/Makefile.am: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+ * ypxfr/ypxfr_xdr.c: Likewise.
+
+2003-06-05 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Define max. number of children ypserv is allowed
+ to have.
+
+ * ypserv/ypserv.c: Remove ypserv_svc_run function, always use
+ system svc_run().
+ * ypserv/server.c: Remove usage of forked variable, make usage
+ of child counting a compile time option.
+
+2003-05-19 Thorsten Kukuk <kukuk@suse.de>
+
+ * yppush/yppush.c: Only include getopt.h if exists.
+ * ypserv/ypserv.c: Likewise.
+ * ypxfr/ypxfr.c: Likewise.
+
+ * lib/ypserv_conf.c: Include alloca.h.
+
+ * ypserv/ypserv.c (ypserv_svc_run): Add version which does not use
+ poll for old SunRPC implementations.
+
+ * configure.in: Check for svc_max_pollfd.
+
+2003-05-15 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/server.c (ypproc_all_2_svc): Set at first result->more to
+ TRUE or the client will not read the error code.
+
+2003-03-03 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/access.c (is_valid): Don't deny access if map does not
+ exist (else the error code is wrong).
+
+2003-02-12 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/log_msg.c (log_msg): Use new file handle debug_output.
+
+2003-02-05 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.8
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Fix debug output.
+
+ * ypserv/server.c (ypproc_xfr_2_svc): Increase children before we
+ fork, to make sure the variable will not become negative in
+ sig_child.
+
+ * lib/access.c (is_valid): If connection is refused, print status
+ for debugging purpose.
+
+ * lib/securenets.c (load_securenets): Fix debug output.
+
+2003-02-04 Peter Breitenlohner <peb@mppmu.mpg.de>
+
+ * yphelper/yphelper.c: Fix compiler warning.
+
+ * ypxfr/ypxfr_xdr.c: Fix compiler warning.
+
+2003-02-04 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.7
+
+ * ypserv/Makefile.am (DEFS): Add MAX_CHILDREN define.
+
+ * ypserv/ypserv.c (sig_child): Readd old sig handler for checking
+ number of running children.
+
+ * configure.in: Check only for gdbm library.
+
+ * ypserv/server.c (ypproc_all_2_svc): fork for sending data to
+ client.
+
+ * etc/Makefile.am: Require automake 1.7
+ * scripts/Makefile.am: Likewise.
+
+ * lib/Makefile.am: Require automake 1.7, rename CFLAGS to AM_CFLAGS
+ * makedbm/Makefile.am: Likewise
+ * mknetid/Makefile.am: Likewise
+ * revnetgroup/Makefile.am: Likewise
+ * rpc.yppasswdd/Makefile.am: Likewise
+ * rpc.ypxfrd/Makefile.am: Likewise
+ * yphelper/Makefile.am: Likewise
+ * yppush/Makefile.am: Likewise
+ * ypserv/Makefile.am: Likewise
+ * ypxfr/Makefile.am: Likewise
+
+2003-01-17 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.8.in: Remove -b/--dns option
+
+2002-10-28 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.6
+
+ * lib/yp_db.c: Make number of max. open file handles configureable.
+ * lib/ypserv_conf.c: max. number of cached_filehandles is 255.
+ * rpc.ypxfrd/ypxfrd.c: set cached_filehandles to 0 after loading
+ config file, rpc.ypxfrd should not cache file handles.
+ * ypserv/ypserv.c (sig_hup): Don't allow to decrease the max. number
+ of cached file handles with SIGHUP.
+ * etc/ypserv.conf.5: Add documentation about new files option.
+
+ * makedbm/makedbm.c (create_file): If we find a <TAB> in a key,
+ assume that <TAB> is the seperator between key and data.
+
+2002-10-26 Thorsten Kukuk <kukuk@suse.de>
+
+ * rpc.ypxfrd/ypxfrd_server.c (ypxfrd_getmap_1_svc): Close file
+ handle of database (we don't need it).
+ Reported by Tsutomu Hoshino <hoshino@sic.shibaura-it.ac.jp>
+
+2002-08-08 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.5
+
+ * configure.in: Check for in_addr_t
+
+2002-08-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * yppush/yppush.8.in: Fix syntax error.
+
+2002-08-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/yp_db.c (ypdb_open): Check if map exist before allocating
+ memory for extra data.
+
+ * lib/access.c (is_valid): If map does not exist, return -2,
+ not success.
+
+2002-07-23 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/server.c (ypproc_xfr_2_svc): Print also name of the
+ expected master if we refuse to transfer a map.
+
+2002-07-02 Thorsten Kukuk <kukuk@suse.de>
+
+ * rpc.ypxfrd/Makefile.in (rpc_ypxfrd_LDADD): link against libyp.a
+ before linking against libgdbm.
+
+ * ypserv/Makefile.in (rpc_ypxfrd_LDADD): Likewise.
+ (Reported by Todd R. Eigenschink <todd@tekinteractive.com>)
+
+002-05-27 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.4
+
+ * scripts/ypMakefile.in (MINUID/MINGID): increase both variables
+ to 500 as defined by LSB and to be compatible with most Linux
+ distributions.
+
+ * lib/ypserv.conf.5: move from here ...
+ * etc/ypserv.conf.5: ... to here. Remove mangle field description.
+ * lib/Makefile.am: Remove ypserv.conf.5
+ * etc/Makefile.am: Add ypserv.conf.5
+
+2002-05-23 Martin Vidner <mvidner@suse.cz>
+
+ * yphelper/yphelper.c: Add -i option to getopt_long
+
+2002-05-14 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.3
+
+ * yppush/yppush.c (hostcmp): Get ride of this function, since it
+ could remove correct slaves which have the same hostname but are
+ in other domains.
+
+ * yphelper/yphelper.c (is_master): New function, check if we are
+ the master for a given map.
+
+ * yphelper/Makefile.am (yphelper_LDADD): Link against dbm library.
+
+2002-05-13 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Prefer libxcrypt over libcrypt.
+
+2002-04-26 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Adjust for new autoconf.
+
+ * config.guess: Deleted.
+ * config.sub: Deleted.
+ * acconfig.h: Deleted.
+
+ * lib/ypserv.conf.5: Document trusted_master option.
+
+ * yphelper/yphelper.c: Fix compiler warnings.
+
+ * mknetid/mknetid.c: Use getline/getdelim instead of fgets
+ to avoid static buffer.
+
+ * scripts/create_printcap.in: Fix syntax error to get it to
+ work with all awk implementations.
+
+2002-04-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * yppush/yppush.c (yppush_xfrrespprog_1): Exit from thread
+ if not YPPUSHPROC_NULL was called.
+
+2001-12-16 Thorsten Kukuk <kukuk@thkukuk.de>
+
+ * ypserv/server.c: Add missing break in switch statement.
+ * ypserv/ypserv.c (main): getopt returns -1, not EOF.
+
+2001-12-03 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypxfr/ypxfr.c (ypxfr): Don't replace name of master with
+ FQDN, else ypserv cannot compare it later.
+
+2001-11-26 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.2
+
+ * scripts/ypinit.in (ypinit_master): Add missing else case
+ (don't print error message in success case). Reported by
+ Michael Sterrett <msterret@coat.com>.
+
+ * lib/access.c (is_valid): Fix return value if host is not
+ allowed to connect.
+ * scripts/ypxfr_1perday.in: Add variable for maps.
+ * scripts/ypxfr_1perhour.in: Likewise.
+ * scripts/ypxfr_2perday.in: Likewise.
+
+2001-10-29 Thorsten Kukuk <kukuk@suse.de>
+
+ * acinclude.m4: New, contains macro for ElectricFence option
+ * configure.in: Add option for dmalloc and ElectricFence
+
+ * ypserv/server.c (ypproc_all_2_svc): Reset callback data
+ at beginning to avoid bogus data if we abort with an error.
+ (ypall_close): Abort if data is NULL.
+
+ * yphelper/yphelper.c: Allow IP numbers as hostname, also
+ lookup hostname from NIS map for compare.
+
+2001-09-02 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.1
+
+ * rpc.yppasswdd/yppasswdd.c: Implement --port parameter to
+ bind to a special port.
+ * rpc.yppasswdd/rpc.yppasswdd.8.in: Document new parameter.
+
+2001-09-02 Martin Vidner <mvidner@suse.cz>
+
+ * Fix various errors in manual pages
+
+2001-08-30 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/Makefile.am: Remove ypproc_all_2.c
+ * ypxfr/ypxfr_xdr.c: Add special ypproc_all_2 function
+ * ypxfr/ypxfr.8: Renamed from this ...
+ * ypxfr/ypxfr.8.in: ... to this
+ * yppush/yppush.8: Renamed from this ...
+ * yppush/yppush.8.in: ... to this
+ * configure.in: create ypxfr/ypxfr.8 and yppush/yppush.8
+ * revnetgroup/revnetgroup.8.in: New
+
+2001-08-26 Thorsten Kukuk <kukuk@suse.de>
+
+ * scripts/Makefile.am: Don't strip scripts
+ * ypserv/server.c: Fix null byte termination of order number
+ (reported by Juergen Holm <holm@Theorie.Physik.UNI-Goettingen.DE>)
+
+2001-08-20 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Create ypserv/ypserv.8
+ * ypserv/ypserv.8: renamed from this ..
+ * ypserv/ypserv.8.in: .. to this.
+
+2001-08-12 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Rename variable MAIL_ALIASES to ALIASES.
+ * lib/Makefile.am: Install ypxfrd.h into include/rpcsvc.
+ * scripts/ypMakefile.in: Fix makedbm path.
+
+2001-08-11 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.c (main): Fix missing format string, only
+ change database directory if we are in debug mode.
+
+2001-08-07 Thorsten Kukuk <kukuk@suse.de>
+
+ * release version 2.0
+
+2001-08-06 Thorsten Kukuk <kukuk@suse.de>
+
+ * scripts/Makefile.am (varyp_SCRIPTS): Add ypMakefile
+ * configure.in: Create scripts/ypMakefile
+
+2001-08-05 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/ypserv_conf.c (load_ypserv_conf):
+
+ * etc/netgroup.5: Add comment about non existing getnetgrent manual
+ page.
+
+ * scripts/ypMakefile.in: Implement 'MINUID' for shadow map.
+
+ * rpc.ypxfrd/ypxfrd.c (closedown): Removed external svs_fdset
+ declaration.
+ Patches from Miquel van Smoorenburg <miquels@cistron.nl>)
+
+ * yphelper/yphelper.c (print_maps): Make a copy of gethostbyname
+ result (we call gethostbyname later again) and fix a minor memory
+ leak. Based on patch by Richard Gooch <rgooch@atnf.csiro.au>
+
+2001-04-08 Thorsten Kukuk <kukuk@suse.de>
+
+ * scripts/Makefile.am: Add ypinit script and manual page
+ * scripts/ypinit.in: New.
+ * scripts/ypinit.8.in: New.
+ * scripts/create_printcap.in: New.
+ * scripts/match_printcap.in: New.
+ * scripts/pwupdate.8.in: New.
+ * scripts/pwupdate.in: New.
+ * mknetid/mknetid.c: New.
+ * mknetid/mknetid.h: New.
+ * mknetid/netid_hash.c: New.
+ * rpc.ypxfrd: New.
+ * rpc.yppasswdd: New.
+
+2001-03-25 Thorsten Kukuk <kukuk@suse.de>
+
+ * configure.in: Create revnetgroup/yphelper Makefile
+ * Makefile.am (SUBDIRS): Add revnetgroup and yphelper directory.
+ * revnetgroup/Makefile.am: New.
+ * revnetgroup/revnetgroup.c: New.
+ * revnetgroup/revnetgroup.8: New.
+ * revnetgroup/getnetgrent.c: New.
+ * revnetgroup/hash.c: New.
+ * yphelper/yphelper.c: New.
+ * yphelper/yphelper.8: New.
+
+ * ypxfr/ypxfr.c (ypxfr): Check return value from NIS server for
+ yp_order call.
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Don't free buffer
+ allocated with alloca, use stpcpy instead of sprintf.
+
+2001-03-11 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/yp_db.c: Enable caching of gdbm file handles.
+
+2000-11-19 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypxfr/ypxfr.c: Major rewrite.
+ * ypxfr/ypxfr.c(ypxfr): properly terminate a string before
+ run "atoi" on it (reported by Andy Stevens <stevens@2agent.com>)
+
+ * ypserv/ypserv.c (main): Fix typo (install SIGCHLD handler)
+
+2000-10-28 Thorsten Kukuk <kukuk@suse.de>
+
+ * ypserv/ypserv.c: Add SIGCHLD handler for forked processes.
+
+ * ypserv/yp_db.c (_db_open): Add hook to set gdbm cache size.
+
+2000-10-24 Thorsten Kukuk <kukuk@suse.de>
+
+ * lib/ypserv_conf.c (load_ypserv_conf): Parse for trusted_master
+
+ * lib/ypserv_conf.h: Add prototype for trusted_master.
+
+ * ypserv/server.c (ypproc_xfr_2_svc): Check if new map is from
+ trusted master
+
+ * ypserv/Makefile.am (noinst_HEADERS): Add access.h
+
+ * start major rewrite of ypserv for version 2
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..62ea076
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,231 @@
+Copyright 1994, 1995, 1996, 1999, 2000, 2001 Free Software Foundation,
+Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for variables by setting
+them in the environment. You can do that on the command line like this:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it cannot guess the host type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the host
+platform (i.e., that on which the generated programs will eventually be
+run) with `--host=TYPE'. In this case, you should also specify the
+build platform with `--build=TYPE', because, in this case, it may not
+be possible to guess the build platform (it sometimes involves
+compiling and running simple test programs, and this can't be done if
+the compiler is a cross compiler).
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..24e5449
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2000, 2001, 2006 Thorsten Kukuk <kukuk@thkukuk.de>
+#
+AUTOMAKE_OPTIONS = 1.5 gnits dist-xz
+#
+SUBDIRS = etc lib ypserv ypxfr yppush makedbm revnetgroup rpc.ypxfrd \
+ rpc.yppasswdd yphelper mknetid scripts
+
+CLEANFILES = *~
+
+M4_FILES = m4/jh_path_xml_catalog.m4
+EXTRA_DIST = $(M4_FILES) conf_post.h
+
+ACLOCAL_AMFLAGS = -I m4
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..90291e8
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,281 @@
+ypserv NEWS -- history of user-visible changes.
+
+Copyright (C) 1998-2021 Thorsten Kukuk
+
+Please send bug reports, questions and suggestions to <kukuk@thkukuk.de>.
+
+Version 4.2
+* Remove temporary files from yp_maplist
+
+Version 4.1
+* Bug fix release
+
+Version 4.0
+* Use libnsl instead of libnis
+* Several bug fixes
+
+Version 3.7
+* ypxfr: better error messages
+* yppush: rewrote callback registration, enable --port again
+
+Version 3.6
+* yppush: register callback for IPv6, too.
+
+Version 3.5
+* yppush: convert more IPv4 only RPC functions to TI-RPC variants
+* rpc.ypxfrd: Likewise.
+
+Version 3.4
+* yppush: convert IPv4 only RPC functions to TI-RPC variants
+
+Version 3.3
+* Adjust debug output for IPv6 addresses
+* Fix yppush
+
+Version 3.2.1
+* ypserv.8 docu enhancements about securenets
+
+Version 3.2
+* Fix memory leak in access library
+
+Version 3.1
+* ypserv: Don't increase RPC buffer
+
+Version 3.0
+* Convert code to use ti-rpc functions
+* Implement IPv6 support
+
+Version 2.32.1
+* Adjust for systemd >= 209
+
+Version 2.32
+* Update autoconf/automake
+* ypserv: remove broken SIGHUP support.
+* /var/yp/Makefile: read MINUID/MINGID from /etc/login.defs
+
+Version 2.31
+* Fix build failures
+
+Version 2.30
+* Add systemd support
+
+Version 2.29
+* Fix memory leaks in error case in rpc.yppasswdd and rpc.ypxfrd
+
+Version 2.28
+* Add support for tokyocabinet (gdbm replacement)
+* Lot of small bug fixes
+
+Version 2.27
+* qdbm support was added
+* Lot of small bug fixes
+
+Version 2.26
+* ypserv: Fix trusted_master option
+* mknetid: Fix group parsing
+
+Version 2.25
+* Lot of small bug fixes/improved error handling
+
+Version 2.24
+* rpc.yppasswdd: Fix -x option
+
+Version 2.23
+* rpc.ypxfrd creates now a pid file
+
+Version 2.22
+* Update ypserv.8 manual page
+* Fix possible memory corruption bug
+
+Version 2.21
+* Better handling of RPC decoding errors
+
+Version 2.20
+* Manual page cleanup
+* Add some sanity checks
+
+Version 2.19
+* Fix ypxfr crashes
+* Fix ypserv crash if own hostname is not resolveable
+
+Version 2.18
+* rpc.yppasswdd: Fix possible buffer overflow with -x/-E option
+
+Version 2.17
+* Fix debug output
+* Don't ignore securenets for ypserv domain functions
+
+Version 2.16
+* Fix signal handlers
+* Fix HP-UX support
+
+Version 2.15
+* makedbm: Use correct seperator if dumping databases
+* rcp.yppasswdd, rpc.ypxfrd, yppush, ypserv: Compile with -fpie
+
+Version 2.14
+* ypxfr: Fix problems with fetching maps from SGI ypserv
+
+Version 2.13
+* ypserv: Set SLP domain attribute if configured
+* ypserv: Fix memory leak if file cache is too small
+
+Version 2.12.2
+* ypserv: Refresh SLP registering after some time
+* ypserv: Fixes for creating services.byservicename
+
+Version 2.12.1
+* ypserv: Change SLP URL to service:ypserv
+
+Version 2.12
+* ypserv: Fix compatibility problems with Solaris 9
+
+Version 2.11
+* ypserv: Add SLP support
+* ypxfr: Fix seg.fault
+* yppush: Add support for fix port
+
+Version 2.10
+* ypserv: Remove fork limit
+* ypserv: Save/restore errno in signal handler
+* makedbm: Remove spaces from end of key
+
+Version 2.9
+* ypxfr: query ypserv for correct master name
+* Make it more portable
+* Make number of allowed childs a compile time option
+* Use system svc_run()
+* Fix return code for wrong/invalid map- and domainname
+* Make source code more portable
+
+Version 2.8
+* Fix compiler warnings
+* Fix bug of counting running childs
+
+Version 2.7
+* ypserv now forks again for transfering complete NIS maps
+* Update to latest autoconf/automake version
+
+Version 2.6
+* Fix bug that rpc.ypxfrd doesn't really close maps
+* Allow user configureable number of cached database file handles
+
+Version 2.5
+* Fix memory leak
+
+Version 2.4
+* Minor bug fixes
+
+Version 2.3
+* Minor bug fixes
+
+Version 2.2
+* Minor bug fixes
+* Allow IP numbers as master host
+* Lookup master name of NIS map to avoid compare problems
+* Fix problems with ypcat
+
+Version 2.1
+* Minor bug fixes/typos
+* Fix paths in manual pages
+* Document removal of tcp_wrapper support
+* Fix bug so that ypxfr transfers the whole map in fallback mode
+* rpc.yppasswdd can now register itself to a given port
+
+Version 2.0
+* Merge bug fixes from Debian
+
+Version 1.99.0
+* Rewrite
+
+Version 1.3.10
+* Fix various problems with SIGCHLD handling
+
+Version 1.3.9
+* Security update
+
+Version 1.3.8
+* yppush fix for ndbm support
+* yppush fix for Irix 6.5.x NIS slave servers
+* rpc.yppasswdd shadow rule fixes
+* rpc.yppasswdd fixes for saving/restoring old file modes
+
+Version 1.3.7
+* All daemons give away controlling tty.
+* Fix possible buffer overflow in rpc.yppasswdd.
+* Use yp_msg and not syslog in rpc.yppasswdd for debug messages
+* Use strcasecmp in yppush for comparing hostnames.
+* Set Endianes for ypxfrd transfer correct.
+* Fix file handle corruption through ypproc_all
+* Fix error handling for fork() call
+* Add support for keys and datum which are longer then 1024 bytes
+* ypinit doesn't need a working ypwhich -m
+* makedbm: some bug fixes for aliases and handling comments
+* Add --debug flag to rpc.yppasswdd
+* Add support for merging passwd with shadow file
+* Add support for merging group with gshadow
+* Minor bug fixes for 64bit platforms
+* Bug fixes for libc5
+* Add support for changing passwd file by external program
+
+Version 1.3.6
+* Fix bug in ypserv.conf parser
+* Fix support for gdbm on 64bit platforms
+* Fix yp_all return code for empty maps
+* Upgrade ypmake to version 0.11 from Olaf Kirch
+* Add support for passwd.adjunct
+* Allow all characters >= 32
+
+Version 1.3.5
+* makedbm bug fixes
+
+Version 1.3.4
+* Fix output of ypxfr
+* Fix /var/yp/Makefile dependency
+
+Version 1.3.3
+* Fix rpc.yppasswdd seg.fault in error case
+* Make compiling with libc5 working again
+
+Version 1.3.2
+* Upate documentation
+* Fix NDBM support
+
+Version 1.3.1
+* Bugfixes
+
+Version 1.3.0
+* Support for ndbm (SunOS 4.x/5.x) (Not complete)
+* Add FQDN support (configure --enable-fqdn). All hostnames will
+ go through gethostbyname to determine the offical hostname
+* Add YP V1 protocol
+
+Version 1.2.8
+* Bugfixes
+
+Version 1.2.7
+* Bugfixes
+
+Version 1.2.6
+* pwupdate and makedbm man pages
+* Remove tryresolve, hacker could stop ypserv with it
+
+Version 1.2.5
+* Add patches from SuSE distribution
+
+Version 1.2.4
+* yppasswd and rpc.yppasswdd bugfixes
+
+Version 1.2.3
+* Fix _dns_gethostbyname problem with Linux/libc5
+
+Version 1.2.2
+* rpc.yppasswdd bugfixes
+* ypMakefile improvements
+
+Version 1.2.1
+* Fix ypserv DB file caching
+* A lot of rpc.yppasswdd bugfixes
+
+Version 1.2.0
+* Cache the DB file handles
diff --git a/README b/README
new file mode 100644
index 0000000..a8e1893
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+
+This a YP (NIS version 2) Server for Linux, but it also runs under
+other OS like SunOS 4.1.x, Solaris 2.x, AIX, HP-UX, IRIS, Ultrix
+and others.
+
+This is NOT an NIS+ (NIS version 3) Server !
+
+See the file COPYING for copying restrictions. It is available under
+the GNU General Public License.
+
+The primary development site for ypserv is:
+https://github.com/thkukuk/ypserv
+
+1024 Byte limit in NIS protocol:
+---------------------------------
+The NIS protocol has one important limit: keys and data are limited
+to 1024 bytes. Today most implementations (especially glibc and this
+ypserv implementation) can handle longer keys and data. But this must
+not be the case for every implementation, so be careful if you use
+entries which are longer.
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..58e86dc
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,20 @@
+ypserv was originally written by Peter Eriksson <pen@lysator.liu.se>.
+Maintainer since version 0.18 and author of ypserv v2 is Thorsten Kukuk.
+
+It would not be what it is today without the invaluable help of these
+people:
+
+Honza Horak <hhorak@redhat.com
+Martin Vidner <mvidner@suse.cz>
+Miquel van Smoorenburg <miquels@cistron.nl>
+Peter Breitenlohner <peb@mppmu.mpg.de>
+Todd R. Eigenschink <todd@tekinteractive.com>
+Petter Reinholdtsen <pere@hungry.com>
+Jonathan Gowland <jgowland@genaware.com>
+Damien Touraine <webmyster@addoc.u-psud.fr>
+Jens Laas <jens.laas@data.slu.se>
+Tony Kew <tonykew@ccr.buffalo.edu>
+Michael Gernoth <simigern@stud.uni-erlangen.de>
+Feng Qin <fengqin@uiuc.edu>
+Jakub Jelinek <jakub@redhat.com>
+Mark Brown <broonie@sirena.org.uk>
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..1ad5d50
--- /dev/null
+++ b/TODO
@@ -0,0 +1,9 @@
+
+Things to do (in no particular order):
+
+ o Rework README
+
+ o ypmaplist needs to be fixed for Sun's NDBM
+
+ o IP numbers in ypserver file doesn't work
+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..d4a7753
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,30 @@
+dnl
+dnl Test for __attribute__ ((unused))
+dnl Based on code from the tcpdump version 3.7.2 source.
+dnl
+
+AC_DEFUN([AC_C___ATTRIBUTE__], [
+AC_MSG_CHECKING(for __attribute__)
+AC_CACHE_VAL(ac_cv___attribute__, [
+AC_TRY_COMPILE([
+#include <stdlib.h>
+static void foo (void) __attribute__ ((unused));
+
+static void
+foo (void)
+{
+ exit(1);
+}
+],
+[
+ exit (0);
+],
+ac_cv___attribute__=yes,
+ac_cv___attribute__=no)])
+if test "$ac_cv___attribute__" = "yes"; then
+ AC_DEFINE(UNUSED, __attribute__ ((unused)), [define if your compiler has __attribute__ ((unused))])
+else
+ AC_DEFINE(UNUSED,,)
+fi
+AC_MSG_RESULT($ac_cv___attribute__)
+])
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..2887365
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1431 @@
+# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 12 (pkg-config-0.29.2)
+
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.2])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+ [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $2])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
+# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.15'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.15.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.15.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
+ [$1], [CXX], [depcc="$CXX" am_compiler_list=],
+ [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+ [$1], [UPC], [depcc="$UPC" am_compiler_list=],
+ [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+ [--enable-dependency-tracking],
+ [do not reject slow dependency extractors])
+AS_HELP_STRING(
+ [--disable-dependency-tracking],
+ [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named 'Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running 'make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "$am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+ [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+ m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+ [ok:ok],,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES([CC])],
+ [m4_define([AC_PROG_CC],
+ m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES([CXX])],
+ [m4_define([AC_PROG_CXX],
+ m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES([OBJC])],
+ [m4_define([AC_PROG_OBJC],
+ m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ [_AM_DEPENDENCIES([OBJCXX])],
+ [m4_define([AC_PROG_OBJCXX],
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+ fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+ [whether $CC understands -c and -o together],
+ [am_cv_prog_cc_c_o],
+ [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+ alias in your environment])
+ fi
+ if test "$[2]" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+ [AC_MSG_CHECKING([that generated files are newer than configure])
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+ [--enable-silent-rules],
+ [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+ [--disable-silent-rules],
+ [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+ [m4_case([$1],
+ [ustar],
+ [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+ if test $am_uid -le $am_max_uid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi
+ AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+ if test $am_gid -le $am_max_gid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi],
+
+ [pax],
+ [],
+
+ [m4_fatal([Unknown tar format])])
+
+ AC_MSG_CHECKING([how to create a $1 tar archive])
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ AM_RUN_LOG([cat conftest.dir/file])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/japhar_grep_cflags.m4])
+m4_include([m4/jh_path_xml_catalog.m4])
+m4_include([acinclude.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a4b08df
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,7 @@
+#!/bin/sh -x
+
+aclocal -I m4
+autoheader
+automake --add-missing --copy
+autoreconf
+chmod 755 configure
diff --git a/conf_post.h b/conf_post.h
new file mode 100644
index 0000000..a47c536
--- /dev/null
+++ b/conf_post.h
@@ -0,0 +1,10 @@
+/* Define common preprocessor symbol for HAVE_LIBGDBM and HAVE_LIBQDBM, since
+ * libraries gdbm and qdbm have same symbol names. */
+#undef HAVE_COMPAT_LIBGDBM
+#ifdef HAVE_LIBGDBM
+#define HAVE_COMPAT_LIBGDBM
+#endif
+#ifdef HAVE_LIBQDBM
+#define HAVE_COMPAT_LIBGDBM
+#endif
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..0cc06a2
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,328 @@
+#
+# Copyright (C) 1999-2021 Thorsten Kukuk <kukuk@thkukuk.de>
+#
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT([ypserv],[4.2],[kukuk@thkukuk.de])
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([ypserv/ypserv.c])
+AC_CONFIG_HEADERS([config.h])
+AC_PREFIX_DEFAULT(/usr)
+AH_BOTTOM([#include <conf_post.h>])
+
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+dnl Some hacks...
+test "${prefix}" = "NONE" && prefix="/usr"
+if test ${prefix} = '/usr'
+then
+dnl If we use /usr as prefix, use /etc for ypserv.conf
+ if test ${sysconfdir} = '${prefix}/etc'
+ then
+ sysconfdir="/etc"
+ fi
+dnl If we use /usr as prefix, use /usr/share/man for manual pages
+ if test ${mandir} = '${prefix}/man'
+ then
+ mandir='${prefix}/share/man'
+ fi
+fi
+dnl Change libexec to lib/yp
+if test ${libexecdir} = '${exec_prefix}/libexec'
+then
+ libexecdir='${exec_prefix}/lib/yp'
+ if test "${exec_prefix}" = "NONE"
+ then
+ YPBINDIR=/usr/lib/yp
+ else
+ YPBINDIR=${exec_prefix}/lib/yp
+ fi
+else
+ YPBINDIR=${libexecdir}
+fi
+AC_SUBST(YPBINDIR)
+
+dnl Location of the NIS maps. default: /var/yp
+AC_ARG_ENABLE([ypmapdir],
+ AS_HELP_STRING([--enable-ypmapdir=path],
+ [Location of NIS maps (default=/var/yp)]),
+ YPMAPDIR=$enableval, YPMAPDIR=/var/yp)
+AC_SUBST(YPMAPDIR)
+
+
+if test ${sbindir} = '${exec_prefix}/sbin'
+then
+ if test "${exec_prefix}" = "NONE"
+ then
+ SBINDIR=/usr/sbin
+ else
+ SBINDIR=${exec_prefix}/sbin
+ fi
+else
+ SBINDIR=${sbindir}
+fi
+AC_SUBST(SBINDIR)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_SEARCH_LIBS([strerror],[cposix])
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AM_PROG_CC_C_O
+AC_USE_SYSTEM_EXTENSIONS
+AC_GNU_SOURCE
+AC_C___ATTRIBUTE__
+
+if eval "test x$GCC = xyes"; then
+ for flag in \
+ -W \
+ -Wall \
+ -Wbad-function-cast \
+ -Wcast-align \
+ -Wcast-qual \
+ -Wmissing-declarations \
+ -Wmissing-prototypes \
+ -Wpointer-arith \
+ -Wreturn-type \
+ -Wstrict-prototypes
+ do
+ JAPHAR_GREP_CFLAGS($flag, [ CFLAGS="$CFLAGS $flag" ])
+ done
+fi
+
+AC_ARG_ENABLE(pie,AS_HELP_STRING([--disable-pie],
+ [Disable position-independent executeables (PIE)]),
+ USE_PIE=$enableval, USE_PIE=yes)
+
+AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl
+ cat > conftest.c <<EOF
+int foo;
+main () { return 0;}
+EOF
+ if test "$USE_PIE" = "yes" &&
+ AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -pie -fpie
+ -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD])
+ then
+ libc_cv_fpie=yes
+ PIE_CFLAGS="-fpie"
+ PIE_LDFLAGS="-pie"
+ else
+ libc_cv_fpie=no
+ PIE_CFLAGS=""
+ PIE_LDFLAGS=""
+ fi
+ rm -f conftest*])
+AC_SUBST(libc_cv_fpie)
+AC_SUBST(PIE_CFLAGS)
+AC_SUBST(PIE_LDFLAGS)
+
+dnl Check for big or little endian system
+AC_C_BIGENDIAN
+dnl Check for 64bit systems
+AC_CHECK_SIZEOF(long)
+
+dnl Search a awk program
+AC_PATH_PROGS(AWK, mawk gawk nawk awk, ERROR)
+if test $AWK = ERROR
+then
+ echo " "
+ echo "ERROR: You must have at last one of the following programs:"
+ echo " mawk, gawk, nawk or awk !"
+ echo " "
+ exit
+fi
+
+dnl Search the bash
+AC_PATH_PROGS(BASH, bash /sbin/sh, /bin/sh)
+
+dnl Search make
+AC_PATH_PROGS(MAKE, gmake make, "", $PATH:/usr/ccs/bin:/usr/local/bin)
+if test x$MAKE = x
+then
+ echo " "
+ echo "Warning: No make on this system?"
+ echo " "
+ exit
+fi
+AC_SUBST(MAKE)
+
+dnl Check for aliases path
+AC_PATH_PROG(ALIASES, aliases, /etc/mail/aliases, /etc/mail:/etc)
+
+dnl Should we use a gethostbyname after gethostname to use FQDN ? default yes
+AC_ARG_ENABLE(fqdn, AS_HELP_STRING([--disable-fqdn],
+ [Always use FQDN (default=yes)]),
+ USE_PARAM_FQDN=$enableval, USE_PARAM_FQDN=yes)
+if test "$USE_PARAM_FQDN" = "no"; then
+ USE_FQDN=0
+else
+ USE_FQDN=1
+fi
+AC_SUBST(USE_FQDN)
+
+dnl Should we allow root to change a password with yppasswd ? default: yes
+AC_ARG_ENABLE([checkroot],AS_HELP_STRING([--disable-checkroot],
+ [Disable check for root password (default=yes)]),
+ CHECKROOT=$enableval, CHECKROOT=yes)
+AC_SUBST(CHECKROOT)
+
+# Check for --with-dbmliborder
+dbmliborder="gdbm ndbm qdbm tokyocabinet"
+AC_MSG_CHECKING(for --with-dbmliborder)
+AC_ARG_WITH(dbmliborder,
+ AS_HELP_STRING([--with-dbmliborder=db1:db2:...], [order to check db backends for dbm. Valid value is a colon separated string with the backend names `ndbm', `gdbm', `qdbm' and `tokyocabinet'.]),
+[
+if test x$with_dbmliborder = xyes
+then
+ AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...])
+else
+ dbmliborder=`echo $with_dbmliborder | sed 's/:/ /g'`
+ for db in $dbmliborder; do
+ if test x$db != xndbm && test x$db != xgdbm && test x$db != xqdbm && test x$db != xtokyocabinet
+ then
+ AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...])
+ fi
+ done
+fi])
+AC_MSG_RESULT($with_dbmliborder)
+
+# find which dbm we have
+for db in $dbmliborder; do
+ if test x$db = xqdbm
+ then
+ AC_CHECK_LIB(qdbm,gdbm_open,LIBDBM="$( pkg-config --libs qdbm )" ; CFLAGS="$( pkg-config --cflags qdbm ) $CFLAGS",LIBDBM="")
+ if test x"" != x"${LIBDBM}"
+ then
+ AC_DEFINE(HAVE_LIBQDBM, 1, [Use qdbm library as database])
+ libdb_parameter=yes
+ break
+ fi
+ elif test x$db = xgdbm
+ then
+ AC_CHECK_LIB(gdbm,gdbm_open,LIBDBM="-lgdbm",LIBDBM="")
+ if test x"" != x"${LIBDBM}"
+ then
+ AC_DEFINE(HAVE_LIBGDBM, 1, [Use gdbm library as database])
+ libdb_parameter=yes
+ break
+ fi
+ elif test x$db = xtokyocabinet
+ then
+ AC_CHECK_LIB(tokyocabinet,tcbdbopen,LIBDBM="-ltokyocabinet",LIBDBM="")
+ if test x"" != x"${LIBDBM}"
+ then
+ AC_DEFINE(HAVE_LIBTC, 1, [Use tokyocabinet library as database])
+ libdb_parameter=yes
+ break
+ fi
+ elif test x$db = xndbm
+ then
+ AC_CHECK_FUNCS(dbm_open)
+ if test x$ac_cv_func_dbm_open = xyes
+ then
+ AC_DEFINE(HAVE_NDBM, 1, [Use ndbm library as database])
+ libdb_parameter=yes
+ break
+ fi
+ fi
+done
+AC_SUBST(LIBDBM)
+
+if test x$libdb_parameter != xyes
+then
+ echo "
+
+ You need the GNU GDBM, QDBM, Tokyo Cabinet or the Solaris NDBM functions for this package !"
+ echo ""
+ echo ""
+ exit
+fi
+
+AC_CHECK_LIB(crypt,crypt,LIBCRYPT="-lcrypt",LIBCRYPT="")
+AC_CHECK_HEADERS(crypt.h)
+AC_SUBST(LIBCRYPT)
+
+dnl save old CFLAGS/CPPFLAGS/LIBS variable, we need to modify them
+dnl to find out which functions they provide
+old_CFLAGS=$CFLAGS
+old_CPPFLAGS=$CPPFLAGS
+old_LIBS=$LIBS
+PKG_CHECK_MODULES([NSL], [libnsl], [], [AC_CHECK_LIB([nsl],[yp_match],[NSL_LIBS="-lnsl"],[NSL_LIBS=""])])
+CFLAGS="$CFLAGS $NSL_CFLAGS"
+CPPFLAGS="$CPPFLAGS $NSL_CFLAGS"
+LIBS="$LIBS $NSL_LIBS"
+PKG_CHECK_MODULES([TIRPC], [libtirpc], [], [TIRPC_LIBS=""])
+if test -n "$TIRPC_LIBS"; then
+ AC_DEFINE(HAVE_TIRPC, 1, [Define to 1 if TIRPC is available])
+fi
+CFLAGS="$CFLAGS $TIRPC_CFLAGS"
+CPPFLAGS="$CPPFLAGS $TIRPC_CFLAGS"
+LIBS="$LIBS $TIRPC_LIBS"
+AC_CHECK_FUNCS([getrpcport rpcb_getaddr])
+CFLAGS="$old_CFLAGS"
+CPPFLAGS="$old_CPPFLAGS"
+LIBS="$old_LIBS"
+
+PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 209], [USE_SD_NOTIFY=1], [USE_SD_NOTIFY=0])
+AC_SUBST(USE_SD_NOTIFY)
+
+AC_CHECK_LIB(resolv, res_gethostbyname, RESOLV="-lresolv", RESOLV="")
+if test x$RESOLV != x
+then
+ AC_DEFINE(HAVE_RES_GETHOSTBYNAME, 1, [Define if you have the res_gethostbyname function.])
+else
+ AC_CHECK_LIB(resolv+, gethostbyname, RESOLV="-lresolv+", RESOLV="")
+fi
+AC_SUBST(RESOLV)
+
+dnl
+dnl Check for xsltproc
+dnl
+enable_man=yes
+AC_PATH_PROG([XSLTPROC], [xsltproc])
+if test -z "$XSLTPROC"; then
+ enable_man=no
+fi
+AC_PATH_PROG([XMLLINT], [xmllint],[/bin/true])
+dnl check for DocBook DTD and stylesheets in the local catalog.
+JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.3//EN],
+ [DocBook XML DTD V4.3], [], enable_man=no)
+JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
+ [DocBook XSL Stylesheets], [], enable_man=no)
+AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test x$enable_man != xno)
+
+AC_CONFIG_FILES([Makefile
+ lib/Makefile etc/Makefile ypserv/Makefile
+ ypxfr/Makefile yppush/Makefile makedbm/Makefile mknetid/Makefile
+ revnetgroup/Makefile rpc.yppasswdd/Makefile rpc.ypxfrd/Makefile
+ yphelper/Makefile scripts/Makefile scripts/ypxfr_1perhour
+ scripts/ypxfr_1perday scripts/ypxfr_2perday scripts/pwupdate
+ scripts/create_printcap scripts/match_printcap
+ scripts/ypinit scripts/ypMakefile])
+AC_OUTPUT
+
+echo "
+Configuration:
+
+ Source code location: ${srcdir}
+ Compiler: ${CC}
+ Compiler flags: ${CFLAGS}
+ Preprocessor: ${CPP}
+ Preprocessor flags: ${CPPFLAGS}
+ Libraries: ${LIBS} ${LIBDBM} ${LIBCRYPT} ${SYSTEMD_LIBS} ${TIRPC_LIBS} ${NSL_LIBS}
+ Awk: ${AWK}
+ Shell: ${BASH}
+ NIS map dir: ${YPMAPDIR}
+ Install path prefix: ${prefix}"
+if test ${sysconfdir} != '${prefix}/etc'
+then
+ echo " Install ypserv.conf in: ${sysconfdir}"
+else
+ echo " Install ypserv.conf in: ${prefix}/etc"
+fi
+ echo " Allow root password: ${CHECKROOT}"
+ echo " Use FQDN as master name: ${USE_FQDN}"
+ echo " Notify systemd: ${USE_SD_NOTIFY}"
+echo ""
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..8d98720
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,436 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000 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., 51 Franklin Street - Suite 500, Boston, MA
+# 02110-1335, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+if test -z "$depfile"; then
+ base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
+ dir=`echo "$object" | sed 's,/.*$,/,'`
+ if test "$dir" = "$object"; then
+ dir=
+ fi
+ # FIXME: should be _deps on DOS.
+ depfile="$dir.deps/$base"
+fi
+
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+ "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. This file always lives in the current directory.
+ # Also, the AIX compiler puts `$object:' at the start of each line;
+ # $object doesn't have directory information.
+ stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+ tmpdepfile="$stripped.u"
+ outname="$stripped.o"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-M
+ else
+ "$@" -M
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+
+ base=`echo "$object" | sed -e 's/\.o$//' -e 's/\.lo$//'`
+ tmpdepfile1="$base.o.d"
+ tmpdepfile2="$base.d"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-MD
+ else
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile1"; then
+ tmpdepfile="$tmpdepfile1"
+ else
+ tmpdepfile="$tmpdepfile2"
+ fi
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a space and a tab in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ test -z "$dashmflag" && dashmflag=-M
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*) # this is libtool, let us make it quiet
+ for arg
+ do # cycle over the arguments
+ case "$arg" in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ # X makedepend
+ (
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in no)
+ set ""; shift
+ cleared=yes
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift;;
+ -*)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ "$@" -E |
+ sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the proprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ ( IFS=" "
+ case " $* " in
+ *" --mode=compile "*)
+ for arg
+ do # cycle over the arguments
+ case $arg in
+ "--mode=compile")
+ # insert --quiet before "--mode=compile"
+ set fnord "$@" --quiet
+ shift # fnord
+ ;;
+ esac
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # "$arg"
+ done
+ ;;
+ esac
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ ) &
+ proc=$!
+ "$@"
+ stat=$?
+ wait "$proc"
+ if test "$stat" != 0; then exit $stat; fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/etc/Makefile.am b/etc/Makefile.am
new file mode 100644
index 0000000..e3037a9
--- /dev/null
+++ b/etc/Makefile.am
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2006 Thorsten Kukuk <kukuk@thkukuk.de>
+#
+
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+EXTRA_DIST = README locale netgroup netmasks securenets timezone ypserv.conf \
+ ${MANS} ${XMLS}
+
+CLEANFILES = *~
+
+man_MANS = netgroup.5 ypserv.conf.5
+XMLS = netgroup.5.xml ypserv.conf.5.xml
+
+if ENABLE_REGENERATE_MAN
+%.5: %.5.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/etc/README b/etc/README
new file mode 100644
index 0000000..259183c
--- /dev/null
+++ b/etc/README
@@ -0,0 +1,5 @@
+You should edit this files and install "securenets" in
+YPMAPDIR (normally /var/yp) and "ypserv.conf" in CONFDIR
+(normally /etc or /usr/etc).
+If you don't have a /etc/locale, /etc/netgroup file, /etc/netmasks or
+/etc/timezone file, copy this versions to /etc.
diff --git a/etc/locale b/etc/locale
new file mode 100644
index 0000000..557d6db
--- /dev/null
+++ b/etc/locale
@@ -0,0 +1,12 @@
+#
+# locale The locale file. Entries look like this:
+#
+# locale NIS-domain
+#
+# So for example a locale for nis.domain could be:
+#
+# en_US nis.domain
+#
+# This file is not used by Linux, only for other Unix like Solaris
+
+# en_US nis.domain
diff --git a/etc/netgroup b/etc/netgroup
new file mode 100644
index 0000000..d2a9aa2
--- /dev/null
+++ b/etc/netgroup
@@ -0,0 +1,22 @@
+#
+# netgroup The netgroup file. Entries look like this:
+#
+# netgroup (host,user,domain) (host,user,domain) ..
+#
+# So for example a netgroup for powerusers could be:
+#
+# powerusers (,miquels,) (,torvalds,) (,fubar,)
+#
+# And an entry in the password file like
+#
+# +@powerusers::::::
+# +:*:::::/etc/NoShell
+#
+# would give access only to the users in "powerusers", while the
+# other users would be known to the system but have an invalid
+# shell AND an invalid password (with Linux, you can also
+# override the password field).
+#
+
+# powerusers (,miquels,) (,torvalds,) (,fubar,)
+# ourhosts (picard,,) (enterprise,,) (laforge,,) (Q,,)
diff --git a/etc/netgroup.5 b/etc/netgroup.5
new file mode 100644
index 0000000..d949a4c
--- /dev/null
+++ b/etc/netgroup.5
@@ -0,0 +1,58 @@
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "NETGROUP" "5" "04/06/2006" "NIS Reference Manual" "NIS Reference Manual"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+netgroup \- specify network groups
+.SH "DESCRIPTION"
+.PP
+The
+\fInetgroup\fR
+file defines "netgroups", which are sets of (host, user, domain) tuples, used for permission checking when doing remote mounts,remote logins and remote shells.
+.PP
+Each line in the file consists of a netgroup name followed by a by a list of members, where a member is either another netgroup name, or a triple:
+.sp
+.nf
+ (\fIhost\fR, \fIuser\fR, \fIdomain\fR)
+.fi
+.PP
+where the
+\fIhost\fR,
+\fIuser\fR, and
+\fIdomain\fR
+are character strings for the corresponding components. Any of the three fields can be empty, in which case it specifies a "wildcard", or may consist of the string "\-" to specify "no valid value". The
+\fIdomain\fR
+field must either be the local domain name or empty for the netgroup entry to be used. This field does not limit the netgroup or provide security. The domain field refers to the domain in which the triple is valid, not the domain containing the the trusted host.
+.PP
+A gateway machine should be listed under all possible hostnames by which it may be recognized:
+.sp
+.nf
+ gateway (server, , ) (server\-sn, , ) (server\-bb, , )
+.fi
+.PP
+The
+\fBgetnetgrent\fR(3), function should normally be used to access the netgroup database.
+.SH "FILES"
+.PP
+\fI/etc/netgroup\fR
+.SH "SEE ALSO"
+.PP
+\fBgetnetgrent\fR(3),
+\fBexports\fR(5),
+\fBmakedbm\fR(8),
+\fBypserv\fR(8)
+.SH "WARNINGS"
+.PP
+The triple (,,domain) allows all users and machines trusted access, and has the same effect as the triple (,,). Use the
+\fIhost\fR
+and
+\fIuser\fR
+fields of the triple to restrict the access correctly to a specific set of members.
+.SH "AUTHOR"
+.PP
+Thorsten Kukuk <kukuk@thkukuk.de>
diff --git a/etc/netgroup.5.xml b/etc/netgroup.5.xml
new file mode 100644
index 0000000..8dea21c
--- /dev/null
+++ b/etc/netgroup.5.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<refentry id='netgroup'>
+ <refmeta>
+ <refentrytitle>netgroup</refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='netgroup-name'>
+ <refname>netgroup</refname>
+ <refpurpose>specify network groups</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsect1 id='description'>
+ <title>DESCRIPTION</title>
+ <para>
+ The <filename>netgroup</filename> file defines "netgroups",
+ which are sets of (host, user, domain) tuples, used for permission
+ checking when doing remote mounts,remote logins and remote shells.
+ </para>
+ <para>
+ Each line in the file consists of a netgroup name followed by a
+ by a list of members, where a member is either another netgroup name,
+ or a triple:
+ </para>
+ <programlisting>
+ (<emphasis>host</emphasis>, <emphasis>user</emphasis>, <emphasis>domain</emphasis>) </programlisting>
+ <para>
+ where the <emphasis>host</emphasis>, <emphasis>user</emphasis>, and
+ <emphasis>domain</emphasis> are character strings for the
+ corresponding components. Any of the three fields can be empty,
+ in which case it specifies a "wildcard", or may consist of the string
+ "-" to specify "no valid value". The <emphasis>domain</emphasis>
+ field must either be the local domain name or empty for the netgroup
+ entry to be used. This field does not limit the netgroup or provide
+ security. The domain field refers to the domain in which the triple
+ is valid, not the domain containing the the trusted host.
+ </para>
+
+ <para>
+ A gateway machine should be listed under all possible hostnames by
+ which it may be recognized:
+ </para>
+
+ <programlisting>
+ gateway (server,&thinsp;,&thinsp;) (server-sn,&thinsp;,&thinsp;) (server-bb,&thinsp;,&thinsp;)</programlisting>
+
+ <para>
+ The <citerefentry><refentrytitle>getnetgrent</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ function should normally be used to access the netgroup database.
+ </para>
+ </refsect1>
+
+ <refsect1 id='files'>
+ <title>FILES</title>
+ <para>
+ <filename>/etc/netgroup</filename>
+ </para>
+ </refsect1>
+
+ <refsect1 id='see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry><refentrytitle>getnetgrent</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>exports</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>makedbm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='warnings'>
+ <title>WARNINGS</title>
+ <para>
+ The triple (,,domain) allows all users and machines trusted
+ access, and has the same effect as the triple (,,). Use the
+ <emphasis>host</emphasis> and <emphasis>user</emphasis>
+ fields of the triple to restrict the access correctly to a specific
+ set of members.
+ </para>
+ </refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>Thorsten Kukuk &lt;kukuk@thkukuk.de&gt;</para>
+ </refsect1>
+</refentry>
diff --git a/etc/netmasks b/etc/netmasks
new file mode 100644
index 0000000..f1d7ca4
--- /dev/null
+++ b/etc/netmasks
@@ -0,0 +1,14 @@
+#
+# netmasks The netmasks file. Entries look like this:
+#
+# network netmask
+#
+# So for example a netmask for the 192.168.0 network could be:
+#
+# 192.168.0 255.255.255.0
+#
+
+# 192.168.0 255.255.255.0
+# 172.16 255.255.0.0
+# 10 255.0.0.0
+
diff --git a/etc/securenets b/etc/securenets
new file mode 100644
index 0000000..bbf05e1
--- /dev/null
+++ b/etc/securenets
@@ -0,0 +1,17 @@
+#
+# securenets This file defines the access rights to your NIS server
+# for NIS clients. This file contains netmask/network
+# pairs. A clients IP address needs to match with at least
+# one of those.
+#
+# One can use the word "host" instead of a netmask of
+# 255.255.255.255. Only IP addresses are allowed in this
+# file, not hostnames.
+#
+# Always allow access for localhost, IPv4 and IPv6
+255.0.0.0 127.0.0.0
+host ::1
+
+# This lines gives access to everybody. PLEASE ADJUST!
+0.0.0.0 0.0.0.0
+::/0
diff --git a/etc/timezone b/etc/timezone
new file mode 100644
index 0000000..f7cd12a
--- /dev/null
+++ b/etc/timezone
@@ -0,0 +1,13 @@
+#
+# timezone The timezone file. Entries look like this:
+#
+# timezone NIS-domain
+#
+# So for example a timezone for nis.domain could be:
+#
+# MET nis.domain
+#
+# This file is not used by Linux, but by other Unix like Solaris
+
+# MET nis.domain
+
diff --git a/etc/ypserv.conf b/etc/ypserv.conf
new file mode 100644
index 0000000..d5418b1
--- /dev/null
+++ b/etc/ypserv.conf
@@ -0,0 +1,46 @@
+#
+# ypserv.conf In this file you can set certain options for the NIS server,
+# and you can deny or restrict access to certain maps based
+# on the originating host.
+#
+# See ypserv.conf(5) for a description of the syntax.
+#
+
+# Some options for ypserv. This things are all not needed, if
+# you have a Linux net.
+
+# How many map file handles should be cached ?
+files: 30
+
+# Should we register ypserv with SLP? Only available if SLP support
+# is compiled in. Deprecated functionality.
+slp: no
+# After how many seconds we should re-register ypserv with SLP?
+slp_timeout: 3600
+
+# xfr requests are only allowed from ports < 1024
+xfr_check_port: yes
+
+# The following, when uncommented, will give you shadow like passwords.
+# Note that it will not work if you have slave NIS servers in your
+# network that do not run the same server as you.
+# IMPORTANT: this rules will be ignored for IPv6 connections!
+
+# Host : Domain : Map : Security
+#
+# * : * : passwd.byname : port
+# * : * : passwd.byuid : port
+
+# Not everybody should see the shadow passwords, not secure, since
+# under MSDOG everbody is root and can access ports < 1024 !!!
+* : * : shadow.byname : port
+* : * : passwd.adjunct.byname : port
+
+# If you comment out the next rule, ypserv and rpc.ypxfrd will
+# look for YP_SECURE and YP_AUTHDES in the maps. This will make
+# the security check a little bit slower, but you only have to
+# change the keys on the master server, not the configuration files
+# on each NIS server.
+# If you have maps with YP_SECURE or YP_AUTHDES, you should create
+# a rule for them above, that's much faster.
+# * : * : * : none
diff --git a/etc/ypserv.conf.5 b/etc/ypserv.conf.5
new file mode 100644
index 0000000..422eeaa
--- /dev/null
+++ b/etc/ypserv.conf.5
@@ -0,0 +1,173 @@
+'\" t
+.\" Title: ypserv.conf
+.\" Author: [see the "AUTHOR" section]
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 03/04/2016
+.\" Manual: NIS Reference Manual
+.\" Source: NIS Reference Manual
+.\" Language: English
+.\"
+.TH "YPSERV\&.CONF" "5" "03/04/2016" "NIS Reference Manual" "NIS Reference Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+ypserv.conf \- configuration file for ypserv and rpc\&.ypxfrd
+.SH "DESCRIPTION"
+.PP
+\fIypserv\&.conf\fR
+is an ASCII file which contains some options for ypserv\&. It also contains a list of rules for special host and map access for ypserv and rpc\&.ypxfrd\&. This file will be read by ypserv and rpc\&.ypxfrd at startup, or when receiving a SIGHUP signal\&.
+.PP
+There is one entry per line\&. If the line is a option line, the format is:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ option: \fIargument\fR
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+The line for an access rule has the format:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ host:domain:map:security
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+All rules are tried one by one\&. If no match is found, access to a map is allowed\&.
+.PP
+Following options exist:
+.PP
+\fBfiles:\fR \fI30\fR
+.RS 4
+This option specifies, how many database files should be cached by
+\fIypserv\fR\&. If
+0
+is specified, caching is disabled\&. Decreasing this number is only possible, if ypserv is restarted\&.
+.RE
+.PP
+\fBtrusted_master:\fR \fIserver\fR
+.RS 4
+If this option is set on a slave server, new maps from the host
+\fIserver\fR
+will be accepted as master\&. The default is, that no trusted master is set and new maps will not be accepted\&.
+.sp
+Example:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ trusted_master: ypmaster\&.example\&.org
+
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
+\fBslp:\fR [\fIyes\fR|\fI<no>\fR|\fIdomain\fR]
+.RS 4
+If this option is enabled and SLP support compiled in, the NIS server registers itself on a SLP server\&. If the variable is set to
+\fIdomain\fR, an attribute
+\fIdomain\fR
+with a comma seperated list of supported domainnames is set\&. Else this attribute will not be set\&. The default is "no" (disabled)\&.
+.RE
+.PP
+\fBxfr_check_port:\fR [\fI<yes>\fR|\fIno\fR]
+.RS 4
+With this option enabled, the NIS master server have to run on a port < 1024\&. The default is "yes" (enabled)\&.
+.RE
+.PP
+The field descriptions for the access rule lines are:
+.PP
+\fBhost\fR
+.RS 4
+IPv4 only address\&. Wildcards are allowed\&. This rules are ignored for IPv6, which means it is better to not use this option at all anymore\&.
+.sp
+Examples:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ 131\&.234\&. = 131\&.234\&.0\&.0/255\&.255\&.0\&.0
+ 131\&.234\&.214\&.0/255\&.255\&.254\&.0
+
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
+\fBdomain\fR
+.RS 4
+specifies the domain, for which this rule should be applied\&. An asterix as wildcard is allowed\&.
+.RE
+.PP
+\fBmap\fR
+.RS 4
+name of the map, or asterisk for all maps\&.
+.RE
+.PP
+\fBsecurity\fR
+.RS 4
+one of
+\fInone\fR,
+\fIport\fR,
+\fIdeny\fR:
+.PP
+\fInone\fR
+.RS 4
+always allow access\&.
+.RE
+.PP
+\fIport\fR
+.RS 4
+allow access if from port < 1024\&. Otherwise do not allow access\&.
+.RE
+.PP
+\fIdeny\fR
+.RS 4
+deny access to this map\&.
+.RE
+.RE
+.SH "FILES"
+.PP
+/etc/ypserv\&.conf
+.SH "SEE ALSO"
+.PP
+\fBypserv\fR(8),
+\fBrpc.ypxfrd\fR(8)
+.SH "WARNINGS"
+.PP
+The access rules for special maps are no real improvement in security, but they make the life a little bit harder for a potential hacker\&.
+.PP
+Solaris clients don\*(Aqt use privileged ports\&. All security options which depend on privileged ports cause big problems on Solaris clients\&.
+.SH "AUTHOR"
+.PP
+Thorsten Kukuk <kukuk@thkukuk\&.de>
diff --git a/etc/ypserv.conf.5.xml b/etc/ypserv.conf.5.xml
new file mode 100644
index 0000000..9391c78
--- /dev/null
+++ b/etc/ypserv.conf.5.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+
+<refentry id='ypserv.conf'>
+
+ <refmeta>
+ <refentrytitle>ypserv.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>ypserv.conf</refname>
+ <refpurpose>configuration file for ypserv and rpc.ypxfrd</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsect1 id='description'>
+ <title>DESCRIPTION</title>
+ <para>
+ <emphasis>ypserv.conf</emphasis> is an ASCII file which contains
+ some options for ypserv. It also contains a list of rules for
+ special host and map access for ypserv and rpc.ypxfrd. This file
+ will be read by ypserv and rpc.ypxfrd at startup, or when receiving
+ a SIGHUP signal.
+ </para>
+
+ <para>
+ There is one entry per line. If the line is a option line, the
+ format is:
+ </para>
+
+ <programlisting>
+ option: <emphasis>argument</emphasis></programlisting>
+
+ <para>
+ The line for an access rule has the format:
+ </para>
+
+ <programlisting>
+ host:domain:map:security</programlisting>
+
+ <para>
+ All rules are tried one by one. If no match is found, access to a
+ map is allowed.
+ </para>
+
+ <para>
+ Following options exist:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><option>files:</option> <emphasis>30</emphasis></term>
+ <listitem>
+ <para>
+ This option specifies, how many database files should be
+ cached by <emphasis>ypserv</emphasis>. If <literal>0</literal>
+ is specified, caching is disabled. Decreasing this number is only
+ possible, if ypserv is restarted.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>trusted_master:</option> <emphasis>server</emphasis></term>
+ <listitem>
+ <para>
+ If this option is set on a slave server, new maps from the
+ host <emphasis>server</emphasis> will be accepted as master. The
+ default is, that no trusted master is set and new maps will not
+ be accepted.
+ </para>
+ <para>
+ Example:
+ </para>
+ <programlisting>
+ trusted_master: ypmaster.example.org
+ </programlisting>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>slp:</option> [<emphasis>yes</emphasis>|<emphasis>&lt;no&gt;</emphasis>|<emphasis>domain</emphasis>]</term>
+ <listitem>
+ <para>
+ If this option is enabled and SLP support compiled in, the NIS
+ server registers itself on a SLP server. If the variable is set
+ to <emphasis>domain</emphasis>, an attribute
+ <emphasis>domain</emphasis> with a comma seperated list of
+ supported domainnames is set. Else this attribute will not be set.
+ The default is "no" (disabled).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>xfr_check_port:</option> [<emphasis>&lt;yes&gt;</emphasis>|<emphasis>no</emphasis>]</term>
+ <listitem>
+ <para>
+ With this option enabled, the NIS master server have to run on a
+ port &lt; 1024. The default is "yes" (enabled).
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ The field descriptions for the access rule lines are:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><option>host</option></term>
+ <listitem>
+ <para>
+ IPv4 only address. Wildcards are allowed. This rules are ignored
+ for IPv6, which means it is better to not use this option at all anymore.
+ </para>
+ <para>
+ Examples:
+ </para>
+ <programlisting>
+ 131.234. = 131.234.0.0/255.255.0.0
+ 131.234.214.0/255.255.254.0
+ </programlisting>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>domain</option></term>
+ <listitem>
+ <para>
+ specifies the domain, for which this rule should be applied. An
+ asterix as wildcard is allowed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>map</option></term>
+ <listitem>
+ <para>
+ name of the map, or asterisk for all maps.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>security</option></term>
+ <listitem>
+ <para>one of <emphasis>none</emphasis>, <emphasis>port</emphasis>, <emphasis>deny</emphasis>:</para>
+ <variablelist>
+ <varlistentry>
+ <term><emphasis>none</emphasis></term>
+ <listitem>
+ <para>always allow access.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis>port</emphasis></term>
+ <listitem>
+ <para>
+ allow access if from port &lt; 1024.
+ Otherwise do not allow access.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis>deny</emphasis></term>
+ <listitem>
+ <para>deny access to this map.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='files'>
+ <title>FILES</title>
+ <para><filename>/etc/ypserv.conf</filename></para>
+ </refsect1>
+
+ <refsect1 id='see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>rpc.ypxfrd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='warnings'>
+ <title>WARNINGS</title>
+ <para>
+ The access rules for special maps are no real improvement in
+ security, but they make the life a little bit harder for a
+ potential hacker.
+ </para>
+ <para>
+ Solaris clients don't use privileged ports. All security options
+ which depend on privileged ports cause big problems on Solaris clients.
+ </para>
+ </refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>Thorsten Kukuk &lt;kukuk@thkukuk.de&gt;</para>
+ </refsect1>
+</refentry>
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..398a88e
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ :
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=$mkdirprog
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ :
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ :
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ :
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+ '
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ :
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ :
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..bbbef58
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2000, 2001, 2003 Thorsten Kukuk <kukuk@suse.de>
+#
+# Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+rpcsvcdir = ${prefix}/include/rpcsvc
+
+EXTRA_DIST = test/ypserv.conf securenets.test
+
+noinst_LIBRARIES = libyp.a
+noinst_HEADERS = log_msg.h yp.h ypserv_conf.h ypxfrd.h access.h yp_db.h \
+ pidfile.h
+
+rpcsvc_HEADERS = ypxfrd.x
+
+DEFS = @DEFS@ -D_REENTRANT=1 -DCONFDIR=\"$(sysconfdir)\" \
+ -DYPMAPDIR=\"@YPMAPDIR@\" -DUSE_SD_NOTIFY=@USE_SD_NOTIFY@
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+AM_CFLAGS = @PIE_CFLAGS@ @NSL_CFLAGS@ @TIRPC_CFLAGS@ -Werror
+
+libyp_a_SOURCES = log_msg.c ypserv_conf.c ypxfrd_xdr.c \
+ ypproc_match_2.c securenets.c access.c yp_db.c \
+ pidfile.c
+
+check_PROGRAMS = test-securenets test-ypserv_conf
+test_securenets_LDADD = securenets.o log_msg.o @TIRPC_LIBS@
+test_ypserv_conf_LDADD = libyp.a @TIRPC_LIBS@ @NSL_LIBS@ @LIBDBM@ @SYSTEMD_LIBS@
+
+TESTS = $(check_PROGRAMS)
+
+CLEANFILES = *~
diff --git a/lib/access.c b/lib/access.c
new file mode 100644
index 0000000..646d798
--- /dev/null
+++ b/lib/access.c
@@ -0,0 +1,312 @@
+/* Copyright (C) 1997-2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <netdb.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#if USE_SD_NOTIFY
+#include <systemd/sd-daemon.h>
+#endif
+
+#include "log_msg.h"
+#include "ypserv_conf.h"
+#include "access.h"
+#include "yp_db.h"
+#include "yp.h"
+
+static conffile_t *conf = NULL;
+const char *confdir = CONFDIR;
+
+void
+load_config (void)
+{
+ conffile_t *tmp;
+
+ if (conf != NULL)
+ {
+ log_msg ("Reloading %s/ypserv.conf", confdir);
+ while (conf)
+ {
+ tmp = conf;
+ conf = conf->next;
+
+ free (tmp->map);
+ free (tmp);
+ }
+ }
+
+ conf = load_ypserv_conf (confdir);
+}
+
+/* Give a string with the DEFINE description back */
+static char *
+ypproc_name (int proc)
+{
+ switch (proc)
+ {
+ case YPPROC_NULL:
+ return "ypproc_null";
+ case YPPROC_DOMAIN:
+ return "ypproc_domain";
+ case YPPROC_DOMAIN_NONACK:
+ return "ypproc_domain_nonack";
+ case YPPROC_MATCH:
+ return "ypproc_match";
+ case YPPROC_FIRST:
+ return "ypproc_first";
+ case YPPROC_NEXT:
+ return "ypproc_next";
+ case YPPROC_XFR:
+ return "ypproc_xfr";
+ case YPPROC_CLEAR:
+ return "ypproc_clear";
+ case YPPROC_ALL:
+ return "ypproc_all";
+ case YPPROC_MASTER:
+ return "ypproc_master";
+ case YPPROC_ORDER:
+ return "ypproc_order";
+ case YPPROC_MAPLIST:
+ return "ypproc_maplist";
+ case YPPROC_NEWXFR:
+ return "ypproc_newxfr";
+ default:
+ log_msg ("Unknown procedure '%i'", proc);
+ return "unknown ?";
+ }
+}
+
+/* The is_valid_domain function checks the domain specified bye the
+ caller to make sure it's actually served by this server.
+
+ Return 1 if the name is a valid domain name served by us, else 0. */
+int
+is_valid_domain (const char *domain)
+{
+ struct stat sbuf;
+
+ if (domain == NULL || domain[0] == '\0' ||
+ strcmp (domain, "binding") == 0 ||
+ strcmp (domain, "..") == 0 ||
+ strcmp (domain, ".") == 0 ||
+ strchr (domain, '/'))
+ return 0;
+
+ if (stat (domain, &sbuf) < 0 || !S_ISDIR (sbuf.st_mode))
+ return 0;
+
+ return 1;
+}
+
+static struct netbuf *
+copy_netbuf (struct netbuf *src)
+{
+ struct netbuf *dst;
+
+ if (src == NULL)
+ return NULL;
+
+ dst = calloc (1, sizeof (struct netbuf));
+ if (dst == NULL)
+ return NULL;
+
+ dst->buf = malloc (src->len);
+ if (dst->buf == NULL)
+ {
+ free (dst);
+ return NULL;
+ }
+
+ dst->len = src->len;
+ dst->maxlen = src->len;
+ memcpy (dst->buf, src->buf, src->len);
+
+ return dst;
+}
+
+/* return values:
+ 0: both IP addresses are identical
+ 1: the IP addresses are not identical */
+static int
+cmp_netbuf (struct netbuf *nbuf1, struct netbuf *nbuf2)
+{
+ if (nbuf1 == NULL || nbuf2 == NULL)
+ return 1;
+
+ if (nbuf1->len != nbuf2->len)
+ return 1;
+
+ if (memcmp (nbuf1->buf, nbuf2->buf, nbuf1->len) == 0)
+ return 0;
+
+ return 1;
+}
+
+/* By default, we use the securenet list, to check if the client
+ is secure.
+
+ return 1, if request comes from an authorized host
+ return 0, if securenets does not allow access from this host
+ return -1, if request comes from an unauthorized host
+ return -2, if the map name is not valid
+ return -3, if the domain is not valid
+ return -4, if the map does not exist */
+int
+is_valid (struct svc_req *rqstp, const char *map, const char *domain)
+{
+ static struct netbuf *oldaddr = NULL; /* so we dont log multiple times */
+ static int oldstatus = -1;
+ struct netconfig *nconf;
+ struct netbuf *rqhost;
+ struct __rpc_sockinfo si;
+ int status;
+
+ if (domain && is_valid_domain (domain) == 0)
+ return -3;
+
+ if (map && (map[0] == '\0' || strchr (map ,'/')))
+ return -2;
+
+ rqhost = svc_getrpccaller (rqstp->rq_xprt);
+ nconf = getnetconfigent (rqstp->rq_xprt->xp_netid);
+
+ status = securenet_host (nconf, rqhost);
+
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return -1;
+
+ if ((map != NULL) && status && si.si_af == AF_INET)
+ {
+ struct sockaddr_in *sin = rqhost->buf;
+ conffile_t *work;
+
+ work = conf;
+ while (work)
+ {
+ if ((sin->sin_addr.s_addr & work->netmask.s_addr) == work->network.s_addr)
+ if (strcmp (work->domain, domain) == 0 ||
+ strcmp (work->domain, "*") == 0)
+ if (strcmp (work->map, map) == 0 || strcmp (work->map, "*") == 0)
+ break;
+ work = work->next;
+ }
+
+ if (work != NULL)
+ switch (work->security)
+ {
+ case SEC_NONE:
+ break;
+ case SEC_DENY:
+ status = -1;
+ break;
+ case SEC_PORT:
+ if (taddr2port (nconf, rqhost) >= IPPORT_RESERVED)
+ status = -1;
+ break;
+ }
+ else if (domain != NULL)
+ {
+ /* The map is not in the access list, maybe it
+ has a YP_SECURE key ? */
+ DB_FILE dbp = ypdb_open (domain, map);
+ if (dbp != NULL)
+ {
+ datum key;
+
+ key.dsize = sizeof ("YP_SECURE") - 1;
+ key.dptr = "YP_SECURE";
+ if (ypdb_exists (dbp, key))
+ if (taddr2port (nconf, rqhost) >= IPPORT_RESERVED)
+ status = -1;
+ ypdb_close (dbp);
+ }
+ else
+ status = -4;
+ }
+ }
+
+ if (debug_flag)
+ {
+ char host[INET6_ADDRSTRLEN];
+
+ log_msg ("%sconnect from %s port %d to procedure %s (%s,%s;%d)",
+ status ? "" : "refused ",
+ taddr2ipstr (nconf, rqhost, host, sizeof (host)),
+ taddr2port (nconf, rqhost), ypproc_name (rqstp->rq_proc),
+ domain ? domain : "", map ? map : "", status);
+ }
+ else
+ {
+ if ((status < 1 && status != -4) &&
+ (cmp_netbuf (oldaddr, rqhost) || (status != oldstatus)))
+ {
+ char host[INET6_ADDRSTRLEN];
+
+ syslog (LOG_WARNING,
+ "refused connect from %s port %d to procedure %s (%s,%s;%d)",
+ taddr2ipstr (nconf, rqhost, host, sizeof (host)),
+ taddr2port (nconf, rqhost), ypproc_name (rqstp->rq_proc),
+ domain ? domain : "", map ? map : "", status);
+ }
+ }
+
+ /* Create a copy of the netbuf and free the old one */
+ if (oldaddr)
+ {
+ if (oldaddr->buf)
+ free (oldaddr->buf);
+ free (oldaddr);
+ }
+ oldaddr = copy_netbuf (rqhost);
+ oldstatus = status;
+
+ freenetconfigent (nconf);
+
+ return status;
+}
+
+/* Send a messages to systemd daemon, that inicialization of daemon
+ is finished and daemon is ready to accept connections.
+ It is a nop if we don't use systemd. */
+void
+announce_ready()
+{
+#if USE_SD_NOTIFY
+ int result;
+
+ result = sd_notifyf(0, "READY=1\n"
+ "STATUS=Processing requests...\n"
+ "MAINPID=%lu", (unsigned long) getpid());
+
+ /* Return code from sd_notifyf can be ignored, as per sd_notifyf(3).
+ However, if we use systemd's native unit file, we need to send
+ this message to let systemd know that daemon is ready.
+ Thus, we want to know that the call had some issues. */
+ if (result < 0)
+ log_msg ("sd_notifyf failed: %s\n", strerror(-result));
+#endif
+}
diff --git a/lib/access.h b/lib/access.h
new file mode 100644
index 0000000..2d2f06a
--- /dev/null
+++ b/lib/access.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2000, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server 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.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifndef __ACCESS_H__
+#define __ACCESS_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rpc/rpc.h>
+
+/* access.c */
+extern void load_config (void);
+extern int is_valid_domain (const char *domain);
+extern int is_valid (struct svc_req *rqstp, const char *map,
+ const char *domain);
+
+/* securenets.c */
+extern int load_securenets (void);
+extern int securenet_host (struct netconfig *nconf, struct netbuf *nbuf);
+extern void dump_securenets (void);
+
+/* systemd */
+extern void announce_ready (void);
+
+#endif
diff --git a/lib/log_msg.c b/lib/log_msg.c
new file mode 100644
index 0000000..cef574e
--- /dev/null
+++ b/lib/log_msg.c
@@ -0,0 +1,47 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include "log_msg.h"
+
+/*
+** Reports a message to stderr, if in debug mode, else to syslog
+*/
+
+int debug_flag = 0; /* per default no debug messages */
+
+FILE *debug_output = NULL;
+
+void
+log_msg (char *fmt,...)
+{
+ va_list ap;
+
+ if (debug_output == NULL)
+ debug_output = stderr;
+
+ va_start (ap, fmt);
+ if (debug_flag)
+ {
+ vfprintf (debug_output, fmt, ap);
+ fputc ('\n', debug_output);
+ fflush (debug_output);
+ }
+ else
+ {
+#ifdef HAVE_VSYSLOG
+ vsyslog (LOG_NOTICE, fmt, ap);
+#else
+ char msg[512];
+
+ vsnprintf (msg, sizeof (msg), fmt, ap);
+ msg[sizeof (msg) -1] = '\0';
+ syslog (LOG_NOTICE, "%s", msg);
+#endif
+ }
+ va_end (ap);
+}
diff --git a/lib/log_msg.h b/lib/log_msg.h
new file mode 100644
index 0000000..982001b
--- /dev/null
+++ b/lib/log_msg.h
@@ -0,0 +1,9 @@
+#ifndef __LOG_MSG_H__
+#define __LOG_MSG_H__ 1
+
+extern int debug_flag;
+
+extern void log_msg (char *, ...);
+
+#endif /* __LOG_MSG_H__ */
+
diff --git a/lib/pidfile.c b/lib/pidfile.c
new file mode 100644
index 0000000..f5ea4ff
--- /dev/null
+++ b/lib/pidfile.c
@@ -0,0 +1,91 @@
+/* Copyright (c) 2009, 2011 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server 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.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#include "pidfile.h"
+#include "log_msg.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
+void
+create_pidfile (const char *filename, const char *daemonname)
+{
+ int fd, left, written;
+ pid_t pid;
+ char pbuf[50], *ptr;
+ struct flock lock;
+
+ fd = open (filename, O_CREAT | O_RDWR | O_CLOEXEC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd < 0)
+ {
+ log_msg ("cannot create pidfile %s", filename);
+ if (debug_flag)
+ log_msg ("\n");
+ exit (1);
+ }
+
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+
+ /* Is the pidfile locked by another daemon ? */
+ if (fcntl (fd, F_GETLK, &lock) < 0)
+ {
+ log_msg ("fcntl error");
+ if (debug_flag)
+ log_msg ("\n");
+ exit (1);
+ }
+ if (lock.l_type == F_UNLCK)
+ pid = 0; /* false, region is not locked by another proc */
+ else
+ pid = lock.l_pid; /* true, return pid of lock owner */
+
+ if (0 != pid)
+ {
+ log_msg ("%s already running (pid %d) - exiting", daemonname, pid);
+ if (debug_flag)
+ log_msg ("\n");
+ exit (1);
+ }
+
+ /* write lock */
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+ if (0 != fcntl (fd, F_SETLK, &lock))
+ log_msg ("cannot lock pidfile");
+ sprintf (pbuf, "%ld\n", (long) getpid ());
+ left = strlen (pbuf);
+ ptr = pbuf;
+ while (left > 0)
+ {
+ if ((written = write (fd, ptr, left)) <= 0)
+ return; /* error */
+ left -= written;
+ ptr += written;
+ }
+ return;
+}
diff --git a/lib/pidfile.h b/lib/pidfile.h
new file mode 100644
index 0000000..d524963
--- /dev/null
+++ b/lib/pidfile.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2009 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server 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.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifndef __PIDFILE_H
+#define __PIDFILE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <paths.h>
+
+#ifndef _PATH_VARRUN
+#define _PATH_VARRUN "/etc/"
+#endif
+
+/* Creates a pidfile on daemon startup. */
+extern void create_pidfile (const char *filename, const char *daemonname);
+
+#endif /* __PIDFILE_H */
diff --git a/lib/securenets.c b/lib/securenets.c
new file mode 100644
index 0000000..90f0910
--- /dev/null
+++ b/lib/securenets.c
@@ -0,0 +1,359 @@
+/* Copyright (c) 1996-2014, 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server 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.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "access.h"
+#include "log_msg.h"
+
+#ifndef SECURENETS
+#define SECURENETS YPMAPDIR "/securenets"
+#endif
+
+const char *securenetsfile = SECURENETS;
+
+typedef struct securenet
+{
+ sa_family_t family;
+ struct sockaddr_storage network;
+ struct sockaddr_storage netmask;
+ struct securenet *next;
+}
+securenet_t;
+
+static securenet_t *securenets = NULL;
+
+
+void
+dump_securenets (void)
+{
+ struct securenet *sn;
+ int i = 0;
+
+ log_msg ("--- securenets start ---");
+ sn = securenets;
+ while (sn)
+ {
+ char host[INET6_ADDRSTRLEN];
+ char mask[INET6_ADDRSTRLEN];
+
+ i++;
+
+ switch (sn->family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *network =
+ (struct sockaddr_in *)&(sn->network);
+ struct sockaddr_in *netmask =
+ (struct sockaddr_in *)&(sn->netmask);
+
+ log_msg ("entry %d: %s %s", i,
+ inet_ntop (AF_INET, &network->sin_addr,
+ host, sizeof (host)),
+ inet_ntop (AF_INET, &netmask->sin_addr,
+ mask, sizeof (mask)));
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *network =
+ (struct sockaddr_in6 *)&(sn->network);
+ struct sockaddr_in6 *netmask =
+ (struct sockaddr_in6 *)&(sn->netmask);
+
+ log_msg ("entry %d: %s %s", i,
+ inet_ntop (AF_INET6, &network->sin6_addr,
+ host, sizeof (host)),
+ inet_ntop (AF_INET6, &netmask->sin6_addr,
+ mask, sizeof (mask)));
+ }
+ break;
+ default:
+ log_msg ("ERROR: Unknown family: %i", sn->family);
+ break;
+ }
+ sn = sn->next;
+ }
+ log_msg ("--- securenets end ---");
+}
+
+int
+load_securenets (void)
+{
+ char buf[2 * NI_MAXHOST + 2];
+ char col_mask[NI_MAXHOST + 1], col_host[NI_MAXHOST + 1];
+ struct addrinfo hints, *res0;
+ FILE *in;
+ securenet_t *work, *tmp;
+ int error, line = 0;
+
+
+ /* If securenets isn't NULL, we should reload the securents file. */
+ if (securenets != NULL)
+ {
+ log_msg ("Reloading securenets file\n");
+ while (securenets != NULL)
+ {
+ work = securenets;
+ securenets = securenets->next;
+ free (work);
+ }
+ }
+ securenets = NULL;
+ work = NULL;
+ tmp = NULL;
+
+ if ((in = fopen (securenetsfile, "r")) == NULL)
+ {
+ log_msg ("WARNING: no %s file found!\n", securenetsfile);
+ return 1;
+ }
+
+ while (!feof (in))
+ {
+ int nr_entries;
+
+ memset (col_mask, 0, sizeof (col_mask));
+ memset (col_host, 0, sizeof (col_host));
+ memset (buf, 0, sizeof (buf));
+ if (fgets (buf, sizeof (buf) -1, in) == NULL)
+ continue;
+ line++;
+
+ if (buf[0] == '\0' || buf[0] == '#' || buf[0] == '\n')
+ continue;
+
+ nr_entries = sscanf (buf, "%s %s", col_mask, col_host);
+
+ if (nr_entries == 2)
+ {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((error = getaddrinfo (col_host, NULL, &hints, &res0)))
+ {
+ log_msg ("securenets (%d) badly formated: %s",
+ line, gai_strerror (error));
+ continue;
+ }
+
+ if ((tmp = malloc (sizeof (securenet_t))) == NULL)
+ {
+ log_msg ("ERROR: could not allocate enough memory! [%s|%d]\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ tmp->next = NULL;
+ memcpy (&tmp->network, res0->ai_addr, res0->ai_addrlen);
+ tmp->family = res0->ai_addr->sa_family;
+ freeaddrinfo(res0);
+
+ if (strcmp (col_mask, "host") == 0)
+ {
+ if (tmp->family == AF_INET)
+ strcpy (col_mask, "255.255.255.255");
+ else if (tmp->family == AF_INET6)
+ strcpy (col_mask, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ else
+ {
+ log_msg ("securenets(%d): unsupported address family: %i", line, tmp->family);
+ free (tmp);
+ continue;
+ }
+ }
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((error = getaddrinfo (col_mask, NULL, &hints, &res0)))
+ {
+ log_msg ("securenets (%d) badly formated: %s",
+ line, gai_strerror (error));
+ free (tmp);
+ continue;
+ }
+ memcpy (&tmp->netmask, res0->ai_addr, res0->ai_addrlen);
+ freeaddrinfo(res0);
+ }
+ else if (nr_entries == 1)
+ {
+ /* 127.0.0.1/8, 2001:0db8:85a3::8a2e:0370:7334/64 */
+ int netmask_len = 0;
+ char *p;
+
+ if ((p = strrchr (buf, '/')))
+ {
+ *p = ' ';
+ nr_entries = sscanf(buf, "%s %i", col_host, &netmask_len);
+ if (nr_entries != 2)
+ goto malformed;
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((error = getaddrinfo (col_host, NULL, &hints, &res0)))
+ {
+ log_msg ("securenets (%d) badly formated: %s",
+ line, gai_strerror (error));
+ continue;
+ }
+ }
+ else
+ goto malformed;
+
+ if ((tmp = malloc (sizeof (securenet_t))) == NULL)
+ {
+ log_msg ("ERROR: could not allocate enough memory! [%s|%d]\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ tmp->next = NULL;
+ memcpy (&tmp->network, res0->ai_addr, res0->ai_addrlen);
+ tmp->family = res0->ai_addr->sa_family;
+ switch (tmp->family) /* prefixlen -> netmask */
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in sin;
+
+ memcpy (&sin, res0->ai_addr, res0->ai_addrlen);
+ sin.sin_addr.s_addr = (0xFFFFFFFFu >> (32 - netmask_len));
+ memcpy (&tmp->netmask, &sin, sizeof (struct sockaddr_in));
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 sin6;
+ int i, j;
+
+ memcpy (&sin6, res0->ai_addr, res0->ai_addrlen);
+ for (i = netmask_len, j = 0; i > 0; i -= 8, ++j)
+ sin6.sin6_addr.s6_addr[ j ] = i >= 8 ? 0xff
+ : (unsigned long)(( 0xffU << ( 8 - i ) ) & 0xffU );
+ memcpy (&tmp->netmask, &sin6, sizeof (struct sockaddr_in6));
+ }
+ break;
+ default:
+ log_msg ("securenets(%d): unsupported address family: %i",
+ line, tmp->family);
+ free (tmp);
+ continue;
+ break;
+ }
+ freeaddrinfo (res0);
+ }
+ else
+ {
+ malformed:
+ log_msg ("securenets(%d): malformed line, ignore it\n", line);
+ continue;
+ }
+
+
+ if (work == NULL)
+ {
+ work = tmp;
+ securenets = work;
+ }
+ else
+ {
+ work->next = tmp;
+ work = work->next;
+ }
+ }
+ fclose (in);
+
+ if (debug_flag)
+ dump_securenets ();
+
+ return 0;
+}
+
+int
+securenet_host (struct netconfig *nconf, struct netbuf *nbuf)
+{
+ securenet_t *ptr;
+ struct __rpc_sockinfo si;
+
+ if (nconf == NULL || nbuf == NULL || nbuf->len <= 0)
+ return 0;
+
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return 0;
+
+ ptr = securenets;
+
+ if (ptr == NULL) /* this means no securenets file, grant access */
+ return 1;
+ else
+ while (ptr != NULL)
+ {
+ if (si.si_af == ptr->family)
+ switch (ptr->family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin1 = nbuf->buf;
+ struct sockaddr_in *sin2 = (struct sockaddr_in *)&(ptr->netmask);
+ struct sockaddr_in *sin3 = (struct sockaddr_in *)&(ptr->network);
+
+ if ((sin1->sin_addr.s_addr & sin2->sin_addr.s_addr) ==
+ sin3->sin_addr.s_addr)
+ return 1;
+ }
+ break;
+ case AF_INET6:
+ {
+ int i;
+ struct sockaddr_in6 *sin1 = nbuf->buf;
+ struct sockaddr_in6 *sin2 =
+ (struct sockaddr_in6 *)&(ptr->netmask);
+ struct sockaddr_in6 *sin3 =
+ (struct sockaddr_in6 *)&(ptr->network);
+
+ for (i = 0; i < 16; i++)
+ if ((sin1->sin6_addr.s6_addr[i] & sin2->sin6_addr.s6_addr[i])
+ != sin3->sin6_addr.s6_addr[i])
+ goto next;
+ return 1;
+ }
+ break;
+ default:
+ goto next; /* Something is wrong here, should not happen. */
+ }
+ next:
+ ptr = ptr->next;
+ }
+ return 0;
+}
diff --git a/lib/securenets.test b/lib/securenets.test
new file mode 100644
index 0000000..2b69845
--- /dev/null
+++ b/lib/securenets.test
@@ -0,0 +1,20 @@
+#
+# securenets This file defines the access rights to your NIS server
+# for NIS clients. This file contains netmask/network
+# pairs. A clients IP address needs to match with at least
+# one of those.
+#
+# One can use the word "host" instead of a netmask of
+# 255.255.255.255. Only IP addresses are allowed in this
+# file, not hostnames.
+#
+# Always allow access for localhost
+255.0.0.0 127.0.0.0
+host ::1
+
+2620:113:80c0:8080::/64
+FE80:0000:0000:0000:0202:B3FF::/96
+172.17.0.0/24
+255.255.0.0 10.160.0.0
+#0.0.0.0 0.0.0.0
+#::/0
diff --git a/lib/test-securenets.c b/lib/test-securenets.c
new file mode 100644
index 0000000..46577a5
--- /dev/null
+++ b/lib/test-securenets.c
@@ -0,0 +1,89 @@
+/* Copyright (c) 2014, 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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, see <http://www.gnu.org/licenses/>. */
+
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+
+#include "access.h"
+
+extern int debug_flag;
+extern const char *securenetsfile;
+
+static int
+check_entry (int af, char *ip)
+{
+ struct __rpc_sockinfo si;
+ struct netconfig *nconf = NULL;
+ struct netbuf *nbuf;
+ const char *netid;
+ char uaddr[100];
+
+ snprintf (uaddr, 100, "%s.0.0", ip);
+
+ nbuf = __rpc_uaddr2taddr_af (af, uaddr);
+ if (nbuf == NULL)
+ {
+ fprintf (stderr, "uaddr2taddr (\"%s\") failed\n", ip);
+ return 1;
+ }
+
+ si.si_af = af;
+ si.si_proto = IPPROTO_UDP;
+ if (!__rpc_sockinfo2netid (&si, &netid))
+ {
+ fprintf (stderr, "__rpc_sockinfo2netid() failed\n");
+ return 1;
+ }
+ nconf = getnetconfigent (netid);
+ if (nconf == NULL)
+ {
+ fprintf (stderr, "getnetconfigent (%s) failed\n", netid);
+ return 1;
+ }
+ if (securenet_host (nconf, nbuf) != 1)
+ return 1;
+
+
+ return 0;
+}
+
+int
+main (void)
+{
+ debug_flag = 1;
+ securenetsfile = "securenets.test";
+
+ if (load_securenets () != 0)
+ return 1;
+ /* dump_securenets (); */
+
+ /* success */
+ if (check_entry (AF_INET, "127.0.0.1") != 0)
+ return 1;
+ /* success */
+ if (check_entry (AF_INET6, "::1") != 0)
+ return 1;
+ /* success */
+ if (check_entry (AF_INET6, "fe80::202:b3ff:ad:245") != 0)
+ return 1;
+ /* fail */
+ if (check_entry (AF_INET, "10.10.0.87") != 1)
+ return 1;
+ /* fail */
+ if (check_entry (AF_INET6, "fe80::202:b3fe:ff:ff") != 1)
+ return 1;
+
+ return 0;
+}
diff --git a/lib/test-ypserv_conf.c b/lib/test-ypserv_conf.c
new file mode 100644
index 0000000..721ac54
--- /dev/null
+++ b/lib/test-ypserv_conf.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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, see <http://www.gnu.org/licenses/>. */
+
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+
+#include "access.h"
+
+extern int debug_flag;
+extern const char *confdir;
+
+int
+main (void)
+{
+ debug_flag = 1;
+ confdir = "test";
+
+ load_config ();
+
+ return 0;
+}
diff --git a/lib/test/ypserv.conf b/lib/test/ypserv.conf
new file mode 100644
index 0000000..8935c1e
--- /dev/null
+++ b/lib/test/ypserv.conf
@@ -0,0 +1,47 @@
+#
+# ypserv.conf In this file you can set certain options for the NIS server,
+# and you can deny or restrict access to certain maps based
+# on the originating host.
+#
+# See ypserv.conf(5) for a description of the syntax.
+#
+
+# Some options for ypserv. This things are all not needed, if
+# you have a Linux net.
+
+# How many map file handles should be cached ?
+files: 30
+
+# Should we register ypserv with SLP? Only available if SLP support
+# is compiled in. Deprecated functionality.
+slp: no
+# After how many seconds we should re-register ypserv with SLP?
+slp_timeout: 3600
+
+# xfr requests are only allowed from ports < 1024
+xfr_check_port: yes
+
+# The following, when uncommented, will give you shadow like passwords.
+# Note that it will not work if you have slave NIS servers in your
+# network that do not run the same server as you.
+# IMPORTANT: this rules will be ignored for IPv6 connections!
+
+# Host : Domain : Map : Security
+#
+# * : * : passwd.byname : port
+# * : * : passwd.byuid : port
+
+# Not everybody should see the shadow passwords, not secure, since
+# under MSDOG everbody is root and can access ports < 1024 !!!
+* : * : shadow.byname : port
+* : * : passwd.adjunct.byname : port
+10.160.* : * : passwd.byname : deny
+
+# If you comment out the next rule, ypserv and rpc.ypxfrd will
+# look for YP_SECURE and YP_AUTHDES in the maps. This will make
+# the security check a little bit slower, but you only have to
+# change the keys on the master server, not the configuration files
+# on each NIS server.
+# If you have maps with YP_SECURE or YP_AUTHDES, you should create
+# a rule for them above, that's much faster.
+# * : * : * : none
diff --git a/lib/yp.h b/lib/yp.h
new file mode 100644
index 0000000..7c3f99e
--- /dev/null
+++ b/lib/yp.h
@@ -0,0 +1,170 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _YP_H_RPCGEN
+#define _YP_H_RPCGEN
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define YPMAXRECORD 1024
+#define YPMAXMAP 64
+
+typedef char *domainname;
+
+typedef char *mapname;
+
+typedef char *peername;
+
+#if defined(HAVE_LIBTC)
+
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+#endif
+
+typedef struct
+{
+ struct
+ {
+ int (*encode)(ypresp_key_val *val, void *data);
+ int (*close)(void *data);
+ } u;
+ void *data;
+} xdr_ypall_cb_t;
+
+#define YPBIND_ERR_ERR 1
+#define YPBIND_ERR_NOSERV 2
+#define YPBIND_ERR_RESC 3
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define YPPROC_NULL 0
+extern enum clnt_stat ypproc_null_2(void *, void *, CLIENT *);
+extern bool_t ypproc_null_2_svc(void *, void *, struct svc_req *);
+#define YPPROC_DOMAIN 1
+extern enum clnt_stat ypproc_domain_2(domainname *, bool_t *, CLIENT *);
+extern bool_t ypproc_domain_2_svc(domainname *, bool_t *, struct svc_req *);
+#define YPPROC_DOMAIN_NONACK 2
+extern enum clnt_stat ypproc_domain_nonack_2(domainname *, bool_t *, CLIENT *);
+extern bool_t ypproc_domain_nonack_2_svc(domainname *, bool_t *, struct svc_req *);
+#define YPPROC_MATCH 3
+extern enum clnt_stat ypproc_match_2(ypreq_key *, ypresp_val *, CLIENT *);
+extern bool_t ypproc_match_2_svc(ypreq_key *, ypresp_val *, struct svc_req *);
+#define YPPROC_FIRST 4
+extern enum clnt_stat ypproc_first_2(ypreq_key *, ypresp_key_val *, CLIENT *);
+extern bool_t ypproc_first_2_svc(ypreq_nokey *, ypresp_key_val *, struct svc_req *);
+#define YPPROC_NEXT 5
+extern enum clnt_stat ypproc_next_2(ypreq_key *, ypresp_key_val *, CLIENT *);
+extern bool_t ypproc_next_2_svc(ypreq_key *, ypresp_key_val *, struct svc_req *);
+#define YPPROC_XFR 6
+extern enum clnt_stat ypproc_xfr_2(ypreq_xfr *, ypresp_xfr *, CLIENT *);
+extern bool_t ypproc_xfr_2_svc(ypreq_xfr *, ypresp_xfr *, struct svc_req *);
+#define YPPROC_CLEAR 7
+extern enum clnt_stat ypproc_clear_2(void *, void *, CLIENT *);
+extern bool_t ypproc_clear_2_svc(void *, void *, struct svc_req *);
+#define YPPROC_ALL 8
+extern enum clnt_stat ypproc_all_2(ypreq_nokey *, ypresp_all *, CLIENT *);
+extern bool_t ypproc_all_2_svc(ypreq_nokey *, ypresp_all *, struct svc_req *);
+#define YPPROC_MASTER 9
+extern enum clnt_stat ypproc_master_2(ypreq_nokey *, ypresp_master *, CLIENT *);
+extern bool_t ypproc_master_2_svc(ypreq_nokey *, ypresp_master *, struct svc_req *);
+#define YPPROC_ORDER 10
+extern enum clnt_stat ypproc_order_2(ypreq_nokey *, ypresp_order *, CLIENT *);
+extern bool_t ypproc_order_2_svc(ypreq_nokey *, ypresp_order *, struct svc_req *);
+#define YPPROC_MAPLIST 11
+extern enum clnt_stat ypproc_maplist_2(domainname *, ypresp_maplist *, CLIENT *);
+extern bool_t ypproc_maplist_2_svc(domainname *, ypresp_maplist *, struct svc_req *);
+#define YPPROC_NEWXFR 12
+extern enum clnt_stat ypproc_newxfr_2(ypreq_newxfr *, ypresp_xfr *, CLIENT *);
+extern bool_t ypproc_newxfr_2_svc(ypreq_newxfr *, ypresp_xfr *, struct svc_req *);
+
+extern int ypprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#else /* K&R C */
+#define YPPROC_NULL 0
+extern enum clnt_stat ypproc_null_2();
+extern bool_t ypproc_null_2_svc();
+#define YPPROC_DOMAIN 1
+extern enum clnt_stat ypproc_domain_2();
+extern bool_t ypproc_domain_2_svc();
+#define YPPROC_DOMAIN_NONACK 2
+extern enum clnt_stat ypproc_domain_nonack_2();
+extern bool_t ypproc_domain_nonack_2_svc();
+#define YPPROC_MATCH 3
+extern enum clnt_stat ypproc_match_2();
+extern bool_t ypproc_match_2_svc();
+#define YPPROC_FIRST 4
+extern enum clnt_stat ypproc_first_2();
+extern bool_t ypproc_first_2_svc();
+#define YPPROC_NEXT 5
+extern enum clnt_stat ypproc_next_2();
+extern bool_t ypproc_next_2_svc();
+#define YPPROC_XFR 6
+extern enum clnt_stat ypproc_xfr_2();
+extern bool_t ypproc_xfr_2_svc();
+#define YPPROC_CLEAR 7
+extern enum clnt_stat ypproc_clear_2();
+extern bool_t ypproc_clear_2_svc();
+#define YPPROC_ALL 8
+extern enum clnt_stat ypproc_all_2();
+extern bool_t ypproc_all_2_svc();
+#define YPPROC_MASTER 9
+extern enum clnt_stat ypproc_master_2();
+extern bool_t ypproc_master_2_svc();
+#define YPPROC_ORDER 10
+extern enum clnt_stat ypproc_order_2();
+extern bool_t ypproc_order_2_svc();
+#define YPPROC_MAPLIST 11
+extern enum clnt_stat ypproc_maplist_2();
+extern bool_t ypproc_maplist_2_svc();
+extern int ypprog_2_freeresult ();
+#endif /* K&R C */
+
+#define YPPUSH_XFRRESPPROG 0x40000000
+#define YPPUSH_XFRRESPVERS 1
+
+#define YPPUSHPROC_NULL 0
+extern enum clnt_stat yppushproc_null_1(void *, void *, CLIENT *);
+extern bool_t yppushproc_null_1_svc(void *, void *, struct svc_req *);
+#define YPPUSHPROC_XFRRESP 1
+extern enum clnt_stat yppushproc_xfrresp_1(yppushresp_xfr *, void *, CLIENT *);
+extern bool_t yppushproc_xfrresp_1_svc(yppushresp_xfr *, void *, struct svc_req *);
+extern int yppush_xfrrespprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+extern bool_t xdr_ypstat (XDR *, ypstat*);
+extern bool_t xdr_ypxfrstat (XDR *, ypxfrstat*);
+extern bool_t xdr_domainname (XDR *, domainname*);
+extern bool_t xdr_mapname (XDR *, mapname*);
+extern bool_t xdr_peername (XDR *, peername*);
+extern bool_t xdr_keydat (XDR *, keydat_t*);
+extern bool_t xdr_valdat (XDR *, valdat_t*);
+extern bool_t xdr_ypmap_parms (XDR *, ypmap_parms*);
+extern bool_t xdr_ypreq_key (XDR *, ypreq_key*);
+extern bool_t xdr_ypreq_nokey (XDR *, ypreq_nokey*);
+extern bool_t xdr_ypreq_xfr (XDR *, ypreq_xfr*);
+extern bool_t xdr_ypresp_val (XDR *, ypresp_val*);
+extern bool_t xdr_ypresp_key_val (XDR *, ypresp_key_val*);
+extern bool_t xdr_ypresp_master (XDR *, ypresp_master*);
+extern bool_t xdr_ypresp_order (XDR *, ypresp_order*);
+extern bool_t xdr_ypresp_all (XDR *, ypresp_all*);
+extern bool_t xdr_ypresp_xfr (XDR *, ypresp_xfr*);
+extern bool_t xdr_ypmaplist (XDR *, ypmaplist*);
+extern bool_t xdr_ypresp_maplist (XDR *, ypresp_maplist*);
+extern bool_t xdr_yppush_status (XDR *, yppush_status*);
+extern bool_t xdr_yppushresp_xfr (XDR *, yppushresp_xfr*);
+
+extern bool_t ypxfr_xdr_ypresp_all (XDR *xdrs, ypresp_all *objp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_YP_H_RPCGEN */
diff --git a/lib/yp_db.c b/lib/yp_db.c
new file mode 100644
index 0000000..c98ec4a
--- /dev/null
+++ b/lib/yp_db.c
@@ -0,0 +1,532 @@
+/* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2009, 2011 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/param.h>
+
+#include "ypserv_conf.h"
+#include "log_msg.h"
+#include "yp_db.h"
+#include "yp.h"
+
+#if defined(HAVE_LIBGDBM)
+#include <gdbm.h>
+#elif defined(HAVE_LIBQDBM)
+#include <hovel.h>
+#elif defined(HAVE_NDBM)
+#include <ndbm.h>
+#elif defined(HAVE_LIBTC)
+#include <tcbdb.h>
+#endif
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+
+/* Open a GDBM database */
+static GDBM_FILE
+_db_open (const char *domain, const char *map)
+{
+ GDBM_FILE dbp;
+ char buf[MAXPATHLEN + 2];
+
+ if (strlen (domain) + strlen (map) < MAXPATHLEN)
+ {
+ sprintf (buf, "%s/%s", domain, map);
+
+ dbp = gdbm_open (buf, 0, GDBM_READER, 0, NULL);
+
+ if (debug_flag && dbp == NULL)
+ log_msg ("gdbm_open: GDBM Error Code #%d", gdbm_errno);
+ else if (debug_flag)
+ log_msg ("\t\t->Returning OK!");
+ }
+ else
+ {
+ dbp = NULL;
+ log_msg ("Path to long: %s/%s", domain, map);
+ }
+
+ return dbp;
+}
+
+static inline int
+_db_close (GDBM_FILE file)
+{
+ gdbm_close (file);
+ return 0;
+}
+
+#elif defined(HAVE_NDBM)
+
+/*****************************************************
+ The following stuff is for NDBM suport !
+******************************************************/
+
+/* Open a NDBM database */
+static DB_FILE
+_db_open (const char *domain, const char *map)
+{
+ DB_FILE dbp;
+ char buf[MAXPATHLEN + 2];
+
+ if (strlen (domain) + strlen (map) < MAXPATHLEN)
+ {
+ sprintf (buf, "%s/%s", domain, map);
+
+ dbp = dbm_open (buf, O_RDONLY, 0600);
+
+ if (debug_flag && dbp == NULL)
+ log_msg ("dbm_open: NDBM Error Code #%d", errno);
+ else if (debug_flag)
+ log_msg ("\t\t->Returning OK!");
+ }
+ else
+ {
+ dbp = NULL;
+ log_msg ("Path to long: %s/%s", domain, map);
+ }
+
+ return dbp;
+}
+
+static inline int
+_db_close (DB_FILE file)
+{
+ dbm_close (file);
+ return 0;
+}
+
+int
+ypdb_exists (DB_FILE dbp, datum key)
+{
+ datum tmp = dbm_fetch (dbp, key);
+
+ if (tmp.dptr != NULL)
+ return 1;
+ else
+ return 0;
+}
+
+datum
+ypdb_nextkey (DB_FILE file, datum key)
+{
+ datum tkey;
+
+ tkey = dbm_firstkey (file);
+ while ((key.dsize != tkey.dsize) ||
+ (strncmp (key.dptr, tkey.dptr, tkey.dsize) != 0))
+ {
+ tkey = dbm_nextkey (file);
+ if (tkey.dptr == NULL)
+ return tkey;
+ }
+ tkey = dbm_nextkey (file);
+
+ return tkey;
+}
+
+#elif defined(HAVE_LIBTC)
+
+/*****************************************************
+ The following stuff is for Tokyo Cabinet suport !
+******************************************************/
+
+/* Open a Tokyo Cabinet B+ Tree database */
+static DB_FILE
+_db_open (const char *domain, const char *map)
+{
+ DB_FILE dbp;
+ char buf[MAXPATHLEN + 2];
+ int isok;
+
+ if (strlen (domain) + strlen (map) < MAXPATHLEN)
+ {
+ sprintf (buf, "%s/%s", domain, map);
+
+ dbp = tcbdbnew ();
+ isok = tcbdbopen (dbp, buf, BDBOREADER | BDBONOLCK);
+
+ if (debug_flag && !isok)
+ {
+ log_msg ("tcbdbopen: Tokyo Cabinet Error: %s",
+ tcbdberrmsg (tcbdbecode (dbp)));
+ log_msg ("tcbdbopen: consider rebuilding maps using ypinit");
+ }
+ else if (debug_flag)
+ log_msg ("\t\t->Returning OK!");
+ if ( !isok )
+ {
+ /* DB not successful opened. Close database object and set return value to NULL. */
+ tcbdbdel (dbp);
+ dbp = NULL;
+ }
+ }
+ else
+ {
+ dbp = NULL;
+ log_msg ("Path too long: %s/%s", domain, map);
+ }
+
+ return dbp;
+}
+
+static inline int
+_db_close (DB_FILE dbp)
+{
+ tcbdbclose (dbp);
+ tcbdbdel (dbp);
+ dbp = NULL;
+ return 0;
+}
+
+datum
+ypdb_firstkey (DB_FILE dbp)
+{
+ datum tkey;
+ BDBCUR *cur;
+
+ /* In case of error, we return original key */
+ if (!(cur = tcbdbcurnew (dbp)) || !tcbdbcurfirst (cur)
+ || (tkey.dptr = tcbdbcurkey (cur, &tkey.dsize)) == NULL)
+ {
+ tkey.dptr = NULL;
+ tkey.dsize = 0;
+ }
+
+ if (cur)
+ tcbdbcurdel (cur);
+
+ return tkey;
+}
+
+int
+ypdb_exists (DB_FILE dbp, datum key)
+{
+ return tcbdbvnum (dbp, key.dptr, key.dsize) > 0;
+}
+
+datum
+ypdb_nextkey (DB_FILE dbp, datum key)
+{
+ datum tkey;
+ BDBCUR *cur;
+
+ tkey.dptr = NULL;
+ tkey.dsize = 0;
+
+ /* In case of error, we return empty key */
+ if (!(cur = tcbdbcurnew (dbp)))
+ return tkey;
+
+ /* We try to jump to key and get next, or we move to the first */
+ if (tcbdbcurjump (cur, key.dptr, key.dsize) && tcbdbcurnext (cur))
+ {
+ if ((tkey.dptr = tcbdbcurkey (cur, &tkey.dsize)) == NULL)
+ tkey.dsize = 0;
+ }
+
+ tcbdbcurdel (cur);
+ return tkey;
+}
+
+datum
+ypdb_fetch (DB_FILE bdb, datum key)
+{
+ datum res;
+
+ if ((res.dptr = tcbdbget (bdb, key.dptr, key.dsize, &res.dsize)) == NULL)
+ res.dsize = 0;
+
+ return res;
+}
+
+#else
+
+#error "No database found or selected!"
+
+#endif
+
+typedef struct _fopen
+{
+ char *domain;
+ char *map;
+ DB_FILE dbp;
+ int flag;
+}
+Fopen, *FopenP;
+
+#define F_OPEN_FLAG 1
+#define F_MUST_CLOSE 2
+
+static int fast_open_init = -1;
+static Fopen fast_open_files[255];
+
+int
+ypdb_close_all (void)
+{
+ int i;
+
+ if (debug_flag)
+ log_msg ("ypdb_close_all() called");
+
+ if (fast_open_init == -1)
+ return 0;
+
+ for (i = 0; i < cached_filehandles; i++)
+ {
+ if (fast_open_files[i].dbp != NULL)
+ {
+ if (fast_open_files[i].flag & F_OPEN_FLAG)
+ {
+ if (debug_flag)
+ log_msg ("ypdb_close_all (%s/%s|%d) MARKED_TO_BE_CLOSE",
+ fast_open_files[i].domain,
+ fast_open_files[i].map, i);
+ fast_open_files[i].flag |= F_MUST_CLOSE;
+ }
+ else
+ {
+ if (debug_flag)
+ log_msg ("ypdb_close_all (%s/%s|%d)",
+ fast_open_files[i].domain,
+ fast_open_files[i].map, i);
+ free (fast_open_files[i].domain);
+ fast_open_files[i].domain = NULL;
+ free (fast_open_files[i].map);
+ fast_open_files[i].map = NULL;
+ _db_close (fast_open_files[i].dbp);
+ fast_open_files[i].dbp = NULL;
+ fast_open_files[i].flag = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+ypdb_close (DB_FILE file)
+{
+ if (debug_flag)
+ log_msg ("ypdb_close() called");
+
+ if (cached_filehandles > 0)
+ {
+ if (fast_open_init != -1)
+ {
+ int i;
+
+ for (i = 0; i < cached_filehandles; ++i)
+ {
+ if (fast_open_files[i].dbp == file)
+ {
+ if (fast_open_files[i].flag & F_MUST_CLOSE)
+ {
+ if (debug_flag)
+ log_msg ("ypdb_MUST_close (%s/%s|%d)",
+ fast_open_files[i].domain,
+ fast_open_files[i].map, i);
+ free (fast_open_files[i].domain);
+ fast_open_files[i].domain = NULL;
+ free (fast_open_files[i].map);
+ fast_open_files[i].map = NULL;
+ _db_close (fast_open_files[i].dbp);
+ fast_open_files[i].dbp = NULL;
+ fast_open_files[i].flag = 0;
+ }
+ else
+ {
+ fast_open_files[i].flag &= ~F_OPEN_FLAG;
+ }
+ return 0;
+ }
+ }
+ }
+ log_msg ("ERROR: Could not close file!");
+ return 1;
+ }
+ else
+ {
+ _db_close (file);
+ return 0;
+ }
+}
+
+DB_FILE
+ypdb_open (const char *domain, const char *map)
+{
+ int i;
+
+ if (debug_flag)
+ log_msg ("\typdb_open(\"%s\", \"%s\")", domain, map);
+
+ if (map[0] == '.' || strchr (map, '/'))
+ {
+ if (debug_flag)
+ log_msg ("\t\t->Returning 0");
+ return NULL;
+ }
+
+ if (cached_filehandles > 0)
+ {
+ /* First call, initialize the fast_open_init struct */
+ if (fast_open_init == -1)
+ {
+ fast_open_init = 0;
+ for (i = 0; i < cached_filehandles; i++)
+ {
+ fast_open_files[i].domain =
+ fast_open_files[i].map = NULL;
+ fast_open_files[i].dbp = (DB_FILE) NULL;
+ fast_open_files[i].flag = 0;
+ }
+ }
+
+ /* Search if we have already open the domain/map file */
+ for (i = 0; i < cached_filehandles; i++)
+ {
+ if (fast_open_files[i].dbp != NULL)
+ {
+ if ((strcmp (domain, fast_open_files[i].domain) == 0) &&
+ (strcmp (map, fast_open_files[i].map) == 0))
+ {
+ /* The file is open and we know the file handle */
+ if (debug_flag)
+ log_msg ("Found: %s/%s (%d)", fast_open_files[i].domain,
+ fast_open_files[i].map, i);
+
+ if (fast_open_files[i].flag & F_OPEN_FLAG)
+ {
+ /* The file is already in use, don't open it twice.
+ I think this could never happen. */
+ log_msg ("\t%s/%s already open.", domain, map);
+ return NULL;
+ }
+ else
+ {
+ /* Mark the file as open */
+ fast_open_files[i].flag |= F_OPEN_FLAG;
+ return fast_open_files[i].dbp;
+ }
+ }
+ }
+ }
+
+ /* Search for free entry. If we do not found one, close the LRU */
+ for (i = 0; i < cached_filehandles; i++)
+ {
+#if 0
+ /* Bad Idea. If one of them is NULL, we will get a seg.fault
+ I think it will only work with Linux libc 5.x */
+ log_msg ("Opening: %s/%s (%d) %x",
+ fast_open_files[i].domain,
+ fast_open_files[i].map,
+ i, fast_open_files[i].dbp);
+#endif
+ if (fast_open_files[i].dbp == NULL)
+ {
+ /* Good, we have a free entry and don't need to close a map */
+ int j;
+ Fopen tmp;
+
+ if ((fast_open_files[i].dbp = _db_open (domain, map)) == NULL)
+ return NULL;
+ /* since .dbp is NULL, .domain must be NULL, too */
+ assert (fast_open_files[i].domain == NULL);
+ fast_open_files[i].domain = strdup (domain);
+ /* since .dbp is NULL, .map must be NULL, too */
+ assert (fast_open_files[i].map == NULL);
+ fast_open_files[i].map = strdup (map);
+ fast_open_files[i].flag |= F_OPEN_FLAG;
+
+ if (debug_flag)
+ log_msg ("Opening: %s/%s (%d) %x", domain, map, i,
+ fast_open_files[i].dbp);
+
+ /* LRU: put this entry at the first position, move all the other
+ one back */
+ tmp = fast_open_files[i];
+ for (j = i; j >= 1; --j)
+ fast_open_files[j] = fast_open_files[j-1];
+
+ fast_open_files[0] = tmp;
+ return fast_open_files[0].dbp;
+ }
+ }
+
+ /* The badest thing, which could happen: no free cache entrys.
+ Search the last entry, which isn't in use. */
+ for (i = (cached_filehandles - 1); i > 0; --i)
+ if ((fast_open_files[i].flag & F_OPEN_FLAG) != F_OPEN_FLAG)
+ {
+ int j;
+ Fopen tmp;
+ DB_FILE dbp;
+
+ /* Check, if we can open the file. Else there is no reason
+ to close a cached handle. */
+ if ((dbp = _db_open (domain, map)) == NULL)
+ return NULL;
+
+ if (debug_flag)
+ {
+ log_msg ("Closing %s/%s (%d)",
+ fast_open_files[i].domain,
+ fast_open_files[i].map, i);
+ log_msg ("Opening: %s/%s (%d)", domain, map, i);
+ }
+ free (fast_open_files[i].domain);
+ free (fast_open_files[i].map);
+ _db_close (fast_open_files[i].dbp);
+
+ fast_open_files[i].domain = strdup (domain);
+ fast_open_files[i].map = strdup (map);
+ fast_open_files[i].flag = F_OPEN_FLAG;
+ fast_open_files[i].dbp = dbp;
+
+ /* LRU: Move the new entry to the first positon */
+ tmp = fast_open_files[i];
+ for (j = i; j >= 1; --j)
+ fast_open_files[j] = fast_open_files[j-1];
+
+ fast_open_files[j] = tmp;
+ return fast_open_files[j].dbp;
+ }
+
+ log_msg ("ERROR: Couldn't find a free cache entry!");
+
+ for (i = 0; i < cached_filehandles; i++)
+ {
+ log_msg ("Open files: %s/%s (%d) %x (%x)",
+ fast_open_files[i].domain,
+ fast_open_files[i].map,
+ i, fast_open_files[i].dbp,
+ fast_open_files[i].flag);
+ }
+ return NULL;
+ }
+ else
+ return _db_open (domain, map);
+}
diff --git a/lib/yp_db.h b/lib/yp_db.h
new file mode 100644
index 0000000..c17d55d
--- /dev/null
+++ b/lib/yp_db.h
@@ -0,0 +1,64 @@
+#ifndef __YP_DB_H__
+#define __YP_DB_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "yp.h"
+
+#define F_ALL 0x01
+#define F_NEXT 0x02
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+#if defined(HAVE_LIBGDBM)
+#include <gdbm.h>
+#elif defined(HAVE_LIBQDBM)
+#include <hovel.h>
+#endif
+
+#define DB_FILE GDBM_FILE
+#define ypdb_fetch(a,b) gdbm_fetch(a,b)
+#define ypdb_exists(a,b) gdbm_exists(a,b)
+#define ypdb_free(a) free(a)
+#define ypdb_firstkey(a) gdbm_firstkey(a)
+#define ypdb_nextkey(a,b) gdbm_nextkey(a,b)
+
+#elif defined(HAVE_NDBM)
+
+#include <ndbm.h>
+
+#define DB_FILE DBM*
+#define ypdb_fetch(a,b) dbm_fetch(a,b)
+#define ypdb_free(a)
+
+extern int ypdb_exists (DB_FILE file, datum key);
+/* extern datum ypdb_firstkey (DB_FILE file); */
+#define ypdb_firstkey(a) dbm_firstkey(a)
+extern datum ypdb_nextkey (DB_FILE file, datum key);
+extern datum ypdb_fetch (DB_FILE file, datum key);
+
+#elif defined(HAVE_LIBTC)
+
+#include <tcbdb.h>
+
+#define DB_FILE TCBDB *
+
+#define ypdb_free(a) free(a)
+
+extern int ypdb_exists (DB_FILE file, datum key);
+extern datum ypdb_firstkey (DB_FILE file);
+extern datum ypdb_nextkey (DB_FILE file, datum key);
+extern datum ypdb_fetch (DB_FILE bdb, datum key);
+
+#else
+
+#error "No database found or selected !"
+
+#endif
+
+extern DB_FILE ypdb_open (const char *domain, const char *map);
+extern int ypdb_close_all (void);
+extern int ypdb_close (DB_FILE file);
+
+#endif
diff --git a/lib/ypproc_all_2.c b/lib/ypproc_all_2.c
new file mode 100644
index 0000000..a98fab5
--- /dev/null
+++ b/lib/ypproc_all_2.c
@@ -0,0 +1,34 @@
+/* Copyright (c) 2000 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "yp.h"
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+enum clnt_stat
+ypproc_all_2 (ypreq_nokey *argp, ypresp_all *clnt_res, CLIENT *clnt)
+{
+ return (clnt_call(clnt, YPPROC_ALL,
+ (xdrproc_t) xdr_ypreq_nokey, (caddr_t) argp,
+ (xdrproc_t) xdr_ypresp_all, (caddr_t) clnt_res,
+ TIMEOUT));
+}
diff --git a/lib/ypproc_match_2.c b/lib/ypproc_match_2.c
new file mode 100644
index 0000000..065c127
--- /dev/null
+++ b/lib/ypproc_match_2.c
@@ -0,0 +1,34 @@
+/* Copyright (c) 2000 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "yp.h"
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+enum clnt_stat
+ypproc_match_2 (ypreq_key *argp, ypresp_val *clnt_res, CLIENT *clnt)
+{
+ return (clnt_call(clnt, YPPROC_MATCH,
+ (xdrproc_t) xdr_ypreq_key, (caddr_t) argp,
+ (xdrproc_t) xdr_ypresp_val, (caddr_t) clnt_res,
+ TIMEOUT));
+}
diff --git a/lib/ypserv_conf.c b/lib/ypserv_conf.c
new file mode 100644
index 0000000..b199799
--- /dev/null
+++ b/lib/ypserv_conf.c
@@ -0,0 +1,656 @@
+/* Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2008, 2011, 2013, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <alloca.h>
+#include <unistd.h>
+
+#include "log_msg.h"
+#include "ypserv_conf.h"
+
+int dns_flag = 0;
+int slp_flag = 0;
+unsigned long int slp_timeout = 3600;
+int xfr_check_port = 0;
+char *trusted_master = NULL;
+/* cached_filehandles (how many databases will be cached):
+ big -> slow list searching, we go 3 times through the list.
+ little -> have to close/open very often.
+ We now uses 30, because searching 3 times in the list is faster
+ then reopening the database.
+ You can open max. 255 file handles.
+*/
+int cached_filehandles = 30;
+
+
+static int
+getipnr (char *n, char *network, char *netmask)
+{
+ char *m;
+ size_t i;
+ int pw, pm;
+ char buf[20];
+
+ pw = pm = 0;
+
+ m = strtok (n, "/");
+
+ sscanf (m, "%19s", buf);
+
+ for (i = 0; i < strlen (buf); i++)
+ if ((buf[i] < '0' || buf[i] > '9') && buf[i] != '.')
+ return 1;
+ else if (buf[i] == '.')
+ ++pw;
+
+ strcpy (network, buf);
+ switch (pw)
+ {
+ case 0:
+ strcat (network, ".0.0.0");
+ ++pw;
+ break;
+ case 1:
+ if (network[strlen (network) - 1] == '.')
+ strcat (network, "0.0.0");
+ else
+ {
+ strcat (network, ".0.0");
+ pw++;
+ }
+ break;
+ case 2:
+ if (network[strlen (network) - 1] == '.')
+ strcat (network, "0.0");
+ else
+ {
+ strcat (network, ".0");
+ pw++;
+ }
+ break;
+ case 3:
+ if (network[strlen (network) - 1] == '.')
+ strcat (network, "0");
+ else
+ pw++;
+ break;
+ default:
+ return 1;
+ break;
+ }
+
+ m = strtok (NULL, "/");
+
+ if ((m != NULL) && (strlen (m) != 0))
+ {
+ sscanf (m, "%s", buf);
+
+ for (i = 0; i < strlen (buf); i++)
+ if ((buf[i] < '0' || buf[i] > '9') && buf[i] != '.')
+ return 1;
+ else if (buf[i] == '.')
+ pm++;
+
+ strcpy (netmask, buf);
+ switch (pm)
+ {
+ case 0:
+ strcat (netmask, ".0.0.0");
+ break;
+ case 1:
+ if (netmask[strlen (netmask) - 1] == '.')
+ strcat (netmask, "0.0.0");
+ else
+ strcat (netmask, ".0.0");
+ break;
+ case 2:
+ if (netmask[strlen (netmask) - 1] == '.')
+ strcat (netmask, "0.0");
+ else
+ strcat (netmask, ".0");
+ break;
+ case 3:
+ if (netmask[strlen (netmask) - 1] == '.')
+ strcat (netmask, "0");
+ break;
+ default:
+ return 1;
+ }
+ }
+ else
+ switch (pw)
+ {
+ case 1:
+ strcpy (netmask, "255.0.0.0");
+ break;
+ case 2:
+ strcpy (netmask, "255.255.0.0");
+ break;
+ case 3:
+ strcpy (netmask, "255.255.255.0");
+ break;
+ case 4:
+ strcpy (netmask, "255.255.255.255");
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+conffile_t *
+load_ypserv_conf (const char *path)
+{
+ FILE *in;
+ int c;
+ char *cp;
+ char buf1[1025], buf2[1025] = "", buf3[1025];
+ long line = 0;
+ conffile_t *ptr = NULL, *work = NULL;
+ char *filename = alloca (strlen (path) + sizeof ("/ypserv.conf") + 1);
+
+ cp = stpcpy (filename, path);
+ strcpy (cp, "/ypserv.conf");
+ if ((in = fopen (filename, "r")) == NULL)
+ {
+ if (debug_flag)
+ log_msg ("WARNING: %s not found!", filename);
+ return NULL;
+ }
+
+ while ((c = fgetc (in)) != EOF)
+ { /*while */
+ line++;
+ switch (tolower (c))
+ {
+ case 'F':
+ case 'f':
+ {
+ size_t i, j;
+ unsigned long files = 30;
+
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL)
+ {
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ }
+
+ i = 0;
+ buf1[sizeof (buf1) - 1] = '\0';
+ while (c != ':' && i <= strlen (buf1))
+ {
+ if ((c == ' ') || (c == '\t'))
+ break;
+ buf2[i] = c;
+ buf2[i + 1] = '\0';
+ c = buf1[i];
+ ++i;
+ }
+
+ while ((buf1[i - 1] != ':') && (i <= strlen (buf1)))
+ ++i;
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "files") == 0))
+ {
+ while (((buf1[i] == ' ') || (buf1[i] == '\t')) &&
+ (i <= strlen (buf1)))
+ ++i;
+ j = 0;
+ while ((buf1[i] != '\0') && (buf1[i] != '\n'))
+ buf3[j++] = buf1[i++];
+ buf3[j] = 0;
+
+ sscanf (buf3, "%lu", &files);
+ }
+ else
+ log_msg ("Parse error in line %d: => Ignore line", line);
+
+ cached_filehandles = files;
+
+ if (cached_filehandles > 255)
+ cached_filehandles = 255;
+
+ if (debug_flag)
+ log_msg ("ypserv.conf: files: %lu", files);
+ break;
+ }
+ case 'D':
+ case 'd':
+ {
+ size_t i, j;
+
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL)
+ {
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ }
+
+ i = 0;
+ while (c != ':' && i <= strlen (buf1))
+ {
+ if ((c == ' ') || (c == '\t'))
+ break;
+ buf2[i] = c;
+ buf2[i + 1] = '\0';
+ c = buf1[i];
+ i++;
+ }
+
+ while ((buf1[i - 1] != ':') && (i <= strlen (buf1)))
+ i++;
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "dns") == 0))
+ {
+ if (!dns_flag) /* Do not overwrite parameter */
+ {
+ while (((buf1[i] == ' ') || (buf1[i] == '\t')) &&
+ (i <= strlen (buf1)))
+ i++;
+ j = 0;
+ while ((buf1[i] != '\0') && (buf1[i] != '\n'))
+ buf3[j++] = buf1[i++];
+ buf3[j] = 0;
+
+ sscanf (buf3, "%s", buf2);
+ if (strcasecmp (buf2, "yes") == 0)
+ dns_flag = 1;
+ else if (strcasecmp (buf2, "no") == 0)
+ dns_flag = 0;
+ else
+ log_msg ("Unknown dns option in line %d: => Ignore line",
+ line);
+ }
+ }
+ else
+ log_msg ("Parse error in line %d: => Ignore line", line);
+
+ if (debug_flag)
+ log_msg ("ypserv.conf: dns: %d", dns_flag);
+ break;
+ }
+ case 'S':
+ case 's':
+ { /* sunos_kludge / slp */
+ size_t i;
+
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL)
+ {
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ }
+
+ i = 0;
+ while (c != ':' && i <= strlen (buf1))
+ {
+ if ((c == ' ') || (c == '\t'))
+ break;
+ buf2[i] = c;
+ buf2[i + 1] = '\0';
+ c = buf1[i];
+ i++;
+ }
+
+ while ((buf1[i - 1] != ':') && (i <= strlen (buf1)))
+ i++;
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "sunos_kludge") == 0))
+ {
+ log_msg ("sunos_kludge (line %d) is not longer supported.",
+ line);
+ }
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "slp") == 0))
+ {
+ size_t j;
+
+ while (((buf1[i] == ' ') || (buf1[i] == '\t')) &&
+ (i <= strlen (buf1)))
+ i++;
+ j = 0;
+ while ((buf1[i] != '\0') && (buf1[i] != '\n'))
+ buf3[j++] = buf1[i++];
+ buf3[j] = 0;
+
+ sscanf (buf3, "%s", buf2);
+ if (strcasecmp (buf2, "yes") == 0)
+ slp_flag = 1;
+ else if (strcasecmp (buf2, "domain") == 0)
+ slp_flag = 2;
+ else if (strcasecmp (buf2, "no") == 0)
+ slp_flag = 0;
+ else
+ log_msg ("Unknown slp option in line %d: => Ignore line",
+ line);
+
+ if (debug_flag)
+ log_msg ("ypserv.conf: slp: %d", slp_flag);
+#if !USE_SLP
+ if (slp_flag != 0)
+ log_msg ("Support for SLP (line %d) is not compiled in.",
+ line);
+#endif
+ }
+ else if ((buf1[i - 1] == ':') &&
+ (strcasecmp (buf2, "slp_timeout") == 0))
+ {
+ size_t j;
+
+ while (((buf1[i] == ' ') || (buf1[i] == '\t')) &&
+ (i <= strlen (buf1)))
+ i++;
+ j = 0;
+ while ((buf1[i] != '\0') && (buf1[i] != '\n'))
+ buf3[j++] = buf1[i++];
+ buf3[j] = 0;
+
+ sscanf (buf3, "%lu", &slp_timeout);
+
+ if (debug_flag)
+ log_msg ("ypserv.conf: slp_timeout: %lu", slp_timeout);
+ }
+ else
+ log_msg ("Parse error in line %d: => Ignore line", line);
+
+ break;
+ }
+ case 'T':
+ case 't':
+ { /* tryresolve / trusted_master */
+ size_t i, j;
+
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL)
+ {
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ }
+
+ i = 0;
+ while (c != ':' && i <= strlen (buf1))
+ {
+ if ((c == ' ') || (c == '\t'))
+ break;
+ buf2[i] = c;
+ buf2[i + 1] = '\0';
+ c = buf1[i];
+ i++;
+ }
+
+ while ((buf1[i - 1] != ':') && (i <= strlen (buf1)))
+ i++;
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "tryresolve") == 0))
+ {
+ log_msg ("tryresolve (line %d) is not longer supported.",
+ line);
+ break;
+ }
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "trusted_master") == 0))
+ {
+ while (((buf1[i] == ' ') || (buf1[i] == '\t')) &&
+ (i <= strlen (buf1)))
+ i++;
+ j = 0;
+ while ((buf1[i] != '\0') && (buf1[i] != '\n'))
+ buf3[j++] = buf1[i++];
+ buf3[j] = 0;
+
+ sscanf (buf3, "%s", buf2);
+ trusted_master = strdup (buf2);
+ }
+ else
+ log_msg ("Parse error in line %d: => Ignore line", line);
+
+ if (debug_flag)
+ log_msg ("ypserv.conf: trusted_master: %s", trusted_master);
+ break;
+ }
+ case 'X':
+ case 'x':
+ { /* xfr_check_port */
+ size_t i, j;
+
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL)
+ {
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ }
+
+ i = 0;
+ while (c != ':' && i <= strlen (buf1))
+ {
+ if ((c == ' ') || (c == '\t'))
+ break;
+ buf2[i] = c;
+ buf2[i + 1] = '\0';
+ c = buf1[i];
+ i++;
+ }
+
+ while ((buf1[i - 1] != ':') && (i <= strlen (buf1)))
+ i++;
+
+ if ((buf1[i - 1] == ':') && (strcasecmp (buf2, "xfr_check_port") == 0))
+ {
+ while (((buf1[i] == ' ') || (buf1[i] == '\t')) &&
+ (i <= strlen (buf1)))
+ i++;
+ j = 0;
+ while ((buf1[i] != '\0') && (buf1[i] != '\n'))
+ buf3[j++] = buf1[i++];
+ buf3[j] = 0;
+
+ sscanf (buf3, "%s", buf2);
+ if (strcasecmp (buf2, "yes") == 0)
+ xfr_check_port = 1;
+ else if (strcasecmp (buf2, "no") == 0)
+ xfr_check_port = 0;
+ else
+ log_msg ("Unknown xfr_check_port option in line %d: => Ignore line",
+ line);
+ }
+ else
+ log_msg ("Parse error in line %d: => Ignore line", line);
+
+ if (debug_flag)
+ log_msg ("ypserv.conf: xfr_check_port: %d", xfr_check_port);
+ break;
+ }
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ case '*':
+ {
+ char *n, *d, *m, *s, *p, *f;
+ conffile_t *tmp;
+
+ buf1[0] = c;
+ if (fgets (&buf1[1], sizeof (buf1) - 2, in) == NULL)
+ {
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ }
+
+ n = strtok (buf1, ":");
+ if (n == NULL)
+ {
+ log_msg ("Parse error in line %d => Ignore line", line);
+ break;
+ }
+ d = strtok (NULL, ":");
+ if (d == NULL)
+ {
+ log_msg ("No domain given in line %d => Ignore line", line);
+ break;
+ }
+ m = strtok (NULL, ":");
+ if (m == NULL)
+ {
+ log_msg ("No map given in line %d => Ignore line", line);
+ break;
+ }
+
+ s = strtok (NULL, ":");
+ if (s == NULL)
+ {
+ log_msg ("No security entry in line %d => Ignore line", line);
+ break;
+ }
+ p = strtok (NULL, ":");
+ if (p != NULL && strlen (p) != 0)
+ f = strtok (NULL, ":");
+ else
+ f = NULL;
+
+ if ((tmp = malloc (sizeof (conffile_t))) == NULL)
+ {
+ log_msg ("ERROR: could not allocate enough memory! [%s|%d]", __FILE__, __LINE__);
+ exit (1);
+ }
+ tmp->next = NULL;
+
+ if (c == '*')
+ {
+#if defined(HAVE_INET_ATON)
+ inet_aton ("0.0.0.0", &tmp->network);
+ inet_aton ("0.0.0.0", &tmp->netmask);
+#else
+ tmp->network.s_addr = inet_addr ("0.0.0.0");
+ tmp->netmask.s_addr = inet_addr ("0.0.0.0");
+#endif
+ }
+ else
+ {
+ if (getipnr (n, buf2, buf3) != 0)
+ {
+ log_msg ("Malformed network/netmask entry in line %d", line);
+ free (tmp->map);
+ free (tmp);
+ break;
+ }
+#if defined(HAVE_INET_ATON)
+ inet_aton (buf2, &tmp->network);
+ inet_aton (buf3, &tmp->netmask);
+#else
+ tmp->network.s_addr = inet_addr (buf2);
+ tmp->netmask.s_addr = inet_addr (buf3);
+#endif
+ }
+ sscanf (d, "%s", buf2);
+ tmp->domain = strdup (buf2);
+ sscanf (m, "%s", buf2);
+ tmp->map = strdup (buf2);
+
+ sscanf (s, "%s", buf2);
+
+ if (strcasecmp (buf2, "none") == 0)
+ tmp->security = SEC_NONE;
+ else if (strcasecmp (buf2, "deny") == 0)
+ tmp->security = SEC_DENY;
+ else if (strcasecmp (buf2, "port") == 0)
+ tmp->security = SEC_PORT;
+ else
+ {
+ log_msg ("Unknown security option \"%s\" in line %d => Ignore line",
+ buf2, line);
+ free (tmp->map);
+ free (tmp);
+ break;
+ }
+
+ if (f != NULL)
+ {
+ log_msg ("Bogus data \"%s\" in line %d => Ignore line", f,
+ line);
+ free (tmp->map);
+ free (tmp);
+ }
+ if (debug_flag)
+ {
+ log_msg ("ypserv.conf: %s/%s:%s:%s:%d",
+ inet_ntoa (tmp->network), inet_ntoa (tmp->netmask),
+ tmp->domain, tmp->map, tmp->security);
+ }
+
+ if (work == NULL)
+ {
+ work = tmp;
+ ptr = work;
+ }
+ else
+ {
+ work->next = tmp;
+ work = work->next;
+ }
+ break;
+ }
+ case ' ':
+ case '\t':
+ line--; /* Ignore Character, no new line */
+ break;
+ case '\n':
+ break; /* Ignore newline */
+ case '#':
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL)
+ log_msg ("Read error in line %d => Ignore line", line);
+ break;
+ default:
+ if (fgets (buf1, sizeof (buf1) - 1, in) == NULL) {};
+ log_msg ("Parse error in line %d: %c%s", line, c, buf1);
+ break;
+ }
+ }
+ fclose (in);
+
+ return ptr;
+}
+
+#if 0
+
+int debug_flag = 1;
+int dns_flag = 0;
+
+void
+main ()
+{
+ conffile_t *ptr;
+
+ ptr = load_ypserv_conf (".");
+
+ log_msg ("Output:");
+
+ while (ptr != NULL)
+ {
+ log_msg ("%s/%s:%s:%d:%d",
+ inet_ntoa (ptr->network), inet_ntoa (ptr->netmask), ptr->map,
+ ptr->security, ptr->mangle);
+ ptr = ptr->next;
+ }
+
+}
+
+#endif
diff --git a/lib/ypserv_conf.h b/lib/ypserv_conf.h
new file mode 100644
index 0000000..817999e
--- /dev/null
+++ b/lib/ypserv_conf.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2000, 2003, 2004 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server 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.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifndef __YPSERV_CONF_H__
+#define __YPSERV_CONF_H__
+
+#include <rpc/rpc.h>
+
+/* Struct for ypserv.conf options */
+typedef struct conffile
+{
+ struct in_addr netmask;
+ struct in_addr network;
+ char *domain;
+ char *map;
+ int security;
+ struct conffile *next;
+} conffile_t;
+
+extern int dns_flag;
+extern int slp_flag;
+extern unsigned long int slp_timeout;
+extern int cached_filehandles;
+extern int xfr_check_port;
+extern char *trusted_master;
+
+extern void load_config(void);
+extern conffile_t *load_ypserv_conf(const char *);
+
+/* Defines for ypserv.conf */
+
+/* Security field: */
+#define SEC_NONE 0
+#define SEC_DENY 1
+#define SEC_PORT 2
+
+#endif
diff --git a/lib/ypxfrd.h b/lib/ypxfrd.h
new file mode 100644
index 0000000..b5f37b4
--- /dev/null
+++ b/lib/ypxfrd.h
@@ -0,0 +1,111 @@
+/* Copyright (c) 2000 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifndef _LIB_YPXFRD_H_
+#define _LIB_YPXFRD_H_
+
+#include <rpc/rpc.h>
+
+#define YPXFRBLOCK 32767
+
+enum xfrstat {
+ XFR_REQUEST_OK = 1,
+ XFR_DENIED = 2,
+ XFR_NOFILE = 3,
+ XFR_ACCESS = 4,
+ XFR_BADDB = 5,
+ XFR_READ_OK = 6,
+ XFR_READ_ERR = 7,
+ XFR_DONE = 8,
+ XFR_DB_ENDIAN_MISMATCH = 9,
+ XFR_DB_TYPE_MISMATCH = 10
+};
+typedef enum xfrstat xfrstat;
+
+enum xfr_db_type {
+ XFR_DB_ASCII = 1,
+ XFR_DB_BSD_HASH = 2,
+ XFR_DB_BSD_BTREE = 3,
+ XFR_DB_BSD_RECNO = 4,
+ XFR_DB_BSD_MPOOL = 5,
+ XFR_DB_BSD_NDBM = 6,
+ XFR_DB_GNU_GDBM = 7,
+ XFR_DB_DBM = 8,
+ XFR_DB_NDBM = 9,
+ XFR_DB_OPAQUE = 10,
+ XFR_DB_ANY = 11,
+ XFR_DB_UNKNOWN = 12,
+ XFR_DB_GNU_GDBM64 = 13,
+ XFR_DB_QDBM = 14,
+ XFR_DB_TC = 15
+};
+typedef enum xfr_db_type xfr_db_type;
+
+enum xfr_byte_order {
+ XFR_ENDIAN_BIG = 1,
+ XFR_ENDIAN_LITTLE = 2,
+ XFR_ENDIAN_ANY = 3
+};
+typedef enum xfr_byte_order xfr_byte_order;
+
+typedef char *xfrdomain;
+typedef char *xfrmap;
+typedef char *xfrmap_filename;
+
+struct ypxfr_mapname {
+ xfrmap xfrmap;
+ xfrdomain xfrdomain;
+ xfrmap_filename xfrmap_filename;
+ xfr_db_type xfr_db_type;
+ xfr_byte_order xfr_byte_order;
+};
+typedef struct ypxfr_mapname ypxfr_mapname;
+
+struct xfr {
+ bool_t ok;
+ union {
+ struct {
+ u_int xfrblock_buf_len;
+ char *xfrblock_buf_val;
+ } xfrblock_buf;
+ xfrstat xfrstat;
+ } xfr_u;
+};
+typedef struct xfr xfr;
+
+#define YPXFRD_FREEBSD_PROG 600100069
+#define YPXFRD_FREEBSD_VERS 1
+
+#define YPXFRD_GETMAP 1
+extern struct xfr *ypxfrd_getmap_1 (ypxfr_mapname *, CLIENT *);
+extern struct xfr *ypxfrd_getmap_1_svc (ypxfr_mapname *, struct svc_req *);
+extern void ypxfrd_freebsd_prog_1 (struct svc_req *, register SVCXPRT *);
+extern int ypxfrd_freebsd_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+extern bool_t xdr_xfrstat (XDR *, xfrstat*);
+extern bool_t xdr_xfr_db_type (XDR *, xfr_db_type*);
+extern bool_t xdr_xfr_byte_order (XDR *, xfr_byte_order*);
+extern bool_t xdr_xfrdomain (XDR *, xfrdomain*);
+extern bool_t xdr_xfrmap (XDR *, xfrmap*);
+extern bool_t xdr_xfrmap_filename (XDR *, xfrmap_filename*);
+extern bool_t xdr_xfrstat (XDR *, xfrstat*);
+extern bool_t xdr_xfr_db_type (XDR *, xfr_db_type*);
+extern bool_t xdr_xfr_byte_order (XDR *, xfr_byte_order*);
+extern bool_t xdr_ypxfr_mapname (XDR *, ypxfr_mapname*);
+extern bool_t xdr_xfr (XDR *, xfr*);
+
+#endif /* !_LIB_YPXFRD_H_ */
diff --git a/lib/ypxfrd.x b/lib/ypxfrd.x
new file mode 100644
index 0000000..1562021
--- /dev/null
+++ b/lib/ypxfrd.x
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 1995, 1996
+ * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This protocol definition file describes a file transfer
+ * system used to very quickly move NIS maps from one host to
+ * another. This is similar to what Sun does with their ypxfrd
+ * protocol, but it must be stressed that this protocol is _NOT_
+ * compatible with Sun's. There are a couple of reasons for this:
+ *
+ * 1) Sun's protocol is proprietary. The protocol definition is
+ * not freely available in any of the SunRPC source distributions,
+ * even though the NIS v2 protocol is.
+ *
+ * 2) The idea here is to transfer entire raw files rather than
+ * sending just the records. Sun uses ndbm for its NIS map files,
+ * while FreeBSD uses Berkeley DB. Both are hash databases, but the
+ * formats are incompatible, making it impossible for them to
+ * use each others' files. Even if FreeBSD adopted ndbm for its
+ * database format, FreeBSD/i386 is a little-endian OS and
+ * SunOS/SPARC is big-endian; ndbm is byte-order sensitive and
+ * not very smart about it, which means an attempt to read a
+ * database on a little-endian box that was created on a big-endian
+ * box (or vice-versa) can cause the ndbm code to eat itself.
+ * Luckily, Berkeley DB is able to deal with this situation in
+ * a more graceful manner.
+ *
+ * While the protocol is incompatible, the idea is the same: we just open
+ * up a TCP pipe to the client and transfer the raw map database
+ * from the master server to the slave. This is many times faster than
+ * the standard yppush/ypxfr transfer method since it saves us from
+ * having to recreate the map databases via the DB library each time.
+ * For example: creating a passwd database with 30,000 entries with yp_mkdb
+ * can take a couple of minutes, but to just copy the file takes only a few
+ * seconds.
+ */
+
+/* cribbed from yp.x */
+const _YPMAXRECORD = 1024;
+const _YPMAXDOMAIN = 64;
+const _YPMAXMAP = 64;
+const _YPMAXPEER = 64;
+
+/* Suggested default -- not necesarrily the one used. */
+const YPXFRBLOCK = 32767;
+
+/*
+ * Possible return codes from the remote server.
+ */
+enum xfrstat {
+ XFR_REQUEST_OK = 1, /* Transfer request granted */
+ XFR_DENIED = 2, /* Transfer request denied */
+ XFR_NOFILE = 3, /* Requested map file doesn't exist */
+ XFR_ACCESS = 4, /* File exists, but I couldn't access it */
+ XFR_BADDB = 5, /* File is not a hash database */
+ XFR_READ_OK = 6, /* Block read successfully */
+ XFR_READ_ERR = 7, /* Read error during transfer */
+ XFR_DONE = 8, /* Transfer completed */
+ XFR_DB_ENDIAN_MISMATCH = 9, /* Database byte order mismatch */
+ XFR_DB_TYPE_MISMATCH = 10 /* Database type mismatch */
+};
+
+/*
+ * Database type specifications. The client can use this to ask
+ * the server for a particular type of database or just take whatever
+ * the server has to offer.
+ */
+enum xfr_db_type {
+ XFR_DB_ASCII = 1, /* Flat ASCII text */
+ XFR_DB_BSD_HASH = 2, /* Berkeley DB, hash method */
+ XFR_DB_BSD_BTREE = 3, /* Berkeley DB, btree method */
+ XFR_DB_BSD_RECNO = 4, /* Berkeley DB, recno method */
+ XFR_DB_BSD_MPOOL = 5, /* Berkeley DB, mpool method */
+ XFR_DB_BSD_NDBM = 6, /* Berkeley DB, hash, ndbm compat */
+ XFR_DB_GNU_GDBM = 7, /* GNU GDBM, 32 bit platforms */
+ XFR_DB_DBM = 8, /* Old, deprecated dbm format */
+ XFR_DB_NDBM = 9, /* ndbm format (used by Sun's NISv2) */
+ XFR_DB_OPAQUE = 10, /* Mystery format -- just pass along */
+ XFR_DB_ANY = 11, /* I'll take any format you've got */
+ XFR_DB_UNKNOWN = 12, /* Unknown format */
+ XFR_DB_GNU_GDBM64 = 13, /* GNU GDBM, 64 bit platforms */
+ XFR_DB_QDBM = 14, /* QDBM */
+ XFR_DB_TC = 15 /* Tokyo Cabinet DB */s
+};
+
+/*
+ * Machine byte order specification. This allows the client to check
+ * that it's copying a map database from a machine of similar byte sex.
+ * This is necessary for handling database libraries that are fatally
+ * byte order sensitive.
+ *
+ * The XFR_ENDIAN_ANY type is for use with the Berkeley DB database
+ * formats; Berkeley DB is smart enough to make up for byte order
+ * differences, so byte sex isn't important.
+ */
+enum xfr_byte_order {
+ XFR_ENDIAN_BIG = 1, /* We want big endian */
+ XFR_ENDIAN_LITTLE = 2, /* We want little endian */
+ XFR_ENDIAN_ANY = 3 /* We'll take whatever you got */
+};
+
+typedef string xfrdomain<_YPMAXDOMAIN>;
+typedef string xfrmap<_YPMAXMAP>;
+typedef string xfrmap_filename<_YPMAXMAP>; /* actual name of map file */
+typedef enum xfrstat xfrstat;
+typedef enum xfr_db_type xfr_db_type;
+typedef enum xfr_byte_order xfr_byte_order;
+
+/*
+ * Ask the remote ypxfrd for a map using this structure.
+ * Note: we supply both a map name and a map file name. These are not
+ * the same thing. In the case of ndbm, maps are stored in two files:
+ * map.bykey.pag and may.bykey.dir. We may also have to deal with
+ * file extensions (on the off chance that the remote server is supporting
+ * multiple DB formats). To handle this, we tell the remote server both
+ * what map we want and, in the case of ndbm, whether we want the .dir
+ * or the .pag part. This name should not be a fully qualified path:
+ * it's up to the remote server to decide which directories to look in.
+ */
+struct ypxfr_mapname {
+ xfrmap xfrmap;
+ xfrdomain xfrdomain;
+ xfrmap_filename xfrmap_filename;
+ xfr_db_type xfr_db_type;
+ xfr_byte_order xfr_byte_order;
+};
+
+/* Read response using this structure. */
+union xfr switch (bool ok) {
+case TRUE:
+ opaque xfrblock_buf<>;
+case FALSE:
+ xfrstat xfrstat;
+};
+
+program YPXFRD_FREEBSD_PROG {
+ version YPXFRD_FREEBSD_VERS {
+ union xfr
+ YPXFRD_GETMAP(ypxfr_mapname) = 1;
+ } = 1;
+} = 600100069; /* 100069 + 60000000 -- 100069 is the Sun ypxfrd prog number */
diff --git a/lib/ypxfrd_xdr.c b/lib/ypxfrd_xdr.c
new file mode 100644
index 0000000..24b8e1f
--- /dev/null
+++ b/lib/ypxfrd_xdr.c
@@ -0,0 +1,110 @@
+/* Copyright (c) 1996, 1997, 1999, 2000 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ypxfrd.h"
+
+bool_t
+xdr_xfrstat (XDR *xdrs, xfrstat *objp)
+{
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_xfr_db_type (XDR *xdrs, xfr_db_type *objp)
+{
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_xfr_byte_order (XDR *xdrs, xfr_byte_order *objp)
+{
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_xfrdomain (XDR *xdrs, xfrdomain *objp)
+{
+ if (!xdr_string (xdrs, objp, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_xfrmap (XDR *xdrs, xfrmap *objp)
+{
+ if (!xdr_string (xdrs, objp, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_xfrmap_filename (XDR *xdrs, xfrmap_filename *objp)
+{
+ if (!xdr_string (xdrs, objp, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_ypxfr_mapname (XDR *xdrs, ypxfr_mapname *objp)
+{
+ if (!xdr_xfrmap (xdrs, &objp->xfrmap))
+ return FALSE;
+ if (!xdr_xfrdomain (xdrs, &objp->xfrdomain))
+ return FALSE;
+ if (!xdr_xfrmap_filename (xdrs, &objp->xfrmap_filename))
+ return FALSE;
+ if (!xdr_xfr_db_type (xdrs, &objp->xfr_db_type))
+ return FALSE;
+ if (!xdr_xfr_byte_order (xdrs, &objp->xfr_byte_order))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_xfr (XDR *xdrs, xfr *objp)
+{
+ if (!xdr_bool (xdrs, &objp->ok))
+ return FALSE;
+
+ switch (objp->ok)
+ {
+ case TRUE:
+ if (!xdr_bytes
+ (xdrs, (char **) &objp->xfr_u.xfrblock_buf.xfrblock_buf_val,
+ (u_int *) &objp->xfr_u.xfrblock_buf.xfrblock_buf_len, ~0))
+ return FALSE;
+ break;
+ case FALSE:
+ if (!xdr_xfrstat (xdrs, &objp->xfr_u.xfrstat))
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/m4/japhar_grep_cflags.m4 b/m4/japhar_grep_cflags.m4
new file mode 100644
index 0000000..5e9fbb3
--- /dev/null
+++ b/m4/japhar_grep_cflags.m4
@@ -0,0 +1,15 @@
+dnl
+dnl JAPHAR_GREP_CFLAGS(flag, cmd_if_missing, cmd_if_present)
+dnl
+dnl From Japhar. Report changes to japhar@hungry.com
+dnl
+AC_DEFUN([JAPHAR_GREP_CFLAGS],
+[case "$CFLAGS" in
+"$1" | "$1 "* | *" $1" | *" $1 "* )
+ ifelse($#, 3, [$3], [:])
+ ;;
+*)
+ $2
+ ;;
+esac
+])
diff --git a/m4/jh_path_xml_catalog.m4 b/m4/jh_path_xml_catalog.m4
new file mode 100644
index 0000000..dd01f16
--- /dev/null
+++ b/m4/jh_path_xml_catalog.m4
@@ -0,0 +1,54 @@
+# Checks the location of the XML Catalog
+# Usage:
+# JH_PATH_XML_CATALOG([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# Defines XMLCATALOG and XML_CATALOG_FILE substitutions
+AC_DEFUN([JH_PATH_XML_CATALOG],
+[
+ # check for the presence of the XML catalog
+ AC_ARG_WITH([xml-catalog],
+ AC_HELP_STRING([--with-xml-catalog=CATALOG],
+ [path to xml catalog to use]),,
+ [with_xml_catalog=/etc/xml/catalog])
+ jh_found_xmlcatalog=true
+ XML_CATALOG_FILE="$with_xml_catalog"
+ AC_SUBST([XML_CATALOG_FILE])
+ AC_MSG_CHECKING([for XML catalog ($XML_CATALOG_FILE)])
+ if test -f "$XML_CATALOG_FILE"; then
+ AC_MSG_RESULT([found])
+ else
+ jh_found_xmlcatalog=false
+ AC_MSG_RESULT([not found])
+ fi
+
+ # check for the xmlcatalog program
+ AC_PATH_PROG(XMLCATALOG, xmlcatalog, no)
+ if test "x$XMLCATALOG" = xno; then
+ jh_found_xmlcatalog=false
+ fi
+
+ if $jh_found_xmlcatalog; then
+ ifelse([$1],,[:],[$1])
+ else
+ ifelse([$2],,[AC_MSG_ERROR([could not find XML catalog])],[$2])
+ fi
+])
+
+# Checks if a particular URI appears in the XML catalog
+# Usage:
+# JH_CHECK_XML_CATALOG(URI, [FRIENDLY-NAME], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+AC_DEFUN([JH_CHECK_XML_CATALOG],
+[
+ AC_REQUIRE([JH_PATH_XML_CATALOG],[JH_PATH_XML_CATALOG(,[:])])dnl
+ AC_MSG_CHECKING([for ifelse([$2],,[$1],[$2]) in XML catalog])
+ if $jh_found_xmlcatalog && \
+ AC_RUN_LOG([$XMLCATALOG --noout "$XML_CATALOG_FILE" "$1" >&2]); then
+ AC_MSG_RESULT([found])
+ ifelse([$3],,,[$3
+])dnl
+ else
+ AC_MSG_RESULT([not found])
+ ifelse([$4],,
+ [AC_MSG_ERROR([could not find ifelse([$2],,[$1],[$2]) in XML catalog])],
+ [$4])
+ fi
+])
diff --git a/makedbm/Makefile.am b/makedbm/Makefile.am
new file mode 100644
index 0000000..906bef6
--- /dev/null
+++ b/makedbm/Makefile.am
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2000, 2001, 2003, 2007, 2016 Thorsten Kukuk <kukuk@linux-nis.org>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\" \
+ -DUSE_FQDN=@USE_FQDN@
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) \
+ -I$(srcdir) @TIRPC_CFLAGS@ @NSL_CFLAGS@
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = makedbm.8
+XMLS = makedbm.8.xml
+
+libexec_PROGRAMS = makedbm
+
+makedbm_SOURCES = makedbm.c
+
+makedbm_LDADD = @LIBDBM@ $(top_builddir)/lib/libyp.a @TIRPC_LIBS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/makedbm/makedbm.8 b/makedbm/makedbm.8
new file mode 100644
index 0000000..bb33e2c
--- /dev/null
+++ b/makedbm/makedbm.8
@@ -0,0 +1,109 @@
+.\" Title: makedbm
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/>
+.\" Date: 09/26/2007
+.\" Manual: NIS Reference Manual
+.\" Source: NIS Reference Manual
+.\"
+.TH "MAKEDBM" "8" "09/26/2007" "NIS Reference Manual" "NIS Reference Manual"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+makedbm - create or dump a ypserv database file
+.SH "SYNOPSIS"
+.HP 20
+\fB/usr/lib/yp/makedbm\fR [\-a | \-r] [\-b] [\-c] [\-s] [\-l] [\-i\ \fIYP_INPUT_NAME\fR] [\-o\ \fIYP_OUTPUT_NAME\fR] [\-m\ \fIYP_MASTER_NAME\fR] \fIinputfile\fR \fIdbname\fR
+.HP 20
+\fB/usr/lib/yp/makedbm\fR \-u\ \fIdbname\fR
+.HP 20
+\fB/usr/lib/yp/makedbm\fR \-c
+.HP 20
+\fB/usr/lib/yp/makedbm\fR \-\-version
+.SH "DESCRIPTION"
+.PP
+\fBmakedbm\fR
+takes the inputfile and converts it to a ypserv database file\. In the moment, GDBM is used as database\. Each line of the input file is converted to a single record\. All characters up to the first TAB or SPACE are the key, and the rest of the line is the data\.
+\fBmakedbm\fR
+does not treat `#\' as a special character\.
+.SH "OPTIONS"
+.PP
+\fB\-a\fR
+.RS 4
+Special support for mail aliases\. We couldn\'t use sendmail for it, since sendmail uses db, but ypserv gdbm as database format\.
+.RE
+.PP
+\fB\-b\fR
+.RS 4
+Insert the
+\fBYP_INTERDOMAIN\fR
+into the output\. This key causes
+\fBypserv\fR(8)
+to use
+\fBDNS\fR
+for host name and address lookups for hosts not found in the maps\.
+.RE
+.PP
+\fB\-c\fR
+.RS 4
+send a
+\fBYPPROC_CLEAR\fR
+to the local
+\fBypserv\fR(8)\. This causes ypserv to invalidate all cached entries\.
+.RE
+.PP
+\fB\-l\fR
+.RS 4
+Convert the keys of the given map to lower case\.
+.RE
+.PP
+\fB\-i\fR\fI YP_INPUT_NAME\fR
+.RS 4
+Create a special entry with the key
+\fBYP_INPUT_NAME\fR\.
+.RE
+.PP
+\fB\-m\fR\fI YP_MASTER_NAME\fR
+.RS 4
+Create a special entry with the key
+\fBYP_MASTER_NAME\fR\. If no master host name is specified,
+\fBYP_MASTER_NAME\fR
+will be set to the local host name\.
+.RE
+.PP
+\fB\-o\fR\fI YP_OUTPUT_NAME\fR
+.RS 4
+Create a special entry with the key
+\fBYP_OUTPUT_NAME\fR\.
+.RE
+.PP
+\fB\-r\fR
+.RS 4
+Handle `#\' as comment sign and remove the comment\.
+.RE
+.PP
+\fB\-s\fR
+.RS 4
+Secure map\. Accept connections from secure
+\fBNIS\fR
+networks only (reserved ports)\.
+.RE
+.PP
+\fB\-u\fR\fI dbname\fR
+.RS 4
+Dump a ypserv database file\. Prints out the file in text format, one entry per line, with a single space separating keys from values\.
+.RE
+.PP
+\fB\-\-no\-limit\-check\fR
+.RS 4
+Don\'t check for NIS key and data limit\.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBypserv\fR(8)
+.SH "AUTHOR"
+.PP
+
+\fBmakedbm\fR
+was written by Thorsten Kukuk <kukuk@linux\-nis\.org>\.
diff --git a/makedbm/makedbm.8.xml b/makedbm/makedbm.8.xml
new file mode 100644
index 0000000..6e51e92
--- /dev/null
+++ b/makedbm/makedbm.8.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='makedbm'>
+
+ <refmeta>
+ <refentrytitle>makedbm</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>makedbm</refname>
+ <refpurpose>create or dump a ypserv database file</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+ <refsynopsisdiv id='synopsis'>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/makedbm</command>
+ <group choice='opt'><arg choice='plain'>-a </arg><arg choice='plain'>-r </arg></group>
+ <arg choice='opt'>-b </arg>
+ <arg choice='opt'>-c </arg>
+ <arg choice='opt'>-s </arg>
+ <arg choice='opt'>-l </arg>
+ <arg choice='opt'>-i <replaceable>YP_INPUT_NAME</replaceable></arg>
+ <arg choice='opt'>-o <replaceable>YP_OUTPUT_NAME</replaceable></arg>
+ <arg choice='opt'>-m <replaceable>YP_MASTER_NAME</replaceable></arg>
+ <arg choice='plain'><replaceable>inputfile</replaceable></arg>
+ <arg choice='plain'><replaceable>dbname</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/makedbm</command>
+ <arg choice='plain'>-u <replaceable>dbname</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/makedbm</command>
+ <arg choice='plain'>-c </arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/makedbm</command>
+ <arg choice='plain'>--version </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><emphasis remap='B'>makedbm</emphasis>
+takes the inputfile and converts it to a ypserv database file. In the
+moment, GDBM is used as database. Each line of the input file is converted
+to a single record. All characters up to the first TAB or SPACE are the key,
+and the rest of the line is the data.
+<emphasis remap='B'>makedbm</emphasis>
+does not treat `#' as a special character.</para>
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-a</option></term>
+ <listitem>
+<para>Special support for mail aliases. We couldn't use sendmail for it, since
+sendmail uses db, but ypserv gdbm as database format.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-b</option></term>
+ <listitem>
+<para>Insert the
+<emphasis remap='B'>YP_INTERDOMAIN</emphasis>
+into the output. This key causes
+<citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+to use
+<emphasis remap='B'>DNS</emphasis>
+for host name and address lookups for hosts not found in the maps.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-c</option></term>
+ <listitem>
+<para>send a
+<emphasis remap='B'>YPPROC_CLEAR</emphasis>
+to the local
+<citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+This causes ypserv to invalidate all cached entries.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-l</option></term>
+ <listitem>
+<para>Convert the keys of the given map to lower case.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-i</option><replaceable> YP_INPUT_NAME</replaceable></term>
+ <listitem>
+<para>Create a special entry with the key
+<emphasis remap='B'>YP_INPUT_NAME</emphasis>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-m</option><replaceable> YP_MASTER_NAME</replaceable></term>
+ <listitem>
+<para>Create a special entry with the key
+<emphasis remap='B'>YP_MASTER_NAME</emphasis>.
+If no master host name is specified,
+<emphasis remap='B'>YP_MASTER_NAME</emphasis>
+will be set to the local host name.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-o</option><replaceable> YP_OUTPUT_NAME</replaceable></term>
+ <listitem>
+<para>Create a special entry with the key
+<emphasis remap='B'>YP_OUTPUT_NAME</emphasis>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-r</option></term>
+ <listitem>
+<para>Handle `#' as comment sign and remove the comment.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-s</option></term>
+ <listitem>
+<para>Secure map. Accept connections from secure
+<emphasis remap='B'>NIS</emphasis>
+networks only (reserved ports).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-u</option><replaceable> dbname</replaceable></term>
+ <listitem>
+<para>Dump a ypserv database file. Prints out the file in text format, one entry
+per line, with a single space separating keys from values.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--no-limit-check</option></term>
+ <listitem>
+<para>Don't check for NIS key and data limit.</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>
+ <command>makedbm</command> was written by
+ Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;.
+ </para>
+ </refsect1>
+</refentry>
+
diff --git a/makedbm/makedbm.c b/makedbm/makedbm.c
new file mode 100644
index 0000000..c69f3d7
--- /dev/null
+++ b/makedbm/makedbm.c
@@ -0,0 +1,758 @@
+/* Copyright (c) 1996-2006, 2011, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <alloca.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+
+#if defined (__NetBSD__) || (defined(__GLIBC__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0))
+/* <rpc/rpc.h> is missing the prototype */
+int callrpc (char *host, u_long prognum, u_long versnum, u_long procnum,
+ xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
+#endif
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+
+#if defined(HAVE_LIBGDBM)
+#include <gdbm.h>
+#elif defined(HAVE_LIBQDBM)
+#include <hovel.h>
+#endif
+
+#define ypdb_store gdbm_store
+#define YPDB_REPLACE GDBM_REPLACE
+#define ypdb_close gdbm_close
+static GDBM_FILE dbm;
+
+#elif defined (HAVE_NDBM)
+
+#include <ndbm.h>
+
+#define ypdb_store dbm_store
+#define YPDB_REPLACE DBM_REPLACE
+#define ypdb_close dbm_close
+static DBM *dbm;
+
+#elif defined (HAVE_LIBTC)
+
+#include <tcbdb.h>
+
+#define YPDB_REPLACE 1
+
+static TCBDB *dbm;
+
+static inline int
+ypdb_store(TCBDB *dbm, datum key, datum data, int mode)
+{
+ if (mode != YPDB_REPLACE)
+ return 1;
+
+ return !tcbdbput(dbm, key.dptr, key.dsize, data.dptr, data.dsize);
+}
+
+static inline void
+ypdb_close (TCBDB *dbm)
+{
+ tcbdbclose (dbm);
+ tcbdbdel (dbm);
+}
+
+#else
+
+#error "No database found or selected!"
+
+#endif
+
+static int lower = 0;
+
+static inline void
+write_data (datum key, datum data)
+{
+ if (ypdb_store (dbm, key, data, YPDB_REPLACE) != 0)
+ {
+ perror ("makedbm: dbm_store");
+ ypdb_close (dbm);
+ exit (1);
+ }
+}
+
+#ifdef HAVE_NDBM
+static char *
+strapp (const char *str1, const char *str2)
+{
+ char *buffer = alloca(strlen (str1) + strlen (str2) + 1);
+
+ strcpy (buffer, str1);
+ strcat (buffer, str2);
+
+ return strdup (buffer);
+}
+#endif
+
+static void
+create_file (char *fileName, char *dbmName, char *masterName,
+ char *domainName, char *inputName,
+ char *outputName, int aliases, int shortlines,
+ int b_flag, int s_flag, int remove_comments,
+ int check_limit)
+{
+ datum kdat, vdat;
+ char *key = NULL;
+ size_t keylen = 0;
+ char *filename = NULL;
+ FILE *input;
+ char orderNum[12];
+ struct timeval tv;
+ struct timezone tz;
+
+ input = strcmp (fileName, "-") ? fopen (fileName, "r") : stdin;
+ if (input == NULL)
+ {
+ fprintf (stderr, "makedbm: Cannot open %s\n", fileName);
+ exit (1);
+ }
+
+ filename = calloc (1, strlen (dbmName) + 3);
+ sprintf (filename, "%s~", dbmName);
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dbm = gdbm_open (filename, 0, GDBM_NEWDB | GDBM_FAST, 0600, NULL);
+#elif defined(HAVE_NDBM)
+ dbm = dbm_open (filename, O_CREAT | O_RDWR, 0600);
+#elif defined(HAVE_LIBTC)
+ dbm = tcbdbnew();
+ if (!tcbdbopen(dbm, filename, BDBOWRITER | BDBOCREAT))
+ {
+ tcbdbdel(dbm);
+ dbm = NULL;
+ }
+#endif
+ if (dbm == NULL)
+ {
+ fprintf (stderr, "makedbm: Cannot open %s\n", filename);
+ exit (1);
+ }
+
+ if (masterName && *masterName)
+ {
+ kdat.dptr = "YP_MASTER_NAME";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = masterName;
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ if (domainName && *domainName)
+ {
+ kdat.dptr = "YP_DOMAIN_NAME";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = domainName;
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ if (inputName && *inputName)
+ {
+ kdat.dptr = "YP_INPUT_NAME";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = inputName;
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ if (outputName && *outputName)
+ {
+ kdat.dptr = "YP_OUTPUT_NAME";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = outputName;
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ if (b_flag)
+ {
+ kdat.dptr = "YP_INTERDOMAIN";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = "";
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ if (s_flag)
+ {
+ kdat.dptr = "YP_SECURE";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = "";
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ if (aliases)
+ {
+ kdat.dptr = "@";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = "@";
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+ }
+
+ gettimeofday (&tv, &tz);
+ sprintf (orderNum, "%ld", (long) tv.tv_sec);
+ kdat.dptr = "YP_LAST_MODIFIED";
+ kdat.dsize = strlen (kdat.dptr);
+ vdat.dptr = orderNum;
+ vdat.dsize = strlen (vdat.dptr);
+ write_data (kdat, vdat);
+
+ while (!feof (input))
+ {
+ char *cptr;
+
+ ssize_t n = getline (&key, &keylen, input);
+ if (n < 1)
+ break;
+ if (key[n - 1] == '\n' || key[n - 1] == '\r')
+ key[n - 1] = '\0';
+ if (n > 1 && (key[n - 2] == '\n' || key[n - 2] == '\r'))
+ key[n - 2] = '\0';
+
+ if (remove_comments)
+ if ((cptr = strchr (key, '#')) != NULL)
+ {
+ *cptr = '\0';
+ --cptr;
+ while (*cptr == ' ' || *cptr == '\t')
+ {
+ *cptr = '\0';
+ --cptr;
+ }
+ }
+
+ if (strlen (key) == 0)
+ continue;
+
+ if (aliases)
+ {
+ int len;
+
+ len = strlen (key);
+ while (key[len - 1] == ' ' || key[len - 1] == '\t')
+ {
+ key[len - 1] = '\0';
+ --len;
+ }
+
+ while (key[len - 1] == ',')
+ {
+ char *nkey = NULL;
+ size_t nkeylen = 0;
+ if (getline (&nkey, &nkeylen, input) == -1)
+ break;
+
+ cptr = nkey;
+ while ((*cptr == ' ') || (*cptr == '\t'))
+ ++cptr;
+ if (strlen (key) + strlen (cptr) < keylen)
+ strcat (key, cptr);
+ else
+ {
+ keylen += nkeylen;
+ key = realloc (key, keylen);
+ if (key == NULL)
+ abort ();
+ strcat (key, cptr);
+ }
+
+ free (nkey);
+
+ if ((cptr = strchr (key, '\n')) != NULL)
+ *cptr = '\0';
+ len = strlen (key);
+ while (key[len - 1] == ' ' || key[len - 1] == '\t')
+ {
+ key[len - 1] = '\0';
+ len--;
+ }
+ }
+ if ((cptr = strchr (key, ':')) != NULL)
+ *cptr = ' ';
+ }
+ else
+ while (key[strlen (key) - 1] == '\\')
+ {
+ char *nkey;
+ size_t nkeylen = 0;
+ ssize_t n = getline (&nkey, &nkeylen, input);
+
+ if (n < 1)
+ break;
+ if (nkey[n - 1] == '\n' || nkey[n - 1] == '\r')
+ nkey[n - 1] = '\0';
+ if (n > 1 && (nkey[n - 2] == '\n' || nkey[n - 2] == '\r'))
+ nkey[n - 2] = '\0';
+
+ key[strlen (key) - 1] = '\0';
+
+ if (shortlines)
+ {
+ int len;
+
+ len = strlen (key);
+ key[len - 1] = '\0';
+ len--;
+ if ((key[len - 1] != ' ') && (key[len - 1] != '\t'))
+ strcat (key, " ");
+ cptr = nkey;
+ while ((*cptr == ' ') || (*cptr == '\t'))
+ ++cptr;
+ if (len + 1 + strlen (cptr) < keylen)
+ strcat (key, cptr);
+ else
+ {
+ keylen += nkeylen;
+ key = realloc (key, keylen);
+ if (key == NULL)
+ abort ();
+ strcat (key, nkey);
+ }
+ }
+ else
+ {
+ keylen += nkeylen;
+ key = realloc (key, keylen);
+ if (key == NULL)
+ abort ();
+ strcat (key, nkey);
+ }
+ free (nkey);
+
+ if ((cptr = strchr (key, '\n')) != NULL)
+ *cptr = '\0';
+ }
+
+ cptr = key;
+
+ /* Hack for spaces in passwd, group and hosts keys. If we
+ find a <TAB> in the string, Makefile generates it to
+ seperate the key. This should be the standard, but is not
+ done for all maps (like bootparamd). */
+ if (strchr (cptr, '\t') == NULL)
+ {
+ while (*cptr && *cptr != '\t' && *cptr != ' ')
+ ++cptr;
+ }
+ else
+ {
+ while (*cptr && *cptr != '\t')
+ ++cptr;
+ /* But a key should not end with a space. */
+ while (cptr[-1] == ' ')
+ --cptr;
+ }
+
+ *cptr++ = '\0';
+
+ while (*cptr == '\t' || *cptr == ' ')
+ ++cptr;
+
+ if (strlen (key) == 0)
+ {
+ if (strlen (cptr) != 0)
+ fprintf (stderr,
+ "makedbm: warning: malformed input data (ignored)\n");
+ }
+ else
+ {
+ int i;
+
+ if (check_limit && strlen (key) > YPMAXRECORD)
+ {
+ fprintf (stderr, "makedbm: warning: key too long: %s\n", key);
+ continue;
+ }
+ kdat.dsize = strlen (key);
+ kdat.dptr = key;
+
+ if (check_limit && strlen (cptr) > YPMAXRECORD)
+ {
+ fprintf (stderr, "makedbm: warning: data too long: %s\n", cptr);
+ continue;
+ }
+ vdat.dsize = strlen (cptr);
+ vdat.dptr = cptr;
+
+ if (lower)
+ for (i = 0; i < kdat.dsize; i++)
+ kdat.dptr[i] = tolower (kdat.dptr[i]);
+
+ write_data (kdat, vdat);
+ }
+ }
+
+ ypdb_close (dbm);
+#if defined(HAVE_NDBM)
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+ {
+ char *dbm_db = strapp (dbmName, ".db");
+ char *filedb = strapp (filename, ".db");
+
+ unlink (dbm_db);
+ rename (filedb, dbm_db);
+ }
+#else
+ {
+ char *dbm_pag = strapp (dbmName, ".pag");
+ char *dbm_dir = strapp (dbmName, ".dir");
+ char *filepag = strapp (filename, ".pag");
+ char *filedir = strapp (filename, ".dir");
+
+ unlink (dbm_pag);
+ unlink (dbm_dir);
+ rename (filepag, dbm_pag);
+ rename (filedir, dbm_dir);
+ }
+#endif
+#else
+ unlink (dbmName);
+#if defined(HAVE_LIBTC)
+ chmod(filename, S_IRUSR|S_IWUSR);
+#endif
+ rename (filename, dbmName);
+#endif
+ free (filename);
+
+ if (strcmp (fileName, "-") != 0)
+ fclose (input);
+}
+
+static void
+dump_file (char *dbmName)
+{
+ datum key, data;
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dbm = gdbm_open (dbmName, 0, GDBM_READER, 0600, NULL);
+#elif defined(HAVE_NDBM)
+ dbm = dbm_open (dbmName, O_RDONLY, 0600);
+#elif defined(HAVE_LIBTC)
+ dbm = tcbdbnew();
+ if (!tcbdbopen (dbm, dbmName, BDBOREADER | BDBONOLCK))
+ {
+ tcbdbdel(dbm);
+ dbm = NULL;
+ }
+#endif
+ if (dbm == NULL)
+ {
+ fprintf (stderr, "makedbm: Cannot open %s\n", dbmName);
+ fprintf (stderr, "makedbm: Consider rebuilding maps using ypinit\n");
+ exit (1);
+ }
+#if defined(HAVE_COMPAT_LIBGDBM)
+ for (key = gdbm_firstkey (dbm); key.dptr; key = gdbm_nextkey (dbm, key))
+ {
+ data = gdbm_fetch (dbm, key);
+ if (!data.dptr)
+ {
+ fprintf (stderr, "Error:\n");
+ perror (dbmName);
+ exit (1);
+ }
+ printf ("%.*s\t%.*s\n",
+ key.dsize, key.dptr,
+ data.dsize, data.dptr);
+ free (data.dptr);
+ }
+#elif defined(HAVE_NDBM)
+ key = dbm_firstkey (dbm);
+ while (key.dptr)
+ {
+ data = dbm_fetch (dbm, key);
+ if (!data.dptr)
+ {
+ fprintf (stderr, "Error:\n");
+ perror (dbmName);
+ exit (1);
+ }
+ printf ("%.*s\t%.*s\n",
+ key.dsize, key.dptr,
+ data.dsize, data.dptr);
+ key = dbm_nextkey (dbm);
+ }
+#elif defined(HAVE_LIBTC)
+ {
+ BDBCUR *cur;
+ cur = tcbdbcurnew (dbm);
+ if (tcbdbcurfirst (cur))
+ {
+ while ((key.dptr = tcbdbcurkey (cur, &key.dsize)) != NULL)
+ {
+ data.dptr = tcbdbcurval (cur, &data.dsize);
+ if (!data.dptr)
+ {
+ fprintf (stderr, "Error:\n");
+ perror (dbmName);
+ exit (1);
+ }
+
+ printf ("%.*s\t%.*s\n",
+ key.dsize, key.dptr,
+ data.dsize, data.dptr);
+
+ if (!tcbdbcurnext (cur))
+ break;
+ }
+ }
+ tcbdbcurdel (cur);
+ }
+#endif
+ ypdb_close (dbm);
+}
+
+static void
+send_clear (void)
+{
+ char in = 0;
+ char *out = NULL;
+ int stat;
+ if ((stat = callrpc ("localhost", YPPROG, YPVERS, YPPROC_CLEAR,
+ (xdrproc_t) xdr_void, &in,
+ (xdrproc_t) xdr_void, out)) != RPC_SUCCESS)
+ {
+ fprintf (stderr, "failed to send 'clear' to local ypserv: %s",
+ clnt_sperrno ((enum clnt_stat) stat));
+ }
+}
+
+static char *
+get_canonical_hostname (const char *hostname)
+{
+#if USE_FQDN
+ struct addrinfo hints, *res0, *res1;
+ int error;
+ char *host = NULL;
+
+ memset (&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+#if 0
+ hints.ai_flags = AI_CANONNAME; /* get the official name of the host */
+#endif
+
+ if ((error = getaddrinfo (hostname, NULL, &hints, &res0)))
+ {
+#if 0
+ printf ("getaddrinfo: %s\n", gai_strerror (error));
+#endif
+ return strdup (hostname);
+ }
+
+ res1 = res0;
+
+ while (res1)
+ {
+ char hostbuf[NI_MAXHOST];
+
+ if ((error = getnameinfo (res1->ai_addr, res1->ai_addrlen,
+ (char *)&hostbuf, sizeof (hostbuf),
+ NULL, 0, NI_NAMEREQD)) == 0)
+ {
+ host = strdup (hostbuf);
+ break;
+ }
+#if 0
+ else
+ printf ("getnameinfo: %s\n", gai_strerror (error));
+#endif
+
+ res1 = res1->ai_next;
+ }
+
+ if (host == NULL)
+ host = strdup (res0->ai_canonname);
+
+ freeaddrinfo (res0);
+
+ return host;
+#else
+ return strdup (hostname);
+#endif
+}
+
+
+static void
+Usage (int exit_code)
+{
+ fprintf (stderr, "usage: makedbm -u dbname\n");
+ fprintf (stderr, " makedbm [-a|-r] [-b] [-c] [-s] [-l] [-i YP_INPUT_NAME]\n");
+ fprintf (stderr, " [-o YP_OUTPUT_NAME] [-m YP_MASTER_NAME] inputfile dbname\n");
+ fprintf (stderr, " makedbm -c\n");
+ fprintf (stderr, " makedbm --version\n");
+ exit (exit_code);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *domainName = NULL;
+ char *inputName = NULL;
+ char *outputName = NULL;
+ char masterName[MAXHOSTNAMELEN + 1] = "";
+ int dump = 0;
+ int aliases = 0;
+ int shortline = 0;
+ int clear = 0;
+ int b_flag = 0;
+ int s_flag = 0;
+ int remove_comments = 0;
+ int check_limit = 1;
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, '\255'},
+ {"dump", no_argument, NULL, 'u'},
+ {"help", no_argument, NULL, 'h'},
+ {"usage", no_argument, NULL, 'h'},
+ {"secure", no_argument, NULL, 's'},
+ {"aliases", no_argument, NULL, 'a'},
+ {"send_clear", no_argument, NULL, 'c'},
+ {"remove-spaces", no_argument, NULL, '\254'},
+ {"remove-comments", no_argument, NULL, 'r'},
+ {"no-limit-check", no_argument, NULL, '\253'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "abcd:hi:lm:o:rsu", long_options, &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'a':
+ aliases++;
+ shortline++;
+ break;
+ case 'b':
+ b_flag++;
+ break;
+ case 'c':
+ clear++;
+ break;
+ case 'l':
+ lower++;
+ break;
+ case 'u':
+ dump++;
+ break;
+ case '\254':
+ shortline++;
+ break;
+ case 'r':
+ remove_comments++;
+ break;
+ case 's':
+ s_flag++;
+ break;
+ case 'd':
+ domainName = optarg;
+ break;
+ case 'i':
+ inputName = optarg;
+ break;
+ case 'o':
+ outputName = optarg;
+ break;
+ case 'm':
+ if (strlen (optarg) <= MAXHOSTNAMELEN)
+ strcpy (masterName, optarg);
+ else
+ fprintf (stderr, "hostname to long: %s\n", optarg);
+ break;
+ case '\253':
+ check_limit = 0;
+ break;
+ case '\255':
+ fprintf (stdout, "makedbm (%s) %s", PACKAGE, VERSION);
+ return 0;
+ case 'h':
+ Usage (0);
+ break;
+ case '?':
+ Usage (1);
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (dump)
+ {
+ if (argc < 1)
+ Usage (1);
+ else
+ dump_file (argv[0]);
+ }
+ else
+ {
+ if (clear && argc == 0)
+ {
+ send_clear ();
+ return 0;
+ }
+
+ if (argc < 2)
+ Usage (1);
+ else
+ {
+ if (strlen (masterName) == 0)
+ {
+ char *cp;
+
+ if (gethostname (masterName, sizeof (masterName)) < 0)
+ perror ("gethostname");
+
+ cp = get_canonical_hostname (masterName);
+ strncpy (masterName, cp, sizeof (masterName) -1);
+ }
+
+ create_file (argv[0], argv[1], masterName, domainName,
+ inputName, outputName, aliases, shortline,
+ b_flag, s_flag, remove_comments, check_limit);
+
+ if (clear)
+ send_clear ();
+ }
+ }
+
+ return 0;
+}
diff --git a/mknetid/Makefile.am b/mknetid/Makefile.am
new file mode 100644
index 0000000..4f63dd8
--- /dev/null
+++ b/mknetid/Makefile.am
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2000, 2001, 2003, 2006 Thorsten Kukuk <kukuk@suse.de>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+#
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\"
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) \
+ -I$(srcdir) @NSL_CFLAGS@ @TIRPC_CFLAGS@
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = mknetid.8
+XMLS = mknetid.8.xml
+
+libexec_PROGRAMS = mknetid
+
+noinst_HEADERS = mknetid.h
+
+mknetid_SOURCES = mknetid.c netid_hash.c
+
+mknetid_LDADD = $(top_builddir)/lib/libyp.a
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
+
diff --git a/mknetid/mknetid.8 b/mknetid/mknetid.8
new file mode 100644
index 0000000..6836e22
--- /dev/null
+++ b/mknetid/mknetid.8
@@ -0,0 +1,111 @@
+.\" Title: mknetid
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/>
+.\" Date: 09/26/2007
+.\" Manual: NIS Reference Manual
+.\" Source: NIS Reference Manual
+.\"
+.TH "MKNETID" "8" "09/26/2007" "NIS Reference Manual" "NIS Reference Manual"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+mknetid - generate data for netid map
+.SH "SYNOPSIS"
+.HP 20
+\fB/usr/lib/yp/mknetid\fR [\-q] [\-h\ \fIhosts\fR] [\-p\ \fIpasswd\fR] [\-g\ \fIgroup\fR] [\-d\ \fIdomain\fR] [\-n\ \fInetid\fR]
+.HP 20
+\fB/usr/lib/yp/mknetid\fR \-\-version
+.SH "DESCRIPTION"
+.PP
+\fBmknetid\fR
+generates the
+\fInetid\.byname\fR
+NIS map from the contents of the group(5), passwd(5), hosts(5) and netid files\. It checks for multiple entrys of netids and warn for them or filters them out\. It is only called by
+\fI/var/yp/Makefile\fR
+when rebuilding the NIS map\.
+.SH "OPTIONS"
+.PP
+\fB\-q\fR
+.RS 4
+This flag turns on \'quiet\' mode, don\'t print a warning message when finding an duplicate netid entry\.
+.RE
+.PP
+\fB\-h\fR\fI hosts\fR
+.RS 4
+The
+\fB\-h\fR
+flag can be used to specify the use of another hosts file than the default
+\fI/etc/hosts\fR\.
+.RE
+.PP
+\fB\-p\fR\fI passwd\fR
+.RS 4
+The
+\fB\-p\fR
+flag can be used to specify the use of another passwd file than the default
+\fI/etc/passwd\fR\.
+.RE
+.PP
+\fB\-g\fR\fI group\fR
+.RS 4
+The
+\fB\-g\fR
+flag can be used to specify the use of another group file than the default
+\fI/etc/group\fR\.
+.RE
+.PP
+\fB\-n\fR\fI netid\fR
+.RS 4
+The
+\fB\-n\fR
+flag can be used to specify the use of another netid file than the default
+\fI/etc/netid\fR\.
+.RE
+.PP
+\fB\-d\fR\fI domain\fR
+.RS 4
+The
+\fBmknetid\fR
+command uses the system domainname by default\. If it is not set or you whish to override it, you must use the
+\fB\-d\fR
+parameter\.
+.RE
+.PP
+\fB\-\-version\fR
+.RS 4
+Prints the version number
+.RE
+.SH "FILES"
+.PP
+\fI/etc/group\fR
+.RS 4
+groups file
+.RE
+.PP
+\fI/etc/hosts\fR
+.RS 4
+hosts database
+.RE
+.PP
+\fI/etc/netid\fR
+.RS 4
+netname database
+.RE
+.PP
+\fI/etc/passwd\fR
+.RS 4
+password file
+.RE
+.SH "SEE ALSO"
+.PP
+\fBpasswd\fR(8),
+\fBgroup\fR(5),
+\fBhosts\fR(5),
+\fBpasswd\fR(5)
+.SH "AUTHOR"
+.PP
+
+\fBmknetid\fR
+was written by Thorsten Kukuk <kukuk@linux\-nis\.org>\.
diff --git a/mknetid/mknetid.8.xml b/mknetid/mknetid.8.xml
new file mode 100644
index 0000000..5ea566b
--- /dev/null
+++ b/mknetid/mknetid.8.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='mknetid'>
+
+ <refmeta>
+ <refentrytitle>mknetid</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>mknetid</refname>
+ <refpurpose>generate data for netid map</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsynopsisdiv id='synopsis'>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/mknetid</command>
+ <arg choice='opt'>-q </arg>
+ <arg choice='opt'>-h <replaceable>hosts</replaceable></arg>
+ <arg choice='opt'>-p <replaceable>passwd</replaceable></arg>
+ <arg choice='opt'>-g <replaceable>group</replaceable></arg>
+ <arg choice='opt'>-d <replaceable>domain</replaceable></arg>
+ <arg choice='opt'>-n <replaceable>netid</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/mknetid</command>
+ <arg choice='plain'>--version </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><emphasis remap='B'>mknetid</emphasis>
+generates the <emphasis remap='I'>netid.byname</emphasis> NIS map from the contents of the
+group(5), passwd(5), hosts(5) and netid files. It checks for multiple
+entrys of netids and warn for them or filters them out. It is only
+called by
+<filename>/var/yp/Makefile</filename>
+when rebuilding the NIS map.</para>
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-q</option></term>
+ <listitem>
+<para>This flag turns on 'quiet' mode, don't print a warning message when
+finding an duplicate netid entry.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option><replaceable> hosts</replaceable></term>
+ <listitem>
+<para>The
+<option>-h</option>
+flag can be used to specify the use of another hosts file
+than the default <filename>/etc/hosts</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option><replaceable> passwd</replaceable></term>
+ <listitem>
+<para>The
+<option>-p</option>
+flag can be used to specify the use of another passwd file
+than the default <filename>/etc/passwd</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-g</option><replaceable> group</replaceable></term>
+ <listitem>
+<para>The
+<option>-g</option>
+flag can be used to specify the use of another group file
+than the default <filename>/etc/group</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-n</option><replaceable> netid</replaceable></term>
+ <listitem>
+<para>The
+<option>-n</option>
+flag can be used to specify the use of another netid file
+than the default <filename>/etc/netid</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-d</option><replaceable> domain</replaceable></term>
+ <listitem>
+<para>The
+<emphasis remap='B'>mknetid</emphasis>
+command uses the system domainname by default. If it is not set
+or you whish to override it, you must use the
+<option>-d</option>
+parameter.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--version</option></term>
+ <listitem>
+<para>Prints the version number</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='files'><title>FILES</title>
+<!-- .PD 0 -->
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><filename>/etc/group</filename></term>
+ <listitem>
+<para>groups file</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>/etc/hosts</filename></term>
+ <listitem>
+<para>hosts database</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>/etc/netid</filename></term>
+ <listitem>
+<para>netname database</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>/etc/passwd</filename></term>
+ <listitem>
+<para>password file</para>
+<!-- .PD -->
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>passwd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>group</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>hosts</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum></citerefentry></para>
+
+</refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>
+ <command>mknetid</command> was written by Thorsten Kukuk
+ &lt;kukuk@linux-nis.org&gt;.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/mknetid/mknetid.c b/mknetid/mknetid.c
new file mode 100644
index 0000000..d43978e
--- /dev/null
+++ b/mknetid/mknetid.c
@@ -0,0 +1,316 @@
+/* Copyright (c) 1996, 1999, 2001, 2002, 2009, 2012, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+/* mknetid - generate netid.byname map. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "mknetid.h"
+
+static int quiet_flag = 0;
+
+char *
+xstrtok (char *cp, int delim)
+{
+ static char *str = NULL;
+
+ if (cp)
+ str = cp;
+
+ if (*str == '\0')
+ return NULL;
+
+ cp = str;
+
+ if (delim == ' ')
+ while (*str && (!isspace (*str)))
+ str++;
+ else
+ while (*str && *str != delim)
+ str++;
+
+ if (*str)
+ *str++ = '\0';
+
+ return cp;
+}
+
+static void
+Usage (int exitcode)
+{
+ fputs ("Usage: mknetid [-q] [-h hosts] [-p passwd] [-g group] [-d domain] [-n netid]\n",
+ stderr);
+ fputs ("Usage: mknetid --version\n", stderr);
+ exit (exitcode);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *line = NULL;
+ size_t length = 0;
+ char *pwname = "/etc/passwd";
+ char *grpname = "/etc/group";
+ char *hostname = "/etc/hosts";
+ char *netidname = "/etc/netid";
+ char *domain = NULL;
+ char domainbuf[1024];
+ FILE *file;
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, 'v'},
+ {"host", required_argument, NULL, 'h'},
+ {"group", required_argument, NULL, 'g'},
+ {"passwd", required_argument, NULL, 'p'},
+ {"netid", required_argument, NULL, 'n'},
+ {"domain", required_argument, NULL, 'd'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"help", no_argument, NULL, 'u'},
+ {"usage", no_argument, NULL, 'u'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "uvqh:g:p:d:n:", long_options, &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'q':
+ quiet_flag = 1;
+ break;
+ case 'h':
+ hostname = optarg;
+ break;
+ case 'g':
+ grpname = optarg;
+ break;
+ case 'p':
+ pwname = optarg;
+ break;
+ case 'n':
+ netidname = optarg;
+ break;
+ case 'd':
+ domain = optarg;
+ break;
+ case 'u':
+ Usage (0);
+ break;
+ case 'v':
+ fprintf (stderr, "mknetid (%s) %s\n", PACKAGE, VERSION);
+ exit (0);
+ default:
+ Usage (1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0)
+ Usage (1);
+
+ if (domain == NULL)
+ {
+ if (getdomainname (domainbuf, sizeof (domainbuf)) != 0)
+ {
+ fprintf (stderr, "YPPUSH: Cannot get default domain\n");
+ return 1;
+ }
+ else
+ domain = domainbuf;
+ }
+
+ if ((file = fopen (pwname, "r")) == NULL)
+ {
+ fprintf (stderr, "ERROR: Can't open %s\n", pwname);
+ exit (1);
+ }
+
+ while (!feof (file))
+ {
+ ssize_t n = getline (&line, &length, file);
+ if (n < 1)
+ break;
+
+ if (line[0] != '+' && line[0] != '-')
+ {
+
+ char *ptr, *key, *uid, *gid;
+ char *err_line = strdup (line);
+
+ key = xstrtok (line, ':');
+ ptr = xstrtok (NULL, ':');
+ uid = xstrtok (NULL, ':');
+ gid = xstrtok (NULL, ':');
+
+ if (key == NULL || ptr == NULL ||
+ uid == NULL || gid == NULL)
+ {
+ int n = strlen (err_line);
+
+ if (err_line[n - 1] == '\n')
+ err_line[n - 1] = '\0';
+
+ if (strlen (err_line) > 0)
+ fprintf (stderr, "WARNING: bad netid entry: '%s'\n",
+ err_line);
+ free (err_line);
+ continue;
+ }
+
+ free (err_line);
+
+ if (insert_user (key, domain, uid, gid) < 0)
+ if (!quiet_flag)
+ fprintf (stderr,
+ "WARNING: unix.%s@%s multiply defined, ignore new one\n",
+ uid, domain);
+ }
+ }
+ fclose (file);
+
+ if ((file = fopen (grpname, "r")) == NULL)
+ {
+ fprintf (stderr, "ERROR: Can't open %s\n", grpname);
+ exit (1);
+ }
+
+ while (!feof (file))
+ {
+ ssize_t n = getline (&line, &length, file);
+ if (n < 1)
+ break;
+
+ if (line[n - 1] == '\n')
+ {
+ if(n < 2)
+ continue; /* empty line */
+ line[n - 1] = '\0';
+ }
+
+ if (line[0] != '+' && line[0] != '-')
+ {
+ char *grpname, *ptr, *gid, *user;
+
+ grpname = xstrtok (line, ':');
+ ptr = xstrtok (NULL, ':');
+ gid = xstrtok (NULL, ':');
+ if(grpname && ptr && gid)
+ length -= gid - line;
+ else
+ {
+ fprintf (stderr, "ERROR: bad format of group \"%s\".\n",
+ grpname);
+ exit (1);
+ }
+ user = xstrtok (NULL, ',');
+ while (user != NULL) {
+ length = length - strlen(user) - 1;
+ if (add_group (user, gid) < 0)
+ if (!quiet_flag)
+ fprintf (stderr, "WARNING: unknown user \"%s\" in group \"%s\".\n",
+ user, grpname);
+ if (length > 0)
+ user = xstrtok (user + strlen(user) + 1, ',');
+ else
+ user = NULL;
+ }
+ }
+ }
+ fclose (file);
+
+ if ((file = fopen (hostname, "r")) == NULL)
+ {
+ fprintf (stderr, "ERROR: Can't open %s\n", hostname);
+ exit (1);
+ }
+
+ while (!feof (file))
+ {
+ ssize_t n = getline (&line, &length, file);
+ if (n < 1)
+ break;
+
+ if (line[0] != '#')
+ {
+ char *host;
+
+ (void)xstrtok (line, ' ');
+ host = xstrtok (NULL, ' ');
+ while (host != NULL && strlen (host) == 0)
+ host = xstrtok (NULL, ' ');
+
+ if (host != NULL)
+ if (insert_host (host, domain) < 0)
+ if (!quiet_flag)
+ fprintf (stderr, "WARNING: unix.%s@%s multiply defined, ignore new one\n",
+ host, domain);
+ }
+ }
+
+ fclose (file);
+
+ print_table ();
+
+ /*
+ ** If /etc/netid does not exist, ignore it
+ */
+ if ((file = fopen (netidname, "r")) != NULL)
+ {
+ while (!feof (file))
+ {
+ ssize_t n = getline (&line, &length, file);
+ if (n < 1)
+ break;
+
+ if (line[0] != '#')
+ {
+ int n = strlen (line);
+
+ if (line[n - 1] == '\n')
+ line[n - 1] = '\0';
+ if (strpbrk (line, " \t") == NULL)
+ {
+ if (strlen (line) > 0)
+ fprintf (stderr,
+ "WARNING: bad netid entry: '%s'\n",
+ line);
+ }
+ else
+ printf ("%s\n", line);
+ }
+ }
+ fclose (file);
+ }
+
+ free (line);
+ return 0;
+}
diff --git a/mknetid/mknetid.h b/mknetid/mknetid.h
new file mode 100644
index 0000000..c2b628e
--- /dev/null
+++ b/mknetid/mknetid.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 1996, 1999, 2001, 2009 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifndef _MKNETID_H_
+#define _MKNETID_H_
+
+extern char *xstrtok (char *cp, int delim);
+extern int insert_user(const char *key, const char *domain,
+ const char *uid, const char *gid);
+extern int insert_host(const char *host, const char *domain);
+extern void print_table(void);
+extern int add_group(const char *key, const char *grp);
+
+#endif
diff --git a/mknetid/netid_hash.c b/mknetid/netid_hash.c
new file mode 100644
index 0000000..3b112e1
--- /dev/null
+++ b/mknetid/netid_hash.c
@@ -0,0 +1,266 @@
+/* Copyright (c) 1996, 1999, 2001, 2009 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#include "mknetid.h"
+
+#define TABLESIZE 997 /*Should be a prime */
+
+typedef struct hash_liste {
+ char *key;
+ char *val;
+ struct hash_liste *next;
+} hash_liste_t;
+
+static inline void *
+xmalloc (unsigned long size)
+{
+ void *ptr;
+
+ ptr = malloc (size);
+
+ if (ptr == NULL)
+ {
+ fprintf (stderr, "ERROR: out of memory!\n");
+ exit (1);
+ }
+
+ return ptr;
+}
+
+static hash_liste_t *user_liste[TABLESIZE];
+static hash_liste_t *host_liste[TABLESIZE];
+static int first = 1;
+static char uid_liste[65535];
+
+static void
+init_table (void)
+{
+ first = 0;
+
+ memset (user_liste, 0, sizeof (user_liste));
+ memset (host_liste, 0, sizeof (host_liste));
+ memset (uid_liste, 0, sizeof (uid_liste));
+}
+
+int
+insert_user (const char *key, const char *domain,
+ const char *uid, const char *gid)
+{
+ long hkey, id;
+ size_t i;
+
+ if (first)
+ init_table ();
+
+ id = atol (uid);
+
+ if (id > 65534)
+ return -2;
+
+ if (uid_liste[id] == 1)
+ return -1;
+ else
+ uid_liste[id] = 1;
+
+ hkey = 0;
+ for (i = 0; i < strlen (key); i++)
+ hkey = (256 * hkey + key[i]) % TABLESIZE;
+
+ if (user_liste[hkey] != NULL)
+ {
+ hash_liste_t *work, *ptr;
+
+ work = user_liste[hkey]->next;
+ ptr = user_liste[hkey];
+
+ while (work != NULL)
+ {
+ ptr = work;
+ work = work->next;
+ }
+
+ ptr->next = xmalloc (sizeof (hash_liste_t));
+ work = ptr->next;
+ work->next = NULL;
+ work->key = xmalloc (strlen (key) + 1);
+ strcpy (work->key, key);
+ work->val =
+ xmalloc (strlen (domain) + 2 * strlen (uid) + strlen (gid) + 100);
+ sprintf (work->val, "unix.%s@%s\t%s:%s", uid, domain, uid, gid);
+ }
+ else
+ {
+ user_liste[hkey] = xmalloc (sizeof (hash_liste_t));
+ user_liste[hkey]->key = xmalloc (strlen (key) + 1);
+ strcpy (user_liste[hkey]->key, key);
+ user_liste[hkey]->next = NULL;
+ user_liste[hkey]->val =
+ xmalloc (strlen (domain) + 2 * strlen (uid) + strlen (gid) + 10);
+ sprintf (user_liste[hkey]->val, "unix.%s@%s\t%s:%s", uid, domain, uid,
+ gid);
+ }
+ return 0;
+}
+
+int
+add_group (const char *key, const char *grp)
+{
+ hash_liste_t *work;
+ long hkey;
+ size_t i;
+
+ if (first)
+ init_table ();
+
+ hkey = 0;
+ for (i = 0; i < strlen (key); i++)
+ hkey = (256 * hkey + key[i]) % TABLESIZE;
+
+ if (user_liste[hkey] == NULL)
+ return -1;
+ else if (strcmp (user_liste[hkey]->key, key) != 0)
+ {
+ if (user_liste[hkey]->next == NULL)
+ return -1;
+ else
+ {
+ work = user_liste[hkey]->next;
+ while (work != NULL)
+ if (strcmp (work->key, key) == 0)
+ break;
+ else
+ work = work->next;
+ if (work == NULL)
+ return -1;
+ }
+ }
+ else
+ work = user_liste[hkey];
+
+ if (strcmp (key, work->key) == 0)
+ {
+ char *ptr, *tmp;
+
+ tmp = strdup (work->val);
+ ptr = xstrtok (tmp, ':');
+
+ while ((ptr = xstrtok (NULL, ',')) != NULL)
+ if (strcmp (ptr, grp) == 0)
+ return 0;
+
+ ptr = xmalloc (strlen (work->val) + strlen (grp) + 5);
+ strcpy (ptr, work->val);
+ strcat (ptr, ",");
+ strcat (ptr, grp);
+ free (work->val);
+ work->val = ptr;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+insert_host (const char *host, const char *domain)
+{
+ long hkey;
+ size_t i;
+
+ if (first)
+ init_table ();
+
+ hkey = 0;
+ for (i = 0; i < strlen (host); i++)
+ hkey = (256 * hkey + host[i]) % TABLESIZE;
+
+ if (host_liste[hkey] != NULL)
+ {
+ if (strcmp (host_liste[hkey]->key, host) == 0)
+ return -1;
+ else
+ {
+ hash_liste_t *work, *ptr;
+
+ work = host_liste[hkey]->next;
+ ptr = host_liste[hkey];
+
+ while (work != NULL)
+ if (strcmp (work->key, host) == 0)
+ return -1;
+ else
+ {
+ ptr = work;
+ work = work->next;
+ }
+
+ ptr->next = xmalloc (sizeof (hash_liste_t));
+ work = ptr->next;
+ work->next = NULL;
+ work->key = strdup (host);
+ work->val = xmalloc (strlen (host) * 2 + strlen (domain) + 20);
+ sprintf (work->val, "unix.%s@%s\t0:%s", host, domain, host);
+ }
+ }
+ else
+ {
+ host_liste[hkey] = xmalloc (sizeof (hash_liste_t));
+ host_liste[hkey]->key = strdup (host);
+ host_liste[hkey]->next = NULL;
+ host_liste[hkey]->val =
+ xmalloc (strlen (host) * 2 + strlen (domain) + 20);
+ sprintf (host_liste[hkey]->val, "unix.%s@%s\t0:%s", host, domain, host);
+ }
+ return 0;
+}
+
+void
+print_table ()
+{
+ hash_liste_t *work;
+ unsigned long i;
+
+ for (i = 0; i < TABLESIZE; i++)
+ {
+ work = user_liste[i];
+ while (work != NULL)
+ {
+ printf ("%s\n", work->val);
+ work = work->next;
+ }
+ }
+
+ for (i = 0; i < TABLESIZE; i++)
+ {
+ work = host_liste[i];
+ while (work != NULL)
+ {
+ printf ("%s\n", work->val);
+ work = work->next;
+ }
+ }
+}
diff --git a/revnetgroup/Makefile.am b/revnetgroup/Makefile.am
new file mode 100644
index 0000000..b31f4e2
--- /dev/null
+++ b/revnetgroup/Makefile.am
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2000, 2001, 2003, 2006, 2014 Thorsten Kukuk <kukuk@suse.de>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+#
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\"
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) \
+ -I$(srcdir) @NSL_CFLAGS@ @TIRPC_CFLAGS@
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = revnetgroup.8
+XMLS = revnetgroup.8.xml
+
+libexec_PROGRAMS = revnetgroup
+
+noinst_HEADERS = hash.h
+
+revnetgroup_SOURCES = revnetgroup.c getnetgrent.c hash.c
+
+revnetgroup_LDADD = $(top_builddir)/lib/libyp.a
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/revnetgroup/getnetgrent.c b/revnetgroup/getnetgrent.c
new file mode 100644
index 0000000..ab717e1
--- /dev/null
+++ b/revnetgroup/getnetgrent.c
@@ -0,0 +1,272 @@
+/* Copyright (C) 1995 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The GNU C Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU C Library; see the file COPYING.LIB. If
+ * not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335, USA.
+ *
+ * Author: Swen Thuemmler <swen@uni-paderborn.de>
+ *
+ * Changes for the use with revnetgroup:
+ * Thorsten Kukuk <kukuk@suse.de>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+
+#include "hash.h"
+
+extern hash_t *input;
+
+void rev_setnetgrent (const char *);
+void rev_endnetgrent (void);
+int rev_getnetgrent (char **, char **, char **);
+
+struct netgrentry
+ {
+ char *host;
+ char *user;
+ char *domain;
+ };
+
+
+struct netgrlist
+ {
+ int maxmembers;
+ int members;
+ struct netgrentry *list;
+ };
+
+
+static void rev_expand_netgroupentry (const char *, struct netgrlist *);
+static void rev_parse_entry (char *, char *, struct netgrlist *);
+static void rev_netgr_free (struct netgrlist *);
+static struct netgrlist list = {0, 0, NULL};
+static int first = 1;
+static char *netgroup = NULL;
+
+static char *
+search_netgroup (hash_t ** liste, const char *key)
+{
+ hash_t *work;
+
+ work = *liste;
+
+ while ((work != NULL) && (0 != strcmp (work->key, key)))
+ work = work->next;
+
+ if (work != NULL)
+ return work->val;
+ else
+ return NULL;
+}
+
+void
+rev_setnetgrent (const char *netgr)
+{
+ if (NULL == netgroup || 0 != strcmp (netgroup, netgr))
+ {
+ rev_endnetgrent ();
+ netgroup = strdup (netgr);
+ rev_expand_netgroupentry (netgr, &list);
+ }
+ first = 1;
+}
+
+void
+rev_endnetgrent (void)
+{
+ if (NULL != netgroup)
+ {
+ free (netgroup);
+ netgroup = NULL;
+ }
+
+ if (NULL != list.list)
+ rev_netgr_free (&list);
+ first = 1;
+}
+
+int
+rev_getnetgrent (char **machinep, char **userp, char **domainp)
+{
+ static int current = 0;
+ struct netgrentry *entry;
+
+ if (1 == first)
+ current = first = 0;
+ else
+ current++;
+
+ if (current < list.members)
+ {
+ entry = &list.list[current];
+ *machinep = entry->host;
+ *userp = entry->user;
+ *domainp = entry->domain;
+ return 1;
+ }
+ return 0;
+}
+
+static void
+rev_netgr_free (struct netgrlist *list)
+{
+ int i;
+ for (i = 0; i < list->members; i++)
+ {
+ free (list->list[i].host);
+ free (list->list[i].user);
+ free (list->list[i].domain);
+ }
+ free (list->list);
+ list->maxmembers = 0;
+ list->members = 0;
+ list->list = NULL;
+}
+
+static void
+rev_expand_netgroupentry (const char *netgr, struct netgrlist *list)
+{
+ char *outval = NULL;
+ char *outptr = NULL;
+ char *start = NULL;
+ char *end = NULL;
+ char *realend = NULL;
+
+ if (*netgr == '\0')
+ return;
+
+ outptr = search_netgroup (&input, netgr);
+ if (outptr == NULL)
+ return;
+
+ /* make a copy to work with */
+ outval = strdup (outptr);
+ if (outval == NULL)
+ {
+ fprintf (stderr, "ERROR: could not allocate enough memory! [%s|%d]\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ /* outval enthaelt den Eintrag. Zuerst Leerzeichen ueberlesen */
+ start = outval;
+ realend = start + strlen (outval);
+ while (isspace (*start) && start < realend)
+ start++;
+
+ while (start < realend)
+ {
+ if ('(' == *start) /* Eintrag gefunden */
+ {
+ /* this a tuple... */
+ end = strchr (start, ')');
+ if (NULL == end)
+ {
+ free (outval);
+ return;
+ }
+
+ /* add the entry to the list? */
+ rev_parse_entry (start + 1, end, list);
+ }
+ else
+ {
+ /* okay, this should be a group (ie. not
+ a tuple... */
+ end = start + 1;
+
+ while ((*end != '\0') && (!isspace (*end)))
+ end++;
+
+ *end = '\0';
+
+ /* recursion */
+ rev_expand_netgroupentry (start, list);
+ }
+
+ /* skip to the next entry */
+ start = end + 1;
+
+ if (end == realend)
+ break;
+
+ assert (start <= realend);
+
+ while ((start < realend) && (isspace (*start)))
+ start++;
+ }
+
+ /* free the copy */
+ free (outval);
+}
+
+static void
+rev_parse_entry (char *start, char *end, struct netgrlist *list)
+{
+ char *host, *user, *domain;
+ struct netgrentry *entry;
+ /* First split entry into fields. Return, when finding malformed entry */
+ host = start;
+ start = strchr (host, ',');
+ if (NULL == start || start >= end)
+ return;
+ *start = '\0';
+ user = start + 1;
+ start = strchr (user, ',');
+ if (NULL == start || start >= end)
+ return;
+ *start = '\0';
+ domain = start + 1;
+ if (start > end)
+ return;
+ *end = '\0';
+ /* Entry is correctly formed, put it into the list */
+ if (0 == list->maxmembers)
+ {
+ list->list = malloc (10 * sizeof (struct netgrentry));
+ if (NULL != list->list)
+ list->maxmembers = 10;
+ else
+ return;
+ }
+
+ if (list->members == list->maxmembers)
+ {
+ list->list = realloc (list->list,
+ (list->maxmembers + 10) * sizeof (struct netgrentry));
+ if (NULL == list->list)
+ {
+ list->maxmembers = 0;
+ list->members = 0;
+ return;
+ }
+ list->maxmembers += 10;
+ }
+ /*
+ * FIXME: this will not handle entries of the form ( asdf, sdfa , asdf )
+ * (note the spaces). This should be handled better!
+ */
+ entry = &list->list[list->members];
+ entry->user = ('\0' == *user) ? NULL : strdup (user);
+ entry->host = ('\0' == *host) ? NULL : strdup (host);
+ entry->domain = ('\0' == *domain) ? NULL : strdup (domain);
+ list->members++;
+ return;
+}
diff --git a/revnetgroup/hash.c b/revnetgroup/hash.c
new file mode 100644
index 0000000..bd38f2b
--- /dev/null
+++ b/revnetgroup/hash.c
@@ -0,0 +1,291 @@
+/*
+** hash.c - functions for a hash table.
+**
+** Copyright (c) 1996, 1997, 1999 Thorsten Kukuk
+**
+** This file is part of the NYS YP Server.
+**
+** The YP Server is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License
+** version 2 as published by the Free Software Foundation.
+**
+** The NYS YP Server 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 the NYS YP Server; see the file COPYING. If
+** not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+** Suite 500, Boston, MA 02110-1335, USA.
+**
+** Author: Thorsten Kukuk <kukuk@suse.de>
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hash.h"
+#include <assert.h>
+
+#define TABLESIZE 997 /*Should be a prime */
+
+/*
+ * hash_malloc(void)
+ *
+ * Initialize a new hash table.
+ */
+hash_t **
+hash_malloc (void)
+{
+ hash_t **work = NULL;
+ int i = 0;
+
+ work = malloc (sizeof (hash_t *) * TABLESIZE);
+ if (work == NULL)
+ {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ for (i = 0; i < TABLESIZE; i++)
+ work[i] = NULL;
+
+ return work;
+}
+
+/*
+ * hash_calc_key(const char* key)
+ *
+ * Calculates the key, returns it.
+ */
+static inline long
+hash_calc_key (const char *key)
+{
+ long hkey = 0;
+ int length = strlen (key);
+ int i = -1;
+
+ for (i = 0; i < length; i++)
+ hkey = (256 * hkey + key[i]) % TABLESIZE;
+
+ assert (hkey < TABLESIZE);
+ return hkey;
+}
+
+
+/*
+ * hash_insert(hash_t **table, const char*, const char*)
+ *
+ * Complete re-write, to insert item into head of list
+ * at it's entry in the table.
+ */
+int
+hash_insert (hash_t **table, const char *key, const char *val)
+{
+ long hkey = -1;
+ hash_t *work = NULL;
+
+ assert (table != NULL);
+ assert (key != NULL);
+ assert (val != NULL);
+
+ hkey = hash_calc_key (key);
+
+ /* look for the item */
+ work = table[hkey];
+ while (work != NULL)
+ {
+ if (strcmp (work->key, key) == 0)
+ {
+ return -1;
+ }
+ work = work->next;
+ }
+
+ /* insert into head of list */
+ work = malloc (sizeof (hash_t));
+ if (work == NULL)
+ {
+ fprintf (stderr, "Out of Memory.\n");
+ exit (1);
+ }
+
+ /* setup the new node */
+ work->key = strdup (key);
+ work->val = strdup (val);
+ work->next = NULL;
+
+ if (table[hkey] != NULL)
+ {
+ work->next = table[hkey];
+ }
+
+ table[hkey] = work;
+
+ return 0;
+}
+
+
+/*
+ * hash_free(hash_t**)
+ *
+ * Deallocates all the structures.
+ *
+ */
+int
+hash_free (hash_t **table UNUSED)
+{
+ /* Not implementet yet! */
+
+ return 0;
+}
+
+
+/*
+ * hash_search(hash_t**, const char*)
+ *
+ * Looks for specified key, returns value if found,
+ * and NULL if not.
+ *
+ */
+char *
+hash_search (hash_t **table, const char *key)
+{
+ hash_t *work = NULL;
+ long hkey = -1;
+
+ assert (table != NULL);
+ assert (key != NULL);
+
+ hkey = hash_calc_key (key);
+
+ /* look for the key in the list */
+ work = table[hkey];
+ while (work != NULL)
+ {
+ if (strcmp (work->key, key) == 0)
+ return work->val;
+
+ work = work->next;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * hash_delkey(hash_t**, const char* )
+ *
+ * Delete the item from the table.
+ */
+int
+hash_delkey (hash_t **table, const char *key)
+{
+ hash_t *work = NULL;
+ hash_t *prev = NULL;
+ long hkey = -1;
+
+ assert (table != NULL);
+ assert (key != NULL);
+
+ hkey = hash_calc_key (key);
+
+ work = table[hkey];
+ prev = table[hkey];
+
+ while (work != NULL)
+ {
+ if (strcmp (work->key, key) == 0)
+ {
+
+ /* delete this node, and return? */
+ if (work == table[hkey])
+ table[hkey] = work->next;
+ else
+ prev->next = work->next;
+
+ free (work->key);
+ free (work->val);
+ free (work);
+ break;
+ }
+
+ prev = work;
+ work = work->next;
+ }
+
+ return 0;
+}
+
+
+/*
+ * hash_first(hash_t**)
+ *
+ * Returns the first item in the hash table.
+ */
+hash_t *
+hash_first (hash_t **table)
+{
+ unsigned long i = 0;
+
+ for (i = 0; i < TABLESIZE; i++)
+ {
+ if (table[i] != NULL)
+ return table[i];
+ }
+
+ return NULL;
+}
+
+/*
+ * hash_next(hash_t**, const char*)
+ *
+ * Returns the next item in the cache.
+ */
+hash_t *
+hash_next (hash_t **table, const char *key)
+{
+ hash_t *work = NULL;
+ long hkey = -1;
+
+ assert (table != NULL);
+ assert (key != NULL);
+
+ hkey = hash_calc_key (key);
+
+ /* look for the item */
+ work = table[hkey];
+ while (work != NULL)
+ {
+ if (strcmp (work->key, key) == 0)
+ {
+ work = work->next;
+ break;
+ }
+ work = work->next;
+ }
+
+ /* at this point, we have seen the key:
+ * starting from here, return the first
+ * valid pointer we find
+ */
+ if (work != NULL)
+ return work;
+
+ /* work is NULL, increment to next list. */
+ hkey++;
+ while (hkey < TABLESIZE)
+ {
+ if (table[hkey] != NULL)
+ return table[hkey];
+
+ hkey++;
+ }
+
+ return NULL;
+}
diff --git a/revnetgroup/hash.h b/revnetgroup/hash.h
new file mode 100644
index 0000000..01f8168
--- /dev/null
+++ b/revnetgroup/hash.h
@@ -0,0 +1,41 @@
+/*
+** Copyright (c) 1996, 1999 Thorsten Kukuk
+**
+** This file is part of the NYS YP Server.
+**
+** The NYS YP Server 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.
+**
+** The NYS YP Server 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 the NYS YP Server; see the file COPYING. If
+** not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+** Suite 500, Boston, MA 02110-1335, USA.
+**
+** Author: Thorsten Kukuk <kukuk@suse.de>
+*/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+typedef struct hash {
+ char *key;
+ char *val;
+ struct hash *next;
+} hash_t;
+
+extern int hash_insert (hash_t **table, const char *key, const char *val);
+extern int hash_free (hash_t **table);
+extern char *hash_search (hash_t **table, const char *key);
+extern int hash_delkey (hash_t **table, const char *key);
+extern hash_t **hash_malloc (void);
+extern hash_t *hash_first (hash_t **table);
+extern hash_t *hash_next (hash_t **table, const char *key);
+
+#endif
diff --git a/revnetgroup/revnetgroup.8.xml b/revnetgroup/revnetgroup.8.xml
new file mode 100644
index 0000000..015bd60
--- /dev/null
+++ b/revnetgroup/revnetgroup.8.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='revnetgroup'>
+ <refmeta>
+ <refentrytitle>revnetgroup</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>revnetgroup</refname>
+ <refpurpose>generate reverse netgroup data</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsynopsisdiv id='synopsis'>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/revnetgroup</command>
+ <group>
+ <arg choice='plain'>-u</arg>
+ <arg choice='plain'>-h</arg>
+ </group>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1 id='description'>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>Revnetgroup</command>
+ processes the standard input in
+ <citerefentry><refentrytitle>netgroup</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ format into what is called
+ <emphasis remap='I'>reverse netgroup</emphasis>
+ form. That is, where the original file shows netgroup memberships in
+ terms of which members reside in a particular
+ group, the reverse netgroup format specifies what groups are associated
+ with a particular member. This information is used to generate the
+ <filename>netgroup.byuser</filename>
+ and <filename>netgroup.byhosts</filename>
+ NIS maps. These reverse netgroup maps are used to help speed up
+ netgroup lookups, particularly for the
+ <function>innetgr()</function> library function.
+ </para>
+ <para>
+ The <command>revnetgroup</command>
+ command prints its results on the standard output. It is usually called
+ only by <filename>/var/yp/Makefile</filename>
+ when rebuilding the NIS netgroup maps.
+ </para>
+ </refsect1>
+
+ <refsect1 id='options'>
+ <title>OPTIONS</title>
+ <variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-u</option></term>
+ <listitem>
+ <para>
+ Generate <filename>netgroup.byuser</filename>
+ output; only username information in the
+ original netgroup file is processed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option></term>
+ <listitem>
+ <para>
+ Generate <filename>netgroup.byhost</filename>
+ output; only hostname information in the
+ original netgroup file is processed.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='files'><title>FILES</title>
+ <variablelist>
+ <varlistentry>
+ <term><filename>/var/yp/Makefile</filename></term>
+ <listitem>
+ <para>The Makefile to build the NIS databases.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>/etc/netgroup</filename></term>
+ <listitem>
+ <para>
+ The default netgroup database file. This file is most
+ often found only on the NIS master server.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry><refentrytitle>getnetgrent</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>netgroup</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ </para>
+ </refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>
+ <command>revnetgroup</command> was written by
+ Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/revnetgroup/revnetgroup.c b/revnetgroup/revnetgroup.c
new file mode 100644
index 0000000..ceb98c8
--- /dev/null
+++ b/revnetgroup/revnetgroup.c
@@ -0,0 +1,349 @@
+/* Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2006 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "hash.h"
+
+#define PARSE_FOR_USERS 0
+#define PARSE_FOR_HOSTS 1
+
+extern void rev_setnetgrent (const char *);
+extern void rev_endnetgrent (void);
+extern int rev_getnetgrent (char **, char **, char **);
+
+static int insert_netgroup (hash_t ** liste, const char *key, const char *val);
+static void usage (int exit_code);
+
+hash_t *input = NULL;
+static hash_t **output = NULL;
+static hash_t **empty = NULL;
+
+int
+main (int argc, char **argv)
+{
+#define BUFSIZE 8192
+ char *host, *user, *domain, *key;
+ char buffer[BUFSIZE + 1];
+ int hosts;
+ hash_t *work
+ ;
+#ifdef DEBUG_NETGROUP
+ FILE *debug_file = NULL;
+#endif
+
+ /* Only -u or -h are allowed, --version will exit the program */
+ /* --users = -u, --hosts = -h */
+ hosts = -1;
+
+ if (argc < 2)
+ usage (1);
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, '\255'},
+ {"hosts", no_argument, NULL, 'h'},
+ {"users", no_argument, NULL, 'u'},
+ {"help", no_argument, NULL, '\254'},
+ {"usage", no_argument, NULL, '\254'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "uh", long_options, &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'u':
+ hosts = PARSE_FOR_USERS;
+ break;
+ case 'h':
+ hosts = PARSE_FOR_HOSTS;
+ break;
+ case '\255':
+ printf ("revnetgroup (%s) %s", PACKAGE, VERSION);
+ exit (0);
+ case '\254':
+ usage (0);
+ break;
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+#ifdef DEBUG_NETGROUP
+ debug_file = fopen ("/etc/netgroup", "rt");
+ if (debug_file == NULL)
+ {
+ perror ("Error: could not open /etc/netgroup:");
+ exit (0);
+ }
+#endif
+
+ /* Put the netgroup names in a list: */
+
+#ifdef DEBUG_NETGROUP
+ while (fgets (buffer, BUFSIZE, debug_file))
+#else
+ while (fgets (buffer, BUFSIZE, stdin))
+#endif
+ {
+ char *val;
+ char *cptr;
+
+ if (buffer[0] == '#')
+ continue;
+
+ if (strlen (buffer) == 0)
+ continue;
+
+ /* Replace first '\n' with '\0' */
+ if ((cptr = strchr (buffer, '\n')) != NULL)
+ *cptr = '\0';
+
+ while (buffer[strlen (buffer) - 1] == '\\')
+ {
+ char *s;
+#ifdef DEBUG_NETGROUP
+ s = fgets (&buffer[strlen (buffer) - 1],
+ BUFSIZE - strlen (buffer), debug_file);
+#else
+ s = fgets (&buffer[strlen (buffer) - 1],
+ BUFSIZE - strlen (buffer), stdin);
+#endif
+ if (s == NULL)
+ continue;
+ if ((cptr = strchr (buffer, '\n')) != NULL)
+ *cptr = '\0';
+ }
+
+ val = (char *) (strpbrk (buffer, " \t"));
+ if (val == NULL)
+ continue;
+ key = (char *) &buffer;
+ *val = '\0';
+ val++;
+ insert_netgroup (&input, key, val);
+#ifdef DEBUG_NETGROUP
+ fprintf (stderr, "KEY: [%s]\n", key);
+#endif
+ }
+
+#ifdef DEBUG_NETGROUP
+ fclose (debug_file);
+#endif
+
+
+#ifdef DEBUG_NETGROUP
+ fprintf (stderr, "About to enter while loop...\n");
+#endif
+
+ /*
+ * Find all members of each netgroup and keep track of which
+ * group they belong to.
+ */
+ empty = hash_malloc ();
+ output = hash_malloc ();
+ work = input;
+ while (work != NULL)
+ {
+ rev_setnetgrent (work->key);
+
+#ifdef DEBUG_NETGROUP
+ fprintf (stderr, "Processing: [%s]\n", work->key);
+#endif
+
+ while (rev_getnetgrent (&host, &user, &domain) != 0)
+ {
+ static char star[] = "*";
+ char *key = NULL;
+ char *dat = NULL;
+
+ /* what are we processing for? */
+ if (hosts == PARSE_FOR_HOSTS)
+ dat = host;
+ else
+ dat = user;
+
+ /* empty fields are wildcard fields = use '-'
+ * to prevent entries
+ */
+ if (dat == NULL)
+ dat = star;
+
+ /* if we have an entry with data... */
+ if (dat[0] != '-')
+ {
+ /* create the dat/domain key */
+ if (domain == NULL)
+ {
+ key = malloc (strlen (dat) + 3);
+ sprintf (key, "%s.*", dat);
+ }
+ else
+ {
+ key = malloc (strlen (dat) + strlen (domain) + 2);
+ sprintf (key, "%s.%s", dat, domain);
+ }
+
+ /* if we have a wildcard search */
+ if (*dat == '*')
+ {
+ char *val = hash_search (empty, key);
+
+ if (val != NULL)
+ {
+ char *buf = NULL;
+ char *buf2 = NULL;
+ int found = 0;
+
+ buf2 = malloc (strlen (val) + 2);
+ sprintf (buf2, "%s,", val);
+ buf = strtok (buf2, ",");
+
+ while ((buf != NULL) && (found == 0))
+ {
+ found = (strcmp (buf, work->key) == 0);
+ buf = strtok (NULL, ",");
+ }
+
+ free (buf2);
+
+ if (!found)
+ {
+ buf = malloc (strlen (work->key) + strlen (val) + 2);
+ sprintf (buf, "%s,%s", val, work->key);
+ hash_delkey (empty, key);
+ hash_insert (empty, key, buf);
+ free (buf);
+ }
+ }
+ else
+ {
+ hash_insert (empty, key, work->key);
+ }
+ }
+ else
+ {
+ /* non-wild card search */
+ char *val = hash_search (output, key);
+
+ if (val != NULL)
+ {
+ char *buf = NULL;
+ char *buf2 = NULL;
+ int found = 0;
+
+ buf2 = malloc (strlen (val) + 2);
+ sprintf (buf2, "%s,", val);
+ buf = strtok (buf2, ",");
+
+ while ((buf != NULL) && (found == 0))
+ {
+ found = (strcmp (buf, work->key) == 0);
+ buf = strtok (NULL, ",");
+ }
+
+ free (buf2);
+
+ if (!found)
+ {
+ buf = malloc (strlen (work->key) + strlen (val) + 2);
+ sprintf (buf, "%s,%s", val, work->key);
+ hash_delkey (output, key);
+
+ hash_insert (output, key, buf);
+ free (buf);
+ }
+ }
+ else
+ {
+ hash_insert (output, key, work->key);
+ }
+ }
+
+ free (key);
+ }
+ }
+ work = work->next;
+ /* Release resources used by the getnetgrent code. */
+ rev_endnetgrent ();
+ }
+
+#ifdef DEBUG_NETGROUP
+ fprintf (stderr, "About to print results...\n");
+#endif
+
+ /* Print the results. */
+ work = hash_first (output);
+ while (work != NULL)
+ {
+ printf ("%s\t%s\n", work->key, work->val);
+ work = hash_next (output, work->key);
+ }
+
+ work = hash_first (empty);
+ while (work != NULL)
+ {
+ printf ("%s\t%s\n", work->key, work->val);
+ work = hash_next (empty, work->key);
+ }
+
+#if 0
+ remove_netgroup (&input);
+ remove_netgroup (&output);
+ remove_netgroup (&empty);
+#endif
+
+ return 0;
+}
+
+static void
+usage (int exit_code)
+{
+ fprintf (stderr, "usage: revnetgroup -u|-h\n");
+ fprintf (stderr, " revnetgroup --version\n");
+ exit (exit_code);
+}
+
+static int
+insert_netgroup (hash_t ** liste, const char *key, const char *val)
+{
+ hash_t *work;
+
+ work = malloc (sizeof (hash_t));
+ work->next = *liste;
+ work->key = malloc (strlen (key) + 1);
+ work->val = malloc (strlen (val) + 1);
+ strcpy (work->key, key);
+ strcpy (work->val, val);
+ *liste = work;
+
+ return 0;
+}
diff --git a/rpc.yppasswdd/Makefile.am b/rpc.yppasswdd/Makefile.am
new file mode 100644
index 0000000..7e2b3be
--- /dev/null
+++ b/rpc.yppasswdd/Makefile.am
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2001, 2003, 2006 Thorsten Kukuk <kukuk@suse.de>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+#
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\" \
+ -DUSE_FQDN=@USE_FQDN@
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = yppasswdd.8 rpc.yppasswdd.8
+XMLS = rpc.yppasswdd.8.xml
+
+noinst_HEADERS = yppwd_local.h yppasswd.x
+
+sbin_PROGRAMS = rpc.yppasswdd
+
+rpc_yppasswdd_SOURCES = update.c yppasswd_xdr.c yppasswdd.c
+
+rpc_yppasswdd_LDADD = @PIE_LDFLAGS@ $(top_builddir)/lib/libyp.a $(LIBDBM) $(LIBCRYPT) @SYSTEMD_LIBS@ @NSL_LIBS@ @TIRPC_LIBS@
+rpc_yppasswdd_CFLAGS = @PIE_CFLAGS@ @SYSTEMD_CFLAGS@ @NSL_CFLAGS@ @TIRPC_CFLAGS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
+
diff --git a/rpc.yppasswdd/rpc.yppasswdd.8.xml b/rpc.yppasswdd/rpc.yppasswdd.8.xml
new file mode 100644
index 0000000..f9d0e0a
--- /dev/null
+++ b/rpc.yppasswdd/rpc.yppasswdd.8.xml
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='rpc.yppasswdd'>
+
+ <refmeta>
+ <refentrytitle>rpc.yppasswdd</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='manual'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>rpc.yppasswdd</refname>
+ <refpurpose>NIS password update daemon</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsynopsisdiv id='synopsis'>
+ <cmdsynopsis>
+ <command>rpc.yppasswdd</command>
+ <arg choice='opt'>-D <replaceable>directory</replaceable></arg>
+ <arg choice='plain'>-e <replaceable>chsh</replaceable>|<replaceable>chfn</replaceable></arg>
+ <arg choice='opt'>--port <replaceable>number</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>rpc.yppasswdd</command>
+ <arg choice='opt'>-s <replaceable>shadow</replaceable></arg>
+ <arg choice='opt'>-p <replaceable>passwd</replaceable></arg>
+ <arg choice='plain'>-e <replaceable>chsh</replaceable>|<replaceable>chfn</replaceable></arg>
+ <arg choice='opt'>--port <replaceable>number</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>rpc.yppasswdd</command>
+ <group choice='plain'>
+ <arg choice='plain'>-x <replaceable>program</replaceable></arg>
+ <arg choice='plain'>-E <replaceable>program</replaceable></arg>
+ </group>
+ <arg choice='plain'>-e <replaceable>chsh</replaceable>|<replaceable>chfn</replaceable></arg>
+ <arg choice='opt'>--port <replaceable>number</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1 id='description'>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>rpc.yppasswdd</command> is the RPC server that lets users
+ change their passwords in the presence of NIS (a.k.a. YP). It must
+ be run on the NIS master server for that NIS domain.
+ </para>
+
+<para>When a
+<citerefentry><refentrytitle>yppasswd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+client contacts the server, it sends the old user
+password along with the new one. <command>rpc.yppasswdd</command> will search the system's
+<emphasis remap='B'>passwd</emphasis>
+file for the specified user name, verify that the
+given (old) password matches, and update the entry. If the user
+specified does not exist, or if the password, UID or GID doesn't match
+the information in the password file, the update request is rejected,
+and an error returned to the client.</para>
+
+<para>If this version of the server is compiled with the CHECKROOT=1 option, the
+password given is also checked against the systems root password.</para>
+
+<para>After updating the
+<emphasis remap='B'>passwd</emphasis>
+file and returning a success notification
+to the client, <command>rpc.yppasswdd</command> executes the <emphasis remap='B'>pwupdate</emphasis> script that
+updates the NIS server's <emphasis remap='B'>passwd.*</emphasis> and <emphasis remap='B'>shadow.byname</emphasis> maps.
+This script assumes all NIS maps are kept in directories named
+<filename>/var/yp/</filename><emphasis remap='I'>nisdomain</emphasis>
+that each contain a <emphasis remap='B'>Makefile</emphasis> customized for that NIS domain. If no
+such <emphasis remap='B'>Makefile</emphasis> is found, the scripts uses the generic one in
+<filename>/var/yp</filename>.</para>
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<para>The following options are available:</para>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-D</option><replaceable> directory</replaceable></term>
+ <listitem>
+<para>The
+<emphasis remap='B'>passwd</emphasis>
+and
+<emphasis remap='B'>shadow</emphasis>
+files are located under the specified directory path.
+<command>rpc.yppasswdd</command>
+will use this files, not
+<filename>/etc/passwd</filename>
+and
+<filename>/etc/shadow.</filename>
+This is useful if you do not want to give all users in the NIS database
+automatic access to your NIS server.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-E</option><replaceable> program</replaceable></term>
+ <listitem>
+<para>Instead of rpc.yppasswdd editing the passwd &amp; shadow files, the
+specified program will be run to do the editing. The following
+environment variables will be set for the program: YP_PASSWD_OLD,
+YP_PASSWD_NEW, YP_USER, YP_GECOS, YP_SHELL. The program should return
+an exit status of 0 if the change completes successfully, 1 if the
+change completes successfully but pwupdate should not be run, and
+otherwise if the change fails.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option><replaceable> passwdfile</replaceable></term>
+ <listitem>
+<para>This options tells <command>rpc.yppasswdd</command> to use a different source file instead
+of <filename>/etc/passwd</filename> This is useful if you do not want to give all users
+in the NIS database automatic access to your NIS server.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-s</option><replaceable> shadowfile</replaceable></term>
+ <listitem>
+<para>This options tells <command>rpc.yppasswdd</command> to use a different source file instead
+of <filename>/etc/passwd</filename>. See below for a brief discussion of shadow support.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-e [chsh|chfn]</option></term>
+ <listitem>
+<para>By default, <command>rpc.yppasswdd</command> will not allow users to change the shell or
+GECOS field of their <emphasis remap='B'>passwd</emphasis> entry. Using the <option>-e</option> option,
+you can enable either of these. Note that when enabling support for
+<citerefentry><refentrytitle>ypchsh</refentrytitle><manvolnum>1</manvolnum></citerefentry>, you have to list all shells users are allowed to
+select in <filename>/etc/shells</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-x program</option></term>
+ <listitem>
+<para>When the -x option is used, rpc.yppasswdd will not attempt to modify
+any files itself, but will instead run the specified program, passing
+to its stdin information about the requested operation(s). There is
+a defined protocol used to communicate with this external program, which
+has total freedom in how it propagates the change request. See
+below for more details on this.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-m</option></term>
+ <listitem>
+<para>Will be ignored, for compatibility with Solaris only.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--port number</option></term>
+ <listitem>
+<para>rpc.yppasswdd will try to register itself to this port. This makes
+it possible to have a router filter packets to the NIS ports.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v --version</option></term>
+ <listitem>
+<para>Prints the version number and if this package is compiled with the
+CHECKROOT option.</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='miscellaneous'><title>MISCELLANEOUS</title>
+
+<refsect2 id='shadow_passwords'><title>Shadow Passwords</title>
+<para>Using Shadow passwords alongside NIS does not make too much sense, because
+the supposedly inaccesible passwords now become readable through a simple
+invocation of
+<citerefentry><refentrytitle>ypcat</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+
+<para>Shadow support in <command>rpc.yppasswdd</command> does not mean that it offers a very
+clever solution to this problem, it simply means that it can read and write
+password entries in the system's
+<emphasis remap='B'>shadow</emphasis>
+file. You have to produce a
+<emphasis remap='B'>shadow.byname</emphasis> NIS map to distribute password information to your NIS
+clients. <command>rpc.yppasswdd</command> will search at first in the <filename>/etc/passwd</filename> file
+for the user and password. If it find's the user, but the password is "x"
+and a <filename>/etc/shadow</filename> file exists, it will update the password in the
+shadow map.</para>
+</refsect2>
+
+<refsect2 id='use_of_the_x_option'><title>Use of the -x option</title>
+<para>The program should expect to read a single line from stdin, which is
+formatted as follows:</para>
+
+<para>&lt;username&gt; o:&lt;oldpass&gt; p:&lt;password&gt; s:&lt;shell&gt; g:&lt;gcos&gt;\n</para>
+
+<para>where any of the three fields [p, s, g] may or may not be present.</para>
+
+<para>This program should write "OK\n" to stdout if the operation succeeded. On
+any other result, rpc.yppasswdd will report failure to the client.</para>
+
+<para>Note that the program specified by the -x option is responsible for doing
+any NIS make and build, and for doing any necessary validation on the
+shell and gcos field information supplied. The password passed to the client
+will be in UNIX crypt() format.</para>
+</refsect2>
+
+<refsect2 id='logging'><title>Logging</title>
+<para><command>rpc.yppasswdd</command> logs all password update requests to <emphasis remap='B'>syslogd(8)</emphasis>'s
+auth facility. The logging information includes the originating host's
+IP address and the user name and UID contained in the request. The
+user-supplied password itself is not logged.</para>
+</refsect2>
+
+ <refsect2 id='security'>
+ <title>Security</title>
+ <para>
+ <command>rpc.yppasswdd</command> should be as secure or insecure
+ as any program relying on simple password authentication. If you
+ feel that this is not enough, you may want to protect
+ <command>rpc.yppasswdd</command> from outside access by using the
+ `securenets' feature of the new <citerefentry>
+ <refentrytitle>portmap</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry> version&nbsp;3. Better still, look at <citerefentry>
+ <refentrytitle>rpasswdd</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect2>
+ </refsect1>
+
+ <refsect1 id='files'>
+ <title>FILES</title>
+ <para>
+ <filename>/usr/sbin/rpc.yppasswdd</filename>
+<!-- .br -->
+ <filename>/usr/lib/yp/pwupdate</filename>
+<!-- .br -->
+ <filename>/etc/passwd</filename>
+<!-- .br -->
+ <filename>/etc/shadow</filename>
+ </para>
+ </refsect1>
+
+ <refsect1 id='see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry><refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>shadow</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>passwd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>rpasswdd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>yppasswd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>ypchsh</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>ypchfn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>ypcat</refentrytitle><manvolnum>1</manvolnum></citerefentry></para>
+ </refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>
+ Olaf Kirch &lt;okir@monad.swb.de&gt; and
+ Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;
+ </para>
+ </refsect1>
+</refentry>
diff --git a/rpc.yppasswdd/update.c b/rpc.yppasswdd/update.c
new file mode 100644
index 0000000..4c656c5
--- /dev/null
+++ b/rpc.yppasswdd/update.c
@@ -0,0 +1,1072 @@
+/* Copyright (c) 1999, 2000, 2001, 2005, 2006, 2010, 2011, 2012, 2014, 2015, 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <alloca.h>
+#include <stdlib.h>
+#include <crypt.h>
+#include <shadow.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#define passwd xpasswd
+#include <rpcsvc/yppasswd.h>
+#undef passwd
+#include <paths.h>
+#include <pwd.h>
+#include "yppwd_local.h"
+#include "log_msg.h"
+
+#ifndef CHECKROOT
+/* Set to 0 if you don't want to check against the root password
+ of the NIS master server. */
+#define CHECKROOT 1
+#endif
+
+#ifndef _PATH_PASSWD
+#define _PATH_PASSWD "/etc/passwd"
+#endif
+#ifndef _PATH_SHADOW
+#define _PATH_SHADOW "/etc/shadow"
+#endif
+#ifndef _PATH_SHELLS
+#define _PATH_SHELLS "/etc/shells"
+#endif
+
+/* How often to retry locking the passwd file... */
+#define MAX_RETRIES 5
+
+char *path_passwd = _PATH_PASSWD;
+char *path_passwd_tmp = NULL;
+char *path_passwd_old = NULL;
+char *path_shadow = _PATH_SHADOW;
+char *path_shadow_tmp = NULL;
+char *path_shadow_old = NULL;
+
+/* Will be set by the main function */
+char *external_update_program = NULL;
+
+static bool_t adjuct_used = FALSE;
+
+static int external_update_env (yppasswd *yppw);
+static int external_update_pipe (yppasswd *yppw);
+static int update_files (yppasswd *yppw, int *shadow_changed,
+ int *passwd_changed, int *chfn, int *chsh);
+
+/* Argument validation. Avoid \n... (ouch).
+ We can't use isprint, because people may use 8bit chars which
+ aren't recognized as printable in the default locale. */
+static int
+validate_string (char *what, char *str)
+{
+ while (*str && *str != ':' && (unsigned char)*str >= 32)
+ ++str
+ ;
+ if (*str == '\0')
+ return 1;
+
+ log_msg ("Invalid characters in %s argument: \"%s\"", what, str);
+
+ return 0;
+}
+
+/* Check that nobody tries to change special NIS entries beginning
+ with +/- and that all chracters are allowed. */
+static inline int
+validate_args (struct xpasswd *pw)
+{
+ if (pw->pw_name[0] == '-' || pw->pw_name[0] == '+')
+ {
+ log_msg ("attempt to modify NIS passwd entry \"%s\"", pw->pw_name);
+ return 0;
+ }
+
+ return validate_string ("password", pw->pw_passwd)
+ && validate_string ("shell", pw->pw_shell)
+ && validate_string ("gecos", pw->pw_gecos);
+}
+
+static int
+shell_ok (char *shell)
+{
+ char buffer[1024];
+ FILE *fp;
+
+ if ((fp = fopen (_PATH_SHELLS, "r")) == NULL)
+ {
+ log_msg ("can't open %s", _PATH_SHELLS);
+ return 0;
+ }
+ while (fgets (buffer, sizeof (buffer), fp) != NULL)
+ {
+ buffer[sizeof (buffer) - 1] = '\0';
+ if (!strncmp (buffer, shell, strcspn (buffer, " \t\n")))
+ {
+ fclose (fp);
+ return 1;
+ }
+ }
+
+ fclose (fp);
+ return 0;
+}
+
+/* Read shadow file manually, to handle different colons count.
+ When we use passwd.adjunct, shadow file contains 6 colons, but if
+ we don't use passwd.adjunct, shadow file contains 8 colons.
+ This function can handle both counts, but fgetspent doesn't */
+static struct spwd *
+fgetspent_adjunct(FILE *fp)
+{
+ static char line_buffer[1024];
+ char *buffer_mark;
+ struct spwd* result;
+ int i, colons = 0;
+
+ /* Reserve two bytes for theoretic colons */
+ while (fgets(line_buffer, sizeof(line_buffer) - 2, fp) != NULL)
+ {
+ /* We don't need a new line character in the end */
+ if ((buffer_mark = strchr(line_buffer, '\n')) != NULL)
+ buffer_mark[0] = '\0';
+
+ /* Skip commented or empty lines */
+ if (line_buffer[0] == '\0' || line_buffer[0] == '#')
+ continue;
+
+ /* Count number of colons in the line */
+ for (i = 0; line_buffer[i] != '\0'; ++i)
+ if (line_buffer[i] == ':')
+ ++colons;
+
+ /* When we use passwd.adjunct, shadow file contains 6 colons,
+ but we need 8 colons to properly parse the line, so we
+ just add two colons to the end of the line */
+ if (colons == 6)
+ {
+ strcat(line_buffer, "::");
+ adjuct_used = TRUE;
+ }
+
+ /* Try to parse the line, if not success, read the next line */
+ if ((result = sgetspent(line_buffer)) != NULL)
+ return result;
+
+ }
+ return NULL;
+}
+
+/* Write an entry to the given stream.
+ When we use passwd.adjunct, shadow file contains 6 colons, but if
+ we don't use passwd.adjunct, shadow file contains 8 colons.
+ This function can handle both counts, but putspent doesn't */
+static int
+putspent_adjunct (const struct spwd *p, FILE *stream)
+{
+ int errors = 0;
+
+ if (!adjuct_used)
+ return putspent(p, stream);
+
+ flockfile (stream);
+
+ if (fprintf (stream, "%s:%s:::::", p->sp_namp, p->sp_pwdp ? p->sp_pwdp : "") < 0)
+ ++errors;
+
+ if (putc_unlocked ('\n', stream) == EOF)
+ ++errors;
+
+ funlockfile (stream);
+
+ return errors ? -1 : 0;
+}
+
+/* Check if the password the user supplied matches the old one */
+static int
+password_ok (char *plain, char *crypted, char *root)
+{
+ char *crypted_new;
+ if (crypted[0] == '\0')
+ return 1;
+ crypted_new = crypt (plain, crypted);
+ if (crypted_new == NULL)
+ {
+ log_msg ("crypt() call failed.");
+ return 0;
+ }
+ if (strcmp (crypted_new, crypted) == 0)
+ return 1;
+#if CHECKROOT
+ crypted_new = crypt (plain, root);
+ if (crypted_new == NULL)
+ {
+ log_msg ("crypt() call failed.");
+ return 0;
+ }
+ if (strcmp (crypted_new, root) == 0)
+ return 1;
+#endif
+
+ return 0;
+}
+
+static inline int
+is_allowed_to_change (const struct spwd *sp)
+{
+ long now;
+
+ if (sp->sp_lstchg == 0 || sp->sp_lstchg == -1)
+ return 1;
+
+ now = time ((time_t *) 0) / (24L*3600L);
+
+ if (sp->sp_min > sp->sp_max)
+ return 0; /* Minimum is bigger then maximum */
+ if (sp->sp_min > 0 && now <= (sp->sp_lstchg + sp->sp_min))
+ return 0; /* It is to early to change password */
+ if (sp->sp_inact >= 0 && sp->sp_max >= 0 &&
+ now >= (sp->sp_lstchg + sp->sp_max + sp->sp_inact))
+ return 0; /* It is to late to change password */
+
+ return 1;
+}
+
+/*********************************************************************
+ * The Update Handler *
+ *********************************************************************/
+
+int *
+yppasswdproc_pwupdate_1 (yppasswd *yppw, struct svc_req *rqstp)
+{
+ char namebuf6[INET6_ADDRSTRLEN];
+ int shadow_changed = 0, passwd_changed = 0, chsh = 0, chfn = 0;
+ int retries;
+ static int res; /* I hate static variables */
+ struct netconfig *nconf;
+ const struct netbuf *rqhost = svc_getrpccaller (rqstp->rq_xprt);
+
+ nconf = getnetconfigent (rqstp->rq_xprt->xp_netid);
+
+ /* Be careful here with the debug option. You can see the old
+ and new password in clear text !! */
+ if (debug_flag)
+ {
+ log_msg ("yppasswdproc_pwupdate(\"%s\") [From: %s port %d]",
+ yppw->newpw.pw_name,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ log_msg ("\toldpass..: %s", yppw->oldpass);
+ log_msg ("\tpw_name..: %s", yppw->newpw.pw_name);
+ log_msg ("\tpw_passwd: %s", yppw->newpw.pw_passwd);
+ log_msg ("\tpw_gecos.: %s", yppw->newpw.pw_gecos);
+ log_msg ("\tpw_dir...: %s", yppw->newpw.pw_dir);
+ log_msg ("\tpw_shell.: %s", yppw->newpw.pw_shell);
+ }
+
+ res = 1; /* res = 1 means no success */
+
+ /* Check if somebody tries to make trouble with not allowed characters */
+ if (!validate_args (&yppw->newpw))
+ {
+ log_msg ("update %.12s (uid=%d) from host %s failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ freenetconfigent (nconf);
+ return &res;
+ }
+
+ /* ATTENTION: The external program needs to do the password checking! */
+ if (external_update_program)
+ {
+ struct passwd *pw;
+
+ if ((pw = getpwnam (yppw->newpw.pw_name)) == NULL)
+ {
+ log_msg ("user %s not found", yppw->newpw.pw_name);
+ freenetconfigent (nconf);
+ return &res;
+ }
+ /* Do we need to update the GECOS information and are we allowed
+ to do it ? */
+ chfn = (strcmp (pw->pw_gecos, yppw->newpw.pw_gecos) != 0);
+ if (chfn && !allow_chfn)
+ {
+ log_msg ("update %.12s (uid=%d) from host %s rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ log_msg ("chfn not permitted");
+ freenetconfigent (nconf);
+ return &res;
+ }
+
+ /* Do we need to update the shell adn are we allowed to do it ? */
+ chsh = (strcmp (pw->pw_shell, yppw->newpw.pw_shell) != 0);
+ if (chsh)
+ {
+ if (!allow_chsh)
+ {
+ log_msg ("update %.12s (uid=%d) from host %s rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ log_msg ("chsh not permitted");
+ freenetconfigent (nconf);
+ return &res;
+ }
+ if (!shell_ok (yppw->newpw.pw_shell))
+ {
+ log_msg ("update %.12s (uid=%d) from host %s rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ log_msg ("invalid shell: %s", yppw->newpw.pw_shell);
+ freenetconfigent (nconf);
+ return &res;
+ }
+ }
+
+ if (x_flag)
+ {
+ res = external_update_pipe (yppw);
+ freenetconfigent (nconf);
+ return &res;
+ }
+ else
+ {
+ res = external_update_env (yppw);
+ if (res >= 2)
+ {
+ freenetconfigent (nconf);
+ return &res;
+ }
+ }
+ passwd_changed = 1; /* We don't know exactly what was changed. */
+ shadow_changed = 1; /* So build everything new. */
+ }
+ else
+ {
+ /* Lock the passwd file. We retry several times. */
+ retries = 0;
+ while (lckpwdf () && retries < MAX_RETRIES)
+ {
+ sleep (1);
+ ++retries;
+ }
+
+ if (retries == MAX_RETRIES)
+ {
+ log_msg ("update %.12s (uid=%d) from host %s failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ log_msg ("password file locked");
+ freenetconfigent (nconf);
+ return &res;
+ }
+
+ res = update_files (yppw, &shadow_changed, &passwd_changed,
+ &chfn, &chsh);
+
+ ulckpwdf ();
+ }
+
+ /* Fork off process to rebuild NIS passwd.* maps. */
+ if (res == 0)
+ /* The child (-E program) may exit(1), which means success, but
+ don't run pwupdate. Bad, we tell the user that there was an
+ error. Needs to be fixed later. */
+ {
+ int c;
+
+ if ((c = fork ()) < 0)
+ {
+ /* Do NOT restore old password file. Someone else may already
+ * be using the new one. */
+ log_msg ("update %.12s (uid=%d) from host %s failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ log_msg ("Couldn't fork map update process: %s", strerror (errno));
+ freenetconfigent (nconf);
+ return &res;
+ }
+
+ if (c == 0) /* We are the child */
+ {
+ if (shadow_changed)
+ execlp (MAP_UPDATE_PATH, MAP_UPDATE, "shadow", NULL);
+ else
+ execlp (MAP_UPDATE_PATH, MAP_UPDATE, "passwd", NULL);
+ log_msg ("Error: couldn't exec map update process: %s",
+ strerror (errno));
+ exit (1);
+ }
+
+ log_msg ("update %.12s (uid=%d) from host %s successful",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ if (chsh || chfn)
+ {
+ log_msg ("Shell %schanged (%s), GECOS %schanged (%s).",
+ chsh ? "" : "un", yppw->newpw.pw_shell,
+ chfn ? "" : "un", yppw->newpw.pw_gecos);
+ }
+ }
+
+ freenetconfigent (nconf);
+ return &res;
+}
+
+/*
+ return code:
+ 0: success
+ 1: error
+*/
+static int
+update_files (yppasswd *yppw, int *shadow_changed,
+ int *passwd_changed, int *chfn, int *chsh)
+{
+ struct passwd *pw;
+ struct spwd *spw = NULL;
+ int gotit = 0;
+ FILE *oldpf = NULL, *newpf = NULL, *oldsf = NULL, *newsf = NULL;
+ struct stat passwd_stat, shadow_stat;
+ char *rootpass = "x";
+
+#if CHECKROOT
+ if ((pw = getpwnam ("root")) != NULL)
+ {
+ if (strcmp (pw->pw_passwd, "x") == 0)
+ {
+ struct spwd *spw;
+
+ if ((spw = getspnam ("root")) != NULL)
+ {
+ rootpass = alloca (strlen (spw->sp_pwdp) + 1);
+ strcpy (rootpass, spw->sp_pwdp);
+ }
+ }
+ else
+ {
+ rootpass = alloca (strlen (pw->pw_passwd) + 1);
+ strcpy (rootpass, pw->pw_passwd);
+ }
+ }
+#endif
+
+ /* Open the passwd file for reading. We can't use getpwent and
+ friends here. */
+ if ((oldpf = fopen (path_passwd, "r")) == NULL)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Can't open %s: %m", path_passwd);
+ return 1;
+ }
+
+ if (fstat (fileno (oldpf), &passwd_stat) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Can't stat %s: %m", path_passwd);
+ fclose (oldpf);
+ return 1;
+ }
+
+ /* Open a temp passwd file */
+ if ((newpf = fopen (path_passwd_tmp, "w+")) == NULL)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Can't open %s: %m", path_passwd_tmp);
+ fclose (oldpf);
+ return 1;
+ }
+ chmod (path_passwd_tmp, passwd_stat.st_mode);
+ if (chown (path_passwd_tmp, passwd_stat.st_uid, passwd_stat.st_gid) == -1)
+ {
+ log_msg ("chown failed: %s", strerror (errno));
+ fclose (oldpf);
+ fclose (newpf);
+ unlink (path_passwd_tmp);
+ return 1;
+ }
+
+ /* Open the shadow file for reading. */
+ if ((oldsf = fopen (path_shadow, "r")) != NULL)
+ {
+ if (fstat (fileno (oldsf), &shadow_stat) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Can't stat %s: %m", path_shadow);
+ fclose (oldpf);
+ fclose (newpf);
+ fclose (oldsf);
+ return 1;
+ }
+
+ if ((newsf = fopen (path_shadow_tmp, "w+")) == NULL)
+ {
+ int err = errno;
+
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Can't open %s.tmp: %s",
+ path_passwd, strerror (err));
+ fclose (oldsf);
+ fclose (newpf);
+ fclose (oldpf);
+ return 1;
+ }
+ chmod (path_shadow_tmp, shadow_stat.st_mode);
+ if (chown (path_shadow_tmp, shadow_stat.st_uid,
+ shadow_stat.st_gid) == -1)
+ {
+ log_msg ("chown failed", strerror (errno));
+ fclose (newsf);
+ fclose (oldsf);
+ fclose (newpf);
+ fclose (oldpf);
+ return 1;
+ }
+ }
+
+ /* Loop over all passwd entries */
+ while ((pw = fgetpwent (oldpf)) != NULL)
+ {
+ /* check if this is the uid we want to change. A few
+ sanity checks added for consistency. */
+ if ((uid_t)yppw->newpw.pw_uid == pw->pw_uid &&
+ (uid_t)yppw->newpw.pw_gid == pw->pw_gid &&
+ !strcmp (yppw->newpw.pw_name, pw->pw_name) && !gotit)
+ {
+ ++gotit;
+
+ /* Check the password. At first check for a shadow password. */
+ if (oldsf != NULL &&
+ ((pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0') ||
+ (pw->pw_passwd[0] == '#' && pw->pw_passwd[1] == '#')))
+ {
+ /* Search for the shadow entry of this user */
+ while ((spw = fgetspent_adjunct (oldsf)) != NULL)
+ {
+ if (strcmp (yppw->newpw.pw_name, spw->sp_namp) == 0)
+ {
+ if (!password_ok (yppw->oldpass, spw->sp_pwdp, rootpass))
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Invalid password.");
+ goto error;
+ }
+ /* Password is ok, leave while loop */
+ break;
+ }
+ else if (putspent_adjunct (spw, newsf) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Error while writing new shadow file: %m");
+ goto error;
+ }
+ }
+ }
+
+ /* We don't have a shadow password file or we don't find the
+ user in it. */
+ if (spw == NULL &&
+ !password_ok (yppw->oldpass, pw->pw_passwd, rootpass))
+ {
+ log_msg ("update %.12s (uid=%d) rekected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Invalid password.");
+ goto error;
+ }
+
+ /*If the new password is not valid,
+ ignore it. User wishes to change GECOS or SHELL in this case. */
+ if (yppw->newpw.pw_passwd != NULL &&
+ !((yppw->newpw.pw_passwd[0] == 'x' ||
+ yppw->newpw.pw_passwd[0] == '*') &&
+ yppw->newpw.pw_passwd[1] == '\0') &&
+ yppw->newpw.pw_passwd[0] != '\0' &&
+ !(yppw->newpw.pw_passwd[0] == '#' &&
+ yppw->newpw.pw_passwd[1] == '#'))
+ {
+ if (spw)
+ {
+ /* test if password is expired */
+ if (spw->sp_pwdp[0] != '!')
+ {
+ if (is_allowed_to_change (spw))
+ {
+ time_t now;
+
+ time(&now);
+ /* set the new passwd */
+ spw->sp_pwdp = yppw->newpw.pw_passwd;
+ spw->sp_lstchg = (long int)now / (24L*3600L);
+ *shadow_changed = 1;
+ }
+ else
+ {
+ log_msg ("update %.12s (uid=%d) rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("now < minimum age for `%s'",
+ spw->sp_namp);
+ goto error;
+ }
+ }
+ if (putspent_adjunct (spw, newsf) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Error while writing new shadow file: %m");
+ *shadow_changed = 0;
+ goto error;
+ }
+
+ /* Copy all missing entries */
+ while ((spw = fgetspent_adjunct (oldsf)) != NULL)
+ if (putspent_adjunct (spw, newsf) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Error while writing new shadow file: %m");
+ *shadow_changed = 0;
+ goto error;
+ }
+ }
+ else /* No shadow entry */
+ {
+ /* set the new passwd */
+ pw->pw_passwd = yppw->newpw.pw_passwd;
+ *passwd_changed = 1;
+ }
+ } /* end changing password */
+ else if (spw)
+ spw = NULL;
+
+ /* Handle chsh and chfn here*/
+
+ /* Do we need to update the GECOS information and are we allowed
+ to do it ? */
+ if (strcmp (pw->pw_gecos, yppw->newpw.pw_gecos) != 0)
+ {
+ if (!allow_chfn)
+ {
+ log_msg ("update %.12s (uid=%d) rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("chfn not permitted");
+ *passwd_changed = 0;
+ goto error;
+ }
+ pw->pw_gecos = yppw->newpw.pw_gecos;
+ *chfn = 1;
+ *passwd_changed = 1;
+ }
+
+ /* Do we need to update the shell adn are we allowed to do it ? */
+ if (strcmp (pw->pw_shell, yppw->newpw.pw_shell) != 0)
+ {
+ if (!allow_chsh)
+ {
+ log_msg ("update %.12s (uid=%d) rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("chsh not permitted");
+ *passwd_changed = 0;
+ goto error;
+ }
+ if (!shell_ok (yppw->newpw.pw_shell))
+ {
+ log_msg ("update %.12s (uid=%d) rejected",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("invalid shell: %s", yppw->newpw.pw_shell);
+ *passwd_changed = 0;
+ goto error;
+ }
+ pw->pw_shell = yppw->newpw.pw_shell;
+ *chsh = 1;
+ *passwd_changed = 1;
+ }
+ } /* Found the entry */
+ /* write the passwd entry to tmp file */
+ if (putpwent (pw, newpf) < 0)
+ {
+ int err = errno;
+
+ log_msg ("update %.12s (uid=%d) failed",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ log_msg ("Error while writing new password file: %s",
+ strerror (err));
+ *passwd_changed = 0;
+ break;
+ }
+ /* fflush (newpf); */
+ } /* while */
+ error:
+ if (newpf) fclose (newpf);
+ if (oldpf) fclose (oldpf);
+ if (newsf) fclose (newsf);
+ if (oldsf) fclose (oldsf);
+ /* If one of them is non-NULL, an error ocured. */
+ if (pw || spw)
+ {
+ unlink (path_passwd_tmp);
+ unlink (path_shadow_tmp);
+ return 1;
+ }
+ if (*shadow_changed)
+ {
+ unlink (path_shadow_old);
+ if (link (path_shadow, path_shadow_old) == -1)
+ log_msg ("Cannot create backup file %s: %s",
+ path_shadow_old, strerror (errno));
+ if (rename (path_shadow_tmp, path_shadow) == -1)
+ {
+ log_msg ("Cannot move temporary file %s to %s: %s",
+ path_shadow_tmp, path_shadow, strerror (errno));
+ *shadow_changed = 0;
+ }
+ }
+ else
+ unlink (path_shadow_tmp);
+
+ if (*passwd_changed)
+ {
+ unlink (path_passwd_old);
+ if (link (path_passwd, path_passwd_old) == -1)
+ log_msg ("Cannot create backup file %s: %s",
+ path_passwd_old, strerror (errno));
+ if (rename (path_passwd_tmp, path_passwd) == -1)
+ {
+ log_msg ("Cannot move temporary file %s to %s: %s",
+ path_passwd_tmp, path_passwd, strerror (errno));
+ *passwd_changed = 0;
+ }
+ }
+ else
+ unlink (path_passwd_tmp);
+
+ return !(*shadow_changed || *passwd_changed);
+}
+
+static int
+external_update_env (yppasswd *yppw)
+{
+ int res = 0;
+ int itmp = fork ();
+
+ if (itmp)
+ { /* Parent - try to get exit status */
+ itmp = waitpid (itmp, &res, 0);
+
+ if (itmp < 0)
+ res = 2;
+ else
+ res = WEXITSTATUS(res);
+ }
+ else
+ { /* Child - run external update program */
+ setenv ("YP_PASSWD_OLD", yppw->oldpass, 1);
+ setenv ("YP_PASSWD_NEW", yppw->newpw.pw_passwd, 1);
+ setenv ("YP_USER", yppw->newpw.pw_name, 1);
+ setenv ("YP_GECOS", yppw->newpw.pw_gecos, 1);
+ setenv ("YP_SHELL", yppw->newpw.pw_shell, 1);
+ execlp (external_update_program, external_update_program, NULL);
+ _exit (1); /* fall-through */
+ }
+ return res;
+}
+
+/*===============================================================*
+ *
+ * If rpc.yppasswdd is run with the -execute option, instead of
+ * trying to manually modify the system passwd and/or shadow files,
+ * we instead try to run the program designated by the -execute
+ * option.
+ *
+ * We open a pair of pipes to communicate with the password-changing
+ * program. We write to the program's stdin a single line in the
+ * form:
+ *
+ * <username> o:<oldpass> p:<password> s:<shell> g:<gcos>\n
+ *
+ * where <oldpass>, <password>, <shell>, and <gcos> are all expanded
+ * into the information from the NIS passwd client. The <oldpass> bit
+ * is mandatory, and is to be used by the external program to validate
+ * permissions to change the user's information. The p:, s:, and g:
+ * fields will be present if those attributes have changed. If any of
+ * those fields have not changed, we won't include that part of the
+ * line, so if only the password has changed, we'll write something
+ * like
+ *
+ * broccol o:<oldpass> p:e6GYrKvFKVBXw\n
+ *
+ * and if we just change the shell, it'll look like
+ *
+ * broccol o:<oldpass> s:/bin/tcsh\n
+ *
+ * In return, we read output from the program. If the program sends
+ *
+ * OK[...]\n
+ *
+ * we return a code indicating a successful password information
+ * change. If the program does not emit OK as the first two
+ * characters to its stdout, we interpret that as failure and we
+ * report a failure to the NIS client.
+ *
+ * Note that the program executed is fully responsible for any
+ * NIS build and propagation issues, as well as for checking
+ * the submitted shell out for validity.
+ *
+ *===============================================================*/
+
+static void
+remove_password (char *str)
+{
+ char *ptr = strstr (str, " o:");
+
+ if (ptr != NULL)
+ {
+ ptr+=3;
+ while (*ptr && *ptr != ' ')
+ *ptr++ = 'X';
+ }
+
+ ptr = strstr (str, " p:");
+ if (ptr != NULL)
+ {
+ ptr+=3;
+ while (*ptr && *ptr != ' ')
+ *ptr++ = 'X';
+ }
+}
+
+static int
+external_update_pipe (yppasswd *yppw)
+{
+ struct passwd *newpw; /* passwd struct passed by the client */
+ int res, pid, tochildpipe[2], toparentpipe[2];
+ FILE *fp;
+ char childresponse[1024];
+
+ char *password = NULL;
+ char *shell = NULL;
+ char *gcos = NULL;
+
+ char *parentmsg;
+ size_t msglen;
+
+ /* - */
+
+ newpw = (struct passwd *)&yppw->newpw;
+ res = 1;
+
+ /*
+ * determine what information we have to change
+ */
+
+ if (newpw->pw_passwd && *(newpw->pw_passwd))
+ password = newpw->pw_passwd;
+
+ if (allow_chsh && newpw->pw_shell && *(newpw->pw_shell))
+ shell = newpw->pw_shell;
+
+ if (allow_chfn && newpw->pw_gecos && *(newpw->pw_gecos))
+ gcos = newpw->pw_gecos;
+
+ if (!password && !shell && !gcos)
+ {
+ log_msg ("update %.12s (uid=%d) failed - no information to change",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ return res;
+ }
+
+ /*
+ * create the pipe we'll use to write to the stdin of the password
+ * change utility we're going to call.
+ */
+
+ if (pipe(tochildpipe) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed - could not create child pipe",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ return res;
+ }
+
+ if (pipe(toparentpipe) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed - could not create parent pipe",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ return res;
+ }
+
+ if ((pid = fork()) < 0)
+ {
+ log_msg ("update %.12s (uid=%d) failed - could not fork",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid);
+ return res;
+ }
+
+ if (pid == 0)
+ {
+ /*
+ * the child executes this code..
+ */
+
+ /*
+ * make the read side of the pipe our stdin for the password
+ * change utilit
+ */
+
+ if (tochildpipe[0] != 0)
+ {
+ close(0);
+ dup2(tochildpipe[0], 0);
+ }
+
+ /*
+ * we're not going to write to ourselves
+ */
+
+ close(tochildpipe[1]);
+
+ /*
+ * make the write side of our end of the pipe stdout
+ */
+
+ if (toparentpipe[1] != 1)
+ {
+ close(1);
+ dup2(toparentpipe[1], 1);
+ }
+
+ /*
+ * we're not going to read from ourselves
+ */
+
+ close (toparentpipe[0]);
+
+ execl (external_update_program, external_update_program, NULL);
+ exit (1);
+ }
+
+ /*
+ * the parent executes this code
+ */
+
+ close (tochildpipe[0]);
+ close (toparentpipe[1]);
+
+ /*
+ * construct our message
+ */
+ msglen = strlen (yppw->newpw.pw_name) + strlen (yppw->oldpass) + 10;
+ if (password)
+ msglen += strlen (password) + 3;
+ if (shell)
+ msglen += strlen (shell) + 3;
+ if (gcos)
+ msglen += strlen (gcos) + 3;
+
+ if ((parentmsg = malloc (msglen)) == NULL)
+ {
+ log_msg ("rpc.yppasswdd: out of memory");
+ return res;
+ }
+
+ strcpy (parentmsg, yppw->newpw.pw_name);
+ strcat (parentmsg, " o:");
+ strcat (parentmsg, yppw->oldpass);
+ strcat (parentmsg, " ");
+
+ if (password)
+ {
+ strcat (parentmsg, "p:");
+ strcat (parentmsg, password);
+ strcat (parentmsg, " ");
+ }
+
+ if (shell)
+ {
+ strcat (parentmsg, "s:");
+ strcat (parentmsg, shell);
+ strcat (parentmsg, " ");
+ }
+
+ if (gcos)
+ {
+ strcat(parentmsg, "g:");
+ strcat(parentmsg, gcos);
+ }
+
+ /*
+ * write the message to our child
+ */
+
+ fp = fdopen(tochildpipe[1], "w");
+ fprintf(fp, "%s\n", parentmsg);
+ fclose(fp);
+
+ /*
+ * get output from the child
+ */
+
+ fp = fdopen(toparentpipe[0], "r");
+ if (!fgets(childresponse, 1024, fp))
+ {
+ childresponse[0] = '\0';
+ log_msg ("fgets() call failed or EOF.");
+ }
+ fclose(fp);
+
+ if (!debug_flag)
+ remove_password (parentmsg);
+
+ if (strspn(childresponse, "OK") < 2)
+ {
+ log_msg ("update %.12s (uid=%d) failed. Change request: %s",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid, parentmsg);
+ log_msg ("Response was '%s'", childresponse);
+ free (parentmsg);
+ return res;
+ }
+
+ log_msg ("update %.12s (uid=%d) successful. Change request: %s",
+ yppw->newpw.pw_name, yppw->newpw.pw_uid, parentmsg);
+
+ free (parentmsg);
+ res = 0;
+
+ return res;
+}
diff --git a/rpc.yppasswdd/yppasswd.x b/rpc.yppasswdd/yppasswd.x
new file mode 100644
index 0000000..5340a35
--- /dev/null
+++ b/rpc.yppasswdd/yppasswd.x
@@ -0,0 +1,71 @@
+/* @(#)yppasswd.x 2.1 88/08/01 4.0 RPCSRC */
+/* @(#)yppasswd.x 1.1 87/04/13 Copyr 1987 Sun Micro */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * This is for compatibility between different rpcgen versions.
+ */
+%#define yppasswdproc_update_1 yppasswdproc_update_1_svc
+
+/*
+ * YP password update protocol
+ * Requires unix authentication
+ */
+program YPPASSWDPROG {
+ version YPPASSWDVERS {
+ /*
+ * Update my passwd entry
+ */
+ int
+ YPPASSWDPROC_UPDATE(yppasswd) = 1;
+ } = 1;
+} = 100009;
+
+
+/*
+ * I had to rename passwd to xpasswd to avoid a conflict with
+ * Linux' idea of the passwd struct (where pw_[ug]id are unsigned
+ * short instead of int. --okir
+ */
+struct xpasswd {
+ string pw_name<>; /* username */
+ string pw_passwd<>; /* encrypted password */
+ int pw_uid; /* user id */
+ int pw_gid; /* group id */
+ string pw_gecos<>; /* in real life name */
+ string pw_dir<>; /* home directory */
+ string pw_shell<>; /* default shell */
+};
+
+struct yppasswd {
+ string oldpass<>; /* unencrypted old password */
+ xpasswd newpw; /* new passwd entry */
+};
+
diff --git a/rpc.yppasswdd/yppasswd_xdr.c b/rpc.yppasswdd/yppasswd_xdr.c
new file mode 100644
index 0000000..5e7eec6
--- /dev/null
+++ b/rpc.yppasswdd/yppasswd_xdr.c
@@ -0,0 +1,37 @@
+/*
+ * yppasswdd
+ * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
+ *
+ * This program is covered by the GNU General Public License, version 2.
+ * It is provided in the hope that it is useful. However, the author
+ * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details.
+ *
+ * This file was generated automatically by rpcgen from yppasswd.x, and
+ * editied manually.
+ */
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+
+
+bool_t
+xdr_passwd(XDR *xdrs, struct passwd *objp)
+{
+ return xdr_string(xdrs, &objp->pw_name, ~0)
+ && xdr_string(xdrs, &objp->pw_passwd, ~0)
+ && xdr_int(xdrs, (int*)&objp->pw_uid) /* cast uid_t* -> int* */
+ && xdr_int(xdrs, (int*)&objp->pw_gid) /* cast gid_t* -> int* */
+ && xdr_string(xdrs, &objp->pw_gecos, ~0)
+ && xdr_string(xdrs, &objp->pw_dir, ~0)
+ && xdr_string(xdrs, &objp->pw_shell, ~0);
+}
+
+
+bool_t
+xdr_yppasswd(XDR *xdrs, yppasswd *objp)
+{
+ return xdr_string(xdrs, &objp->oldpass, ~0)
+ && xdr_passwd(xdrs, &objp->newpw);
+}
diff --git a/rpc.yppasswdd/yppasswdd.8 b/rpc.yppasswdd/yppasswdd.8
new file mode 100644
index 0000000..ae6806b
--- /dev/null
+++ b/rpc.yppasswdd/yppasswdd.8
@@ -0,0 +1 @@
+.so man8/rpc.yppasswdd.8
diff --git a/rpc.yppasswdd/yppasswdd.c b/rpc.yppasswdd/yppasswdd.c
new file mode 100644
index 0000000..f9609eb
--- /dev/null
+++ b/rpc.yppasswdd/yppasswdd.c
@@ -0,0 +1,566 @@
+/*
+ Copyright (c) 1996-2006, 2010, 2011, 2012, 2014, 2015, 2016 Thorsten Kukuk, <kukuk@thkukuk.de>
+ Copyright (c) 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
+
+ This file is part of the NYS YP Server.
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The NYS YP Server 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 the NYS YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/yppasswd.h>
+#include <getopt.h>
+
+#include "yppwd_local.h"
+#include "log_msg.h"
+#include "pidfile.h"
+#include "access.h"
+
+#define _YPPASSWDD_PIDFILE _PATH_VARRUN"yppasswdd.pid"
+
+int use_shadow = 0;
+int allow_chsh = 0;
+int allow_chfn = 0;
+int solaris_mode = -1;
+int x_flag = -1;
+
+static int foreground_flag = 0;
+
+void yppasswdprog_1 (struct svc_req *rqstp, SVCXPRT * transp);
+void reaper (int sig);
+
+/*==============================================================*
+ * RPC dispatch function
+ *==============================================================*/
+void
+yppasswdprog_1 (struct svc_req *rqstp, SVCXPRT * transp)
+{
+ yppasswd argument;
+ int *result;
+ xdrproc_t xdr_argument, xdr_result;
+
+ switch (rqstp->rq_proc)
+ {
+ case NULLPROC:
+ svc_sendreply (transp, (xdrproc_t) xdr_void, (char *) NULL);
+ return;
+
+ case YPPASSWDPROC_UPDATE:
+ xdr_argument = (xdrproc_t) xdr_yppasswd;
+ xdr_result = (xdrproc_t) xdr_int;
+ break;
+
+ default:
+ svcerr_noproc (transp);
+ return;
+ }
+ memset ((char *) &argument, 0, sizeof (argument));
+ if (!svc_getargs (transp, xdr_argument, (caddr_t) &argument))
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf;
+ const struct netbuf *rqhost = svc_getrpccaller (rqstp->rq_xprt);
+
+ nconf = getnetconfigent (rqstp->rq_xprt->xp_netid);
+
+ log_msg ("cannot decode arguments for %d from %s",
+ rqstp->rq_proc, taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ /* try to free already allocated memory during decoding */
+ svc_freeargs (transp, xdr_argument, (caddr_t) &argument);
+ svcerr_decode (transp);
+ freenetconfigent (nconf);
+
+ return;
+ }
+ result = yppasswdproc_pwupdate_1 (&argument, rqstp);
+ if (result != NULL
+ && !svc_sendreply (transp, (xdrproc_t) xdr_result, (char *)result))
+ {
+ svcerr_systemerr (transp);
+ }
+ if (!svc_freeargs (transp, xdr_argument, (caddr_t) &argument))
+ {
+ log_msg ("unable to free arguments\n");
+ exit (1);
+ }
+}
+
+static void
+usage (FILE * fp, int n)
+{
+ fputs ("Usage: rpc.yppasswdd [--debug] [-s shadowfile] [-p passwdfile] [-e chsh|chfn] [-f|--foreground]\n", fp);
+ fputs (" rpc.yppasswdd [--debug] [-D directory] [-e chsh|chfn] [-f|--foreground]\n", fp);
+ fputs (" rpc.yppasswdd [--debug] [-x program |-E program] [-e chsh|chfn] [-f|--foreground]\n", fp);
+ fputs (" rpc.yppasswdd --port number\n", fp);
+ fputs (" rpc.yppasswdd --version\n", fp);
+ exit (n);
+}
+
+static void
+sig_child (int sig UNUSED)
+{
+ int save_errno = errno;
+
+ while (wait3 (NULL, WNOHANG, NULL) > 0)
+ ;
+ errno = save_errno;
+}
+
+/* Clean up if we quit the program. */
+static void
+sig_quit (int sig UNUSED)
+{
+ rpcb_unset (YPPASSWDPROG, YPPASSWDVERS, NULL);
+ unlink (_YPPASSWDD_PIDFILE);
+ exit (0);
+}
+
+
+static void
+install_sighandler (void)
+{
+ struct sigaction sa;
+
+ sigaction (SIGPIPE, NULL, &sa);
+ sa.sa_handler = SIG_IGN;
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+ /* The opposite to SA_ONESHOT, do not restore
+ the signal action. This provides behavior
+ compatible with BSD signal semantics. */
+#endif
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGPIPE, &sa, NULL);
+ /* Clear up if child exists */
+ sigaction (SIGCHLD, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_child;
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGCHLD, &sa, NULL);
+ /* If program quits, give ports free. */
+ sigaction (SIGTERM, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_quit;
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGTERM, &sa, NULL);
+
+ sigaction (SIGINT, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_quit;
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGINT, &sa, NULL);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ struct netconfig *nconf;
+ int my_port = -1;
+ void *nc_handle;
+ int c;
+ int could_register = 0;
+
+ /* Initialize logging. */
+ openlog ("rpc.yppasswdd", LOG_PID, LOG_AUTH);
+
+ /* Parse the command line options and arguments. */
+ while (1)
+ {
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, 'v'},
+ {"usage", no_argument, NULL, 'h'},
+ {"help", no_argument, NULL, 'h'},
+ {"execute", required_argument, NULL, 'x'},
+ {"foreground", no_argument, NULL, 'f'},
+ {"debug", no_argument, NULL, '\254'},
+ {"port", required_argument, NULL, '\253'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c=getopt_long (argc, argv, "e:p:s:fuhvD:E:x:m", long_options,
+ &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'e':
+ if (!strcmp (optarg, "chsh"))
+ allow_chsh = 1;
+ else if (!strcmp (optarg, "chfn"))
+ allow_chfn = 1;
+ else
+ usage (stderr, 1);
+ break;
+ case 'p':
+ if (solaris_mode == 1)
+ usage (stderr, 1);
+ solaris_mode = 0;
+ path_passwd = optarg;
+ break;
+ case 'f':
+ foreground_flag = 1;
+ break;
+ case 's':
+ if (solaris_mode == 1)
+ usage (stderr, 1);
+ solaris_mode = 0;
+ path_shadow = optarg;
+ break;
+ case 'D':
+ if (solaris_mode == 0)
+ usage (stderr, 1);
+ solaris_mode = 1;
+ path_passwd = malloc (strlen (optarg) + 8);
+ sprintf (path_passwd, "%s/passwd", optarg);
+ path_shadow = malloc (strlen (optarg) + 8);
+ sprintf (path_shadow, "%s/shadow", optarg);
+ break;
+ case 'E':
+ external_update_program = strdup(optarg);
+ x_flag = 0;
+ break;
+ case 'x':
+ external_update_program = strdup(optarg);
+ x_flag = 1;
+ break;
+ case 'm':
+ if (solaris_mode == 0)
+ usage (stderr, 1);
+ solaris_mode = 1;
+ /* do nothing for now. We always run make, and we uses the
+ fastest arguments */
+ break;
+ case 'h':
+ usage (stdout, 0);
+ break;
+ case '\253':
+ my_port = atoi (optarg);
+ if (my_port <= 0 || my_port > 0xffff) {
+ /* Invalid port number */
+ fprintf (stdout, "Warning: rpc.yppasswdd: Invalid port %d (0x%x)\n",
+ my_port, my_port);
+ my_port = -1;
+ }
+ if (debug_flag)
+ log_msg ("Using port %d\n", my_port);
+ break;
+ case 'v':
+#if CHECKROOT
+ fprintf (stdout, "rpc.yppasswdd - YP server version %s (with CHECKROOT)\n",
+ VERSION);
+#else /* NO CHECKROOT */
+ fprintf (stdout, "rpc.yppasswdd - YP server version %s\n",
+ VERSION);
+#endif /* CHECKROOT */
+ exit (0);
+ case '\254': /* --debug */
+ debug_flag = 1;
+ break;
+ default:
+ usage (stderr, 1);
+ }
+ }
+
+ /* No more arguments allowed. */
+ if (optind != argc)
+ usage (stderr, 1);
+
+ /* Create tmp and .OLD file names for "passwd" */
+ path_passwd_tmp = malloc (strlen (path_passwd) + 5);
+ if (path_passwd_tmp == NULL)
+ {
+ log_msg ("rpc.yppasswdd: out of memory\n");
+ exit (-1);
+ }
+ sprintf (path_passwd_tmp, "%s.tmp", path_passwd);
+ path_passwd_old = malloc (strlen (path_passwd) + 5);
+ if (path_passwd_old == NULL)
+ {
+ log_msg ("rpc.yppasswdd: out of memory\n");
+ exit (-1);
+ }
+ sprintf (path_passwd_old, "%s.OLD", path_passwd);
+ /* Create tmp and .OLD file names for "shadow" */
+ path_shadow_tmp = malloc (strlen (path_shadow) + 5);
+ if (path_shadow_tmp == NULL)
+ {
+ log_msg ("rpc.yppasswdd: out of memory\n");
+ exit (-1);
+ }
+ sprintf (path_shadow_tmp, "%s.tmp", path_shadow);
+ path_shadow_old = malloc (strlen (path_shadow) + 5);
+ if (path_shadow_old == NULL)
+ {
+ log_msg ("rpc.yppasswdd: out of memory\n");
+ exit (-1);
+ }
+ sprintf (path_shadow_old, "%s.OLD", path_shadow);
+
+ if (debug_flag)
+ {
+#if CHECKROOT
+ log_msg ("rpc.yppasswdd - NYS YP server version %s (with CHECKROOT)\n",
+ VERSION);
+#else /* NO CHECKROOT */
+ log_msg ("rpc.yppasswdd - NYS YP server version %s\n", VERSION);
+#endif /* CHECKROOT */
+ }
+ else if (!foreground_flag)
+ {
+ int i;
+
+ /* We first fork off a child. */
+ if ((i = fork ()) > 0)
+ exit (0);
+
+ if (i < 0)
+ {
+ log_msg ("rpc.yppasswdd: cannot fork: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ if (setsid() == -1)
+ {
+ log_msg ("rpc.yppasswdd: cannot setsid: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ if ((i = fork ()) > 0)
+ exit (0);
+
+ if (i < 0)
+ {
+ int err = errno;
+ log_msg ("rpc.yppasswdd: cannot fork: %s\n", strerror (err));
+ exit (err);
+ }
+
+ for (i = 0; i < getdtablesize (); ++i)
+ close (i);
+ errno = 0;
+
+ if (chdir ("/") == -1)
+ {
+ int err = errno;
+ log_msg ("rpc.yppasswdd: chdir failed: %s\n", strerror (err));
+ exit (err);
+ }
+ umask(0);
+ i = open("/dev/null", O_RDWR);
+ if (i == -1)
+ {
+ int err = errno;
+ log_msg ("rpc.yppasswdd: open /dev/null failed: %s\n",
+ strerror (err));
+ exit (err);
+ }
+
+ /* two dups, we have stdin, stdout, stderr */
+ if (dup(i) == -1)
+ {
+ int err = errno;
+ log_msg ("rpc.yppasswdd: dup failed: %s\n", strerror (err));
+ exit (err);
+ }
+
+ if (dup(i) == -1)
+ {
+ int err = errno;
+ log_msg ("rpc.yppasswdd: dup failed: %s\n", strerror (err));
+ exit (err);
+ }
+ }
+
+ create_pidfile (_YPPASSWDD_PIDFILE, "rpc.yppasswdd");
+
+ /* Register a signal handler to reap children after they terminated */
+ install_sighandler ();
+
+ /* Create the RPC server */
+ rpcb_unset (YPPASSWDPROG, YPPASSWDVERS, NULL);
+
+ nc_handle = __rpc_setconf ("netpath"); /* open netconfig file */
+ if (nc_handle == NULL)
+ {
+ log_msg ("could not read /etc/netconfig, exiting..");
+ return 1;
+ }
+
+
+ while ((nconf = __rpc_getconf (nc_handle)))
+ {
+ SVCXPRT *xprt;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ int sock;
+ sa_family_t family; /* AF_INET, AF_INET6 */
+ int type; /* SOCK_DGRAM (udp), SOCK_STREAM (tcp) */
+ int proto; /* IPPROTO_UDP, IPPROTO_TCP */
+
+ if (debug_flag)
+ log_msg ("Register ypserv for %s,%s",
+ nconf->nc_protofmly, nconf->nc_proto);
+
+ if (strcmp (nconf->nc_protofmly, "inet6") == 0)
+ family = AF_INET6;
+ else if (strcmp (nconf->nc_protofmly, "inet") == 0)
+ family = AF_INET;
+ else
+ continue; /* we don't support nconf->nc_protofmly */
+
+ if (strcmp (nconf->nc_proto, "udp") == 0)
+ {
+ type = SOCK_DGRAM;
+ proto = IPPROTO_UDP;
+ }
+ else if (strcmp (nconf->nc_proto, "tcp") == 0)
+ {
+ type = SOCK_STREAM;
+ proto = IPPROTO_TCP;
+ }
+ else
+ continue; /* We don't support nconf->nc_proto */
+
+ if ((sock = socket (family, type, proto)) < 0)
+ {
+ log_msg ("Cannot create socket for %s,%s: %s",
+ nconf->nc_protofmly, nconf->nc_proto,
+ strerror (errno));
+ continue;
+ }
+
+ if (family == AF_INET6)
+ {
+ /* Disallow v4-in-v6 to allow host-based access checks */
+
+ int i;
+
+ if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &i, sizeof(i)) == -1)
+ {
+ log_msg ("ERROR: cannot disable v4-in-v6 on %s6 socket",
+ nconf->nc_proto);
+ return 1;
+ }
+ }
+
+ switch (family)
+ {
+ case AF_INET:
+ memset (&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (my_port > 0)
+ sin.sin_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin;
+ break;
+ case AF_INET6:
+ memset (&sin6, 0, sizeof (sin6));
+ sin6.sin6_family = AF_INET6;
+ if (my_port > 0)
+ sin6.sin6_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin6;
+ break;
+ default:
+ log_msg ("Unsupported address family %d", family);
+ return -1;
+ }
+
+ if (bindresvport_sa (sock, sa) == -1)
+ {
+ if (my_port > 0)
+ log_msg ("Cannot bind to reserved port %d (%s)",
+ my_port, strerror (errno));
+ else
+ log_msg ("bindresvport failed: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ if (type == SOCK_STREAM)
+ {
+ listen (sock, SOMAXCONN);
+ xprt = svc_vc_create (sock, 0, 0);
+ }
+ else
+ xprt = svc_dg_create (sock, 0, 0);
+
+ if (xprt == NULL)
+ {
+ log_msg ("terminating: cannot create rpcbind handle");
+ return 1;
+ }
+
+ rpcb_unset (YPPASSWDPROG, YPPASSWDVERS, nconf);
+ if (!svc_reg (xprt, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, nconf))
+ {
+ log_msg ("unable to register (YPPASSWDPROG, 1) for %s, %s.",
+ nconf->nc_protofmly, nconf->nc_proto);
+ continue;
+ }
+ else
+ could_register = 1;
+ }
+ __rpc_endconf (nc_handle);
+
+ if (!could_register)
+ {
+ log_msg ("terminating: rpcbind not running?");
+ return 1;
+ }
+
+ /* If we use systemd as an init system, we may want to give it
+ a message, that this daemon is ready to accept connections.
+ At this time, sockets for receiving connections are already
+ created, so we can say we're ready now. It is a nop if we
+ don't use systemd. */
+ announce_ready();
+
+ /* Run the server */
+ svc_run ();
+ log_msg ("svc_run returned\n");
+ unlink (_YPPASSWDD_PIDFILE);
+ return 1;
+}
diff --git a/rpc.yppasswdd/yppwd_local.h b/rpc.yppasswdd/yppwd_local.h
new file mode 100644
index 0000000..296266b
--- /dev/null
+++ b/rpc.yppasswdd/yppwd_local.h
@@ -0,0 +1,46 @@
+/*
+ * yppasswdd
+ * Copyright 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
+ *
+ * This program is covered by the GNU General Public License, version 2.
+ * It is provided in the hope that it is useful. However, the author
+ * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details.
+ *
+ * This file was generated automatically by rpcgen from yppasswd.x, and
+ * editied manually.
+ */
+
+#ifndef _YPPWD_LOCAL_H_
+#define _YPPWD_LOCAL_H_
+
+/* The server procedure invoked by the main loop. */
+void yppasswdprog_1(struct svc_req *rqstp, SVCXPRT *transp);
+
+/* Handlers for the update RPC call, one for normal passwd files, and
+ * one for shadow passwords.
+ */
+int * yppasswdproc_pwupdate_1(yppasswd *yppw, struct svc_req *rqstp);
+int * yppasswdproc_spwupdate_1(yppasswd *yppw, struct svc_req *rqstp);
+
+/*
+ * Command-line options to yppasswdd.
+ */
+extern int allow_chsh;
+extern int allow_chfn;
+extern int use_shadow;
+extern int x_flag;
+extern char *path_passwd;
+extern char *path_passwd_tmp;
+extern char *path_passwd_old;
+extern char *path_shadow;
+extern char *path_shadow_tmp;
+extern char *path_shadow_old;
+extern char *external_update_program;
+
+/* This command is forked to rebuild the NIS maps after a successful
+ * update. MAP_UPDATE0 is used as argv[0].
+ */
+#define MAP_UPDATE "pwupdate"
+#define MAP_UPDATE_PATH YPBINDIR "/" MAP_UPDATE
+
+#endif /* _YPPASSWD_H_ */
diff --git a/rpc.ypxfrd/Makefile.am b/rpc.ypxfrd/Makefile.am
new file mode 100644
index 0000000..1f54d92
--- /dev/null
+++ b/rpc.ypxfrd/Makefile.am
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2001, 2003, 2007, 2014 Thorsten Kukuk <kukuk@suse.de>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+#
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\" \
+ -DUSE_FQDN=@USE_FQDN@ -DXFRBLOCKSIZE=65535
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = rpc.ypxfrd.8 ypxfrd.8
+XMLS = rpc.ypxfrd.8.xml
+
+sbin_PROGRAMS = rpc.ypxfrd
+
+rpc_ypxfrd_SOURCES = ypxfrd.c ypxfrd_server.c ypxfrd_svc.c
+
+rpc_ypxfrd_LDADD = @PIE_LDFLAGS@ $(top_builddir)/lib/libyp.a \
+ @LIBDBM@ @SYSTEMD_LIBS@ @NSL_LIBS@ @TIRPC_LIBS@
+rpc_ypxfrd_CFLAGS = @PIE_CFLAGS@ @NSL_CFLAGS@ @SYSTEMD_CFLAGS@ @TIRPC_CFLAGS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/rpc.ypxfrd/rpc.ypxfrd.8.xml b/rpc.ypxfrd/rpc.ypxfrd.8.xml
new file mode 100644
index 0000000..f43162e
--- /dev/null
+++ b/rpc.ypxfrd/rpc.ypxfrd.8.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="iso8859-15"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='rpc.ypxfrd'>
+ <refmeta>
+ <refentrytitle>rpc.ypxfrd</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>rpc.ypxfrd</refname>
+ <refpurpose>NIS map transfer server</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsynopsisdiv id='synopsis'>
+ <cmdsynopsis>
+ <command>/usr/sbin/rpc.ypxfrd</command>
+ <arg choice='opt'>-d <replaceable>path</replaceable></arg>
+ <arg choice='opt'>-p <replaceable>port</replaceable></arg>
+ <arg choice='opt'>--debug </arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>/usr/sbin/rpc.ypxfrd</command>
+ <arg choice='plain'>--version </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1 id='description'>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>rpc.ypxfrd</command> is used for speed up the transfer
+ of very large NIS maps from a NIS master to the NIS slave server.
+ If a NIS slave server receives a message that there is a new map,
+ it will start <command>ypxfr</command> for transfering the new map.
+ <command>ypxfr</command> will read the contents of a map from the
+ master server using the <function>yp_all</function>() function.
+ </para>
+ <para>
+ The <command>rpc.ypxfrd</command> server speeds up the transfer
+ process by allowing NIS slave servers to simply copy the master
+ servers map files rather than building their own from scratch.
+ <command>rpc.ypxfrd</command> uses an RPC-based file transfer
+ protocol.
+ </para>
+ <para>
+ If the on-disk format of the database on both machines is not
+ the same, <command>rpc.ypxfrd</command> will refuse to send the
+ data and <command>ypxfr</command> will fallback to
+ <function>yp_all</function>() and fetch every single entry alone.
+ </para>
+ <para>
+ <command>rpc.ypxfrd</command> could be started by inetd. But
+ since it starts very slowly, it should be started after
+ <command>ypserv</command> from <command>/etc/init.d/ypxfrd</command>.
+ </para>
+ </refsect1>
+
+ <refsect1 id='options'>
+ <title>OPTIONS</title>
+ <variablelist remap='TP'>
+ <varlistentry>
+ <term><option>--debug</option></term>
+ <listitem>
+ <para>
+ Causes the server to run in debugging mode.
+ In debug mode, the server does not background itself and
+ prints extra status messages to stderr for each request
+ that it revceives.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-d</option> <replaceable>path</replaceable></term>
+ <listitem>
+ <para>
+ <command>rpc.ypxfrd</command> is using this directory
+ instead of <filename>/var/yp</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option> <replaceable>port</replaceable></term>
+ <listitem>
+ <para>
+ <command>rpc.ypxfrd</command> will bind itself to this port,
+ which makes it possible to have a router filter packets
+ to the NIS ports. This can restricted the access to the NIS
+ server from hosts on the Internet.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--version</option></term>
+ <listitem>
+ <para>Prints the version number</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='security'>
+ <title>SECURITY</title>
+ <para>
+ <command>rpc.ypxfrd</command> uses the same functions for
+ checking a host as <command>ypserv</command>. At first,
+ <command>rpc.ypxfrd</command> will check a request from an address
+ with <filename>/var/yp/securenets</filename> or the tcp wrapper.
+ If the host is allowed to connect to the server,
+ <command>rpc.ypxfrd</command> will uses the rules from
+ <filename>/etc/ypserv.conf</filename> to check the requested map.
+ If a mapname doesn't match a rule, <command>rpc.ypxfrd</command>
+ will look for the YP_SECURE key in the map. If it exists,
+ <command>rpc.ypxfrd</command> will only allow requests on a
+ reserved port.
+ </para>
+ </refsect1>
+
+ <refsect1 id='notes'>
+ <title>NOTES</title>
+ <para>
+ The FreeBSD <command>ypxfrd</command> protocol is not compatible
+ with that used by SunOS. This is unfortunate but unavoidable: SUNs
+ protocol is not freely available, and even if it were it would
+ probably not be useful since the SunOS NIS v2 implementation
+ uses the original ndbm package for its map databases whereas the
+ other implementation uses GNU DBM or Berkeley DB. These packages
+ uses vastly different file formats. Furthermore, ndbm and gdbm are
+ byte-order and word width sensitive and not very smart about it,
+ meaning that a gdbm or ndbm database created on a big endian or
+ 64bit system cannot be read on a little endian or 32bit system.
+ The FreeBSD <command>ypxfrd</command> protocol checks, if both,
+ master and slave, uses the same database packages and, if necessary,
+ the byte order of the system.
+ </para>
+ </refsect1>
+
+
+ <refsect1 id='files'>
+ <title>FILES</title>
+ <variablelist>
+ <varlistentry>
+ <term><filename>/etc/ypserv.conf</filename></term>
+ <listitem>
+ <para>Configuration file for options and access rights</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>/var/yp/securenets</filename></term>
+ <listitem>
+ <para>Configuration file for access rights</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>makedbm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>yppush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>ypxfr</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>
+ ypxfrd protocol and FreeBSD Implementation:
+ Bill Paul &lt;wpaul@ctr.columbia.edu&gt;
+ </para>
+ <para>
+ Linux Implementation: Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;
+ </para>
+ </refsect1>
+</refentry>
diff --git a/rpc.ypxfrd/ypxfrd.8 b/rpc.ypxfrd/ypxfrd.8
new file mode 100644
index 0000000..7b11b5b
--- /dev/null
+++ b/rpc.ypxfrd/ypxfrd.8
@@ -0,0 +1 @@
+.so man8/rpc.ypxfrd.8
diff --git a/rpc.ypxfrd/ypxfrd.c b/rpc.ypxfrd/ypxfrd.c
new file mode 100644
index 0000000..f605c84
--- /dev/null
+++ b/rpc.ypxfrd/ypxfrd.c
@@ -0,0 +1,474 @@
+/* Copyright (c) 1996-1999, 2001-2003, 2005, 2006, 2010, 2014, 2015 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+/* ypxfrd - ypxfrd main routines. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <getopt.h>
+#include "ypxfrd.h"
+#include "access.h"
+#include "ypserv_conf.h"
+
+#ifndef SA_RESTART
+#define SA_RESTART 0
+#endif
+
+#include "log_msg.h"
+#include "pidfile.h"
+
+#define _YPXFRD_PIDFILE _PATH_VARRUN"ypxfrd.pid"
+
+extern void ypxfrd_freebsd_prog_1 (struct svc_req *, SVCXPRT *);
+
+int _rpcpmstart = 0;
+int _rpcfdtype = 0;
+int _rpcsvcdirty = 0;
+
+#ifndef _RPCSVC_CLOSEDOWN
+#define _RPCSVC_CLOSEDOWN 120
+#endif
+
+char *path_ypdb = YPMAPDIR;
+char *progname;
+
+static int foreground_flag = 0;
+
+/*
+** Needed, if we start rpc.ypxfrd from inetd
+*/
+static void
+closedown (int sig)
+{
+ signal(sig, closedown);
+ if (_rpcsvcdirty == 0)
+ {
+ static int size;
+ int i, openfd;
+
+ if (_rpcfdtype == SOCK_DGRAM)
+ exit(0);
+ if (size == 0)
+ size = svc_maxfd+1;
+
+ for (i = 0, openfd = 0; i < size && openfd < 2; ++i)
+ if (FD_ISSET(i, &svc_fdset))
+ openfd++;
+ if (openfd <= 1)
+ exit(0);
+ }
+ alarm(_RPCSVC_CLOSEDOWN);
+}
+
+/* Clean up after child processes signal their termination. */
+static void
+sig_child (int sig UNUSED)
+{
+ int save_errno = errno;
+
+ while (wait3 (NULL, WNOHANG, NULL) > 0)
+ ;
+ errno = save_errno;
+}
+
+/* Clean up if we quit the program. */
+static void
+sig_quit (int sig UNUSED)
+{
+ svc_unreg (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS);
+ unlink (_YPXFRD_PIDFILE);
+ exit (0);
+}
+
+/*
+** Reload securenets and config file
+*/
+static void
+sig_hup (int sig UNUSED)
+{
+ load_securenets();
+ load_config();
+ /* we don't wish to cache the file handles. */
+ cached_filehandles = 0;
+}
+
+static void
+usage (int exitcode)
+{
+ fputs ("usage: rpc.ypxfrd [--debug] [-d path] [-p port] [-f|--foreground]\n", stderr);
+ fputs (" rpc.ypxfrd --version\n", stderr);
+
+ exit (exitcode);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct netconfig *nconf;
+ void *nc_handle;
+ int my_port = -1;
+ struct sigaction sa;
+
+ progname = strrchr (argv[0], '/');
+ if (progname == (char *) NULL)
+ progname = argv[0];
+ else
+ progname++;
+
+ openlog(progname, LOG_PID, LOG_DAEMON);
+
+ while(1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, '\255'},
+ {"debug", no_argument, NULL, '\254'},
+ {"port", required_argument, NULL, 'p'},
+ {"path", required_argument, NULL, 'd'},
+ {"dir", required_argument, NULL, 'd'},
+ {"foreground", no_argument, NULL, 'f'},
+ {"usage", no_argument, NULL, 'u'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c=getopt_long(argc, argv, "p:d:fuh",long_options, &option_index);
+ if (c==EOF) break;
+ switch (c)
+ {
+ case '\255':
+ debug_flag = 1;
+ log_msg("rpc.ypxfrd (%s) %s\n", PACKAGE, VERSION);
+ exit(0);
+ case '\254':
+ debug_flag++;
+ break;
+ case 'd':
+ path_ypdb = optarg;
+ if (debug_flag)
+ log_msg("Using database directory: %s\n", path_ypdb);
+ break;
+ case 'p':
+ my_port = atoi(optarg);
+ if (my_port <= 0 || my_port > 0xffff) {
+ /* Invalid port number */
+ fprintf (stdout, "Warning: rpc.ypxfrd: Invalid port %d (0x%x)\n",
+ my_port, my_port);
+ my_port = -1;
+ }
+ if (debug_flag)
+ log_msg("Using port %d\n", my_port);
+ break;
+ case 'f':
+ foreground_flag = 1;
+ break;
+ case 'u':
+ case 'h':
+ usage(0);
+ break;
+ case '?':
+ usage(1);
+ break;
+ }
+ }
+
+ argc-=optind;
+ argv+=optind;
+
+ if (debug_flag)
+ log_msg("[Welcome to the rpc.ypxfrd Daemon, version %s]\n", VERSION);
+ else
+ if (!_rpcpmstart && !foreground_flag)
+ {
+ int i;
+
+ if ((i = fork()) > 0)
+ exit(0);
+
+ if (i < 0)
+ {
+ log_msg ("Cannot fork: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ if (setsid() == -1)
+ {
+ log_msg ("Cannot setsid: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ if ((i = fork()) > 0)
+ exit(0);
+
+ if (i < 0)
+ {
+ log_msg ("Cannot fork: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ for (i = 0; i < getdtablesize(); ++i)
+ close(i);
+ errno = 0;
+
+ umask(0);
+ i = open("/dev/null", O_RDWR);
+ if (dup(i) == -1)
+ {
+ int err = errno;
+ log_msg ("dup failed: %s\n", strerror (err));
+ exit (err);
+ }
+ if (dup(i) == -1)
+ {
+ int err = errno;
+ log_msg ("dup failed: %s\n", strerror (err));
+ exit (err);
+ }
+ }
+
+ create_pidfile (_YPXFRD_PIDFILE, "rpc.ypxfrd");
+
+ /* Change current directory to database location */
+ if (chdir(path_ypdb) < 0)
+ {
+ log_msg("%s: chdir: %", argv[0], strerror(errno));
+ exit(1);
+ }
+
+ load_securenets();
+ load_config();
+ /* we don't wish to cache the file handles. */
+ cached_filehandles = 0;
+
+ /*
+ * Ignore SIGPIPEs. They can hurt us if someone does a ypcat
+ * and then hits CTRL-C before it terminates.
+ */
+ sigaction(SIGPIPE, NULL, &sa);
+ sa.sa_handler = SIG_IGN;
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+ /*
+ * The opposite to SA_ONESHOT, do not restore
+ * the signal action. This provides behavior
+ * compatible with BSD signal semantics.
+ */
+#endif
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGPIPE, &sa, NULL);
+ /*
+ * Clear up if child exists
+ */
+ sigaction(SIGCHLD, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_child;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGCHLD, &sa, NULL);
+ /*
+ * If program quits, give ports free.
+ */
+ sigaction(SIGTERM, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_quit;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGTERM, &sa, NULL);
+
+ sigaction(SIGINT, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_quit;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+
+ /*
+ * If we get a SIGHUP, reload the securenets and config file.
+ */
+ sigaction(SIGHUP, NULL, &sa);
+#if !defined(sun) || (defined(sun) && defined(__svr4__))
+ sa.sa_flags |= SA_RESTART;
+#endif
+ sa.sa_handler = sig_hup;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGHUP, &sa, NULL);
+
+ rpcb_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, NULL);
+ nc_handle = __rpc_setconf ("netpath"); /* open netconfig file */
+ if (nc_handle == NULL)
+ {
+ log_msg ("could not read /etc/netconfig, exiting..");
+ return 1;
+ }
+
+ while ((nconf = __rpc_getconf (nc_handle)))
+ {
+ SVCXPRT *xprt;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ int sock;
+ sa_family_t family; /* AF_INET, AF_INET6 */
+ int type; /* SOCK_DGRAM (udp), SOCK_STREAM (tcp) */
+ int proto; /* IPPROTO_UDP, IPPROTO_TCP */
+
+ if (debug_flag)
+ log_msg ("Register ypserv for %s,%s",
+ nconf->nc_protofmly, nconf->nc_proto);
+
+ if (strcmp (nconf->nc_protofmly, "inet6") == 0)
+ family = AF_INET6;
+ else if (strcmp (nconf->nc_protofmly, "inet") == 0)
+ family = AF_INET;
+ else
+ continue; /* we don't support nconf->nc_protofmly */
+
+ if (strcmp (nconf->nc_proto, "udp") == 0)
+ {
+ type = SOCK_DGRAM;
+ proto = IPPROTO_UDP;
+ }
+ else if (strcmp (nconf->nc_proto, "tcp") == 0)
+ {
+ type = SOCK_STREAM;
+ proto = IPPROTO_TCP;
+ }
+ else
+ continue; /* We don't support nconf->nc_proto */
+
+ if ((sock = socket (family, type, proto)) < 0)
+ {
+ log_msg ("Cannot create socket for %s,%s: %s",
+ nconf->nc_protofmly, nconf->nc_proto,
+ strerror (errno));
+ continue;
+ }
+
+ if (family == AF_INET6)
+ {
+ /* Disallow v4-in-v6 to allow host-based access checks */
+
+ int i;
+
+ if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &i, sizeof(i)) == -1)
+ {
+ log_msg ("ERROR: cannot disable v4-in-v6 on %s6 socket",
+ nconf->nc_proto);
+ return 1;
+ }
+ }
+
+ switch (family)
+ {
+ case AF_INET:
+ memset (&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (my_port > 0)
+ sin.sin_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin;
+ break;
+ case AF_INET6:
+ memset (&sin6, 0, sizeof (sin6));
+ sin6.sin6_family = AF_INET6;
+ if (my_port > 0)
+ sin6.sin6_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin6;
+ break;
+ default:
+ log_msg ("Unsupported address family %d", family);
+ return -1;
+ }
+
+ if (bindresvport_sa (sock, sa) == -1)
+ {
+ if (my_port > 0)
+ log_msg ("Cannot bind to reserved port %d (%s)",
+ my_port, strerror (errno));
+ else
+ log_msg ("bindresvport failed: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ if (type == SOCK_STREAM)
+ {
+ listen (sock, SOMAXCONN);
+ xprt = svc_vc_create (sock, 0, 0);
+ }
+ else
+ xprt = svc_dg_create (sock, 0, 0);
+
+ if (xprt == NULL)
+ {
+ log_msg ("terminating: cannot create rpcbind handle");
+ return 1;
+ }
+
+ rpcb_unset (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, nconf);
+ if (!svc_reg (xprt, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS,
+ ypxfrd_freebsd_prog_1, nconf))
+ {
+ log_msg ("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS) for %s, %s.",
+ nconf->nc_protofmly, nconf->nc_proto);
+ return 1;
+ }
+ }
+ __rpc_endconf (nc_handle);
+
+ if (_rpcpmstart)
+ {
+ signal (SIGALRM, closedown);
+ alarm (_RPCSVC_CLOSEDOWN);
+ }
+
+ /* If we use systemd as an init system, we may want to give it
+ a message, that this daemon is ready to accept connections.
+ At this time, sockets for receiving connections are already
+ created, so we can say we're ready now. It is a nop if we
+ don't use systemd. */
+ announce_ready();
+
+ svc_run();
+ log_msg("svc_run returned");
+ unlink (_YPXFRD_PIDFILE);
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/rpc.ypxfrd/ypxfrd_server.c b/rpc.ypxfrd/ypxfrd_server.c
new file mode 100644
index 0000000..48c35b3
--- /dev/null
+++ b/rpc.ypxfrd/ypxfrd_server.c
@@ -0,0 +1,223 @@
+/* Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002, 2009, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include "log_msg.h"
+#include "ypxfrd.h"
+#include "access.h"
+#include "yp_db.h"
+
+static int file = 0;
+
+/* Read a block from a file and call xdr_xfr for sending */
+static bool_t
+xdr_ypxfrd_xfr (register XDR *xdrs, xfr *objp)
+{
+ static unsigned char buf[XFRBLOCKSIZE];
+ long len;
+
+ while (1)
+ {
+ if ((len = read (file, &buf, XFRBLOCKSIZE)) != -1)
+ {
+ /* We could send the next data block */
+ objp->ok = TRUE;
+ objp->xfr_u.xfrblock_buf.xfrblock_buf_len = len;
+ objp->xfr_u.xfrblock_buf.xfrblock_buf_val = (char *) &buf;
+ }
+ else
+ {
+ /* We could not read the next data block, so send an
+ error status */
+ objp->ok = FALSE;
+ objp->xfr_u.xfrstat = XFR_READ_ERR;
+ log_msg ("read error: %s", strerror (errno));
+ }
+
+ /* call the next function for sending the data or status */
+ if (!xdr_xfr (xdrs, objp))
+ return FALSE;
+
+ /* We have send the status report successfully, so exit the function
+ with an OK message. This does not mean that there were no errors
+ when reading the map, it only means that there were no errors
+ while sending data or the status. */
+ if (objp->ok == FALSE)
+ return TRUE;
+
+ /* Now, if we have send the last packet successfully, we could
+ send the XFR_DONE message and quit the function with the
+ return code of the xdr_xfr function */
+ if (objp->xfr_u.xfrblock_buf.xfrblock_buf_len < XFRBLOCKSIZE)
+ {
+ /* This was the last packet, send the XFR_DONE message */
+ objp->ok = FALSE;
+ objp->xfr_u.xfrstat = XFR_DONE;
+ return (xdr_xfr (xdrs, objp));
+ }
+ }
+}
+
+struct xfr *
+ypxfrd_getmap_1_svc (ypxfr_mapname *argp, struct svc_req *rqstp)
+{
+ static struct xfr result;
+ char buf[MAXPATHLEN];
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+
+ log_msg ("ypproc_null() [From: %s port: %d]",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ log_msg ("\txfrdomain=%s", argp->xfrdomain);
+ log_msg ("\txfrmap=%s", argp->xfrmap);
+ log_msg ("\txfrmap_filename=%s", argp->xfrmap_filename);
+ freenetconfigent (nconf);
+ }
+ }
+ result.ok = FALSE;
+ result.xfr_u.xfrstat = XFR_DENIED;
+
+ if ((valid = is_valid (rqstp, argp->xfrmap, argp->xfrdomain)) < 1)
+ {
+ if (valid == 0)
+ {
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ }
+ else
+ {
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain/map)");
+ }
+ ypdb_close_all ();
+
+ return &result;
+ }
+ ypdb_close_all ();
+
+#if defined(HAVE_LIBGDBM)
+#if SIZEOF_LONG == 8
+ if ((argp->xfr_db_type != XFR_DB_GNU_GDBM64) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#else
+ if ((argp->xfr_db_type != XFR_DB_GNU_GDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#endif
+#elif defined (HAVE_LIBNDBM)
+#if defined(__sun__) || defined(sun)
+ if ((argp->xfr_db_type != XFR_DB_NDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#else
+ if ((argp->xfr_db_type != XFR_DB_BSD_NDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#endif /* sun */
+#elif defined (HAVE_LIBQDBM)
+ if ((argp->xfr_db_type != XFR_DB_QDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#elif defined (HAVE_LIBTC)
+ if ((argp->xfr_db_type != XFR_DB_TC) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#else
+ if (argp->xfr_db_type != XFR_DB_ANY)
+#endif
+ {
+ result.xfr_u.xfrstat = XFR_DB_TYPE_MISMATCH;
+ return &result;
+ }
+
+#if defined(WORDS_BIGENDIAN)
+ if ((argp->xfr_byte_order != XFR_ENDIAN_BIG) &&
+ (argp->xfr_byte_order != XFR_ENDIAN_ANY))
+#else
+ if ((argp->xfr_byte_order != XFR_ENDIAN_LITTLE) &&
+ (argp->xfr_byte_order != XFR_ENDIAN_ANY))
+#endif
+ {
+ result.xfr_u.xfrstat = XFR_DB_ENDIAN_MISMATCH;
+ return &result;
+ }
+
+ /* check, if the xfrmap and xfrmap_filename means the same map,
+ not that some bad boys tell us that they will have the mail.aliases map,
+ but put "../../../etc/shadow" in the xfrmap_filename. */
+ if (strchr (argp->xfrmap_filename, '/') != NULL)
+ {
+ /* We don't have files in other directorys */
+ result.xfr_u.xfrstat = XFR_NOFILE;
+ return &result;
+ }
+
+ if (strncmp (argp->xfrmap, argp->xfrmap_filename, strlen (argp->xfrmap))
+ != 0)
+ return &result;
+
+ if (strlen (argp->xfrdomain) + strlen (argp->xfrmap_filename) + 2
+ < sizeof (buf))
+ sprintf (buf, "%s/%s", argp->xfrdomain, argp->xfrmap_filename);
+ else
+ {
+ log_msg ("Buffer overflow! [%s|%d]", __FILE__, __LINE__);
+ result.xfr_u.xfrstat = XFR_NOFILE;
+ return &result;
+ }
+
+ if (access ((char *) &buf, R_OK) == -1)
+ {
+ result.xfr_u.xfrstat = XFR_ACCESS;
+ return &result;
+ }
+
+ if ((file = open ((char *) &buf, O_RDONLY)) == -1)
+ {
+ result.xfr_u.xfrstat = XFR_READ_ERR;
+ return (&result);
+ }
+
+ /* Start with sending the database file */
+ svc_sendreply (rqstp->rq_xprt, (xdrproc_t) xdr_ypxfrd_xfr, (char *) &result);
+
+ close (file);
+
+ return NULL;
+}
diff --git a/rpc.ypxfrd/ypxfrd_svc.c b/rpc.ypxfrd/ypxfrd_svc.c
new file mode 100644
index 0000000..8e66f94
--- /dev/null
+++ b/rpc.ypxfrd/ypxfrd_svc.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 1996, 1997, 1998, 1999, 2001, 2004, 2012, 2014, 2015 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <rpcsvc/yp_prot.h>
+#include "ypxfrd.h"
+#include "log_msg.h"
+
+#define _RPCSVC_CLOSEDOWN 120
+
+extern int _rpcsvcdirty; /* Still serving ? */
+
+static
+void _msgout(char* msg)
+{
+ log_msg ("%s", msg);
+}
+
+void
+ypxfrd_freebsd_prog_1 (struct svc_req *rqstp, SVCXPRT *transp)
+{
+ union {
+ ypxfr_mapname ypxfrd_getmap_1_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ char *(*local)(char *, struct svc_req *);
+
+ _rpcsvcdirty = 1;
+ switch (rqstp->rq_proc)
+ {
+ case NULLPROC:
+ svc_sendreply(transp, (xdrproc_t) xdr_void, NULL);
+ _rpcsvcdirty = 0;
+ return;
+
+ case YPXFRD_GETMAP:
+ xdr_argument = (xdrproc_t) xdr_ypxfr_mapname;
+ xdr_result = (xdrproc_t) xdr_xfr;
+ local = (char *(*)(char *, struct svc_req *)) ypxfrd_getmap_1_svc;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ _rpcsvcdirty = 0;
+ return;
+ }
+ memset(&argument, 0, sizeof (argument));
+ if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument))
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf;
+ const struct netbuf *nbuf = svc_getrpccaller (rqstp->rq_xprt);
+
+ nconf = getnetconfigent (rqstp->rq_xprt->xp_netid);
+
+ log_msg ("cannot decode arguments for %d from %s",
+ rqstp->rq_proc, taddr2ipstr (nconf, nbuf,
+ namebuf6, sizeof (namebuf6)));
+ /* try to free already allocated memory during decoding */
+ svc_freeargs (transp, xdr_argument, (caddr_t) &argument);
+
+ freenetconfigent (nconf);
+ svcerr_decode(transp);
+ _rpcsvcdirty = 0;
+ return;
+ }
+ result = (*local)((char *)&argument, rqstp);
+ if (result != NULL && !svc_sendreply (transp, xdr_result, result))
+ svcerr_systemerr (transp);
+
+ if (!svc_freeargs (transp, xdr_argument, (caddr_t) &argument))
+ {
+ _msgout ("unable to free arguments");
+ exit (1);
+ }
+ _rpcsvcdirty = 0;
+ return;
+}
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
new file mode 100644
index 0000000..9624008
--- /dev/null
+++ b/scripts/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2001, 2003, 2007, 2014 Thorsten Kukuk <kukuk@linux-nis.org>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+#
+
+CLEANFILES = *~ ${SCRIPTS}
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+varypdir = @YPMAPDIR@
+
+man_MANS = pwupdate.8 ypinit.8
+XMLS = pwupdate.8.xml ypinit.8.xml
+
+libexec_SCRIPTS = ypxfr_1perhour ypxfr_1perday ypxfr_2perday \
+ create_printcap match_printcap pwupdate ypinit
+
+noinst_SCRIPTS = ypMakefile
+
+install-data-local:
+ $(mkdir_p) "$(DESTDIR)$(varypdir)"
+ $(install_sh_DATA) $(top_builddir)/scripts/ypMakefile "$(DESTDIR)$(varypdir)/Makefile"
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/scripts/create_printcap.in b/scripts/create_printcap.in
new file mode 100644
index 0000000..aa0f9ba
--- /dev/null
+++ b/scripts/create_printcap.in
@@ -0,0 +1,36 @@
+#!/usr/bin/awk -f
+#
+# create_printcap
+#
+# Converts a printcap into a format suitable for loading into the NIS
+# printcap map. Use the match_printcap script to extract printer
+# information from NIS.
+#
+# Copyright (C) 2000 Massimo Dal Zotto <dz@cs.unitn.it>
+# This file is distributed under the GNU General Public License version 2
+
+BEGIN { FS=":"; OFS="\t"; delim="_"; space="^B"; cont=1 }
+/^[\t ]*#/ { next }
+/^[^\t ]/ { if (!cont) print_entry() }
+ { sub("^[\t ]+", ":"); cont = sub("\\\\$", ""); entry = entry $0 }
+END { print_entry(); print_all() }
+
+function print_entry() {
+ gsub(":+", ":", entry); sub(":*$", "", entry)
+ split(entry, fields, ":"); n = split(fields[1], names, "|")
+ for (i=1; i<=n; i++) {
+ if (!(name=names[i])) { continue }
+ if (i==1 && !match(name,"^[._@]") && !p[name]++) { all = all "," name }
+ suffix = delim (++count[name])
+ gsub("[ \t]", space, name)
+ print name suffix, name suffix "|" entry
+ }
+ entry = ""
+}
+
+function print_all() {
+ sub("^,", "", all)
+ if (all) { print "all" delim "1", "all" delim "1|all:all=" all }
+}
+
+# end of file
diff --git a/scripts/match_printcap.in b/scripts/match_printcap.in
new file mode 100644
index 0000000..641f4b8
--- /dev/null
+++ b/scripts/match_printcap.in
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Extracts printer information from the NIS printcap map, which must
+# have been created with the create_printcap filter.
+#
+# Copyright (C) 1999 Massimo Dal Zotto <dz@cs.unitn.it>
+# This file is distributed under the GNU General Public License version 2
+
+delim="_" # delimiter used in nis map key
+space="" # space replacement in nis map key
+
+case "$1" in
+ -a|-all|--all)
+ # Invoked interactively, dump the entire printer NIS map.
+ # This is different than matching the key "all".
+ ypcat printcap | sort | sed 's/.*[0-9]*|//' | uniq
+ exit 0
+ ;;
+ -*|"")
+ # Called by lprng, read key from stdin
+ read key
+ ;;
+ *)
+ # Invoked interactively, used only for testing
+ key="$1"
+ ;;
+esac
+key="$(echo "$key" | sed "s/ /${space}/g")"
+
+n=1
+while ypmatch "${key}${delim}${n}" printcap 2>/dev/null; do
+ n=$[$n + 1]
+done \
+| sed "s/^.*${delim}[0-9]*|//"
diff --git a/scripts/pwupdate.8.xml b/scripts/pwupdate.8.xml
new file mode 100644
index 0000000..671914d
--- /dev/null
+++ b/scripts/pwupdate.8.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<!-- lifted from troff+man by doclifter -->
+<refentry id='pwupdate8'>
+<!-- \-*\- nroff \-*\- -->
+<refmeta>
+<refentrytitle>PWUPDATE</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo class='source'>Jan 1998</refmiscinfo>
+<refmiscinfo class='manual'>NYS YP Server</refmiscinfo>
+</refmeta>
+<refnamediv id='name'>
+<refname>pwupdate</refname>
+<refpurpose>updates passwd and shadow NIS map</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+ <command>/usr/lib/yp/pwupdate</command>
+ <arg choice='opt'><replaceable>shadow</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><emphasis remap='B'>pwupdate</emphasis>
+is invoked by
+<citerefentry><refentrytitle>rpc.yppasswdd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+after changing the password and it should update the passwd and shadow NIS map.
+Never run it by hand.</para>
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><emphasis remap='B'>shadow</emphasis></term>
+ <listitem>
+<para>Normally, only the passwd map will be updated. With this option,
+<emphasis remap='B'>pwupdate</emphasis>
+will update the shadow map, too.</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='files'><title>FILES</title>
+<!-- .PD 0 -->
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><filename>/etc/passwd</filename></term>
+ <term><filename>/etc/shadow</filename></term>
+ <listitem>
+<!-- .PD -->
+<para></para> <!-- FIXME: blank list item -->
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>rpc.yppasswdd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>Olaf Kirch &lt;okir@monad.swb.de&gt;,
+<!-- .br -->
+Thorsten Kukuk &lt;kukuk@suse.de&gt;</para>
+</refsect1>
+</refentry>
+
diff --git a/scripts/pwupdate.in b/scripts/pwupdate.in
new file mode 100644
index 0000000..26093e1
--- /dev/null
+++ b/scripts/pwupdate.in
@@ -0,0 +1,88 @@
+#!@BASH@
+# pwupdate - update NIS passwd maps.
+# Copyright (C) 1997, 1998 Thorsten Kukuk
+# (C) 1994 Olaf Kirch, <okir@monad.swb.de>
+# This software is covered by the GNU GPL.
+#
+# This script is invoked by rpc.yppasswdd after changing the password in
+# /etc/shadow or /etc/passwd and it should update the passwd.* and shadow.*
+# maps for all domains served by this host.
+# We make a feeble attempt at locking, so as to avoid concurrent builds on
+# the databases. However, this locking does _not_ guard us against the
+# NIS maintainer running make while we build our maps.
+### variables
+YPMAPDIR=@YPMAPDIR@
+
+# Use lock in YPMAPDIR, for security (guessable temp file name).
+# We should use the system lock directory (eg /var/lock) and a safer
+# locking method instead.
+tmp=$YPMAPDIR/ypwd.upd.$$
+lock=$YPMAPDIR/yppasswd.lock
+
+mailinfo ()
+{
+ if [ -x /bin/mailx -o /usr/bin/mailx ]; then
+ mailx -s "$1" $2
+ else
+ (echo "Subject: $1"; echo; cat) | /usr/sbin/sendmail $2
+ fi
+}
+
+echo $$ > $tmp
+i=0;
+while ! ln $tmp $lock; do
+ sleep 10;
+ i=`expr $i + 1`;
+ if [ $i -gt 60 ]; then
+ echo "NIS passwd maps seem permanently locked" |
+ mailinfo "Could not remake NIS passwd.* maps" root
+ rm -f $tmp
+ exit 2
+ fi
+done
+
+# Use temp files in YPMAPDIR, for security (guessable temp file name)
+mtemp=$YPMAPDIR/ypw.tmp.$$
+merr=$YPMAPDIR/ypw.err.$$
+domain=`domainname`
+
+cd $YPMAPDIR
+for dir in *; do
+ if [ -d $dir -a "$dir" != "binding" ]; then
+ (
+ # Find out where the Makefile is.
+ # If this directory does not have its own Makefile, and
+ # it is not our default domain directory, skip it.
+ if [ -f $dir/Makefile ]; then
+ makefile=Makefile
+ else
+ [ "$dir" != "$domain" ] && continue
+ makefile=../Makefile
+ fi
+ cd $dir &&
+ if ! @MAKE@ -f $makefile -k passwd > $mtemp 2>&1; then
+ echo "Errors in `pwd`:"
+ cat $mtemp
+ echo
+ fi >> $merr
+ if [ $1x = "shadow"x ]; then
+ if ! @MAKE@ -f $makefile -k shadow > $mtemp 2>&1; then
+ echo "Errors in `pwd`:"
+ cat $mtemp
+ echo
+ fi >> $merr
+ fi
+ )
+ fi
+done
+
+if [ -s $merr ]; then
+ (
+ echo "The following errors occurred while remaking the NIS passwd maps"
+ echo
+ cat $merr
+ ) | mailinfo "Errors while remaking NIS passwd.* maps" root
+fi
+rm -f $mtemp $merr
+
+rm -f $tmp $lock
diff --git a/scripts/ypMakefile.in b/scripts/ypMakefile.in
new file mode 100644
index 0000000..69213ac
--- /dev/null
+++ b/scripts/ypMakefile.in
@@ -0,0 +1,474 @@
+#
+# Makefile for the NIS databases
+#
+# This Makefile should only be run on the NIS master server of a domain.
+# All updated maps will be pushed to all NIS slave servers listed in the
+# /var/yp/ypservers file. Please make sure that the hostnames of all
+# NIS servers in your domain are listed in /var/yp/ypservers.
+#
+# This Makefile can be modified to support more NIS maps if desired.
+#
+
+# Set the following variable to "-b" to have NIS servers use the domain
+# name resolver for hosts not in the current domain. This is only needed,
+# if you have SunOS slave YP server, which gets here maps from this
+# server. The NYS YP server will ignore the YP_INTERDOMAIN key.
+#B=-b
+B=
+
+# If we have only one server, we don't have to push the maps to the
+# slave servers (NOPUSH=true). If you have slave servers, change this
+# to "NOPUSH=false" and put all hostnames of your slave servers in the file
+# /var/yp/ypservers.
+NOPUSH=true
+
+# yppush copies updated NIS databases (or maps) from the master NIS server
+# to the slave servers within a NIS domain and listens for their answer.
+# yppush will ask portmap to assign it a random port number to listen on
+# by default. To specify a fixed port number or any aditional options,
+# edit variable YPPUSH_ARGS.
+# e.g. YPPUSH_ARGS = --port 836
+YPPUSH_ARGS =
+
+# We do not put password entries with lower UIDs (the root and system
+# entries) in the NIS password database, for security. MINUID is the
+# lowest uid that will be included in the password maps. If you
+# create shadow maps, the UserID for a shadow entry is taken from
+# the passwd file. If no entry is found, this shadow entry is
+# ignored.
+# MINGID is the lowest gid that will be included in the group maps.
+MINUID=$(shell TMP=`egrep '^UID_MIN\s+[0-9]+' /etc/login.defs|sed -e 's/^UID_MIN//'` ; [ -n "$$TMP" ] && echo "$$TMP" || echo 1000)
+MINGID=$(shell TMP=`egrep '^GID_MIN\s+[0-9]+' /etc/login.defs|sed -e 's/^GID_MIN//'` ; [ -n "$$TMP" ] && echo "$$TMP" || echo 1000)
+
+# Should we merge the passwd file with the shadow file ?
+# MERGE_PASSWD=true|false
+MERGE_PASSWD=true
+
+# Should we merge the group file with the gshadow file ?
+# MERGE_GROUP=true|false
+MERGE_GROUP=true
+
+# These are commands which this Makefile needs to properly rebuild the
+# NIS databases. Don't change these unless you have a good reason.
+AWK = @AWK@
+MAKE = @MAKE@
+UMASK = umask 066
+
+#
+# These are the source directories for the NIS files; normally
+# that is /etc but you may want to move the source for the password
+# and group files to (for example) /var/yp/ypfiles. The directory
+# for passwd, group and shadow is defined by YPPWDDIR, the rest is
+# taken from YPSRCDIR.
+#
+YPSRCDIR = /etc
+YPPWDDIR = /etc
+YPBINDIR = @YPBINDIR@
+YPSBINDIR = @SBINDIR@
+YPDIR = @YPMAPDIR@
+YPMAPDIR = $(YPDIR)/$(DOMAIN)
+
+# These are the files from which the NIS databases are built. You may edit
+# these to taste in the event that you wish to keep your NIS source files
+# seperate from your NIS server's actual configuration files.
+#
+GROUP = $(YPPWDDIR)/group
+PASSWD = $(YPPWDDIR)/passwd
+SHADOW = $(YPPWDDIR)/shadow
+GSHADOW = $(YPPWDDIR)/gshadow
+ADJUNCT = $(YPPWDDIR)/passwd.adjunct
+#ALIASES = $(YPSRCDIR)/aliases # aliases could be in /etc or /etc/mail
+ALIASES = @ALIASES@
+ETHERS = $(YPSRCDIR)/ethers # ethernet addresses (for rarpd)
+BOOTPARAMS = $(YPSRCDIR)/bootparams # for booting Sun boxes (bootparamd)
+HOSTS = $(YPSRCDIR)/hosts
+NETWORKS = $(YPSRCDIR)/networks
+PRINTCAP = $(YPSRCDIR)/printcap
+PROTOCOLS = $(YPSRCDIR)/protocols
+PUBLICKEYS = $(YPSRCDIR)/publickey
+RPC = $(YPSRCDIR)/rpc
+SERVICES = $(YPSRCDIR)/services
+NETGROUP = $(YPSRCDIR)/netgroup
+NETID = $(YPSRCDIR)/netid
+AMD_HOME = $(YPSRCDIR)/amd.home
+TIMEZONE = $(YPSRCDIR)/timezone
+LOCALE = $(YPSRCDIR)/locale
+NETMASKS = $(YPSRCDIR)/netmasks
+AUTO_MAPS = auto.master auto.home auto.local
+
+YPSERVERS = $(YPDIR)/ypservers # List of all NIS slave servers
+
+target: Makefile
+ @test ! -d $(LOCALDOMAIN) && mkdir $(LOCALDOMAIN) ; \
+ cd $(LOCALDOMAIN) ; \
+ $(NOPUSH) || $(MAKE) -f ../Makefile ypservers; \
+ $(MAKE) -f ../Makefile all
+
+# If you don't want some of these maps built, feel free to comment
+# them out from this list.
+
+all: passwd group hosts rpc services netid protocols netgrp mail \
+ shadow publickey # networks ethers bootparams printcap \
+ # amd.home autofs passwd.adjunct \
+ # timezone locale netmasks
+
+
+########################################################################
+# #
+# DON'T EDIT ANYTHING BELOW IF YOU DON'T KNOW WHAT YOU ARE DOING !!! #
+# #
+########################################################################
+
+DBLOAD = $(YPBINDIR)/makedbm -c -m `$(YPBINDIR)/yphelper --hostname`
+MKNETID = $(YPBINDIR)/mknetid
+YPPUSH = $(YPSBINDIR)/yppush $(YPPUSH_ARGS)
+MERGER = $(YPBINDIR)/yphelper
+DOMAIN = `basename \`pwd\``
+LOCALDOMAIN = `/bin/domainname`
+REVNETGROUP = $(YPBINDIR)/revnetgroup
+CREATE_PRINTCAP = $(YPBINDIR)/create_printcap
+
+ethers: ethers.byname ethers.byaddr
+hosts: hosts.byname hosts.byaddr
+networks: networks.byaddr networks.byname
+protocols: protocols.bynumber protocols.byname
+rpc: rpc.byname rpc.bynumber
+services: services.byname services.byservicename
+passwd: passwd.byname passwd.byuid
+group: group.byname group.bygid
+shadow: shadow.byname
+passwd.adjunct: passwd.adjunct.byname
+netid: netid.byname
+netgrp: netgroup netgroup.byhost netgroup.byuser
+publickey: publickey.byname
+mail: mail.aliases
+timezone: timezone.byname
+locale: locale.byname
+netmasks: netmasks.byaddr
+autofs: $(AUTO_MAPS)
+
+ypservers: $(YPSERVERS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#") print $$0"\t"$$0 }' \
+ $(YPSERVERS) | $(DBLOAD) -i $(YPSERVERS) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+$(YPSERVERS):
+ @echo -n "Generating $*..."
+ @uname -n > $(YPSERVERS)
+
+bootparams: $(BOOTPARAMS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#" && $$1 != "+") \
+ print $$0 }' $(BOOTPARAMS) | $(DBLOAD) -r -i $(BOOTPARAMS) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+ethers.byname: $(ETHERS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#" && $$1 != "+") \
+ print $$2"\t"$$0 }' $(ETHERS) | $(DBLOAD) -r -i $(ETHERS) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+ethers.byaddr: $(ETHERS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#" && $$1 != "+") \
+ print $$1"\t"$$0 }' $(ETHERS) | $(DBLOAD) -r -i $(ETHERS) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+netgroup: $(NETGROUP) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#" && $$1 != "+") \
+ print $$0 }' $(NETGROUP) | $(DBLOAD) -i $(NETGROUP) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+netgroup.byhost: $(NETGROUP) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(REVNETGROUP) -h < $(NETGROUP) | $(DBLOAD) -i $(NETGROUP) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+netgroup.byuser: $(NETGROUP) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(REVNETGROUP) -u < $(NETGROUP) | $(DBLOAD) -i $(NETGROUP) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+hosts.byname: $(HOSTS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '/^[0-9]/ { for (n=2; n<=NF && $$n !~ "#"; n++) \
+ print $$n"\t"$$0 }' $(HOSTS) | $(DBLOAD) -r $(B) -l \
+ -i $(HOSTS) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+hosts.byaddr: $(HOSTS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") print $$1"\t"$$0 }' \
+ $(HOSTS) | $(DBLOAD) -r $(B) -i $(HOSTS) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+networks.byname: $(NETWORKS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if($$1 !~ "#" && $$1 != "") { print $$1"\t"$$0; \
+ for (n=3; n<=NF && $$n !~ "#"; n++) print $$n"\t"$$0 \
+ }}' $(NETWORKS) | $(DBLOAD) -r -i $(NETWORKS) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+networks.byaddr: $(NETWORKS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") print $$2"\t"$$0 }' \
+ $(NETWORKS) | $(DBLOAD) -r -i $(NETWORKS) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+protocols.byname: $(PROTOCOLS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") { print $$1"\t"$$0; \
+ for (n=3; n<=NF && $$n !~ "#"; n++) \
+ print $$n"\t"$$0}}' $(PROTOCOLS) | $(DBLOAD) -r -i \
+ $(PROTOCOLS) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+protocols.bynumber: $(PROTOCOLS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") print $$2"\t"$$0 }' \
+ $(PROTOCOLS) | $(DBLOAD) -r -i $(PROTOCOLS) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+rpc.byname: $(RPC) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") { print $$1"\t"$$0; \
+ for (n=3; n<=NF && $$n !~ "#"; n++) print $$n"\t"$$0 \
+ }}' $(RPC) | $(DBLOAD) -r -i $(RPC) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+rpc.bynumber: $(RPC) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") print $$2"\t"$$0 }' $(RPC) \
+ | $(DBLOAD) -r -i $(RPC) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+services.byname: $(SERVICES) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") print $$2"\t"$$0 }' \
+ $(SERVICES) | $(DBLOAD) -r -i $(SERVICES) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+services.byservicename: $(SERVICES) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 !~ "#" && $$1 != "") { \
+ split($$2,A,"/") ; TMP = "/" A[2] ; \
+ print $$1 TMP"\t"$$0 ; \
+ if (! seen[$$1]) { seen[$$1] = 1 ; print $$1"\t"$$0 ; } \
+ for (N = 3; N <= NF && $$N !~ "#" ; N++) { \
+ if ($$N !~ "#" && $$N != "") print $$N TMP"\t"$$0 ; \
+ if (! seen[$$N]) { seen[$$N] = 1 ; print $$N"\t"$$0 ; } \
+ } } } ' \
+ $(SERVICES) | $(DBLOAD) -r -i $(SERVICES) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+ifeq (x$(MERGE_PASSWD),xtrue)
+passwd.byname: $(PASSWD) $(SHADOW) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(MERGER) -p $(PASSWD) $(SHADOW) | \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINUID) ) \
+ print $$1"\t"$$0 }' | $(DBLOAD) -i $(PASSWD) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+passwd.byuid: $(PASSWD) $(SHADOW) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(MERGER) -p $(PASSWD) $(SHADOW) | \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINUID) ) \
+ print $$3"\t"$$0 }' | $(DBLOAD) -i $(PASSWD) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+# Don't build a shadow map !
+shadow.byname:
+ @echo "Updating $@... Ignored -> merged with passwd"
+
+else
+
+passwd.byname: $(PASSWD) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINUID) ) \
+ print $$1"\t"$$0 }' $(PASSWD) | $(DBLOAD) -i $(PASSWD) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+passwd.byuid: $(PASSWD) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINUID) ) \
+ print $$3"\t"$$0 }' $(PASSWD) | $(DBLOAD) -i $(PASSWD) \
+ -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+shadow.byname: $(SHADOW) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(AWK) -F: '{ if (FILENAME ~ /shadow$$/) { \
+ if (UID[$$1] >= $(MINUID) ) print $$1"\t"$$0; \
+ } else UID[$$1] = $$3; }' $(PASSWD) $(SHADOW) \
+ | $(DBLOAD) -s -i $(SHADOW) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+endif
+
+passwd.adjunct.byname: $(ADJUNCT) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" ) print $$1"\t"$$0 }' \
+ $(ADJUNCT) | $(DBLOAD) -s -i $(ADJUNCT) -o $(YPMAPDIR)/$@ - $@
+ @chmod 700 $(YPDIR)/$(DOMAIN)/$@*
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+ifeq (x$(MERGE_GROUP),xtrue)
+group.byname: $(GROUP) $(GSHADOW) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(MERGER) -g $(GROUP) $(GSHADOW) | \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINGID) ) \
+ print $$1"\t"$$0 }' | $(DBLOAD) -i $(GROUP) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+group.bygid: $(GROUP) $(GSHADOW) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(MERGER) -g $(GROUP) $(GSHADOW) | \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINGID) ) \
+ print $$3"\t"$$0 }' | $(DBLOAD) -i $(GROUP) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+else
+
+group.byname: $(GROUP) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINGID) ) \
+ print $$1"\t"$$0 }' $(GROUP) \
+ | $(DBLOAD) -i $(GROUP) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+group.bygid: $(GROUP) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(UMASK); \
+ $(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINGID) ) \
+ print $$3"\t"$$0 }' $(GROUP) \
+ | $(DBLOAD) -i $(GROUP) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+endif
+
+netid.byname: $(GROUP) $(PASSWD) $(HOSTS) $(wildcard $(NETID)) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(MKNETID) -q -p $(PASSWD) -g $(GROUP) -h $(HOSTS) -d $(DOMAIN) \
+ -n $(NETID) | $(DBLOAD) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+mail.aliases: $(ALIASES) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ \
+ if ($$1 ~ "^#.*") \
+ next; \
+ if ($$1 == "" || $$1 == "+") { \
+ if (line != "") \
+ {print line; line = "";} \
+ next; \
+ } \
+ if ($$0 ~ /^[[:space:]]/) \
+ line = line $$0; \
+ else { \
+ if (line != "") \
+ {print line; line = "";} \
+ line = $$0; \
+ } \
+ } \
+ END {if (line != "") print line}' \
+ $(ALIASES) | $(DBLOAD) --aliases \
+ -i $(ALIASES) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+publickey.byname: $(PUBLICKEYS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if($$1 !~ "#" && $$1 != "") { print $$1"\t"$$2 }}' \
+ $(PUBLICKEYS) | $(DBLOAD) -i $(PUBLICKEYS) \
+ -o $(YPMAPDIR)/$@ - $@
+ @$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+printcap: $(PRINTCAP) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(CREATE_PRINTCAP) < $(PRINTCAP) | \
+ $(DBLOAD) -i $(PRINTCAP) -o $(YPMAPDIR)/$@ - $@
+ @$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+$(AUTO_MAPS): %: $(YPSRCDIR)/%
+ @echo "Updating $@..."
+ -@sed -e "/^#/d" -e s/#.*$$// "$<" | $(DBLOAD) \
+ -i "$<" -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+amd.home: $(AMD_HOME) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ -@sed -e "s/#.*$$//" -e "/^$$/d" $(AMD_HOME) | \
+ $(AWK) '{\
+ for (i = 1; i <= NF; i++)\
+ if (i == NF) { \
+ if (substr($$i, length($$i), 1) == "\\") \
+ printf("%s", substr($$i, 1, length($$i) -1)); \
+ else \
+ printf("%s\n",$$i); \
+ } \
+ else \
+ printf("%s ",$$i);\
+ }' | $(DBLOAD) -i $(AMD_HOME) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+timezone.byname: $(TIMEZONE) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#") \
+ print $$2"\t"$$0 }' $(TIMEZONE) | $(DBLOAD) \
+ -r -i $(TIMEZONE) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+locale.byname: $(LOCALE) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#") \
+ print $$2"\t"$$0"\n"$$1"\t"$$2"\t"$$1 }' $(LOCALE) | $(DBLOAD) \
+ -r -i $(LOCALE) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+
+
+netmasks.byaddr: $(NETMASKS) $(YPDIR)/Makefile
+ @echo "Updating $@..."
+ @$(AWK) '{ if ($$1 != "" && $$1 !~ "#") \
+ print $$1"\t"$$2 }' $(NETMASKS) | $(DBLOAD) \
+ -r -i $(NETMASKS) -o $(YPMAPDIR)/$@ - $@
+ -@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
diff --git a/scripts/ypinit.8.xml b/scripts/ypinit.8.xml
new file mode 100644
index 0000000..113ee76
--- /dev/null
+++ b/scripts/ypinit.8.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='ypinit'>
+ <refmeta>
+ <refentrytitle>ypinit</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>ypinit</refname>
+ <refpurpose>NIS database install and build program</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsynopsisdiv id='synopsis'>
+ <cmdsynopsis>
+ <command>/usr/lib/yp/ypinit</command>
+ <arg choice='opt'>-m </arg>
+ <arg choice='opt'><arg choice='plain'>-s</arg> <arg choice='plain'><replaceable>master_name</replaceable></arg></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id='description'>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>ypinit</command> builds the domain subdirectory of
+ <filename>/var/yp</filename> for the current default domain.
+ After building the domain subdirectory,
+ <command>ypinit</command> builds a complete set of administrative
+ maps for your system and places them in this directory. The first
+ map created by <userinput>ypinit -m</userinput> is the ypservers
+ map. You should run it as root on the hosts, which should be the
+ master ypserver.You should have only one master server per NIS domain.
+ </para>
+
+ <para>
+ All databases are built from scratch, either from information
+ available to the program at runtime, or from the <acronym>ASCII</acronym>
+ data base files in <filename>/etc</filename>. These files are
+ listed below under <acronym>FILES</acronym>.
+ </para>
+
+ <para>
+ An <acronym>NIS</acronym> database on a slave server is set up
+ by copying an existing database from a running server. The
+ <userinput>master_name</userinput> argument should be the
+ hostname of an <acronym>NIS</acronym> server (either the
+ master server for all the maps, or a server on which the data
+ base is up-to-date and stable).
+ </para>
+ </refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-m</option></term>
+ <listitem>
+<para>If the local host is the
+<acronym>NIS</acronym>
+master.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-s</option></term>
+ <listitem>
+<para>Set up a slave server with the database from
+<emphasis remap='I'>master_name</emphasis></para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='files'><title>FILES</title>
+<!-- .PD 0 -->
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><filename>/etc/passwd</filename></term>
+ <term><filename>/etc/group</filename></term>
+ <term><filename>/etc/hosts</filename></term>
+ <term><filename>/etc/networks</filename></term>
+ <term><filename>/etc/services</filename></term>
+ <term><filename>/etc/protocols</filename></term>
+ <term><filename>/etc/netgroup</filename></term>
+ <term><filename>/etc/rpc</filename></term>
+ <listitem>
+<!-- .PD -->
+<para></para> <!-- FIXME: blank list item -->
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>makedbm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>revnetgroup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>yppush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypxfr</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+</refsect1>
+
+ <refsect1 id='bugs'>
+ <title>BUGS</title>
+ <para>There is no good error handling at the moment.</para>
+ </refsect1>
+
+ <refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;</para>
+ </refsect1>
+
+</refentry>
diff --git a/scripts/ypinit.in b/scripts/ypinit.in
new file mode 100644
index 0000000..b82ec4c
--- /dev/null
+++ b/scripts/ypinit.in
@@ -0,0 +1,185 @@
+#! /bin/sh
+#
+# ypinit - set up the YP directory on a master server or a slave server.
+#
+### some variables
+
+YPMAPDIR=@YPMAPDIR@
+YPBINDIR=@YPBINDIR@
+
+HOST=""
+DOMAIN=""
+MASTER=""
+is_correct=F
+
+### some functions, which make the life easier
+
+ypinit_slave()
+{
+ if [ $HOST = $MASTER ]
+ then
+ echo "The host specified should be a running master NIS server, not this machine."
+ exit 1
+ fi
+# maps=`ypwhich -m | egrep $MASTER$| awk '{ printf("%s ",$1) }' -`
+ maps=`$YPBINDIR/yphelper --maps $MASTER`
+
+ if [ -z "$maps" ]
+ then
+ echo "Can't enumerate maps from $MASTER. Please check that it is running."
+ exit 1
+ fi
+
+ mkdir -p $YPMAPDIR/$DOMAIN
+
+ echo "We will need a few minutes to copy the data from $MASTER."
+
+ for map in $maps
+ do
+ echo "Transferring $map..."
+ $YPBINDIR/ypxfr -f -h $MASTER -c -d $DOMAIN $map
+
+ if [ $? -ne 0 ]
+ then
+ echo "YPINIT: WARNING: Couldn't exec $YPBINDIR/ypxfr -f -h $MASTER -c -d $DOMAIN $map"
+ fi
+ done
+
+ echo ""
+ echo "${HOST}'s NIS data base has been set up."
+ echo "If there were warnings, please figure out what went wrong, and fix it."
+ echo ""
+ echo "At this point, make sure that /etc/passwd and /etc/group have"
+ echo "been edited so that when the NIS is activated, the data bases you"
+ echo "have just created will be used, instead of the /etc ASCII files."
+
+ exit 0
+
+}
+
+ypinit_master()
+{
+ mkdir -p $YPMAPDIR/$DOMAIN
+
+ rm -f $YPMAPDIR/$DOMAIN/*
+
+ while [ $is_correct = F ]; do
+ echo $HOST >$YPMAPDIR/ypservers
+ echo ""
+ echo "At this point, we have to construct a list of the hosts which will run NIS"
+ echo "servers. $HOST is in the list of NIS server hosts. Please continue to add"
+ echo "the names for the other hosts, one per line. When you are done with the"
+ echo "list, type a <control D>."
+ echo " next host to add: $HOST"
+ echo -n " next host to add: "
+
+ while read h
+ do
+ echo -n " next host to add: "
+ echo $h >>$YPMAPDIR/ypservers
+ done
+
+ echo ""
+ echo "The current list of NIS servers looks like this:"
+ echo ""
+
+ cat $YPMAPDIR/ypservers
+ echo ""
+ echo -n "Is this correct? [y/n: y] "
+ read hostlist_ok
+
+ case $hostlist_ok in
+ N) echo "Let's try again...";;
+ n) echo "Let's try again...";;
+ *) is_correct=T;;
+ esac
+ done
+
+ echo "We need a few minutes to build the databases..."
+ echo "Building $YPMAPDIR/$DOMAIN/ypservers..."
+ cat $YPMAPDIR/ypservers | awk '{print $0, $0}' | $YPBINDIR/makedbm - $YPMAPDIR/$DOMAIN/ypservers
+
+ if [ $? -ne 0 ]
+ then
+ echo "Couldn't build yp data base $YPMAPDIR/$DOMAIN/ypservers."
+ echo "Please fix it."
+ fi
+
+ echo "Running $YPMAPDIR/Makefile..."
+ cd $YPMAPDIR && make NOPUSH=true
+
+ if [ $? -ne 0 ]
+ then
+ echo "Error running Makefile."
+ echo "Please try it by hand."
+ else
+ echo ""
+ echo "$HOST has been set up as a NIS master server."
+ echo ""
+ echo "Now you can run ypinit -s $HOST on all slave server."
+ fi
+}
+
+usage()
+{
+ echo "usage:"
+ echo " ypinit -m"
+ echo " ypinit -s master"
+ echo ""
+ echo "where -m is used to build the data bases on a master NIS server,"
+ echo "and -s is used for a slave data base. master must be an existing"
+ echo "reachable NIS server."
+
+ exit 1
+}
+
+
+### Begin of the shell script
+
+HOST=`$YPBINDIR/yphelper --hostname`
+if [ $? -ne 0 ]
+then
+ echo "Can't get local host's name. Please check your path."
+ exit 1
+fi
+
+if [ -z "$HOST" ]
+then
+ echo "The local host's name hasn't been set. Please set it."
+ exit 1
+fi
+
+DOMAIN=`domainname`
+if [ $? -ne 0 ]
+then
+ echo "Can't find domainname. Please fix your PATH"
+ exit 1
+fi
+
+if [ "${DOMAIN}x" = "x" ] || [ "${DOMAIN}" = "(none)" ]
+then
+ echo "The local host's domain name hasn't been set. Please set it."
+ exit 1
+fi
+
+if [ ! -d $YPMAPDIR -o -f $YPMAPDIR ]
+then
+ echo "The directory $YPMAPDIR doesn't exist."
+ echo "Create it or run make install-* from the sourcen."
+ exit 1
+fi
+
+case $# in
+1) case $1 in
+ -m) ypinit_master;;
+ *) usage;;
+ esac;;
+
+2) case $1 in
+ -s) MASTER=$2
+ ypinit_slave;;
+ *) usage;;
+ esac;;
+
+*) usage;;
+esac
diff --git a/scripts/ypxfr_1perday.in b/scripts/ypxfr_1perday.in
new file mode 100644
index 0000000..96bacb3
--- /dev/null
+++ b/scripts/ypxfr_1perday.in
@@ -0,0 +1,14 @@
+#! /bin/sh
+#
+# ypxfr_1perday - Do daily NIS map check/updates, to see, if we
+# have missed one update.
+#
+
+YPBINDIR=@YPBINDIR@
+
+MAPS_TO_GET="group.byname group.bygid protocols.byname protocols.bynumber networks.byname networks.byaddr rpc.byname rpc.bynumber services.byname ypservers"
+
+for map in $MAPS_TO_GET
+do
+ $YPBINDIR/ypxfr $map
+done
diff --git a/scripts/ypxfr_1perhour.in b/scripts/ypxfr_1perhour.in
new file mode 100644
index 0000000..d1c8ec6
--- /dev/null
+++ b/scripts/ypxfr_1perhour.in
@@ -0,0 +1,14 @@
+#! /bin/sh
+#
+# ypxfr_1perhour - Do hourly NIS map check/updates, to see, if we
+# have missed one update.
+#
+
+YPBINDIR=@YPBINDIR@
+
+MAPS_TO_GET="passwd.byname passwd.byuid shadow.byname publickey.byname"
+
+for map in $MAPS_TO_GET
+do
+ $YPBINDIR/ypxfr $map
+done
diff --git a/scripts/ypxfr_2perday.in b/scripts/ypxfr_2perday.in
new file mode 100644
index 0000000..5c24be8
--- /dev/null
+++ b/scripts/ypxfr_2perday.in
@@ -0,0 +1,15 @@
+#! /bin/sh
+#
+# ypxfr_2perday - Do twice-daily NIS map check/updates, to see, if we
+# have missed one update.
+#
+
+YPBINDIR=@YPBINDIR@
+
+MAPS_TO_GET="hosts.byname hosts.byaddr netgroup netgroup.byuser netgroup.byhost"
+
+for map in $MAPS_TO_GET
+do
+ $YPBINDIR/ypxfr $map
+done
+
diff --git a/yphelper/Makefile.am b/yphelper/Makefile.am
new file mode 100644
index 0000000..9c34cbe
--- /dev/null
+++ b/yphelper/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2001, 2002, 2003, 2007, 2009 Thorsten Kukuk <kukuk@linux-nis.org>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+localedir = $(datadir)/locale
+
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\" \
+ -DUSE_FQDN=@USE_FQDN@
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+XMLS = yphelper.8.xml
+man_MANS = yphelper.8
+
+libexec_PROGRAMS = yphelper
+
+yphelper_SOURCES = yphelper.c
+
+yphelper_LDADD = $(top_builddir)/lib/libyp.a @LIBDBM@ @NSL_LIBS@ @TIRPC_LIBS@
+yphelper_CFLAGS = @NSL_CFLAGS@ @TIRPC_CFLAGS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/yphelper/yphelper.8.xml b/yphelper/yphelper.8.xml
new file mode 100644
index 0000000..c9b38fb
--- /dev/null
+++ b/yphelper/yphelper.8.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<refentry id='yphelper8'>
+ <refmeta>
+ <refentrytitle>yphelper</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='manual'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>yphelper</refname>
+ <refpurpose>helper application for internal use</refpurpose>
+ </refnamediv>
+
+
+<!-- body begins here -->
+<refsect1 id='description'><title>DESCRIPTION</title>
+ <para><emphasis remap='B'>yphelper</emphasis>
+ is a internal helper application for ypserv and should not be
+ used by the normal user or system administrator.</para>
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+ <variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-d </option><emphasis remap='I'>domainname</emphasis></term>
+ <listitem>
+ <para>
+ Use <emphasis remap='I'>domainname</emphasis> as default domain.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option></term>
+ <listitem>
+ <para>Print the canonical hostname.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-i </option><emphasis remap='I'>map</emphasis></term>
+ <listitem>
+ <para>Return '0' if we are the NIS master of
+ <emphasis remap='I'>map</emphasis> or '1' if not.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-m </option><emphasis remap='I'>master</emphasis></term>
+ <listitem>
+ <para>Print the name of all NIS maps where
+ <emphasis remap='I'>master</emphasis> is the NIS master server.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p </option><emphasis remap='I'>passwd</emphasis><emphasis remap='I'>shadow</emphasis></term>
+ <listitem>
+ <para>
+ Merge the <emphasis remap='I'>passwd</emphasis> and
+ <emphasis remap='I'>shadow</emphasis> files.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-g </option><emphasis remap='I'>group</emphasis><emphasis remap='I'>gshadow</emphasis></term>
+ <listitem>
+ <para>
+ Merge the <emphasis remap='I'>group</emphasis> and
+ <emphasis remap='I'>gshadow</emphasis> files.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+</refsect1>
+
+<refsect1 id='author'>
+ <title>AUTHOR</title>
+ <para>
+ <command>yphelper</command> was written by
+ Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;.
+ </para>
+</refsect1>
+</refentry>
diff --git a/yphelper/yphelper.c b/yphelper/yphelper.c
new file mode 100644
index 0000000..cd3ac7c
--- /dev/null
+++ b/yphelper/yphelper.c
@@ -0,0 +1,654 @@
+/* Copyright (c) 1999, 2001, 2002, 2011, 2013, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+#include <netdb.h>
+#include <rpc/types.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <alloca.h>
+#include <stdlib.h>
+#include <getopt.h>
+#if defined(HAVE_LIBGDBM)
+#include <gdbm.h>
+#elif defined(HAVE_LIBQDBM)
+#include <hovel.h>
+#elif defined(HAVE_NDBM)
+#include <ndbm.h>
+#elif defined(HAVE_LIBTC)
+#include <tcbdb.h>
+#endif
+#include "yp.h"
+#include <rpcsvc/ypclnt.h>
+#include <arpa/nameser.h>
+#include <shadow.h>
+
+struct __sgrp {
+ char *sg_name; /* group name */
+ char *sg_passwd; /* group password */
+};
+
+
+#ifndef YPERR_SUCCESS
+#define YPERR_SUCCESS 0
+#endif
+
+static struct timeval UDPTIMEOUT = {5, 0};
+
+static int
+_yp_maplist (const char *server, char *indomain,
+ struct ypmaplist **outmaplist)
+{
+ CLIENT *clnt;
+ struct ypresp_maplist resp;
+ enum clnt_stat result;
+
+ if (indomain == NULL || indomain[0] == '\0')
+ return YPERR_BADARGS;
+
+ memset (&resp, '\0', sizeof (resp));
+ clnt = clnt_create (server, YPPROG, YPVERS, "udp");
+ if (clnt == NULL)
+ exit (1);
+
+ result = clnt_call (clnt, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
+ (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist,
+ (caddr_t) & resp, UDPTIMEOUT);
+
+ if (result != YPERR_SUCCESS)
+ return result;
+ if (resp.status != YP_TRUE)
+ return ypprot_err (resp.status);
+
+ *outmaplist = resp.list;
+ /* We give the list not free, this will be done by ypserv
+ xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
+
+ return YPERR_SUCCESS;
+}
+
+static int
+_yp_master (const char *server, char *indomain, char *inmap, char **outname)
+{
+ CLIENT *clnt;
+ ypreq_nokey req;
+ ypresp_master resp;
+ enum clnt_stat result;
+
+ if (indomain == NULL || indomain[0] == '\0' ||
+ inmap == NULL || inmap[0] == '\0')
+ return YPERR_BADARGS;
+
+ req.domain = indomain;
+ req.map = inmap;
+
+ memset (&resp, '\0', sizeof (resp));
+ clnt = clnt_create (server, YPPROG, YPVERS, "udp");
+ if (clnt == NULL)
+ exit (1);
+ result = clnt_call (clnt, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
+ (caddr_t) & req, (xdrproc_t) xdr_ypresp_master,
+ (caddr_t) & resp, UDPTIMEOUT);
+
+ if (result != YPERR_SUCCESS)
+ return result;
+ if (resp.status != YP_TRUE)
+ return ypprot_err (resp.status);
+
+ *outname = strdup (resp.master);
+ xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
+
+ return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
+}
+
+static char *
+get_canonical_hostname (const char *hostname)
+{
+#if USE_FQDN
+ struct addrinfo hints, *res0, *res1;
+ int error;
+ char *host = NULL;
+
+ memset (&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+#if 0
+ hints.ai_flags = AI_CANONNAME; /* get the official name of the host */
+#endif
+
+ if ((error = getaddrinfo (hostname, NULL, &hints, &res0)))
+ {
+#if 0
+ printf ("getaddrinfo: %s\n", gai_strerror (error));
+#endif
+ return strdup (hostname);
+ }
+
+ res1 = res0;
+
+ while (res1)
+ {
+ char hostbuf[NI_MAXHOST];
+
+ if ((error = getnameinfo (res1->ai_addr, res1->ai_addrlen,
+ (char *)&hostbuf, sizeof (hostbuf),
+ NULL, 0, NI_NAMEREQD)) == 0)
+ {
+ host = strdup (hostbuf);
+ break;
+ }
+#if 0
+ else
+ printf ("getnameinfo: %s\n", gai_strerror (error));
+#endif
+
+ res1 = res1->ai_next;
+ }
+
+ if (host == NULL)
+ host = strdup (res0->ai_canonname);
+
+ freeaddrinfo (res0);
+
+ return host;
+#else
+ return strdup (hostname);
+#endif
+}
+
+/* print theofficial name of the host as returned by DNS */
+static void
+print_hostname (char *param)
+{
+ char hostname[MAXHOSTNAMELEN + 1];
+
+ if (param == NULL)
+ gethostname (hostname, sizeof (hostname));
+ else
+ {
+ strncpy (hostname, param, sizeof (hostname));
+ hostname[sizeof (hostname) - 1] = '\0';
+ }
+
+ printf ("%s\n", get_canonical_hostname (hostname));
+
+ exit (0);
+}
+
+/* Show the master for all maps */
+static void
+print_maps (char *server, char *domain)
+{
+ char *master = NULL, *domainname;
+ struct ypmaplist *ypmap = NULL, *y, *old;
+ int ret;
+
+ if (domain != NULL)
+ domainname = domain;
+ else
+ if ((ret = yp_get_default_domain (&domainname)) != 0)
+ {
+ fprintf (stderr, "can't get local yp domain: %s\n",
+ yperr_string (ret));
+ exit (1);
+ }
+
+ server = get_canonical_hostname (server);
+
+ ret = _yp_maplist (server, domainname, &ypmap);
+ switch (ret)
+ {
+ case YPERR_SUCCESS:
+ for (y = ypmap; y;)
+ {
+ ret = _yp_master (server, domainname, y->map, &master);
+ if (ret == YPERR_SUCCESS)
+ {
+ if (strcasecmp (server, master) == 0)
+ printf ("%s\n", y->map);
+
+ free (master);
+ }
+ old = y;
+ y = y->next;
+ free (old);
+ }
+ break;
+ default:
+#if 0
+ printf ("_yp_maplist %s\n", yperr_string (ret));
+#endif
+ exit (1);
+ }
+
+ free (server);
+ exit (0);
+}
+
+static void
+merge_passwd (char *passwd, char *shadow)
+{
+ FILE *p_input, *s_input;
+ struct passwd *pwd;
+ struct spwd *spd;
+
+ p_input = fopen (passwd, "r");
+ if (p_input == NULL)
+ {
+ fprintf (stderr, "yphelper: Cannot open %s\n", passwd);
+ exit (1);
+ }
+
+ s_input = fopen (shadow, "r");
+ if (s_input == NULL)
+ {
+ fclose (p_input);
+ fprintf (stderr, "yphelper: Cannot open %s\n", shadow);
+ exit (1);
+ }
+
+ while ((pwd = fgetpwent (p_input)) != NULL)
+ {
+ char *pass;
+
+ if (pwd->pw_name[0] == '-' || pwd->pw_name[0] == '+' ||
+ pwd->pw_name == NULL || pwd->pw_name[0] == '\0')
+ continue;
+
+ /* If we found an passwd entry which could have a shadow
+ password, we try the following:
+ At first, try the next entry in the shadow file. If we
+ have luck, the shadow file is sorted in the same order
+ then as the passwd file is. If not, try the whole shadow
+ file. */
+
+ /* Some systems and old programs uses '*' as marker for shadow! */
+ if (pwd->pw_passwd[1] == '\0' &&
+ (pwd->pw_passwd[0] == 'x' || pwd->pw_passwd[0] == '*'))
+ {
+ pass = NULL;
+ spd = fgetspent (s_input);
+ if (spd != NULL)
+ {
+ if (strcmp (pwd->pw_name, spd->sp_namp) == 0)
+ pass = spd->sp_pwdp;
+ }
+ if (pass == NULL)
+ {
+ rewind (s_input);
+ while ((spd = fgetspent (s_input)) != NULL)
+ {
+ if (strcmp (pwd->pw_name, spd->sp_namp) == 0)
+ {
+ pass = spd->sp_pwdp;
+ break;
+ }
+ }
+ }
+ if (pass == NULL)
+ pass = pwd->pw_passwd;
+ }
+ else
+ pass = pwd->pw_passwd;
+
+ fprintf (stdout, "%s:%s:%d:%d:%s:%s:%s\n",
+ pwd->pw_name, pass, pwd->pw_uid,
+ pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
+ pwd->pw_shell);
+ }
+ fclose (p_input);
+ fclose (s_input);
+
+ exit (0);
+}
+
+static struct __sgrp *
+fgetsgent (FILE *fp)
+{
+ static struct __sgrp sgroup;
+ static char sgrbuf[BUFSIZ*4];
+ char *cp;
+
+ if (! fp)
+ return 0;
+
+ if (fgets (sgrbuf, sizeof (sgrbuf), fp) != (char *) 0)
+ {
+ if ((cp = strchr (sgrbuf, '\n')))
+ *cp = '\0';
+
+ sgroup.sg_name = sgrbuf;
+ if ((cp = strchr (sgrbuf, ':')))
+ *cp++ = '\0';
+
+ if (cp == NULL)
+ return 0;
+
+ sgroup.sg_passwd = cp;
+ if ((cp = strchr (cp, ':')))
+ *cp++ = '\0';
+
+ return &sgroup;
+ }
+ return 0;
+}
+
+static void
+merge_group (char *group, char *gshadow)
+{
+ FILE *g_input, *s_input;
+ struct group *grp;
+ struct __sgrp *spd;
+ int i;
+
+ g_input = fopen (group, "r");
+ if (g_input == NULL)
+ {
+ fprintf (stderr, "yphelper: Cannot open %s\n", group);
+ exit (1);
+ }
+
+ s_input = fopen (gshadow, "r");
+ if (s_input == NULL)
+ {
+ fclose (g_input);
+ fprintf (stderr, "yphelper: Cannot open %s\n", gshadow);
+ exit (1);
+ }
+
+ while ((grp = fgetgrent (g_input)) != NULL)
+ {
+ char *pass;
+
+ if (grp->gr_name[0] == '-' || grp->gr_name[0] == '+' ||
+ grp->gr_name == NULL || grp->gr_name[0] == '\0')
+ continue;
+
+ /* If we found an group entry which could have a shadow
+ password, we try the following:
+ At first, try the next entry in the gshadow file. If we
+ have luck, the gshadow file is sorted in the same order
+ then as the group file is. If not, try the whole gshadow
+ file. */
+ /* Some systems and old programs uses '*' as marker for shadow! */
+ if (grp->gr_passwd[1] == '\0' &&
+ (grp->gr_passwd[0] == 'x' || grp->gr_passwd[0] == '*'))
+ {
+ pass = NULL;
+
+ spd = fgetsgent (s_input);
+ if (spd != NULL)
+ {
+ if (strcmp (grp->gr_name, spd->sg_name) == 0)
+ pass = spd->sg_passwd;
+ }
+ if (pass == NULL)
+ {
+ rewind (s_input);
+ while ((spd = fgetsgent (s_input)) != NULL)
+ {
+ if (strcmp (grp->gr_name, spd->sg_name) == 0)
+ {
+ pass = spd->sg_passwd;
+ break;
+ }
+ }
+ }
+
+ if (pass == NULL)
+ pass = grp->gr_passwd;
+ }
+ else
+ pass = grp->gr_passwd;
+
+ fprintf (stdout, "%s:%s:%d:", grp->gr_name, pass, grp->gr_gid);
+ i = 0;
+ while (grp->gr_mem[i] != NULL)
+ {
+ if (i != 0)
+ fprintf (stdout, ",");
+ fprintf (stdout, "%s", grp->gr_mem[i]);
+ ++i;
+ }
+ printf ("\n");
+ }
+ fclose (g_input);
+ fclose (s_input);
+
+ exit (0);
+}
+
+static char *
+get_dbm_entry (char *key, char *map, char *domainname)
+{
+ static char mappath[MAXPATHLEN + 2];
+ char *val;
+ datum dkey, dval;
+#if defined(HAVE_COMPAT_LIBGDBM)
+ GDBM_FILE dbm;
+#elif defined (HAVE_NDBM)
+ DBM *dbm;
+#elif defined (HAVE_LIBTC)
+ TCBDB *dbm;
+#endif
+
+ if (strlen (YPMAPDIR) + strlen (domainname) + strlen (map) + 3 < MAXPATHLEN)
+ sprintf (mappath, "%s/%s/%s", YPMAPDIR, domainname, map);
+ else
+ {
+ fprintf (stderr, "yphelper: path to long: %s/%s/%s\n", YPMAPDIR, domainname, map);
+ exit (1);
+ }
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dbm = gdbm_open (mappath, 0, GDBM_READER, 0600, NULL);
+#elif defined(HAVE_NDBM)
+ dbm = dbm_open (mappath, O_RDONLY, 0600);
+#elif defined(HAVE_LIBTC)
+ dbm = tcbdbnew();
+ if (!tcbdbopen(dbm, mappath, BDBOREADER | BDBONOLCK))
+ {
+ tcbdbdel(dbm);
+ dbm = NULL;
+ }
+#endif
+ if (dbm == NULL)
+ {
+ fprintf (stderr, "yphelper: cannot open %s\n", mappath);
+ fprintf (stderr, "yphelper: consider rebuilding maps using ypinit\n");
+ exit (1);
+ }
+
+ dkey.dptr = key;
+ dkey.dsize = strlen (dkey.dptr);
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dval = gdbm_fetch (dbm, dkey);
+#elif defined(HAVE_NDBM)
+ dval = dbm_fetch (dbm, dkey);
+#elif defined(HAVE_LIBTC)
+ dval.dptr = tcbdbget (dbm, dkey.dptr, dkey.dsize, &dval.dsize);
+#endif
+ if (dval.dptr == NULL)
+ val = NULL;
+ else
+ {
+ val = malloc (dval.dsize + 1);
+ strncpy (val, dval.dptr, dval.dsize);
+ val[dval.dsize] = 0;
+ }
+#if defined(HAVE_COMPAT_LIBGDBM)
+ gdbm_close (dbm);
+#elif defined(HAVE_NDBM)
+ dbm_close (dbm);
+#elif defined(HAVE_LIBTC)
+ tcbdbclose (dbm);
+ tcbdbdel (dbm);
+#endif
+ return val;
+}
+
+/* Show the master for all maps */
+static void
+is_master (char *map, char *domainname, char *host)
+{
+ char h_tmp[MAXHOSTNAMELEN+1];
+ char *hostname, *val;
+ int ret;
+
+ if (host)
+ hostname = host;
+ else
+ {
+ if (gethostname (h_tmp, sizeof (h_tmp)) != 0)
+ {
+ perror ("gethostname");
+ exit (1);
+ }
+ hostname = h_tmp;
+ }
+
+ hostname = get_canonical_hostname (hostname);
+
+ if (strcasecmp (hostname,
+ (val = get_dbm_entry ("YP_MASTER_NAME", map, domainname)))
+ == 0)
+ ret = 0;
+ else
+ ret = 1;
+
+ free(hostname);
+ exit (ret);
+}
+
+static void
+Warning (void)
+{
+ fprintf (stderr, "yphelper: This program is for internal use from some\n");
+ fprintf (stderr, " ypserv scripts and should never be called\n");
+ fprintf (stderr, " from a terminal\n");
+ exit (1);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int hostname = 0;
+ char *master = NULL;
+ char *domainname = NULL;
+ char *map = NULL;
+ int merge_pwd = 0;
+ int merge_grp = 0;
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"hostname", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {"maps", required_argument, NULL, 'm'},
+ {"merge_passwd", no_argument, NULL, 'p'},
+ {"merge-passwd", no_argument, NULL, 'p'},
+ {"merge_group", no_argument, NULL, 'g'},
+ {"merge-group", no_argument, NULL, 'g'},
+ {"domainname", required_argument, NULL, 'd'},
+ {"is_master", required_argument, NULL, 'i'},
+ {"is-master", required_argument, NULL, 'i'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "d:hvm:pgi:", long_options, &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'd':
+ domainname = optarg;
+ break;
+ case 'h':
+ ++hostname;
+ break;
+ case 'm':
+ master = optarg;
+ break;
+ case 'p':
+ merge_pwd = 1;
+ break;
+ case 'g':
+ merge_grp = 1;
+ break;
+ case 'v':
+ printf ("yphelper (%s) %s", PACKAGE, VERSION);
+ exit (0);
+ case 'i':
+ map = optarg;
+ break;
+ default:
+ Warning ();
+ return 1;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (hostname)
+ {
+ if (argc == 0)
+ print_hostname (NULL);
+ else
+ print_hostname (argv[0]);
+ }
+
+ if (merge_pwd && argc == 2)
+ merge_passwd (argv[0], argv[1]);
+
+ if (merge_grp && argc == 2)
+ merge_group (argv[0], argv[1]);
+
+ if (domainname == NULL)
+ {
+ int ret;
+
+ if ((ret = yp_get_default_domain (&domainname)) != 0)
+ {
+ fprintf (stderr, "can't get local yp domain: %s\n",
+ yperr_string (ret));
+ exit (1);
+ }
+ }
+
+ if (master != NULL)
+ print_maps (master, domainname);
+
+ if (map)
+ is_master (map, domainname, NULL);
+
+ Warning ();
+ return 1;
+}
diff --git a/yppush/Makefile.am b/yppush/Makefile.am
new file mode 100644
index 0000000..08057c8
--- /dev/null
+++ b/yppush/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2000, 2001, 2003, 2007, 2009 Thorsten Kukuk <kukuk@linux-nis.org>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DCONFDIR=\"$(sysconfdir)\" -DYPMAPDIR=\"@YPMAPDIR@\" \
+ -DUSE_FQDN=@USE_FQDN@
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+
+CLEANFILES = *~ ${MANS}
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = yppush.8
+XMLS = yppush.8.xml
+
+sbin_PROGRAMS = yppush
+
+yppush_SOURCES = yppush.c
+
+yppush_LDADD = @PIE_LDFLAGS@ @LIBDBM@ $(top_builddir)/lib/libyp.a \
+ @NSL_LIBS@ @TIRPC_LIBS@
+yppush_CFLAGS = @PIE_CFLAGS@ @NSL_CFLAGS@ @TIRPC_CFLAGS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/yppush/yppush.8.xml b/yppush/yppush.8.xml
new file mode 100644
index 0000000..2243312
--- /dev/null
+++ b/yppush/yppush.8.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='yppush'>
+
+ <refmeta>
+ <refentrytitle>yppush</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>yppush</refname>
+ <refpurpose>force propagation of changed NIS databases</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+ <command>/usr/sbin/yppush</command>
+ <arg choice='opt'>-d <replaceable>domain</replaceable></arg>
+ <arg choice='opt'>-t <replaceable>timeout</replaceable></arg>
+ <group choice='opt'>
+ <arg choice='plain'>--parallel <replaceable>#</replaceable></arg>
+ <arg choice='plain'>--port <replaceable>port</replaceable></arg>
+ </group>
+ <arg choice='opt'>-h <replaceable>host</replaceable></arg>
+ <arg choice='opt'>-v</arg>
+ <arg choice='plain' rep='repeat'><replaceable>mapname</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><emphasis remap='B'>yppush</emphasis>
+copies updated NIS databases (or maps) from the master NIS server to
+the slave servers within a NIS domain. It is normally run only on
+the NIS master by
+<emphasis remap='I'>/var/yp/Makefile</emphasis>
+after the master databases are changed.
+<emphasis remap='I'>/var/yp/Makefile</emphasis>
+does not invoke
+<emphasis remap='B'>yppush</emphasis>
+by default, the
+<emphasis remap='B'>NOPUSH=true</emphasis>
+line must be commented out.
+<!-- .br -->
+<emphasis remap='B'>yppush</emphasis>
+first constructs a list of NIS slave servers by reading the NIS map
+<emphasis remap='B'>ypservers</emphasis>
+within the
+<emphasis remap='I'>domain.</emphasis>
+A destination host (or a list of hosts with multiple -h commands)
+can also be specified on the command line.
+A "transfer map" request is sent to the NIS server at each slave, along
+with the information needed by the transfer agent ypxfr(8) to callback
+to yppush, which may be printed the result to stderr. Messages are
+also printed when a transfer is not possible; for instance when the request
+message is undeliverable.</para>
+<para>
+To specify a port number or use any other
+<emphasis remap='B'>yppush</emphasis> options you can edit
+<emphasis remap='I'>/var/yp/Makefile</emphasis> directly.</para>
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-d </option><emphasis remap='I'>domain</emphasis></term>
+ <listitem>
+<para>Specify a particular domain. The NIS domain of the local host system is
+used by default. If the local host's domain name is not set, the domain
+name must be specified with this flag.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-t </option><emphasis remap='I'>timeout</emphasis></term>
+ <listitem>
+<para>The timeout flag is used to specify a timeout value in seconds. This timeout
+controls how long
+<emphasis remap='B'>yppush</emphasis>
+will wait for a response from a slave server before sending a
+map transfer request to the next slave server in the list.
+By default,
+<emphasis remap='B'>yppush</emphasis>
+will wait 90 seconds. For big maps, this is not long enough.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--parallel</option><replaceable> #</replaceable>,<option> -p </option><replaceable>#</replaceable></term>
+ <listitem>
+<para><emphasis remap='B'>yppush</emphasis>
+normally performs transfers serially, meaning that it will
+send a map transfer request to one slave server and then wait for
+it to respond before sending the next map transfer request to the
+next slave server. In environments with many slaves, it is more
+efficient to initiate several map transfers at once so that the
+transfers can take place in parallel.
+It is not possible to run in parallel and assign a fixed port with
+the
+<option>--port</option>
+flag</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--port </option><emphasis remap='I'>port</emphasis></term>
+ <listitem>
+<para>specify a port for
+<emphasis remap='B'>yppush</emphasis>
+to listen on. By default,
+<emphasis remap='B'>yppush</emphasis>
+will ask
+<emphasis remap='B'>portmap(8)</emphasis>
+to assign it a random port number.
+It is not possible to assign a port with this option and run in parallel with
+the
+<option>--parallel</option>
+or
+<option>-p</option>
+flag</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h </option><emphasis remap='I'>host</emphasis></term>
+ <listitem>
+<para>The host flag can be used to transfer a map to a user-specified machine or
+group of machines instead of the list of servers contained in
+the
+<emphasis remap='B'>ypservers</emphasis>
+map. A list of hosts can be specified by using multiple
+instances of the
+<option>-h</option>
+flag.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option></term>
+ <listitem>
+<para>Verbose mode: causes
+<emphasis remap='B'>yppush</emphasis>
+to print debugging messages as it runs. Note specifying this flag twice
+makes
+<emphasis remap='B'>yppush</emphasis>
+even more verbose.</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>domainname</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypxfr</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+
+</refsect1>
+
+<refsect1 id='bugs'><title>BUGS</title>
+<para>The mechanism for transferring NIS maps in NIS v1 is different
+that that in NIS version 2. This version of
+<emphasis remap='B'>yppush</emphasis>
+has support for transferring maps to NIS v2 systems only.</para>
+
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;</para>
+</refsect1>
+</refentry>
diff --git a/yppush/yppush.c b/yppush/yppush.c
new file mode 100644
index 0000000..f919d01
--- /dev/null
+++ b/yppush/yppush.c
@@ -0,0 +1,922 @@
+/* Copyright (c) 1996-2005, 2014, 2015, 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <rpc/rpc.h>
+#include <time.h>
+#include "yp.h"
+#include <rpcsvc/ypclnt.h>
+#include <rpc/svc.h>
+#include <arpa/inet.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <errno.h>
+#include <string.h>
+#include <memory.h>
+#if defined(HAVE_LIBGDBM)
+#include <gdbm.h>
+#elif defined(HAVE_LIBQDBM)
+#include <hovel.h>
+#elif defined(HAVE_NDBM)
+#include <ndbm.h>
+#include <fcntl.h>
+#elif defined(HAVE_LIBTC)
+#include <tcbdb.h>
+#endif
+#include <getopt.h>
+
+#include "log_msg.h"
+
+struct hostlist {
+ char *hostname;
+ struct hostlist *next;
+};
+
+struct hostlist *hostliste = NULL;
+
+static char *DomainName = NULL;
+int verbose_flag = 0;
+static char local_hostname[MAXHOSTNAMELEN + 2];
+static char *current_map;
+static u_int CallbackProg = 0;
+static u_int timeout = 90;
+static u_int MapOrderNum;
+static u_int maxchildren = 1;
+static u_int children = 0;
+static int my_port = -1;
+
+
+static char *
+yppush_err_string (enum yppush_status status)
+{
+ switch (status)
+ {
+ case YPPUSH_SUCC:
+ return "Success";
+ case YPPUSH_AGE:
+ return "Master's version not newer";
+ case YPPUSH_NOMAP:
+ return "Can't find server for map";
+ case YPPUSH_NODOM:
+ return "Domain not supported";
+ case YPPUSH_RSRC:
+ return "Local resource alloc failure";
+ case YPPUSH_RPC:
+ return "RPC failure talking to server";
+ case YPPUSH_MADDR:
+ return "Can't get master address";
+ case YPPUSH_YPERR:
+ return "YP server/map db error";
+ case YPPUSH_BADARGS:
+ return "Request arguments bad";
+ case YPPUSH_DBM:
+ return "Local dbm operation failed";
+ case YPPUSH_FILE:
+ return "Local file I/O operation failed";
+ case YPPUSH_SKEW:
+ return "Map version skew during transfer";
+ case YPPUSH_CLEAR:
+ return "Can't send \"Clear\" req to local ypserv";
+ case YPPUSH_FORCE:
+ return "No local order number in map use -f flag.";
+ case YPPUSH_XFRERR:
+ return "ypxfr error";
+ case YPPUSH_REFUSED:
+ return "Transfer request refused by ypserv";
+ case YPPUSH_NOALIAS:
+ return "Alias not found for map or domain";
+ }
+ return "YPPUSH: Unknown Error, this should not happen!";
+}
+
+bool_t
+yppushproc_null_1_svc (void *req UNUSED,
+ void *resp UNUSED,
+ struct svc_req *rqstp UNUSED)
+{
+ resp = NULL;
+
+ if (verbose_flag > 1)
+ log_msg ("yppushproc_null_1_svc");
+
+ return TRUE;
+}
+
+
+bool_t
+yppushproc_xfrresp_1_svc (yppushresp_xfr *req,
+ void *resp UNUSED, struct svc_req *rqstp)
+{
+ char hostbuf[NI_MAXHOST];
+ struct netconfig *nconf;
+ struct netbuf *nbuf;
+
+ if (verbose_flag > 1)
+ log_msg ("yppushproc_xfrresp_1_svc");
+
+ nbuf = svc_getrpccaller (rqstp->rq_xprt);
+ nconf = getnetconfigent (rqstp->rq_xprt->xp_netid);
+
+ if (verbose_flag)
+ {
+ log_msg ("Status received from ypxfr on %s",
+ taddr2host (nconf, nbuf, hostbuf, sizeof (hostbuf)));
+ log_msg ("\tTransfer %sdone: %s",
+ req->status == YPPUSH_SUCC ? "" : "not ",
+ yppush_err_string (req->status));
+ }
+ else if (req->status != YPPUSH_SUCC)
+ log_msg ("%s: %s", taddr2host (nconf, nbuf, hostbuf, sizeof (hostbuf)),
+ yppush_err_string (req->status));
+ freenetconfigent (nconf);
+
+ return TRUE;
+}
+
+static void
+yppush_xfrrespprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+ union {
+ yppushresp_xfr yppushproc_xfrresp_1_arg;
+ } argument;
+ bool_t retval;
+ xdrproc_t _xdr_argument, _xdr_result;
+ bool_t (*local)(char *, void *, struct svc_req *);
+
+ if (verbose_flag > 1)
+ log_msg ("yppush_xfrrespprog_1");
+
+ switch (rqstp->rq_proc) {
+ case YPPUSHPROC_NULL:
+ _xdr_argument = (xdrproc_t) xdr_void;
+ _xdr_result = (xdrproc_t) xdr_void;
+ local = (bool_t (*) (char *, void *, struct svc_req *))yppushproc_null_1_svc;
+ break;
+
+ case YPPUSHPROC_XFRRESP:
+ _xdr_argument = (xdrproc_t) xdr_yppushresp_xfr;
+ _xdr_result = (xdrproc_t) xdr_void;
+ local = (bool_t (*) (char *, void *, struct svc_req *))yppushproc_xfrresp_1_svc;
+ break;
+
+ default:
+ svcerr_noproc (transp);
+ return;
+ }
+ memset ((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument))
+ {
+ char hostbuf[NI_MAXHOST];
+ struct netconfig *nconf;
+ struct netbuf *nbuf = svc_getrpccaller (rqstp->rq_xprt);
+
+ nconf = getnetconfigent (rqstp->rq_xprt->xp_netid);
+
+ log_msg ("cannot decode arguments for %d from %s",
+ rqstp->rq_proc,
+ taddr2host (nconf, nbuf, hostbuf, sizeof (hostbuf)));
+ /* try to free already allocated memory during decoding */
+ svc_freeargs (transp, _xdr_argument, (caddr_t) &argument);
+ freenetconfigent (nconf);
+ svcerr_decode (transp);
+ return;
+ }
+ retval = (bool_t) (*local)((char *)&argument, NULL, rqstp);
+ if (retval > 0 && !svc_sendreply(transp, _xdr_result, NULL))
+ {
+ svcerr_systemerr (transp);
+ }
+ if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument)) {
+ log_msg ("unable to free arguments");
+ exit (1);
+ }
+
+ if (rqstp->rq_proc != YPPUSHPROC_NULL)
+ exit (0);
+
+ return;
+}
+
+static void
+yppush_svc_run (char *target)
+{
+ fd_set readfds;
+ struct timeval tr, tb;
+
+ tb.tv_sec = timeout;
+ tb.tv_usec = 0;
+ tr = tb;
+
+ for (;;)
+ {
+ readfds = svc_fdset;
+
+ switch (select (svc_maxfd+1, &readfds, (void *) 0, (void *) 0, &tr))
+ {
+ case -1:
+ if (errno == EINTR)
+ {
+ tr = tb; /* Read the Linux select.2 manpage ! */
+ continue;
+ }
+ log_msg ("yppush_svc_run: - select failed (%s)", strerror (errno));
+ return;
+ case 0:
+ log_msg ("%s->%s: Callback timed out", current_map, target);
+ exit (0);
+ default:
+ svc_getreqset (&readfds);
+ break;
+ }
+ }
+}
+
+static char *
+get_dbm_entry (char *key)
+{
+ static char mappath[MAXPATHLEN + 2];
+ char *val;
+ datum dkey, dval;
+#if defined(HAVE_COMPAT_LIBGDBM)
+ GDBM_FILE dbm;
+#elif defined (HAVE_NDBM)
+ DBM *dbm;
+#elif defined (HAVE_LIBTC)
+ TCBDB *dbm;
+#endif
+
+ if (strlen (YPMAPDIR) + strlen (DomainName) + strlen (current_map) + 3 < MAXPATHLEN)
+ sprintf (mappath, "%s/%s/%s", YPMAPDIR, DomainName, current_map);
+ else
+ {
+ log_msg ("YPPUSH ERROR: Path to long: %s/%s/%s", YPMAPDIR, DomainName, current_map);
+ exit (1);
+ }
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dbm = gdbm_open (mappath, 0, GDBM_READER, 0600, NULL);
+#elif defined(HAVE_NDBM)
+ dbm = dbm_open (mappath, O_RDONLY, 0600);
+#elif defined(HAVE_LIBTC)
+ dbm = tcbdbnew();
+ if (!tcbdbopen(dbm, mappath, BDBOREADER | BDBONOLCK))
+ {
+ tcbdbdel(dbm);
+ dbm = NULL;
+ }
+#endif
+ if (dbm == NULL)
+ {
+ log_msg ("YPPUSH: Cannot open %s", mappath);
+ log_msg ("YPPUSH: consider rebuilding maps using ypinit");
+ exit (1);
+ }
+
+ dkey.dptr = key;
+ dkey.dsize = strlen (dkey.dptr);
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dval = gdbm_fetch (dbm, dkey);
+#elif defined(HAVE_NDBM)
+ dval = dbm_fetch (dbm, dkey);
+#elif defined(HAVE_LIBTC)
+ dval.dptr = tcbdbget (dbm, dkey.dptr, dkey.dsize, &dval.dsize);
+#endif
+ if (dval.dptr == NULL)
+ val = NULL;
+ else
+ {
+ val = malloc (dval.dsize + 1);
+ strncpy (val, dval.dptr, dval.dsize);
+ val[dval.dsize] = 0;
+ }
+#if defined(HAVE_COMPAT_LIBGDBM)
+ gdbm_close (dbm);
+#elif defined(HAVE_NDBM)
+ dbm_close (dbm);
+#elif defined(HAVE_LIBTC)
+ tcbdbclose (dbm);
+ tcbdbdel (dbm);
+#endif
+ return val;
+}
+
+static u_int
+getordernum (void)
+{
+ char *val;
+ u_int i;
+
+ val = get_dbm_entry ("YP_LAST_MODIFIED");
+
+ if (val == NULL)
+ {
+ if (verbose_flag > 1)
+ log_msg ("YPPUSH ERROR: Cannot determine order number for %s", current_map);
+ free (val);
+ return 0;
+ }
+
+ for (i = 0; i < strlen (val); ++i)
+ {
+ if (!isdigit (val[i]))
+ {
+ log_msg ("YPPUSH ERROR: Order number '%s' in map %s is invalid!",
+ current_map, val);
+ free (val);
+ return 0;
+ }
+ }
+
+ i = atoi (val);
+ free (val);
+ return i;
+}
+
+/* Create with the ypservers or slaves.hostname map a list with all
+ slave servers we should send the new map */
+
+/* NetBSD has a different prototype in struct ypall_callback */
+#if defined(__NetBSD__)
+static int
+add_slave_server (u_long status, char *key, int keylen,
+ char *val, int vallen, void *data UNUSED)
+#else
+static int
+add_slave_server (int status, char *key, int keylen,
+ char *val, int vallen, char *data UNUSED)
+#endif
+{
+ char host[YPMAXPEER + 2];
+ struct hostlist *tmp;
+
+ if (verbose_flag > 1)
+ log_msg ("add_slave_server: Key=%.*s, Val=%.*s, status=%d", keylen, key,
+ vallen, val, status);
+
+ if (status != YP_TRUE)
+ return status;
+
+ if (vallen < YPMAXPEER)
+ sprintf (host, "%.*s", vallen, val);
+ else
+ {
+ log_msg ("YPPUSH ERROR: add_slave_server: %.*s to long", vallen, val);
+ exit (1);
+ }
+
+ /* Do not add ourself! But don't put to much work into it. If
+ the ypserver entry does not much the local name, we can also
+ send the data to ourself. Better then to ignore a host only
+ because it starts with the same name but is in a different
+ domain. */
+ if (strcasecmp (local_hostname, host) == 0)
+ {
+ if (verbose_flag > 1)
+ log_msg ("YPPUSH INFO: skipping %s", host);
+ return 0;
+ }
+
+ if ((tmp = (struct hostlist *) malloc (sizeof (struct hostlist))) == NULL)
+ {
+ log_msg ("malloc() failed: %s", strerror (errno));
+ return -1;
+ }
+ tmp->hostname = strdup (host);
+ tmp->next = hostliste;
+ hostliste = tmp;
+
+ return 0;
+}
+
+static void
+child_sig_int (int sig UNUSED)
+{
+ if (CallbackProg != 0)
+ svc_unreg (CallbackProg, 1);
+ exit (1);
+}
+
+static int
+yppush_foreach (const char *host)
+{
+ SVCXPRT *CallbackXprt;
+ CLIENT *PushClient;
+ struct ypreq_newxfr newreq;
+ struct timeval tv = {10, 0};
+ u_int transid;
+ char server[YPMAXPEER + 2];
+ int i, sock;
+ struct sigaction sig;
+ struct netconfig *nconf;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ enum clnt_stat res;
+
+ if (verbose_flag > 1)
+ log_msg ("yppush_foreach: host=%s", host);
+
+ sig.sa_handler = child_sig_int;
+ sigemptyset (&sig.sa_mask);
+ sig.sa_flags = SA_NOMASK;
+ /* Do not prevent the signal from being
+ received from within its own signal handler. */
+ sigaction (SIGINT, &sig, NULL);
+
+ if (strlen (host) < YPMAXPEER)
+ sprintf (server, "%s", host);
+ else
+ {
+ log_msg ("YPPUSH ERROR: yppush_foreach: %s to long", host);
+ exit (1);
+ }
+
+ PushClient = clnt_create (server, YPPROG, YPVERS, "datagram_n");
+ if (PushClient == NULL)
+ {
+ clnt_pcreateerror (server);
+ return 1;
+ }
+
+ /* Register a socket for IPv4 and, if supported, for IPv6, too */
+ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ {
+ log_msg ("Cannot create UDP socket for AF_INET: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ memset (&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (my_port > 0)
+ sin.sin_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin;
+
+ if (bindresvport_sa (sock, sa) == -1)
+ {
+ if (my_port > 0)
+ log_msg ("Cannot bind to reserved port %d (%s)",
+ my_port, strerror (errno));
+ else
+ log_msg ("bindresvport failed: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ if ((CallbackXprt = svc_dg_create (sock, 0, 0)) == NULL)
+ {
+ log_msg ("terminating: cannot create rpcbind handle");
+ return 1;
+ }
+
+ nconf = getnetconfigent ("udp");
+ if (nconf == NULL)
+ {
+ log_msg ("YPPUSH: getnetconfigent (\"udp\") failed.");
+ exit (1);
+ }
+ for (CallbackProg = 0x40000000; CallbackProg < 0x5fffffff; CallbackProg++)
+ {
+ if (svc_reg (CallbackXprt, CallbackProg, 1,
+ yppush_xfrrespprog_1, nconf))
+ break;
+ }
+ freenetconfigent (nconf);
+
+ if (CallbackProg == 0x5FFFFFFF)
+ {
+ log_msg ("can't register yppush_xfrrespprog_1");
+ exit (1);
+ }
+ else if (verbose_flag > 1)
+ log_msg ("yppush_xfrrespprog_1 registered at %x", CallbackProg);
+
+ /* And now do the same for IPv6 */
+ if ((sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0)
+ {
+ /* Disallow v4-in-v6 to allow host-based access checks */
+ if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &i, sizeof(i)) == -1)
+ {
+ log_msg ("ERROR: cannot disable v4-in-v6 on %s6 socket",
+ nconf->nc_proto);
+ return 1;
+ }
+ memset (&sin6, 0, sizeof (sin6));
+ sin6.sin6_family = AF_INET6;
+ if (my_port > 0)
+ sin6.sin6_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin6;
+
+ if (bindresvport_sa (sock, sa) == -1)
+ {
+ if (my_port > 0)
+ log_msg ("Cannot bind to reserved port %d (%s)",
+ my_port, strerror (errno));
+ else
+ log_msg ("bindresvport failed: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ if ((CallbackXprt = svc_dg_create (sock, 0, 0)) == NULL)
+ {
+ log_msg ("terminating: cannot create rpcbind handle");
+ return 1;
+ }
+
+ nconf = getnetconfigent ("udp6");
+ if (nconf == NULL)
+ {
+ log_msg ("YPPUSH: getnetconfigent (\"udp6\") failed.");
+ exit (1);
+ }
+ if (!svc_reg (CallbackXprt, CallbackProg, 1,
+ yppush_xfrrespprog_1, nconf))
+ log_msg ("YPPUSH: couldn't register IPv6");
+ freenetconfigent (nconf);
+ }
+ else if (errno != EAFNOSUPPORT)
+ {
+ log_msg ("Cannot create UDP socket for AF_INET6: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ switch (transid = fork ())
+ {
+ case -1:
+ perror ("Cannot fork");
+ exit (-1);
+ case 0:
+ yppush_svc_run (server);
+ exit (0);
+ default:
+ newreq.map_parms.domain = (char *) DomainName;
+ newreq.map_parms.map = (char *) current_map;
+ /* local_hostname is correct since we have compared it
+ with YP_MASTER_NAME. */
+ newreq.map_parms.owner = local_hostname;
+ newreq.map_parms.ordernum = MapOrderNum;
+ newreq.transid = transid;
+ newreq.proto = CallbackProg;
+ // req.port = CallbackXprt->xp_port;
+ newreq.name = server;
+
+ if (verbose_flag)
+ {
+ log_msg ("%s has been called.", server);
+ if (verbose_flag > 1)
+ {
+ log_msg ("\t->target: %s", server);
+ log_msg ("\t->domain: %s", newreq.map_parms.domain);
+ log_msg ("\t->map: %s", newreq.map_parms.map);
+ log_msg ("\t->tarnsid: %d", newreq.transid);
+ log_msg ("\t->proto: %d", newreq.proto);
+ log_msg ("\t->master: %s", newreq.map_parms.owner);
+ log_msg ("\t->ordernum: %d", newreq.map_parms.ordernum);
+ log_msg ("\t->name: %s", newreq.name);
+ }
+ }
+
+
+ res = clnt_call (PushClient, YPPROC_NEWXFR, (xdrproc_t) xdr_ypreq_newxfr,
+ (caddr_t) &newreq, (xdrproc_t) xdr_void, NULL, tv);
+
+ if (res == RPC_PROCUNAVAIL)
+ {
+ struct ypreq_xfr oldreq;
+
+ oldreq.map_parms.domain = (char *) DomainName;
+ oldreq.map_parms.map = (char *) current_map;
+ oldreq.map_parms.owner = local_hostname;
+ oldreq.map_parms.ordernum = MapOrderNum;
+ oldreq.transid = transid;
+ oldreq.proto = CallbackProg;
+ oldreq.port = 0; /* we don't really need that */
+
+ res = clnt_call (PushClient, YPPROC_XFR, (xdrproc_t) xdr_ypreq_xfr,
+ (caddr_t) &oldreq, (xdrproc_t) xdr_void, NULL, tv);
+ }
+
+ if (res != RPC_SUCCESS)
+ {
+ log_msg ("YPPUSH: Cannot call YPPROC_XFR on host \"%s\"%s", server,
+ clnt_sperror (PushClient, ""));
+ kill (transid, SIGTERM);
+ }
+
+ waitpid (transid, &sock, 0);
+ svc_unreg (CallbackProg, 1);
+ CallbackProg = 0;
+ if (PushClient != NULL)
+ {
+ clnt_destroy (PushClient);
+ PushClient = NULL;
+ }
+ }
+
+ return 0;
+}
+
+static char *
+get_canonical_hostname (const char *hostname)
+{
+#if USE_FQDN
+ struct addrinfo hints, *res0, *res1;
+ int error;
+ char *host = NULL;
+
+ memset (&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+#if 0
+ hints.ai_flags = AI_CANONNAME; /* get the official name of the host */
+#endif
+
+ if ((error = getaddrinfo (hostname, NULL, &hints, &res0)))
+ {
+#if 0
+ printf ("getaddrinfo: %s\n", gai_strerror (error));
+#endif
+ return strdup (hostname);
+ }
+
+ res1 = res0;
+
+ while (res1)
+ {
+ char hostbuf[NI_MAXHOST];
+
+ if ((error = getnameinfo (res1->ai_addr, res1->ai_addrlen,
+ (char *)&hostbuf, sizeof (hostbuf),
+ NULL, 0, NI_NAMEREQD)) == 0)
+ {
+ host = strdup (hostbuf);
+ break;
+ }
+#if 0
+ else
+ printf ("getnameinfo: %s\n", gai_strerror (error));
+#endif
+
+ res1 = res1->ai_next;
+ }
+
+ if (host == NULL)
+ host = strdup (res0->ai_canonname);
+
+ freeaddrinfo (res0);
+
+ return host;
+#else
+ return strdup (hostname);
+#endif
+}
+
+static void
+sig_child (int sig UNUSED)
+{
+ int status;
+ int save_errno = errno;
+
+ while (waitpid (-1, &status, WNOHANG) > 0)
+ {
+ if (verbose_flag > 1)
+ log_msg ("Child %d exits", WEXITSTATUS (status));
+ children--;
+ }
+
+ errno = save_errno;
+}
+
+static inline void
+Usage (int exit_code)
+{
+ log_msg ("Usage:\n yppush [-d domain] [-t timeout] [--parallel # | --port #] [-h host] [-v] mapname ...");
+ log_msg (" yppush --version");
+ exit (exit_code);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct hostlist *tmp;
+ enum ypstat y;
+ struct sigaction sig;
+
+ debug_flag = 1;
+
+ sig.sa_handler = sig_child;
+ sigemptyset (&sig.sa_mask);
+#if defined(linux) || (defined(sun) && defined(__srv4__))
+ sig.sa_flags = SA_NOMASK;
+ /* Do not prevent the signal from being
+ received from within its own signal handler. */
+#endif
+ sigaction (SIGCHLD, &sig, NULL);
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, '\255'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"host", required_argument, NULL, 'h'},
+ {"help", no_argument, NULL, 'u'},
+ {"usage", no_argument, NULL, 'u'},
+ {"parallel", required_argument, NULL, 'p'},
+ {"port", required_argument, NULL, '\254'},
+ {"timeout", required_argument, NULL, 't'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "d:vh:ut:p:j:", long_options, &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'd':
+ DomainName = optarg;
+ break;
+ case 'v':
+ verbose_flag++;
+ break;
+ case 't':
+ timeout = atoi (optarg);
+ break;
+ case 'j':
+ case 'p':
+ maxchildren = atoi (optarg);
+ if (my_port >= 0)
+ {
+ log_msg ("yppush cannot run in parallel with a fixed port");
+ return 1;
+ }
+ break;
+ case 'h':
+ /* we can handle multiple hosts */
+ tmp = (struct hostlist *) malloc (sizeof (struct hostlist));
+ if (tmp == NULL)
+ {
+ log_msg ("malloc() failed: %s", strerror (errno));
+ return 1;
+ }
+ tmp->hostname = strdup (optarg);
+ tmp->next = hostliste;
+ hostliste = tmp;
+ break;
+ case 'u':
+ Usage (0);
+ break;
+ case '\255':
+ log_msg ("yppush (%s) %s", PACKAGE, VERSION);
+ return 0;
+ case '\254':
+ my_port = atoi (optarg);
+ if (maxchildren > 1)
+ {
+ log_msg ("yppush cannot run in parallel with a fixed port");
+ return 1;
+ }
+ if (my_port <= 0 || my_port > 0xffff) {
+ /* Invalid port number */
+ fprintf (stdout, "Warning: yppush: Invalid port %d (0x%x)\n",
+ my_port, my_port);
+ my_port = -1;
+ }
+ break;
+ default:
+ Usage (1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ Usage (1);
+
+ if (DomainName == NULL)
+ {
+ if (yp_get_default_domain (&DomainName) != 0)
+ {
+ log_msg ("YPPUSH: Cannot get default domain");
+ return 1;
+ }
+ if (strlen(DomainName) == 0)
+ {
+ log_msg ("YPPUSH: Domainname not set");
+ return 1;
+ }
+ }
+
+ if (gethostname (local_hostname, MAXHOSTNAMELEN) != 0)
+ {
+ perror ("YPPUSH: gethostname");
+ log_msg ("YPPUSH: Cannot determine local hostname");
+ return 1;
+ }
+ else
+ {
+ char *cp;
+
+ cp = get_canonical_hostname (local_hostname);
+ strncpy (local_hostname, cp, sizeof (local_hostname) -1);
+ }
+
+
+ if (hostliste == NULL)
+ {
+ struct ypall_callback f;
+
+ memset (&f, 0, sizeof f);
+ f.foreach = add_slave_server;
+ y = yp_all (DomainName, "ypservers", &f);
+ if (y && y != YP_NOMORE)
+ {
+ log_msg ("Could not read ypservers map: %d %s", y, yperr_string (y));
+ }
+ }
+
+ while (*argv)
+ {
+ char *val;
+
+ current_map = *argv++;
+ val = get_dbm_entry ("YP_MASTER_NAME");
+ if (val && strcasecmp (val, local_hostname) != 0)
+ {
+ log_msg ("YPPUSH: %s is not the master for %s, try it from %s.",
+ local_hostname, current_map, val);
+ free (val);
+ continue;
+ }
+ else if (val)
+ free (val);
+
+ MapOrderNum = getordernum ();
+#if 0
+ if (MapOrderNum == 0xffffffff)
+ continue;
+#endif
+ tmp = hostliste;
+ while (tmp != NULL)
+ {
+ while (children >= maxchildren)
+ sleep (1);
+ children++;
+ switch (fork ())
+ {
+ case -1:
+ perror ("YPPUSH: Cannot fork");
+ exit (1);
+ case 0:
+ yppush_foreach (tmp->hostname);
+ exit (children);
+ default:
+ if (verbose_flag > 1)
+ log_msg ("Start new child (%d)", children);
+ break;
+ }
+ tmp = tmp->next;
+ }
+ while (children != 0)
+ {
+ sleep (10);
+ if (verbose_flag > 1)
+ log_msg ("Running Children: %d", children);
+ }
+ }
+
+ if (verbose_flag > 1)
+ log_msg ("all done (%d running childs)", children);
+
+ return 0;
+}
diff --git a/ypserv/Makefile.am b/ypserv/Makefile.am
new file mode 100644
index 0000000..500fe9e
--- /dev/null
+++ b/ypserv/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2000, 2001, 2003, 2007, 2009 Thorsten Kukuk <kukuk@linux-nis.org>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPBINDIR=\"$(libexecdir)\" \
+ -DYPMAPDIR=\"@YPMAPDIR@\" -DUSE_FQDN=@USE_FQDN@
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+
+CLEANFILES = *~
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = ypserv.8
+XMLS = ypserv.8.xml
+
+sbin_PROGRAMS = ypserv
+
+ypserv_SOURCES = ypserv.c server.c ypserv_xdr.c
+ypserv_CFLAGS = @PIE_CFLAGS@ @NSL_CFLAGS@ @SYSTEMD_CFLAGS@ @TIRPC_CFLAGS@
+ypserv_LDADD = @PIE_LDFLAGS@ ../lib/libyp.a @NSL_LIBS@ @LIBDBM@ @SYSTEMD_LIBS@ @TIRPC_LIBS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/ypserv/reg_slp.c b/ypserv/reg_slp.c
new file mode 100644
index 0000000..f66fa6b
--- /dev/null
+++ b/ypserv/reg_slp.c
@@ -0,0 +1,301 @@
+/* Copyright (c) 2003, 2004, 2006 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if USE_SLP
+
+#include <netdb.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <slp.h>
+
+#include "reg_slp.h"
+#include "log_msg.h"
+
+#include "ypserv_conf.h"
+
+/* This is the minimum we'll use, irrespective of config setting.
+ definately don't set to less than about 30 seconds. */
+#define SLP_MIN_TIMEOUT 120
+
+static void
+ypservSLPRegReport (SLPHandle hslp UNUSED, SLPError errcode, void* cookie)
+{
+ /* return the error code in the cookie */
+ *(SLPError*)cookie = errcode;
+}
+
+static void
+do_refresh (int sig UNUSED)
+{
+ if (debug_flag)
+ log_msg ("Service registration almost expired, refreshing it");
+ register_slp ();
+}
+
+
+/* the URL we use to register. */
+static char *url = NULL;
+
+static char hostname[1024];
+#if USE_FQDN
+static struct hostent *hp = NULL;
+#endif
+static char *hname;
+
+static
+char *create_domain_attr (void)
+{
+ DIR *dp;
+ struct dirent *dep;
+ char *str = NULL;
+
+ dp = opendir (YPMAPDIR);
+ if (dp == NULL)
+ return NULL;
+
+ while ((dep = readdir (dp)) != NULL)
+ {
+ struct stat st;
+
+ /* ignore files starting with . */
+ if (dep->d_name[0] == '.')
+ continue;
+
+ /* Ignore all files which are not a directory. */
+ if (stat (dep->d_name, &st) < 0)
+ continue; /* Don't add something we cannot stat. */
+
+ if (!S_ISDIR (st.st_mode))
+ continue;
+
+ /* We also don't wish to see ypbind data as domain name. */
+ if (strcmp (dep->d_name, "binding") == 0)
+ continue;
+
+ if (str == NULL)
+ {
+ if (asprintf (&str, "(domain=%s", dep->d_name) < 0)
+ {
+ log_msg ("Out of memory");
+ return NULL;
+ }
+ }
+ else
+ {
+ char *cp;
+
+ if (asprintf (&cp, "%s,%s", str, dep->d_name) < 0)
+ {
+ log_msg ("Out of memory");
+ return NULL;
+ }
+ free (str);
+ str = cp;
+ }
+ }
+ closedir (dp);
+ if (str)
+ {
+ char *cp;
+
+ if (asprintf (&cp, "%s)", str) < 0)
+ {
+ log_msg ("Out of memory");
+ return NULL;
+ }
+ free (str);
+ return cp;
+ }
+ return NULL;
+}
+
+int
+register_slp ()
+{
+ SLPError err;
+ SLPError callbackerr;
+ SLPHandle hslp;
+ int timeout;
+ char *attr = NULL;
+
+ if (url != NULL)
+ {
+ free (url);
+ url = NULL;
+ }
+ else
+ {
+ gethostname (hostname, sizeof (hostname));
+#if !USE_FQDN
+ hname = hostname;
+#else
+ if (isdigit (hostname[0]))
+ {
+ char addr[INADDRSZ];
+ if (inet_pton (AF_INET, hostname, &addr))
+ hp = gethostbyaddr (addr, sizeof (addr), AF_INET);
+ }
+ else
+ hp = gethostbyname (hostname);
+ if (hp == NULL)
+ {
+ log_msg ("Broken setup: cannot resolve %s, please fix",
+ hostname);
+ hname = hostname;
+ }
+ else
+ hname = hp->h_name;
+#endif
+ }
+
+ if (slp_timeout == 0)
+ timeout = SLP_LIFETIME_MAXIMUM; /* don't expire, ever */
+ else if (SLP_MIN_TIMEOUT > slp_timeout)
+ timeout = SLP_MIN_TIMEOUT; /* use a reasonable minimum */
+ else if (SLP_LIFETIME_MAXIMUM <= slp_timeout)
+ timeout = (SLP_LIFETIME_MAXIMUM - 1); /* as long as possible */
+ else
+ timeout = slp_timeout;
+
+ if (asprintf (&url, "service:ypserv://%s/", hname) < 0)
+ {
+ log_msg ("Out of memory");
+ return -1;
+ }
+
+ err = SLPOpen ("en", SLP_FALSE, &hslp);
+ if(err != SLP_OK)
+ {
+ log_msg ("Error opening slp handle %i", err);
+ return -1;
+ }
+
+ if (slp_flag == 2)
+ attr = create_domain_attr ();
+
+ if (attr == NULL) /* can also be NULL if create_domain_attr fails. */
+ attr = strdup ("");
+
+ /* Register a service with SLP */
+ err = SLPReg (hslp, url, timeout, 0,
+ attr,
+ SLP_TRUE,
+ ypservSLPRegReport,
+ &callbackerr);
+
+ free (attr);
+
+ /* err may contain an error code that occurred as the slp library */
+ /* _prepared_ to make the call. */
+ if ((err != SLP_OK) || (callbackerr != SLP_OK))
+ {
+ log_msg ("Error registering service with slp %i", err);
+ return -1;
+ }
+
+ /* callbackerr may contain an error code (that was assigned through */
+ /* the callback cookie) that occurred as slp packets were sent on */
+ /* the wire */
+ if( callbackerr != SLP_OK)
+ {
+ log_msg ("Error registering service with slp %i",
+ callbackerr);
+ return callbackerr;
+ }
+
+ /* Now that we're done using slp, close the slp handle */
+ SLPClose (hslp);
+
+ /* Set up a timer to refresh the service records */
+ if (timeout != SLP_LIFETIME_MAXIMUM)
+ {
+ if (signal (SIGALRM, do_refresh) == SIG_ERR)
+ log_msg ("SLP: error establishing signal handler\n");
+
+ alarm (timeout - 15);
+ }
+
+ return 0;
+}
+
+int
+deregister_slp ()
+{
+ SLPError err;
+ SLPError callbackerr;
+ SLPHandle hslp;
+
+ if (url == NULL)
+ {
+ log_msg ("URL not registerd!");
+ return -1;
+ }
+
+ err = SLPOpen ("en", SLP_FALSE, &hslp);
+ if(err != SLP_OK)
+ {
+ log_msg ("Error opening slp handle %i", err);
+ return -1;
+ }
+
+ /* Disable possibel alarm call. */
+ alarm (0);
+
+ /* DeRegister a service with SLP */
+ err = SLPDereg (hslp, url, ypservSLPRegReport, &callbackerr);
+
+ free (url);
+ url = NULL;
+
+ /* err may contain an error code that occurred as the slp library */
+ /* _prepared_ to make the call. */
+ if ((err != SLP_OK) || (callbackerr != SLP_OK))
+ {
+ log_msg ("Error registering service with slp %i", err);
+ return -1;
+ }
+
+ /* callbackerr may contain an error code (that was assigned through */
+ /* the callback cookie) that occurred as slp packets were sent on */
+ /* the wire */
+ if( callbackerr != SLP_OK)
+ {
+ log_msg ("Error registering service with slp %i",
+ callbackerr);
+ return callbackerr;
+ }
+
+ /* Now that we're done using slp, close the slp handle */
+ SLPClose (hslp);
+
+ return 0;
+}
+
+#endif
diff --git a/ypserv/reg_slp.h b/ypserv/reg_slp.h
new file mode 100644
index 0000000..a9fd87d
--- /dev/null
+++ b/ypserv/reg_slp.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2003 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifndef __REG_SLP_H__
+#define __REG_SLP_H__ 1
+
+int register_slp (void);
+int deregister_slp (void);
+
+#endif /* __REG_SLP_H__ */
+
diff --git a/ypserv/server.c b/ypserv/server.c
new file mode 100644
index 0000000..e64ed8b
--- /dev/null
+++ b/ypserv/server.c
@@ -0,0 +1,1544 @@
+/* Copyright (c) 2000-2016, 2021 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <alloca.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <netdb.h>
+#include <rpcsvc/yp_prot.h>
+#include "yp.h"
+#include "yp_db.h"
+#include "access.h"
+#include "ypserv_conf.h"
+#include "log_msg.h"
+
+bool_t
+ypproc_null_2_svc (void *argp UNUSED, void *result UNUSED,
+ struct svc_req *rqstp)
+{
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_null_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+
+ if (is_valid (rqstp, NULL, NULL) < 1)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+bool_t
+ypproc_domain_2_svc (domainname *argp, bool_t *result,
+ struct svc_req *rqstp)
+{
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_domain_2(%s) from %s port %d", *argp,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+
+ switch (is_valid (rqstp, NULL, *argp))
+ {
+ case -4: /* -4 should not happen */
+ case -3:
+ case -2: /* -2 should not happen */
+ *result = FALSE;
+ break;
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ *result = FALSE;
+ break;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ *result = FALSE;
+ break;
+ default:
+ *result = TRUE;
+ }
+
+ if (debug_flag)
+ log_msg ("\t-> %s.",
+ (*result == TRUE ? "Ok" : "Not served by us"));
+
+ return TRUE;
+}
+
+
+bool_t
+ypproc_domain_nonack_2_svc (domainname *argp, bool_t *result,
+ struct svc_req *rqstp)
+{
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_domain_nonack_2(%s) from %s port %d", *argp,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+
+ switch (is_valid (rqstp, NULL, *argp))
+ {
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ /* Bail out and don't return any RPC value */
+ return FALSE;
+ case -4: /* Should not happen */
+ case -2: /* Should not happen */
+ log_msg ("Map name not valid/does not exist, this cannot happen???");
+ return FALSE;
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ return FALSE;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ return FALSE;
+ default:
+ *result = TRUE;
+ break;
+ }
+
+ if (debug_flag)
+ log_msg ("\t-> OK.");
+
+ return TRUE;
+}
+
+
+bool_t
+ypproc_match_2_svc (ypreq_key *argp, ypresp_val *result,
+ struct svc_req *rqstp)
+{
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_match_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\t\tdomainname = \"%s\"", argp->domain);
+ log_msg ("\t\tmapname = \"%s\"", argp->map);
+ log_msg ("\t\tkeydat = \"%.*s\"", (int) argp->keydat.keydat_len,
+ argp->keydat.keydat_val);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_val));
+
+ valid = is_valid (rqstp, argp->map, argp->domain);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->status = YP_NOMAP;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid map name)");
+ result->status = YP_BADARGS;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ result->status = YP_NODOM;
+ break;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->status = YP_NOMAP;
+ break;
+ case -4:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map name not found)");
+ result->status = YP_NOMAP;
+ break;
+ }
+ return TRUE;
+ }
+
+ if (argp->keydat.keydat_len == 0 || argp->keydat.keydat_val[0] == '\0')
+ result->status = YP_BADARGS;
+ else
+ {
+ datum rdat, qdat;
+
+ DB_FILE dbp = ypdb_open (argp->domain, argp->map);
+ if (dbp == NULL)
+ result->status = YP_NOMAP;
+ else
+ {
+ qdat.dsize = argp->keydat.keydat_len;
+ qdat.dptr = argp->keydat.keydat_val;
+
+ rdat = ypdb_fetch (dbp, qdat);
+
+ if (rdat.dptr != NULL)
+ {
+ result->status = YP_TRUE;
+ result->valdat.valdat_len = rdat.dsize;
+ result->valdat.valdat_val = rdat.dptr;
+ }
+ else
+ result->status = YP_NOKEY;
+
+ ypdb_close (dbp);
+ }
+ }
+
+ if (debug_flag)
+ {
+ if (result->status == YP_TRUE)
+ log_msg ("\t-> Value = \"%.*s\"",
+ (int) result->valdat.valdat_len, result->valdat.valdat_val);
+ else
+ log_msg ("\t-> Error #%d", result->status);
+ }
+
+ return TRUE;
+}
+
+
+bool_t
+ypproc_first_2_svc (ypreq_nokey *argp, ypresp_key_val *result,
+ struct svc_req *rqstp)
+{
+ DB_FILE dbp;
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_first_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\tdomainname = \"%s\"", argp->domain);
+ log_msg ("\tmapname = \"%s\"", argp->map);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_key_val));
+
+ valid = is_valid (rqstp, argp->map, argp->domain);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->status = YP_NOMAP;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid map name)");
+ result->status = YP_BADARGS;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ result->status = YP_NODOM;
+ break;
+ case -4:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map does not exist)");
+ result->status = YP_NOMAP;
+ break;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->status = YP_NOMAP;
+ break;
+ }
+ return TRUE;
+ }
+
+ dbp = ypdb_open (argp->domain, argp->map);
+ if (dbp == NULL)
+ result->status = YP_NOMAP;
+ else
+ {
+ datum dkey = ypdb_firstkey (dbp);
+
+ while (dkey.dptr != NULL && dkey.dptr[0] == 'Y' &&
+ dkey.dptr[1] == 'P' && dkey.dptr[2] == '_')
+ {
+#if defined(HAVE_NDBM)
+ /* This is much more faster then ypdb_nextkey, but
+ it is terrible to port to other databases */
+ dkey = dbm_nextkey (dbp);
+#else
+ datum tkey = dkey;
+ dkey = ypdb_nextkey (dbp, tkey);
+ ypdb_free (tkey.dptr);
+#endif
+ }
+
+ if (dkey.dptr != NULL)
+ {
+ datum dval = ypdb_fetch (dbp, dkey);
+ result->status = YP_TRUE;
+
+ result->keydat.keydat_len = dkey.dsize;
+ result->keydat.keydat_val = dkey.dptr;
+
+ result->valdat.valdat_len = dval.dsize;
+ result->valdat.valdat_val = dval.dptr;
+ }
+ else
+ result->status = YP_NOKEY;
+ ypdb_close (dbp);
+ }
+
+ if (debug_flag)
+ {
+ if (result->status == YP_TRUE)
+ log_msg ("\t-> Key = \"%.*s\", Value = \"%.*s\"",
+ (int) result->keydat.keydat_len, result->keydat.keydat_val,
+ (int) result->valdat.valdat_len, result->valdat.valdat_val);
+ else if (result->status == YP_NOMORE)
+ log_msg ("\t-> No more entry's");
+ else
+ log_msg ("\t-> Error #%d", result->status);
+ }
+ return TRUE;
+}
+
+
+bool_t
+ypproc_next_2_svc (ypreq_key *argp, ypresp_key_val *result,
+ struct svc_req *rqstp)
+{
+ DB_FILE dbp;
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_next_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\tdomainname = \"%s\"", argp->domain);
+ log_msg ("\tmapname = \"%s\"", argp->map);
+ log_msg ("\tkeydat = \"%.*s\"",
+ (int) argp->keydat.keydat_len,
+ argp->keydat.keydat_val);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_key_val));
+
+ valid = is_valid (rqstp, argp->map, argp->domain);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->status = YP_NOMAP;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid map name)");
+ result->status = YP_BADARGS;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ result->status = YP_NODOM;
+ break;
+ case -4:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map does not exist)");
+ result->status = YP_NOMAP;
+ break;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->status = YP_NOMAP;
+ break;
+ }
+ return TRUE;
+ }
+
+ dbp = ypdb_open (argp->domain, argp->map);
+ if (dbp == NULL)
+ result->status = YP_NOMAP;
+ else
+ {
+ datum oldkey, dkey;
+
+ oldkey.dsize = argp->keydat.keydat_len;
+ oldkey.dptr = strndup (argp->keydat.keydat_val, oldkey.dsize);
+
+ dkey = ypdb_nextkey (dbp, oldkey);
+ while (dkey.dptr != NULL && dkey.dptr[0] == 'Y' &&
+ dkey.dptr[1] == 'P' && dkey.dptr[2] == '_')
+ {
+ free (oldkey.dptr);
+ oldkey.dsize = dkey.dsize;
+ oldkey.dptr = strndup (dkey.dptr, dkey.dsize);
+ ypdb_free (dkey.dptr);
+ dkey = ypdb_nextkey (dbp, oldkey);
+ }
+
+ free (oldkey.dptr);
+
+ if (dkey.dptr == NULL)
+ result->status = YP_NOMORE;
+ else
+ {
+ datum dval = ypdb_fetch (dbp, dkey);
+
+ result->status = YP_TRUE;
+ result->keydat.keydat_len = dkey.dsize;
+ result->keydat.keydat_val = dkey.dptr;
+
+ result->valdat.valdat_len = dval.dsize;
+ result->valdat.valdat_val = dval.dptr;
+ }
+ ypdb_close (dbp);
+ }
+
+ if (debug_flag)
+ {
+ if (result->status == YP_TRUE)
+ log_msg ("\t-> Key = \"%.*s\", Value = \"%.*s\"",
+ (int) result->keydat.keydat_len, result->keydat.keydat_val,
+ (int) result->valdat.valdat_len, result->valdat.valdat_val);
+ else if (result->status == YP_NOMORE)
+ log_msg ("\t-> No more entry's");
+ else
+ log_msg ("\t-> Error #%d", result->status);
+ }
+
+ return TRUE;
+}
+
+static bool_t
+ypproc_xfr_all_svc (ypreq_xfr *argp, ypresp_xfr *result,
+ struct svc_req *rqstp)
+{
+ DB_FILE dbp;
+ int valid;
+
+ memset (result, 0, sizeof (ypresp_xfr));
+ result->transid = argp->transid;
+
+ valid = is_valid (rqstp, argp->map_parms.map, argp->map_parms.domain);
+ if (valid < 1 && valid != -4) /* Map does not exist has a special meaning */
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf = NULL;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+
+ switch (valid)
+ {
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ else
+ log_msg ("refuse to transfer map from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ result->xfrstat = YPXFR_REFUSED;
+ break;
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ else
+ log_msg ("refuse to transfer map from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ result->xfrstat = YPXFR_REFUSED;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map contains \"/\"!)");
+ else
+ log_msg ("refuse to transfer map from %s port %d, no valid mapname",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ result->xfrstat = YPXFR_REFUSED;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ else
+ log_msg ("refuse to transfer map from %s%i, no valid domain",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ result->xfrstat = YPXFR_NODOM;
+ break;
+ }
+ if (nconf)
+ freenetconfigent (nconf);
+ return TRUE;
+ }
+
+ if (xfr_check_port)
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf = NULL;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+
+ if(taddr2port (nconf, rqhost) >= IPPORT_RESERVED)
+ {
+ if (debug_flag)
+ log_msg ("\t-> Ignored (no reserved port!)");
+ else
+ log_msg ("refuse to transfer %s from %s port %d, no valid port",
+ argp->map_parms.map,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ if (nconf)
+ freenetconfigent (nconf);
+ result->xfrstat = YPXFR_REFUSED;
+ return TRUE;
+ }
+ if (nconf)
+ freenetconfigent (nconf);
+ }
+
+ /* If we have the map, check, if the master name is the same as in
+ the ypreq_xfr struct. If we doesn't have the map, refuse. */
+ dbp = ypdb_open(argp->map_parms.domain, argp->map_parms.map);
+ if (dbp != NULL)
+ {
+ datum key;
+
+ key.dsize = sizeof ("YP_MASTER_NAME") - 1;
+ key.dptr = "YP_MASTER_NAME";
+
+ if(ypdb_exists (dbp, key))
+ {
+ datum val = ypdb_fetch (dbp, key);
+
+ if ((size_t)val.dsize != strlen (argp->map_parms.owner) ||
+ strncmp (val.dptr, argp->map_parms.owner, val.dsize) != 0)
+ {
+ char *buf = alloca (val.dsize + 1);
+
+ strncpy (buf, val.dptr, val.dsize);
+ buf[val.dsize] = '\0';
+
+ if (debug_flag)
+ log_msg ("\t->Ignored (%s is not the master, master is %s)",
+ argp->map_parms.owner, buf);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid))
+ == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ log_msg ("refuse to transfer %s from %s port %d, master is %s)",
+ argp->map_parms.map,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost), buf);
+ freenetconfigent (nconf);
+ }
+ }
+ ypdb_close (dbp);
+ result->xfrstat = YPXFR_NODOM;
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* If we do not have a YP_MASTER_NAME key, we don't have a
+ master/slave NIS system */
+ if (debug_flag)
+ log_msg ("\t->Ignored (no YP_MASTER_NAME key in local map)");
+
+ ypdb_close (dbp);
+ result->xfrstat = YPXFR_REFUSED;
+ return TRUE;
+ }
+ ypdb_close (dbp);
+ }
+ else if (trusted_master != NULL)
+ {
+ /* We have a new map. We only allow new maps from a NIS master
+ we trust (which means, the admin told us this master is ok. */
+ if (strcasecmp (trusted_master, argp->map_parms.owner) != 0)
+ {
+ if (debug_flag)
+ log_msg ("\t->Ignored (%s is not a trusted master!)",
+ argp->map_parms.owner);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+
+ log_msg ("refuse to transfer %s from %s port %d, no trusted master",
+ argp->map_parms.map,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+ result->xfrstat = YPXFR_NODOM;
+ return TRUE;
+ }
+ else
+ {
+ if (debug_flag)
+ log_msg ("\t->New map %s from %s (is a trusted master!)",
+ argp->map_parms.map, argp->map_parms.owner);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ log_msg ("New map %s from trusted master %s port %d",
+ argp->map_parms.map,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+ }
+ }
+ /* If you wish to allow the transfer of new maps, change the next
+ #if 1 statement to #if 0 */
+#if 1
+ else
+ {
+ /* We doesn't have the map, refuse the transfer */
+ char namebuf6[INET6_ADDRSTRLEN];
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ if (debug_flag)
+ log_msg ("\t->Ignored (transfer %s from %s, map doesn't exist local)",
+ argp->map_parms.map,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ else
+ log_msg ("refuse to transfer %s from %s, map doesn't exist local",
+ argp->map_parms.map,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)));
+ freenetconfigent (nconf);
+ }
+ result->xfrstat = YPXFR_REFUSED;
+ return TRUE;
+ }
+#endif
+
+ switch (fork ())
+ {
+ case 0:
+ {
+ char hostbuf[NI_MAXHOST];
+ const char *host;
+ char *ypxfr_command = alloca (sizeof (YPBINDIR) + 8);
+ char proto[30], transid[30];
+ int i;
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ umask (0);
+ i = open ("/dev/null", O_RDWR);
+ if (dup (i) == -1)
+ {
+ int err = errno;
+ log_msg ("ypxfr execl(): %s", strerror (err));
+ exit (err);
+ }
+ if (dup (i) == -1)
+ {
+ int err = errno;
+ log_msg ("ypxfr execl(): %s", strerror (err));
+ exit (err);
+ }
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ {
+ int err = ENOENT;
+ exit (err);
+ }
+ host = taddr2host (nconf, rqhost, hostbuf, sizeof hostbuf);
+
+ sprintf (ypxfr_command, "%s/ypxfr", YPBINDIR);
+ snprintf (transid, sizeof (transid), "%u", argp->transid);
+ snprintf (proto, sizeof (proto), "%u", argp->proto);
+
+ if (debug_flag)
+ execl (ypxfr_command, "ypxfr", "--debug", "-d",
+ argp->map_parms.domain, "-h", argp->map_parms.owner,
+ "-C", transid, proto, host, "0", argp->map_parms.map, NULL);
+ else
+ execl (ypxfr_command, "ypxfr", "-d", argp->map_parms.domain, "-h",
+ argp->map_parms.owner, "-C", transid, proto, host, "0",
+ argp->map_parms.map, NULL);
+
+ log_msg ("ypxfr execl(): %s", strerror (errno));
+ exit (0);
+ }
+ case -1:
+ log_msg ("Cannot fork: %s", strerror (errno));
+ result->xfrstat = YPXFR_XFRERR;
+ break;
+ default:
+ result->xfrstat = YPXFR_SUCC;
+ break;
+ }
+
+ return TRUE;
+}
+
+bool_t ypproc_newxfr_2_svc (ypreq_newxfr *argp, ypresp_xfr *result,
+ struct svc_req *rqstp)
+{
+ ypreq_xfr *oldxfr;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_newxfr_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\t\tdomain = \"%s\"", argp->map_parms.domain);
+ log_msg ("\t\tmap = \"%s\"", argp->map_parms.map);
+ log_msg ("\t\tordernum = %u", argp->map_parms.ordernum);
+ log_msg ("\t\towner = \"%s\"", argp->map_parms.owner);
+ log_msg ("\t\ttransid = %u", argp->transid);
+ log_msg ("\t\tproto = %u", argp->proto);
+ log_msg ("\t\tname = %s", argp->name);
+ }
+ }
+
+ oldxfr = (ypreq_xfr *) argp;
+ return ypproc_xfr_all_svc (oldxfr, result, rqstp);
+}
+
+bool_t
+ypproc_xfr_2_svc (ypreq_xfr *argp, ypresp_xfr *result,
+ struct svc_req *rqstp)
+{
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_xfr_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\t\tdomain = \"%s\"", argp->map_parms.domain);
+ log_msg ("\t\tmap = \"%s\"", argp->map_parms.map);
+ log_msg ("\t\tordernum = %u", argp->map_parms.ordernum);
+ log_msg ("\t\towner = \"%s\"", argp->map_parms.owner);
+ log_msg ("\t\ttransid = %u", argp->transid);
+ log_msg ("\t\tproto = %u", argp->proto);
+ log_msg ("\t\tport = %u", argp->port);
+ }
+ }
+
+ return ypproc_xfr_all_svc (argp, result, rqstp);
+}
+
+bool_t ypproc_clear_2_svc (void *argp UNUSED, void *result UNUSED,
+ struct svc_req *rqstp)
+{
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_clear_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+
+ if (is_valid (rqstp, NULL, NULL) < 1)
+ {
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ }
+ else
+ ypdb_close_all ();
+
+ return TRUE;
+}
+
+/* We need the struct for giving ypall_encode the DB_FILE handle */
+typedef struct ypall_data {
+ DB_FILE dbm;
+ datum dkey;
+ datum dval;
+} *ypall_data_t;
+
+static int
+ypall_close (void *data)
+{
+ if (data == NULL)
+ {
+ log_msg ("ypall_close() called with NULL pointer.");
+ return 0;
+ }
+
+ ypdb_close (((ypall_data_t) data)->dbm);
+ if (((ypall_data_t) data)->dkey.dptr)
+ ypdb_free (((ypall_data_t) data)->dkey.dptr);
+ if (((ypall_data_t) data)->dval.dptr)
+ ypdb_free (((ypall_data_t) data)->dval.dptr);
+ free (data);
+ return 0;
+}
+
+static int
+ypall_encode (ypresp_key_val *val, void *data)
+{
+ datum oldkey;
+
+ oldkey.dsize = val->keydat.keydat_len;
+ oldkey.dptr = strndup (val->keydat.keydat_val, oldkey.dsize);
+ ypdb_free (((ypall_data_t) data)->dkey.dptr);
+ ((ypall_data_t) data)->dkey.dptr = NULL;
+ ypdb_free (((ypall_data_t) data)->dval.dptr);
+ ((ypall_data_t) data)->dval.dptr = NULL;
+
+ ((ypall_data_t) data)->dkey = ypdb_nextkey (((ypall_data_t) data)->dbm,
+ oldkey);
+
+ while (((ypall_data_t) data)->dkey.dptr != NULL &&
+ ((ypall_data_t) data)->dkey.dptr[0] == 'Y' &&
+ ((ypall_data_t) data)->dkey.dptr[1] == 'P' &&
+ ((ypall_data_t) data)->dkey.dptr[2] == '_')
+ {
+ free (oldkey.dptr);
+ oldkey.dsize = ((ypall_data_t) data)->dkey.dsize;
+ oldkey.dptr = strndup (((ypall_data_t) data)->dkey.dptr,
+ ((ypall_data_t) data)->dkey.dsize);
+ ypdb_free (((ypall_data_t) data)->dkey.dptr);
+ ((ypall_data_t) data)->dkey.dptr = NULL;
+
+ ((ypall_data_t) data)->dkey = ypdb_nextkey (((ypall_data_t) data)->dbm,
+ oldkey);
+ }
+
+ free (oldkey.dptr);
+
+ if (((ypall_data_t) data)->dkey.dptr == NULL)
+ val->status = YP_NOMORE;
+ else
+ {
+ ((ypall_data_t) data)->dval =
+ ypdb_fetch (((ypall_data_t) data)->dbm, ((ypall_data_t) data)->dkey);
+
+ val->status = YP_TRUE;
+
+ val->keydat.keydat_val = ((ypall_data_t) data)->dkey.dptr;
+ val->keydat.keydat_len = ((ypall_data_t) data)->dkey.dsize;
+
+ val->valdat.valdat_val = ((ypall_data_t) data)->dval.dptr;
+ val->valdat.valdat_len = ((ypall_data_t) data)->dval.dsize;
+ }
+ return val->status;
+}
+
+extern xdr_ypall_cb_t xdr_ypall_cb;
+
+bool_t
+ypproc_all_2_svc (ypreq_nokey *argp, ypresp_all *result, struct svc_req *rqstp)
+{
+ ypall_data_t data;
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_all_2_svc from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\t\tdomain = \"%s\"", argp->domain);
+ log_msg ("\t\tmap = \"%s\"", argp->map);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_all));
+ xdr_ypall_cb.u.encode = NULL;
+ xdr_ypall_cb.u.close = NULL;
+ xdr_ypall_cb.data = NULL;
+
+ /* Set this to TRUE so that the client will be forced to read
+ at least one record from us. This could be the error code. */
+ result->more = TRUE;
+
+ valid = is_valid (rqstp, argp->map, argp->domain);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->ypresp_all_u.val.status = YP_NOMAP;
+ break;
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->ypresp_all_u.val.status = YP_NOMAP;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid map name)");
+ result->ypresp_all_u.val.status = YP_BADARGS;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ result->ypresp_all_u.val.status = YP_NODOM;
+ break;
+ case -4:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map does not exist)");
+ result->ypresp_all_u.val.status = YP_NOMAP;
+ break;
+ }
+ return TRUE;
+ }
+
+ switch (fork ())
+ {
+ case 0: /* child */
+#ifdef DEBUG
+ log_msg ("ypserv has forked for ypproc_all(): pid=%i", getpid ());
+#endif
+ break;
+ case -1: /* parent, error */
+ log_msg ("WARNING(ypproc_all_2_svc): cannot fork: %s",
+ strerror (errno));
+ result->ypresp_all_u.val.status = YP_YPERR;
+ return TRUE;
+ default: /* parent, default */
+ return FALSE;
+ break;
+ }
+
+ /* We are now in the child part. Don't let the child ypserv share
+ DB handles with the parent process. */
+ ypdb_close_all();
+
+ if ((data = calloc (1, sizeof (struct ypall_data))) == NULL)
+ {
+ log_msg ("ERROR: could not allocate enough memory! [%s|%d]",
+ __FILE__, __LINE__);
+ result->ypresp_all_u.val.status = YP_YPERR;
+ goto out;
+ }
+
+ data->dbm = ypdb_open (argp->domain, argp->map);
+
+ if (data->dbm == NULL)
+ result->ypresp_all_u.val.status = YP_NOMAP;
+ else
+ {
+ data->dkey = ypdb_firstkey (data->dbm);
+
+ while (data->dkey.dptr != NULL && data->dkey.dptr[0] == 'Y'
+ && data->dkey.dptr[1] == 'P' && data->dkey.dptr[2] == '_')
+ {
+ datum tkey = data->dkey;
+ data->dkey = ypdb_nextkey (data->dbm, tkey);
+ ypdb_free (tkey.dptr);
+ }
+
+ if (data->dkey.dptr != NULL)
+ {
+ data->dval = ypdb_fetch (data->dbm, data->dkey);
+
+ result->ypresp_all_u.val.status = YP_TRUE;
+
+ result->ypresp_all_u.val.keydat.keydat_len = data->dkey.dsize;
+ result->ypresp_all_u.val.keydat.keydat_val = data->dkey.dptr;
+
+ result->ypresp_all_u.val.valdat.valdat_len = data->dval.dsize;
+ result->ypresp_all_u.val.valdat.valdat_val = data->dval.dptr;
+
+ xdr_ypall_cb.u.encode = ypall_encode;
+ xdr_ypall_cb.u.close = ypall_close;
+ xdr_ypall_cb.data = (void *) data;
+
+ if (debug_flag)
+ log_msg ("\t -> First value returned.");
+
+ if (result->ypresp_all_u.val.status == YP_TRUE)
+ goto out; /* We return to commit the data.
+ This also means, we don't give
+ data free here */
+ }
+ else
+ result->ypresp_all_u.val.status = YP_NOMORE;
+
+ ypdb_close (data->dbm);
+ }
+
+ free (data);
+
+ if (debug_flag)
+ log_msg ("\t -> Exit from ypproc_all without sending data.");
+
+ out:
+ if (!svc_sendreply (rqstp->rq_xprt, (xdrproc_t) xdr_ypresp_all,
+ (caddr_t) result))
+ svcerr_systemerr (rqstp->rq_xprt);
+ /* Note: no need to free args; we're exiting. */
+ _exit(0);
+}
+
+bool_t
+ypproc_master_2_svc (ypreq_nokey *argp, ypresp_master *result,
+ struct svc_req *rqstp)
+{
+ DB_FILE dbp;
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_master_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\t\tdomain = \"%s\"", argp->domain);
+ log_msg ("\t\tmap = \"%s\"", argp->map);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_master));
+
+ valid = is_valid (rqstp, argp->map, argp->domain);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->status = YP_NOMAP;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid map name)");
+ result->status = YP_BADARGS;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a domain)");
+ result->status = YP_NODOM;
+ break;
+ case -4:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map does not exist)");
+ result->status = YP_NOMAP;
+ break;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->status = YP_NOMAP;
+ break;
+ }
+ result->master = strdup ("");
+ return TRUE;
+ }
+
+ dbp = ypdb_open (argp->domain, argp->map);
+ if (dbp == NULL)
+ result->status = YP_NOMAP;
+ else
+ {
+ datum key, val;
+
+ key.dsize = sizeof ("YP_MASTER_NAME") - 1;
+ key.dptr = "YP_MASTER_NAME";
+
+ val = ypdb_fetch (dbp, key);
+ if (val.dptr == NULL)
+ {
+ /* No YP_MASTER_NAME record in map? There is someting wrong */
+ result->status = YP_BADDB;
+ }
+ else
+ {
+ int i;
+ char *hostbuf = alloca (val.dsize + 1);
+
+ /* put the eof string mark at the end of the string */
+ for (i = 0; i < val.dsize; ++i)
+ hostbuf[i] = val.dptr[i];
+ hostbuf[val.dsize] = '\0';
+ ypdb_free (val.dptr);
+
+ if ((result->master = strdup (hostbuf)) == NULL)
+ result->status = YP_YPERR;
+ else
+ result->status = YP_TRUE;
+ }
+
+ ypdb_close (dbp);
+ }
+
+ if (result->master == NULL)
+ result->master = strdup ("");
+
+ if (debug_flag)
+ log_msg ("\t-> Master = \"%s\"", result->master);
+
+ return TRUE;
+}
+
+
+/* Get the DateTimeModified value for a certain map database */
+static inline unsigned long
+get_dtm (const char *domain, const char *map)
+{
+ struct stat sbuf;
+ char *buf = alloca (strlen (domain) + strlen (map) + 3);
+ char *cp;
+
+ cp = stpcpy (buf, domain);
+ *cp++ = '/';
+ strcpy (cp, map);
+
+ if (stat (buf, &sbuf) < 0)
+ return time (NULL); /* We set it to the current time. */
+ else
+ return (unsigned long) sbuf.st_mtime;
+}
+
+bool_t
+ypproc_order_2_svc (ypreq_nokey *argp, ypresp_order *result,
+ struct svc_req *rqstp)
+{
+ DB_FILE dbp;
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_order_2 from %s port %d",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ log_msg ("\t\tdomain = \"%s\"", argp->domain);
+ log_msg ("\t\tmap = \"%s\"", argp->map);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_order));
+
+ valid = is_valid (rqstp, argp->map, argp->domain);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->status = YP_NOMAP;
+ break;
+ case -2:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid map name)");
+ result->status = YP_BADARGS;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ result->status = YP_NODOM;
+ break;
+ case -4:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (map does not exist)");
+ result->status = YP_NOMAP;
+ break;
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->status = YP_NOMAP;
+ break;
+ }
+ return TRUE;
+ }
+
+ dbp = ypdb_open (argp->domain, argp->map);
+
+ if (dbp == NULL)
+ result->status = YP_NOMAP;
+ else
+ {
+ datum key, val;
+
+ key.dsize = sizeof ("YP_LAST_MODIFIED") - 1;
+ key.dptr = "YP_LAST_MODIFIED";
+
+ val = ypdb_fetch (dbp, key);
+ if (val.dptr == NULL)
+ {
+ /* No YP_LAST_MODIFIED record in map? Use DTM timestamp.. */
+ result->ordernum = get_dtm (argp->domain, argp->map);
+ }
+ else
+ {
+ char *buf = alloca (val.dsize + 1);
+
+ memcpy (buf, val.dptr, val.dsize);
+ buf[val.dsize] = '\0';
+ result->ordernum = atoi (buf);
+ ypdb_free (val.dptr);
+ }
+
+ result->status = YP_TRUE;
+ ypdb_close (dbp);
+ }
+
+ if (debug_flag)
+ log_msg ("-> Order # %u", result->ordernum);
+
+ return TRUE;
+}
+
+
+static int
+add_maplist (ypmaplist **mlhp, char *map)
+{
+ ypmaplist *mlp;
+#if defined(HAVE_NDBM)
+#if defined(sun) || defined(__sun__)
+ int len = strlen (map);
+
+ /* We have all maps twice: with .dir and with .pag. Ignore .pag */
+ if (len > 3 && map[len - 4] == '.' && map[len - 3] == 'p' &&
+ map[len - 2] == 'a' && map[len - 1] == 'g')
+ return 0;
+
+ if (len > 3 && map[len - 4] == '.' && map[len - 3] == 'd' &&
+ map[len - 2] == 'i' && map[len - 1] == 'r')
+ map[len - 4] = '\0';
+#else
+ int len = strlen (map);
+
+ if (len > 2 && map[len - 3] == '.' && map[len - 2] == 'd' &&
+ map[len - 1] == 'b')
+ map[len - 3] = '\0';
+#endif
+#endif
+
+ if ((mlp = malloc (sizeof (*mlp))) == NULL)
+ return -1;
+
+ if ((mlp->map = strdup (map)) == NULL)
+ {
+ free (mlp);
+ return -1;
+ }
+
+ mlp->next = *mlhp;
+ *mlhp = mlp;
+
+ return 0;
+}
+
+bool_t
+ypproc_maplist_2_svc (domainname *argp, ypresp_maplist *result,
+ struct svc_req *rqstp)
+{
+ DIR *dp;
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+ log_msg ("ypproc_maplist_2(%s) from %s port %d", *argp,
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ freenetconfigent (nconf);
+ }
+ }
+
+ memset (result, 0, sizeof (ypresp_maplist));
+
+ valid = is_valid (rqstp, NULL, *argp);
+ if (valid < 1)
+ {
+ switch (valid)
+ {
+ case 0:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (forbidden by securenets)");
+ result->status = YP_NOMAP;
+ break;
+ case -1:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ result->status = YP_NOMAP;
+ break;
+ case -4: /* should never happen */
+ case -2: /* should never happen */
+ result->status = YP_NOMAP;
+ break;
+ case -3:
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain)");
+ result->status = YP_NODOM;
+ break;
+ }
+ return TRUE;
+ }
+
+ /* open domain directory */
+ dp = opendir (*argp);
+ if (dp == NULL)
+ {
+ if (debug_flag)
+ log_msg ("opendir: %s", strerror (errno));
+
+ result->status = YP_BADDB;
+ }
+ else
+ {
+ struct dirent *dep;
+
+ while ((dep = readdir (dp)) != NULL)
+ {
+ /* ignore files starting with . */
+ if (dep->d_name[0] == '.')
+ continue;
+ /* ignore temporary files ending with ~, created
+ by makedbm and ypxfr if updating maps */
+ if (dep->d_name[strlen(dep->d_name) - 1] == '~')
+ continue;
+ if (add_maplist (&result->list, dep->d_name) < 0)
+ {
+ result->status = YP_YPERR;
+ break;
+ }
+ }
+ closedir (dp);
+ result->status = YP_TRUE;
+ }
+
+ if (debug_flag)
+ {
+ if (result->status == YP_TRUE)
+ {
+ ypmaplist *p;
+
+ p = result->list;
+ log_msg ("-> ");
+ while (p)
+ {
+ if (p->next)
+ log_msg (" %s,", p->map);
+ else
+ log_msg (" %s", p->map);
+ p = p->next;
+ }
+ }
+ else
+ log_msg ("\t-> Error #%d", result->status);
+ }
+
+ return TRUE;
+}
+
+int
+ypprog_2_freeresult (SVCXPRT *transp UNUSED,
+ xdrproc_t xdr_result, caddr_t result)
+{
+ xdr_free (xdr_result, result);
+
+ return 1;
+}
diff --git a/ypserv/ypserv.8.xml b/ypserv/ypserv.8.xml
new file mode 100644
index 0000000..c864818
--- /dev/null
+++ b/ypserv/ypserv.8.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='makedbm'>
+
+ <refmeta>
+ <refentrytitle>ypserv</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>ypserv</refname>
+ <refpurpose>NIS Server</refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+ <command>/usr/sbin/ypserv</command>
+ <arg choice='opt'>-d <arg choice='opt'><replaceable>path</replaceable></arg></arg>
+ <arg choice='opt'>-p <replaceable>port</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><indexterm><primary>ypserv</primary><secondary>ypserv &mdash; NIS server process</secondary></indexterm></para>
+
+<para>The
+Network Information Service (NIS)
+provides a simple network lookup service
+consisting of databases and processes. The databases are
+<emphasis remap='B'>gdbm</emphasis>
+files in a directory tree rooted at
+<filename>/var/yp</filename>.</para>
+
+<para>The
+<emphasis remap='B'>ypserv</emphasis>
+daemon is typically activated at system startup.
+<emphasis remap='B'>ypserv</emphasis>
+runs only on
+<acronym>NIS</acronym>
+server machines with a complete
+<acronym>NIS</acronym>
+database. On other machines using the
+<acronym>NIS</acronym>
+services, you have to run
+<emphasis remap='B'>ypbind</emphasis>
+as client or under Linux you could use the libc with
+<acronym>NYS</acronym>
+support.
+<emphasis remap='B'>ypbind</emphasis>
+must run on every machine which has
+<acronym>NIS</acronym>
+client processes;
+<emphasis remap='B'>ypserv</emphasis>
+may or may not be running on the same node,
+but must be running somewhere
+on the network. On startup
+<emphasis remap='B'>ypserv</emphasis>
+parses the file
+<filename>/etc/ypserv.conf.</filename></para>
+
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-d</option>, <option>--debug </option>[<replaceable>path</replaceable>]</term>
+ <listitem>
+<para>Causes the server to run in debugging mode. Normally,
+<emphasis remap='B'>ypserv</emphasis>
+reports only errors (access violations, dbm failures)
+using the syslog(3) facility. In debug mode, the server does not
+background itself and prints extra status messages to stderr for
+each request that it revceives.
+<emphasis remap='B'>path</emphasis>
+is an optionally parameter.
+<emphasis remap='B'>ypserv</emphasis>
+is using this directory instead of /var/yp</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option>, <option>--port</option> <replaceable>port</replaceable></term>
+ <listitem>
+<para><emphasis remap='B'>ypserv</emphasis>
+will bind itself to this port.
+This makes it possible to have a router filter packets
+to the NIS ports, so that access to the NIS server from
+hosts on the Internet can be restricted.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option>, <option>--version</option></term>
+ <listitem>
+<para>Prints the version number</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='security'><title>SECURITY</title>
+<para>In general, any remote user can issue an RPC to
+<emphasis remap='B'>ypserv</emphasis>
+and retrieve the contents of your NIS maps, if he knows your
+domain name. To prevent such unauthorized transactions,
+<emphasis remap='B'>ypserv</emphasis>
+supports a feature called
+<emphasis remap='B'>securenets</emphasis>
+which can be used to restrict access to a given set of hosts.
+At startup <emphasis remap='B'>ypserv</emphasis>
+will attempt to load the securenets information from a file
+called
+<filename>/var/yp/securenets .</filename>
+This file contains entries that consist of a netmask
+and a network pair separated by white spaces or network/number of bits
+of netmask entries. One per line.
+Lines starting with &ldquo;#&rdquo; are considered to be comments.</para>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term>A sample securenets file might look like this:</term>
+ <listitem>
+
+<para>
+<programlisting>
+# allow connections from local host -- necessary
+host 127.0.0.1
+host ::1
+# same as 255.255.255.255 127.0.0.1
+#
+# allow connections from any host
+# on the 131.234.223.0 network
+255.255.255.0 131.234.223.0
+# allow connections from any host
+# between 131.234.214.0 and 131.234.215.255
+255.255.254.0 131.234.214.0
+# allow some IPv6 connections
+FE80::0202:B3FF::/96
+# allow IPv6 connections from all machines
+::/0
+</programlisting>
+</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+
+<para>If
+<emphasis remap='B'>ypserv</emphasis>
+receives a request from an address that fails to match a rule,
+the request will be ignored and a warning message will be
+logged. If the
+<filename>/var/yp/securenets</filename>
+file does not exist,
+<emphasis remap='B'>ypserv</emphasis>
+will allow connections from any host.</para>
+
+<para>In the
+<filename>/etc/ypserv.conf</filename>
+you could specify some access rules for special maps and hosts. But
+it is not very secure, it makes the life only a little bit harder
+for a potential hacker. If a mapname doesn't match a rule, ypserv will
+look for the YP_SECURE key in the map. If it exists, ypserv will
+only allow requests on a reserved port.</para>
+
+<para>For security reasons, ypserv will only accept ypproc_xfr requests for
+updating maps from the same master server as the old one. This means,
+you have to reinstall the slave servers if you change the master server
+for a map.</para>
+</refsect1>
+
+<refsect1 id='files'><title>FILES</title>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><filename>/etc/ypserv.conf</filename></term>
+ <listitem>
+<para>configuration file.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><filename>/var/yp/securenets</filename></term>
+ <listitem>
+<para>which hosts are allowed to contact <command>ypserv</command>.</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>domainname</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypcat</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypmatch</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypserv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>netgroup</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>makedbm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>revnetgroup</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypinit</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>yppoll</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>yppush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypset</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypwhich</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypxfr</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>rpc.ypxfrd</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
+
+<para>The Network Information Service
+(NIS)
+was formerly known as Sun Yellow Pages
+(YP).
+The functionality of the two remains the same;
+only the name has changed.
+The name Yellow Pages is a registered trademark in the United Kingdom
+of British Telecommunications plc,
+and may not be used without permission.</para>
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para><emphasis remap='B'>ypserv</emphasis>
+was written by Peter Eriksson &lt;pen@lysator.liu.se&gt;.
+Thorsten Kukuk &lt;kukuk@linux-nis.org&gt; added support for master/slave
+server and is the new Maintainer.</para>
+</refsect1>
+</refentry>
diff --git a/ypserv/ypserv.c b/ypserv/ypserv.c
new file mode 100644
index 0000000..d8876e9
--- /dev/null
+++ b/ypserv/ypserv.c
@@ -0,0 +1,601 @@
+/* Copyright (c) 1996-2011, 2014, 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@thkukuk.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#include <rpc/nettype.h>
+
+#include "yp.h"
+#include "access.h"
+#include "log_msg.h"
+#include "ypserv_conf.h"
+#include "pidfile.h"
+
+#define _YPSERV_PIDFILE _PATH_VARRUN"ypserv.pid"
+
+#ifndef YPOLDVERS
+#define YPOLDVERS 1
+#endif
+
+static char *path_ypdb = YPMAPDIR;
+static int foreground_flag = 0;
+
+static void
+ypprog_2 (struct svc_req *rqstp, register SVCXPRT * transp)
+{
+ union {
+ domainname ypproc_domain_2_arg;
+ domainname ypproc_domain_nonack_2_arg;
+ ypreq_key ypproc_match_2_arg;
+ ypreq_nokey ypproc_first_2_arg;
+ ypreq_key ypproc_next_2_arg;
+ ypreq_xfr ypproc_xfr_2_arg;
+ ypreq_nokey ypproc_all_2_arg;
+ ypreq_nokey ypproc_master_2_arg;
+ ypreq_nokey ypproc_order_2_arg;
+ domainname ypproc_maplist_2_arg;
+ } argument;
+ union {
+ bool_t ypproc_domain_2_res;
+ bool_t ypproc_domain_nonack_2_res;
+ ypresp_val ypproc_match_2_res;
+ ypresp_key_val ypproc_first_2_res;
+ ypresp_key_val ypproc_next_2_res;
+ ypresp_xfr ypproc_xfr_2_res;
+ ypresp_all ypproc_all_2_res;
+ ypresp_master ypproc_master_2_res;
+ ypresp_order ypproc_order_2_res;
+ ypresp_maplist ypproc_maplist_2_res;
+ } result;
+ bool_t retval;
+ xdrproc_t _xdr_argument, _xdr_result;
+ bool_t (*local) (char *, void *, struct svc_req *);
+
+ switch (rqstp->rq_proc)
+ {
+ case YPPROC_NULL:
+ _xdr_argument = (xdrproc_t) xdr_void;
+ _xdr_result = (xdrproc_t) xdr_void;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_null_2_svc;
+ break;
+
+ case YPPROC_DOMAIN:
+ _xdr_argument = (xdrproc_t) xdr_domainname;
+ _xdr_result = (xdrproc_t) xdr_bool;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_domain_2_svc;
+ break;
+
+ case YPPROC_DOMAIN_NONACK:
+ _xdr_argument = (xdrproc_t) xdr_domainname;
+ _xdr_result = (xdrproc_t) xdr_bool;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *))
+ ypproc_domain_nonack_2_svc;
+ break;
+
+ case YPPROC_MATCH:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_key;
+ _xdr_result = (xdrproc_t) xdr_ypresp_val;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_match_2_svc;
+ break;
+
+ case YPPROC_FIRST:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+ _xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_first_2_svc;
+ break;
+
+ case YPPROC_NEXT:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_key;
+ _xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_next_2_svc;
+ break;
+
+ case YPPROC_XFR:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_xfr;
+ _xdr_result = (xdrproc_t) xdr_ypresp_xfr;
+ local = (bool_t (*)(char *, void *, struct svc_req *)) ypproc_xfr_2_svc;
+ break;
+
+ case YPPROC_NEWXFR:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_newxfr;
+ _xdr_result = (xdrproc_t) xdr_ypresp_xfr;
+ local = (bool_t (*)(char *, void *, struct svc_req *)) ypproc_newxfr_2_svc;
+ break;
+
+ case YPPROC_CLEAR:
+ _xdr_argument = (xdrproc_t) xdr_void;
+ _xdr_result = (xdrproc_t) xdr_void;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_clear_2_svc;
+ break;
+
+ case YPPROC_ALL:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+ _xdr_result = (xdrproc_t) xdr_ypresp_all;
+ local = (bool_t (*)(char *, void *, struct svc_req *)) ypproc_all_2_svc;
+ break;
+
+ case YPPROC_MASTER:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+ _xdr_result = (xdrproc_t) xdr_ypresp_master;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_master_2_svc;
+ break;
+
+ case YPPROC_ORDER:
+ _xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+ _xdr_result = (xdrproc_t) xdr_ypresp_order;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_order_2_svc;
+ break;
+
+ case YPPROC_MAPLIST:
+ _xdr_argument = (xdrproc_t) xdr_domainname;
+ _xdr_result = (xdrproc_t) xdr_ypresp_maplist;
+ local =
+ (bool_t (*)(char *, void *, struct svc_req *)) ypproc_maplist_2_svc;
+ break;
+
+ default:
+ svcerr_noproc (transp);
+ return;
+ }
+
+ memset ((char *) &argument, 0, sizeof (argument));
+ if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument))
+ {
+ int error;
+ char host[NI_MAXHOST];
+ char serv[NI_MAXSERV];
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ struct sockaddr *sap = (struct sockaddr *)(rqhost->buf);
+
+ error = getnameinfo (sap, sizeof (struct sockaddr),
+ host, sizeof(host), serv, sizeof(serv),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error)
+ {
+ log_msg ("ypprog_2: getnameinfo(): %s",
+ gai_strerror(error));
+ }
+ else
+ {
+ log_msg ("ERROR: Cannot decode arguments for %d from %s:%s",
+ rqstp->rq_proc, host, serv);
+ }
+
+ /* try to free already allocated memory during decoding.
+ bnc#471924 */
+ svc_freeargs (transp, _xdr_argument, (caddr_t) &argument);
+
+ svcerr_decode (transp);
+ return;
+ }
+
+ retval = (bool_t) (*local) ((char *) &argument, (void *) &result, rqstp);
+ if (retval > 0 && !svc_sendreply (transp, _xdr_result, (char *) &result))
+ svcerr_systemerr (transp);
+
+ if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument))
+ {
+ log_msg ("ERROR: Unable to free arguments");
+ return; /* don't abort */
+ }
+
+ if (!ypprog_2_freeresult (transp, _xdr_result, (caddr_t) &result))
+ log_msg ("ERROR: Unable to free results");
+
+ return;
+}
+
+extern FILE *debug_output;
+/* SIGUSR1: enable/disable debug output. */
+static void
+sig_usr1 (int sig UNUSED)
+{
+ int save_errno = errno;
+
+ if (debug_flag)
+ {
+ debug_flag = 0;
+ if (debug_output != stderr)
+ fclose (debug_output);
+ debug_output = stderr;
+ }
+ else
+ {
+ debug_output = fopen ("/var/yp/ypserv.log", "a");
+ if (debug_output != NULL)
+ debug_flag = 1;
+ }
+ errno = save_errno;
+}
+
+/* Clean up if we quit the program. */
+static void
+sig_quit (int sig UNUSED)
+{
+ rpcb_unset (YPPROG, YPVERS, NULL);
+ rpcb_unset (YPPROG, YPOLDVERS, NULL);
+ unlink (_YPSERV_PIDFILE);
+
+ exit (0);
+}
+
+/* Clean up after child processes signal their termination. */
+static void
+sig_child (int sig UNUSED)
+{
+ int save_errno = errno;
+
+ while (wait3 (NULL, WNOHANG, NULL) > 0)
+ ;
+ errno = save_errno;
+}
+
+static void
+Usage (int exitcode)
+{
+ fputs ("usage: ypserv [-d] [-p port] [-f|--foreground]\n", stderr);
+ fputs (" ypserv --version\n", stderr);
+
+ exit (exitcode);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct netconfig *nconf;
+ void *nc_handle;
+ int my_port = -1;
+ int could_register = 0;
+
+ openlog ("ypserv", LOG_PID, LOG_DAEMON);
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"version", no_argument, NULL, 'v'},
+ {"debug", no_argument, NULL, 'd'},
+ {"port", required_argument, NULL, 'p'},
+ {"usage", no_argument, NULL, 'u'},
+ {"help", no_argument, NULL, 'h'},
+ {"foreground", no_argument, NULL, 'f'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "vdp:fbuh", long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c)
+ {
+ case 'v':
+ debug_flag = 1;
+ log_msg ("ypserv (%s) %s\n", PACKAGE, VERSION);
+ return 0;
+ case 'd':
+ ++debug_flag;
+ break;
+ case 'p':
+ my_port = atoi (optarg);
+ if (my_port <= 0 || my_port > 0xffff) {
+ /* Invalid port number */
+ fprintf (stdout, "Warning: ypserv: Invalid port %d (0x%x)\n",
+ my_port, my_port);
+ my_port = -1;
+ }
+ if (debug_flag)
+ log_msg ("Using port %d\n", my_port);
+ break;
+ case 'f':
+ foreground_flag = 1;
+ break;
+ case 'u':
+ case 'h':
+ Usage (0);
+ break;
+ default:
+ Usage (1);
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (debug_flag)
+ log_msg ("[ypserv (%s) %s]\n", PACKAGE, VERSION);
+ else if (! foreground_flag)
+ {
+ int i;
+
+ if ((i = fork ()) > 0)
+ exit (0);
+
+ if (i < 0)
+ {
+ log_msg ("Cannot fork: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ if (setsid () == -1)
+ {
+ log_msg ("Cannot setsid: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ if ((i = fork ()) > 0)
+ exit (0);
+
+ if (i < 0)
+ {
+ log_msg ("Cannot fork: %s\n", strerror (errno));
+ exit (-1);
+ }
+
+ for (i = 0; i < getdtablesize (); ++i)
+ close (i);
+ errno = 0;
+
+ umask (0);
+ i = open ("/dev/null", O_RDWR);
+ if (i == -1)
+ {
+ log_msg ("opening /dev/null failed: %s\n", strerror (errno));
+ exit (1);
+ }
+ /* two dups: stdin, stdout, stderr */
+ if (dup (i) == -1)
+ {
+ log_msg ("dup failed: %s\n", strerror (errno));
+ exit (1);
+ }
+ if (dup (i) == -1)
+ {
+ log_msg ("dup failed: %s\n", strerror (errno));
+ exit (1);
+ }
+ }
+
+ if (argc > 0 && debug_flag)
+ {
+ path_ypdb = argv[0];
+ log_msg ("Using database directory: %s\n", path_ypdb);
+ }
+
+ /* Change current directory to database location */
+ if (chdir (path_ypdb) < 0)
+ {
+ log_msg ("ypserv: chdir: %s", strerror (errno));
+ exit (1);
+ }
+
+ create_pidfile (_YPSERV_PIDFILE, "ypserv");
+
+ load_securenets ();
+ load_config ();
+
+ /*
+ * Ignore SIGPIPEs. They can hurt us if someone does a ypcat
+ * and then hits CTRL-C before it terminates.
+ */
+ signal (SIGPIPE, SIG_IGN);
+ /*
+ * If program quits, give ports free.
+ */
+ signal (SIGTERM, sig_quit);
+ signal (SIGINT, sig_quit);
+ /*
+ * Ignore SIGHUP, it's not safe and we cannot reload all variables
+ */
+ signal (SIGHUP, SIG_IGN);
+ /*
+ * If we get a SIGUSR1, enable/disable debuging.
+ */
+ signal (SIGUSR1, sig_usr1);
+ /*
+ * On SIGCHLD wait for the child process, so it can give free all
+ * resources.
+ */
+ signal (SIGCHLD, sig_child);
+
+ rpcb_unset (YPPROG, YPVERS, NULL);
+ rpcb_unset (YPPROG, YPOLDVERS, NULL);
+
+ nc_handle = __rpc_setconf ("netpath"); /* open netconfig file */
+ if (nc_handle == NULL)
+ {
+ log_msg("could not read /etc/netconfig, exiting..");
+ return 1;
+ }
+
+ while ((nconf = __rpc_getconf (nc_handle)))
+ {
+ SVCXPRT *xprt;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ int sock;
+ sa_family_t family; /* AF_INET, AF_INET6 */
+ int type; /* SOCK_DGRAM (udp), SOCK_STREAM (tcp) */
+ int proto; /* IPPROTO_UDP, IPPROTO_TCP */
+
+ if (debug_flag)
+ log_msg ("Register ypserv for %s,%s",
+ nconf->nc_protofmly, nconf->nc_proto);
+
+ if (strcmp (nconf->nc_protofmly, "inet6") == 0)
+ family = AF_INET6;
+ else if (strcmp (nconf->nc_protofmly, "inet") == 0)
+ family = AF_INET;
+ else
+ continue; /* we don't support nconf->nc_protofmly */
+
+ if (strcmp (nconf->nc_proto, "udp") == 0)
+ {
+ type = SOCK_DGRAM;
+ proto = IPPROTO_UDP;
+ }
+ else if (strcmp (nconf->nc_proto, "tcp") == 0)
+ {
+ type = SOCK_STREAM;
+ proto = IPPROTO_TCP;
+ }
+ else
+ continue; /* We don't support nconf->nc_proto */
+
+ if ((sock = socket (family, type, proto)) < 0)
+ {
+ log_msg ("Cannot create socket for %s,%s: %s",
+ nconf->nc_protofmly, nconf->nc_proto,
+ strerror (errno));
+ continue;
+ }
+
+ if (family == AF_INET6)
+ {
+ /* Disallow v4-in-v6 to allow host-based access checks */
+ int i;
+
+ if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &i, sizeof(i)) == -1)
+ {
+ log_msg ("ERROR: cannot disable v4-in-v6 on %s6 socket",
+ nconf->nc_proto);
+ return 1;
+ }
+ }
+
+ switch (family)
+ {
+ case AF_INET:
+ memset (&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (my_port > 0)
+ sin.sin_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin;
+ break;
+ case AF_INET6:
+ memset (&sin6, 0, sizeof (sin6));
+ sin6.sin6_family = AF_INET6;
+ if (my_port > 0)
+ sin6.sin6_port = htons (my_port);
+ sa = (struct sockaddr *)(void *)&sin6;
+ break;
+ default:
+ log_msg ("Unsupported address family %d", family);
+ return -1;
+ }
+
+ if (bindresvport_sa (sock, sa) == -1)
+ {
+ if (my_port > 0)
+ log_msg ("Cannot bind to reserved port %d (%s)",
+ my_port, strerror (errno));
+ else
+ log_msg ("bindresvport failed: %s",
+ strerror (errno));
+ return 1;
+ }
+
+ if (type == SOCK_STREAM)
+ {
+ listen (sock, SOMAXCONN);
+ xprt = svc_vc_create (sock, 0, 0);
+ }
+ else
+ xprt = svc_dg_create (sock, 0, 0);
+
+ if (xprt == NULL)
+ {
+ log_msg ("terminating: cannot create rpcbind handle");
+ return 1;
+ }
+
+ rpcb_unset (YPPROG, YPVERS, nconf);
+ if (!svc_reg (xprt, YPPROG, YPVERS, ypprog_2, nconf))
+ {
+ log_msg ("unable to register (YPPROG, 2) for %s, %s.",
+ nconf->nc_protofmly, nconf->nc_proto);
+ continue;
+ }
+ else
+ could_register = 1;
+
+ if (family == AF_INET)
+ {
+ rpcb_unset (YPPROG, YPVERS_ORIG, nconf);
+ if (!svc_reg (xprt, YPPROG, YPVERS_ORIG,
+ ypprog_2, nconf))
+ {
+ log_msg ("unable to register (YPPROG, 1) [%s]",
+ nconf->nc_netid);
+ continue;
+ }
+ else
+ could_register = 1;
+ }
+ }
+ __rpc_endconf (nc_handle);
+
+ if (!could_register)
+ {
+ log_msg ("terminating: rpcbind not running?");
+ return 1;
+ }
+
+ /* If we use systemd as an init system, we may want to give it
+ a message, that this daemon is ready to accept connections.
+ At this time, sockets for receiving connections are already
+ created, so we can say we're ready now. It is a nop if we
+ don't use systemd. */
+ announce_ready();
+
+ svc_run ();
+ log_msg ("svc_run returned");
+ unlink (_YPSERV_PIDFILE);
+ exit (1);
+ /* NOTREACHED */
+}
diff --git a/ypserv/ypserv_xdr.c b/ypserv/ypserv_xdr.c
new file mode 100644
index 0000000..404295e
--- /dev/null
+++ b/ypserv/ypserv_xdr.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ 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, see <http://www.gnu.org/licenses/>. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rpc/rpc.h>
+#include "yp.h"
+
+xdr_ypall_cb_t xdr_ypall_cb;
+
+bool_t
+xdr_ypresp_maplist (XDR *xdrs, ypresp_maplist *objp)
+{
+ char **tp;
+
+ if (!xdr_ypstat (xdrs, &objp->status))
+ return FALSE;
+ /* Prevent gcc warning about alias violation. */
+ tp = (void *) &objp->list;
+ return xdr_pointer (xdrs, tp, sizeof (ypmaplist), (xdrproc_t) xdr_ypmaplist);
+}
+
+bool_t
+xdr_ypresp_all(XDR *xdrs, ypresp_all *objp)
+{
+ if (xdrs->x_op == XDR_ENCODE)
+ {
+ while (1)
+ {
+ if (xdr_bool(xdrs, &objp->more) == FALSE ||
+ xdr_ypresp_key_val(xdrs, &objp->ypresp_all_u.val) == FALSE)
+ {
+ if (xdr_ypall_cb.u.close != NULL)
+ (*(xdr_ypall_cb.u.close))(xdr_ypall_cb.data);
+
+ xdr_ypall_cb.data = NULL;
+
+ return FALSE;
+ }
+
+ if ((objp->ypresp_all_u.val.status != YP_TRUE) ||
+ (*xdr_ypall_cb.u.encode)(&objp->ypresp_all_u.val,
+ xdr_ypall_cb.data) != YP_TRUE)
+ {
+ objp->more = FALSE;
+
+ if (xdr_ypall_cb.u.close != NULL)
+ (*(xdr_ypall_cb.u.close))(xdr_ypall_cb.data);
+
+ xdr_ypall_cb.data = NULL;
+
+ if (!xdr_bool(xdrs, &objp->more))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ }
+ }
+
+#ifdef NOTYET /* This code isn't needed in the server */
+ else if (xdrs->x_op == XDR_DECODE)
+ {
+ int more = 0;
+
+
+ while (1)
+ {
+ if (!xdr_bool(xdrs, &objp->more))
+ return FALSE;
+
+ switch (objp->more)
+ {
+ case TRUE:
+ if (!xdr_ypresp_key_val(xdrs, &objp->ypresp_all_u.val))
+ return FALSE;
+
+ if (more == 0)
+ more = (*xdr_ypall_callback->foreach.decoder)
+ (&objp->ypresp_all_u.val, xdr_ypall_callback->data);
+ break;
+
+ case FALSE:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
diff --git a/ypxfr/Makefile.am b/ypxfr/Makefile.am
new file mode 100644
index 0000000..7b01f52
--- /dev/null
+++ b/ypxfr/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2000, 2001, 2003, 2007, 2009 Thorsten Kukuk <kukuk@linux-nis.org>
+#
+AUTOMAKE_OPTIONS = 1.7 gnits
+
+localedir = $(datadir)/locale
+
+DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" -DYPMAPDIR=\"@YPMAPDIR@\"
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)
+
+CLEANFILES = *~
+
+
+EXTRA_DIST = ${MANS} ${XMLS}
+
+man_MANS = ypxfr.8
+XMLS = ypxfr.8.xml
+
+noinst_HEADERS = ypxfr.h
+
+libexec_PROGRAMS = ypxfr
+
+ypxfr_SOURCES = ypxfr.c ypxfr_clnt.c ypxfr_xdr.c
+
+ypxfr_LDADD = @LIBDBM@ $(top_builddir)/lib/libyp.a @NSL_LIBS@ @TIRPC_LIBS@
+ypxfr_CFLAGS = @NSL_CFLAGS@ @TIRPC_CFLAGS@
+
+if ENABLE_REGENERATE_MAN
+%.8: %.8.xml
+ $(XMLLINT) --nonet --xinclude --postvalid --noout $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude --nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+endif
diff --git a/ypxfr/ypxfr.8.xml b/ypxfr/ypxfr.8.xml
new file mode 100644
index 0000000..8ef3de4
--- /dev/null
+++ b/ypxfr/ypxfr.8.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+<refentry id='ypxfr'>
+
+ <refmeta>
+ <refentrytitle>ypxfr</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>NIS Reference Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='name'>
+ <refname>ypxfr</refname>
+ <refpurpose>transfer NIS database from remote server to local host</refpurpose>
+ </refnamediv>
+
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+ <command>/usr/lib/yp/ypxfr</command>
+ <arg choice='opt'>-f</arg>
+ <arg choice='opt'>-c</arg>
+ <arg choice='opt'>-d <replaceable>target</replaceable> <replaceable>domain</replaceable></arg>
+ <arg choice='opt'>-h <replaceable>source</replaceable> <replaceable>host</replaceable></arg>
+ <arg choice='opt'>-s <replaceable>source</replaceable> <replaceable>domain</replaceable></arg>
+ <arg choice='opt'>-C <replaceable>taskid</replaceable> <replaceable>program-number</replaceable> <replaceable>host</replaceable> <replaceable>port</replaceable></arg>
+ <arg choice='opt'>-p <replaceable>yp_path</replaceable></arg>
+ <arg choice='plain' rep='repeat'><replaceable>mapname</replaceable></arg>
+
+ <sbr/>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><emphasis remap='B'>ypxfr</emphasis>
+copies an NIS database from one NIS server to the local host by
+using the NIS service.
+<emphasis remap='B'>ypxfr</emphasis>
+is generally invoked by
+<emphasis remap='B'>ypinit</emphasis>
+or by
+<emphasis remap='B'>ypserv,</emphasis>
+when
+<emphasis remap='B'>ypserv</emphasis>
+receives a map transfer request from
+<emphasis remap='B'>yppush.</emphasis>
+It creates a temporary map in the directory
+<filename>/var/yp/domain</filename>
+(this directory must already exist;
+<emphasis remap='I'>domain</emphasis>
+is the default domainname for the local host), fills it by getting
+the map's entries and fetches the map parameters (master and order number).
+If the transfer was successful, the old version of the map will be
+deleted and the temporary copy will be moved into its place.
+Then,
+<emphasis remap='B'>ypxfr</emphasis>
+will attempt to send a "clear current map" request to the local
+<emphasis remap='B'>ypserv.</emphasis></para>
+
+<para>If run interactively,
+<emphasis remap='B'>ypxfr</emphasis>
+writes its output to stderr.
+However, if it is invoked without a controlling terminal, it will
+log the output to syslog.</para>
+
+<para><emphasis remap='B'>ypxfr</emphasis>
+is used primarily in environments where several NIS servers are in use.
+For all maps, you have a NIS master server, which maintains a canonical
+copy of the NIS map, and all the other servers, the NIS slaves, copy
+the new version of the map from the master whenever a update was made.
+Normally, you have one NIS master for all maps.</para>
+
+<para>In order to maintain consistency across all NIS servers,
+<emphasis remap='B'>ypxfr</emphasis>
+can be run periodically in a
+<emphasis remap='B'>cron</emphasis>
+job. Maps which change infrequently need only be updated once a day
+(preferably late at night when system usage is lowest), where those
+with frequent changes (such as
+<emphasis remap='I'>passwd.byname</emphasis>
+and
+<emphasis remap='I'>passwd.byuid )</emphasis>
+should be updated perhaps once every hour.
+Examples are in
+<filename>/usr/lib/yp: ypxfr_1perday, ypxfr_2perday,</filename>
+and
+<emphasis remap='B'>ypxfr_1perhour.</emphasis>
+They can serve as reasonable first cuts.</para>
+
+<para>Normally all updates should be propagated by
+<emphasis remap='B'>yppush</emphasis>
+when
+<filename>/var/yp/Makefile</filename>
+is run on the NIS master server, however it is a good practice
+on large networks where possible outages could cause NIS slaves to
+fall out of sync with the master.</para>
+
+
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<para>The following options are supported:</para>
+<variablelist remap='TP'>
+ <varlistentry>
+ <term><option>-f</option></term>
+ <listitem>
+<para>Force a map transfer. Normally,
+<emphasis remap='B'>ypxfr</emphasis>
+will not transfer a map if it determines that the NIS master's copy
+is not newer than the existing copy already on the local host. This
+flag forces a transfer regardless of which server's version is more
+recent.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-c</option></term>
+ <listitem>
+<para>Do not send a "clear current map" request to the
+<emphasis remap='B'>ypserv</emphasis>
+process running on the local host. This flag is normally used when
+invoking
+<emphasis remap='B'>ypxfr</emphasis>
+by
+<emphasis remap='B'>ypinit</emphasis>
+or if
+<emphasis remap='B'>ypserv</emphasis>
+is not running locally at the time you are running
+<emphasis remap='B'>ypxfr.</emphasis>
+Otherwise,
+<emphasis remap='B'>ypxfr</emphasis>
+will complain that it cannot talk to the local
+<emphasis remap='B'>ypserv,</emphasis>
+and the transfer will fail.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-d</option><replaceable> domain</replaceable></term>
+ <listitem>
+<para>Specify a domain other than the default NIS domain.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option><replaceable> source host</replaceable></term>
+ <listitem>
+<para>Get the map from
+<emphasis remap='I'>host</emphasis>,
+regardless of what the map says the master is. If
+<emphasis remap='I'>host</emphasis>
+is not specified,
+<emphasis remap='B'>ypxfr</emphasis>
+asks the
+<acronym>NIS</acronym>
+service for the name of the master, and tries to get the
+map from there. This option is used to insure that ypxfr only copies
+maps from the NIS master server.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-s</option><replaceable> source domain</replaceable></term>
+ <listitem>
+<para>Specify a source domain from which to transfer a map that should be the same
+across domains.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-C</option><replaceable> taskid progam-number host port</replaceable></term>
+ <listitem>
+<para>This option is
+<emphasis remap='B'>only</emphasis>
+for use by
+<emphasis remap='B'>ypserv .</emphasis>
+When
+<emphasis remap='B'>ypserv</emphasis>
+invokes
+<emphasis remap='B'>ypxfr</emphasis>,
+it specifies that
+<emphasis remap='B'>ypxfr</emphasis>
+should call back a
+<emphasis remap='B'>yppush</emphasis>
+process at the host with
+<acronym>IP</acronym>
+address or name
+<emphasis remap='I'>host</emphasis>,
+registered as program number
+<emphasis remap='I'>progam-number</emphasis>,
+listening on port
+<emphasis remap='I'>port</emphasis>,
+and waiting for a response to transaction
+<emphasis remap='I'>taskid</emphasis>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option><replaceable> yp_path</replaceable></term>
+ <listitem>
+<para>Change the directory for the maps to
+<emphasis remap='I'>yp_path/[domainname]/</emphasis>, the default
+is <filename>/var/yp/[domainname]</filename>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis remap='I'>mapname</emphasis></term>
+ <listitem>
+<para>One or more names of the map to transfer.</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='files'><title>FILES</title>
+<para>/var/yp/[domainname]/[maps]</para>
+</refsect1>
+
+<refsect1 id='see_also'><title>SEE ALSO</title>
+<para><citerefentry><refentrytitle>ypserv</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>yppush</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>ypinit</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>cron</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>crontab</refentrytitle><manvolnum>5</manvolnum></citerefentry></para>
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>Thorsten Kukuk &lt;kukuk@linux-nis.org&gt;</para>
+</refsect1>
+</refentry>
diff --git a/ypxfr/ypxfr.c b/ypxfr/ypxfr.c
new file mode 100644
index 0000000..7aac333
--- /dev/null
+++ b/ypxfr/ypxfr.c
@@ -0,0 +1,1011 @@
+/* Copyright (c) 2000-2005, 2011, 2014, 2015, 2016 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <alloca.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include "log_msg.h"
+#include "yp.h"
+#include "ypxfr.h"
+#include "ypxfrd.h"
+#include <rpcsvc/ypclnt.h>
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+#if defined(HAVE_LIBGDBM)
+#include <gdbm.h>
+#elif defined(HAVE_LIBQDBM)
+#include <hovel.h>
+#endif
+
+#define ypdb_store gdbm_store
+#define YPDB_REPLACE GDBM_REPLACE
+#define ypdb_close gdbm_close
+#define ypdb_fetch gdbm_fetch
+static GDBM_FILE dbm;
+#elif defined (HAVE_NDBM)
+#include <ndbm.h>
+
+#define ypdb_store dbm_store
+#define YPDB_REPLACE DBM_REPLACE
+#define ypdb_close dbm_close
+#define ypdb_fetch dbm_fetch
+static DBM *dbm;
+#elif defined(HAVE_LIBTC)
+#include <tcbdb.h>
+
+#define YPDB_REPLACE 1
+
+static inline int
+ypdb_close (TCBDB *dbp)
+{
+ tcbdbclose (dbp);
+ tcbdbdel (dbp);
+ dbp = NULL;
+ return 0;
+}
+
+static int
+ypdb_store (TCBDB *dbm, datum key, datum data, int mode)
+{
+ if (mode != YPDB_REPLACE)
+ return 1;
+
+ return !tcbdbput(dbm, key.dptr, key.dsize, data.dptr, data.dsize);
+}
+
+static datum
+ypdb_fetch (TCBDB *bdb, datum key)
+{
+ datum res;
+
+ if (!(res.dptr = tcbdbget(bdb, key.dptr, key.dsize, &res.dsize)))
+ {
+ res.dptr = NULL;
+ res.dsize = 0;
+ }
+
+ return res;
+}
+
+static TCBDB *dbm;
+
+#endif
+
+static char *path_ypdb = YPMAPDIR;
+
+static void
+Usage (int exit_code)
+{
+ fprintf (stderr, "usage: ypxfr [-f] [-c] [-d target domain] [-h source host] [-s source domain]\n");
+ fprintf (stderr, " [-C taskid program-number ipaddr port] [-p yp_path] mapname ...\n");
+ fprintf (stderr, " ypxfr --version\n");
+ fprintf (stderr, "\n");
+ fprintf (stderr, "where\n");
+ fprintf (stderr, "\t-f forces transfer even if the master's copy is not newer.\n");
+ fprintf (stderr, "\thost may be either a name or an internet\n");
+ fprintf (stderr, "\t address of form ww.xx.yy.zz\n");
+ fprintf (stderr, "\t-c inhibits sending a \"Clear map\" message to the local ypserv.\n");
+ fprintf (stderr, "\t-C is used by ypserv to pass callback information.\n");
+ exit (exit_code);
+}
+
+
+static char *
+ypxfr_err_string (enum ypxfrstat error)
+{
+ switch (error)
+ {
+ case YPXFR_SUCC:
+ return "Success";
+ case YPXFR_AGE:
+ return "Master's version not newer";
+ case YPXFR_NOMAP:
+ return "Can't find server for map";
+ case YPXFR_NODOM:
+ return "Domain not supported";
+ case YPXFR_RSRC:
+ return "Local resource alloc failure";
+ case YPXFR_RPC:
+ return "RPC failure talking to server";
+ case YPXFR_MADDR:
+ return "Can't get master address";
+ case YPXFR_YPERR:
+ return "YP server/map db error";
+ case YPXFR_BADARGS:
+ return "Request arguments bad";
+ case YPXFR_DBM:
+ return "Local dbm operation failed";
+ case YPXFR_FILE:
+ return "Local file I/O operation failed";
+ case YPXFR_SKEW:
+ return "Map version skew during transfer";
+ case YPXFR_CLEAR:
+ return "Can't send \"Clear\" req to local ypserv";
+ case YPXFR_FORCE:
+ return "No local order number in map use -f flag.";
+ case YPXFR_XFRERR:
+ return "ypxfr error";
+ case YPXFR_REFUSED:
+ return "Transfer request refused by ypserv";
+ }
+ return "Unknown Error, should not happen";
+}
+
+static int ypxfrd_file = 0;
+
+static bool_t
+xdr_ypxfr_xfr (XDR *xdrs, xfr *objp)
+{
+ while (1)
+ {
+ if (!xdr_xfr (xdrs, objp))
+ return (FALSE);
+ if (objp->ok == TRUE)
+ {
+ if (write (ypxfrd_file, objp->xfr_u.xfrblock_buf.xfrblock_buf_val,
+ objp->xfr_u.xfrblock_buf.xfrblock_buf_len) == -1)
+ {
+ log_msg ("write failed: %s", strerror (errno));
+ return FALSE;
+ }
+ }
+ xdr_free ((xdrproc_t) xdr_xfr, (char *) objp);
+ if (objp->ok == FALSE)
+ {
+ switch (objp->xfr_u.xfrstat)
+ {
+ case XFR_DONE:
+ return TRUE;
+ break;
+ case XFR_DENIED:
+ log_msg ("access to map denied by rpc.ypxfrd");
+ return FALSE;
+ break;
+ case XFR_NOFILE:
+ log_msg ("reqested map does not exist");
+ return FALSE;
+ break;
+ case XFR_ACCESS:
+ log_msg ("rpc.ypxfrd couldn't access the map");
+ return FALSE;
+ break;
+ case XFR_BADDB:
+ log_msg ("file is not a database");
+ return FALSE;
+ break;
+ case XFR_READ_OK:
+ if (debug_flag)
+ log_msg ("block read successfully");
+ return TRUE;
+ break;
+ case XFR_READ_ERR:
+ log_msg ("got read error from rpc.ypxfrd");
+ return FALSE;
+ break;
+ case XFR_DB_ENDIAN_MISMATCH:
+ log_msg ("rpc.ypxfrd databases have the wrong endian");
+ return FALSE;
+ break;
+ case XFR_DB_TYPE_MISMATCH:
+ log_msg ("rpc.ypxfrd doesn't support the needed database type");
+ return FALSE;
+ break;
+ default:
+ log_msg ("got unknown status from rpc.ypxfrd");
+ return FALSE;
+ break;
+ }
+ }
+ }
+}
+
+#ifdef HAVE_RPCB_GETADDR
+static unsigned short
+__taddr2port (const struct netconfig *nconf, const struct netbuf *nbuf)
+{
+ unsigned short port = 0;
+ struct __rpc_sockinfo si;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return 0;
+
+ switch (si.si_af)
+ {
+ case AF_INET:
+ sin = nbuf->buf;
+ port = sin->sin_port;
+ break;
+ case AF_INET6:
+ sin6 = nbuf->buf;
+ port = sin6->sin6_port;
+ break;
+ default:
+ break;
+ }
+
+ return htons (port);
+}
+#endif
+
+static int
+ypxfrd_transfer (char *host, char *map, char *domain, char *tmpname)
+{
+ CLIENT *clnt;
+ struct ypxfr_mapname req;
+ struct xfr resp;
+ struct timeval timeout = {25, 0};
+ int port = 0;
+#if defined(HAVE_RPCB_GETADDR)
+ struct netconfig *nconf;
+ struct netbuf svcaddr;
+ char addrbuf[INET6_ADDRSTRLEN];
+ void *handle;
+ int found;
+#endif
+
+ if (debug_flag)
+ fprintf (stderr, "Trying ypxfrd ...");
+
+#ifdef HAVE_RPCB_GETADDR
+ svcaddr.len = 0;
+ svcaddr.maxlen = sizeof (addrbuf);
+ svcaddr.buf = addrbuf;
+ found = 0;
+
+ handle = setnetconfig();
+ while ((nconf = getnetconfig(handle)) != NULL)
+ {
+ if (!strcmp(nconf->nc_proto, "udp"))
+ {
+ if (rpcb_getaddr(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS,
+ nconf, &svcaddr, host))
+ {
+ port = __taddr2port (nconf, &svcaddr);
+ endnetconfig (handle);
+ found=1;
+ break;
+ }
+
+ if (rpc_createerr.cf_stat != RPC_UNKNOWNHOST)
+ {
+ clnt_pcreateerror (host);
+ log_msg ("rpcb_getaddr (%s) failed!", host);
+ return 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ log_msg ("Cannot find suitable transport for protocol 'udp'");
+ return 1;
+ }
+#else
+ port = getrpcport (host, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS,
+ IPPROTO_TCP))
+#endif
+ if (port == 0)
+ {
+ if (debug_flag)
+ log_msg (" not running");
+ return 1;
+ }
+
+ req.xfrmap = map;
+ req.xfrdomain = domain;
+ req.xfrmap_filename = map;
+#if defined(HAVE_LIBGDBM)
+#if SIZEOF_LONG == 8
+ req.xfr_db_type = XFR_DB_GNU_GDBM64;
+#else
+ req.xfr_db_type = XFR_DB_GNU_GDBM;
+#endif
+#if defined(WORDS_BIGENDIAN)
+ req.xfr_byte_order = XFR_ENDIAN_BIG;
+#else
+ req.xfr_byte_order = XFR_ENDIAN_LITTLE;
+#endif
+#elif defined (HAVE_NDBM)
+#if defined(__sun__) || defined (sun)
+ req.xfr_db_type = XFR_DB_NDBM;
+#if defined(WORDS_BIGENDIAN)
+ req.xfr_byte_order = XFR_ENDIAN_BIG;
+#else
+ req.xfr_byte_order = XFR_ENDIAN_LITTLE;
+#endif
+#else
+ req.xfr_db_type = XFR_DB_BSD_NDBM;
+ req.xfr_byte_order = XFR_ENDIAN_ANY;
+#endif
+#elif defined (HAVE_LIBQDBM)
+ req.xfr_db_type = XFR_DB_QDBM;
+#if defined(WORDS_BIGENDIAN)
+ req.xfr_byte_order = XFR_ENDIAN_BIG;
+#else
+ req.xfr_byte_order = XFR_ENDIAN_LITTLE;
+#endif
+#elif defined (HAVE_LIBTC)
+ req.xfr_db_type = XFR_DB_TC;
+ req.xfr_byte_order = XFR_ENDIAN_ANY;
+#endif
+ memset (&resp, 0, sizeof (resp));
+
+ if ((clnt = clnt_create (host, YPXFRD_FREEBSD_PROG,
+ YPXFRD_FREEBSD_VERS, "tcp")) == NULL)
+ goto error;
+
+ if ((ypxfrd_file = open (tmpname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
+ {
+ clnt_destroy (clnt);
+ log_msg ("couldn't open %s: %s", tmpname, strerror (errno));
+ goto error;
+ }
+
+ if (clnt_call (clnt, YPXFRD_GETMAP, (xdrproc_t) xdr_ypxfr_mapname,
+ (caddr_t) &req, (xdrproc_t) xdr_ypxfr_xfr,
+ (caddr_t) &resp, timeout) != RPC_SUCCESS)
+ {
+ log_msg ("%s", clnt_sperror (clnt, "call to rpc.ypxfrd failed"));
+ unlink (tmpname);
+ clnt_destroy (clnt);
+ close (ypxfrd_file);
+ goto error;
+ }
+
+ clnt_destroy (clnt);
+ close (ypxfrd_file);
+
+ if (debug_flag)
+ log_msg (" success\n");
+
+ return 0;
+
+error:
+ if (debug_flag)
+ log_msg (" (failed, fallback to enumeration)\n");
+ return 1;
+}
+
+static int
+ypxfr_foreach (int status, char *key, int keylen,
+ char *val, int vallen, char *data UNUSED)
+{
+ datum outKey, outData;
+
+ if (debug_flag > 1)
+ {
+ if (keylen != 0 && vallen != 0)
+ log_msg ("ypxfr_foreach: key=%.*s, val=%.*s", keylen, key,
+ vallen, val);
+ else
+ log_msg ("ypxfr_foreach: empty key/value pair!");
+ }
+
+ if (status == YP_NOMORE)
+ return 0;
+
+ if (status != YP_TRUE)
+ {
+ int s = ypprot_err (status);
+ log_msg ("%s", yperr_string (s));
+ return 1;
+ }
+
+ if (keylen != 0)
+ {
+ /* Hack for broken maps: If keylen/vallen includes the trailing 0,
+ decrement it. */
+ if (keylen > 0 && key[keylen - 1] == '\0')
+ --keylen;
+ if (vallen > 0 && val[vallen - 1] == '\0')
+ --vallen;
+ /* Now save it */
+ outKey.dptr = keylen ? key : "";
+ outKey.dsize = keylen;
+ outData.dptr = vallen ? val : "";
+ outData.dsize = vallen;
+ if (ypdb_store (dbm, outKey, outData, YPDB_REPLACE) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+extern struct ypall_callback *xdr_ypall_callback;
+
+/* Don't replace the source_host with the FQDN in this function. Or ypserv
+ cannot compare the name of the host, who initiated a yppush, with the
+ master name of the map. */
+static enum ypxfrstat
+ypxfr (char *map, char *source_host, char *source_domain, char *target_domain,
+ int noclear, int force)
+{
+ struct ypall_callback callback;
+ char dbName_orig[MAXPATHLEN + 1];
+ char dbName_temp[MAXPATHLEN + 1];
+ char *master_host = NULL;
+ char *server = NULL;
+ struct ypreq_key req_key;
+ struct ypresp_val resp_val;
+ struct ypresp_all resp_all;
+ datum outKey, outData;
+ CLIENT *clnt_udp;
+ struct ypresp_order resp_order;
+ struct ypresp_master resp_master;
+ struct ypreq_nokey req_nokey;
+ time_t masterOrderNum;
+ int result;
+
+ /* Name of the map file */
+ if (strlen (path_ypdb) + strlen (target_domain) + strlen (map) + 3 < MAXPATHLEN)
+ sprintf (dbName_orig, "%s/%s/%s", path_ypdb, target_domain, map);
+ else
+ {
+ log_msg ("ERROR: Path to long: %s/%s/%s", path_ypdb, target_domain, map);
+ return YPXFR_RSRC;
+ }
+
+ /* Name of the temporary map file */
+ if (strlen (path_ypdb) + strlen (target_domain) + strlen (map) + 4 < MAXPATHLEN)
+ sprintf (dbName_temp, "%s/%s/%s~", path_ypdb, target_domain, map);
+ else
+ {
+ log_msg ("ERROR: Path to long: %s/%s/%s~", path_ypdb, target_domain, map);
+ return YPXFR_RSRC;
+ }
+
+ /* Build a connection to the host with the master map, not to
+ the nearest ypserv, because this map could be out of date. */
+ if (source_host)
+ server = source_host;
+ else
+ {
+ /* Get the Master hostname for the map, if no explicit
+ sourcename is given. */
+ char *master_name = NULL;
+
+ if (yp_master (source_domain, map, &master_name))
+ return YPXFR_MADDR;
+ server = strdupa (master_name);
+ free (master_name);
+ }
+ clnt_udp = clnt_create (server, YPPROG, YPVERS, "udp");
+ if (clnt_udp == NULL)
+ {
+ log_msg (clnt_spcreateerror ("YPXFR"));
+ return YPXFR_RPC;
+ }
+
+ /* We cannot use the libc functions since we don't know which host
+ they use. So query the host we must use to get the official master
+ server name for the map on the master host. */
+ req_nokey.domain = source_domain;
+ req_nokey.map = map;
+ memset (&resp_master, 0, sizeof (resp_master));
+ if (ypproc_master_2 (&req_nokey, &resp_master, clnt_udp) != RPC_SUCCESS)
+ {
+ log_msg (clnt_sperror (clnt_udp, "ypproc_master_2"));
+ clnt_destroy (clnt_udp);
+ return YPXFR_YPERR;
+ }
+ else if (resp_master.status != YP_TRUE)
+ {
+ clnt_destroy (clnt_udp);
+ switch (resp_master.status)
+ {
+ case YP_NOMAP:
+ return YPXFR_NOMAP;
+ case YP_NODOM:
+ return YPXFR_NODOM;
+ case YP_BADDB:
+ return YPXFR_DBM;
+ case YP_YPERR:
+ return YPXFR_YPERR;
+ case YP_BADARGS:
+ return YPXFR_BADARGS;
+ default:
+ log_msg ("ERROR: not expected value: %s", resp_master.status);
+ return YPXFR_XFRERR;
+ }
+ }
+ else
+ {
+ master_host = alloca (strlen (resp_master.master) + 1);
+ strcpy (master_host, resp_master.master);
+ xdr_free ((xdrproc_t) xdr_ypresp_master, (caddr_t) &resp_master);
+ }
+
+ /* We cannot use the libc functions since we don't know which host
+ they use. So query the host we must use to get the order number
+ for the map on the master host. */
+ req_nokey.domain = source_domain;
+ req_nokey.map = map;
+ memset (&resp_order, 0, sizeof (resp_order));
+ if (ypproc_order_2 (&req_nokey, &resp_order, clnt_udp) != RPC_SUCCESS)
+ {
+ log_msg (clnt_sperror (clnt_udp, "ypproc_order_2"));
+ clnt_destroy (clnt_udp);
+ return YPXFR_YPERR; /* return error when not possible to
+ get masterOrder */
+ }
+ else if (resp_order.status != YP_TRUE)
+ {
+ clnt_destroy (clnt_udp);
+ switch (resp_order.status)
+ {
+ case YP_NOMAP:
+ return YPXFR_NOMAP;
+ case YP_NODOM:
+ return YPXFR_NODOM;
+ case YP_BADDB:
+ return YPXFR_DBM;
+ case YP_YPERR:
+ return YPXFR_YPERR;
+ case YP_BADARGS:
+ return YPXFR_BADARGS;
+ default:
+ log_msg ("ERROR: not expected value: %s", resp_order.status);
+ return YPXFR_XFRERR;
+ }
+ }
+ else
+ {
+ masterOrderNum = resp_order.ordernum;
+ xdr_free ((xdrproc_t) xdr_ypresp_order, (caddr_t) &resp_order);
+ }
+
+ /* If we doesn't force the map, look, if the new map is really newer */
+ if (!force)
+ {
+ time_t localOrderNum = 0;
+ datum inKey, inVal;
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dbm = gdbm_open (dbName_orig, 0, GDBM_READER, 0600, NULL);
+#elif defined(HAVE_NDBM)
+ dbm = dbm_open (dbName_orig, O_RDONLY, 0600);
+#elif defined(HAVE_LIBTC)
+ dbm = tcbdbnew ();
+ if (!tcbdbopen (dbm, dbName_orig, BDBOREADER | BDBONOLCK))
+ {
+ tcbdbdel (dbm);
+ dbm = NULL;
+ }
+#endif
+ if (dbm == NULL)
+ {
+ if (debug_flag)
+ log_msg ("Cannot open old %s - ignored.", dbName_orig);
+ localOrderNum = 0;
+ }
+ else
+ {
+ inKey.dptr = "YP_LAST_MODIFIED";
+ inKey.dsize = strlen (inKey.dptr);
+ inVal = ypdb_fetch (dbm, inKey);
+ if (inVal.dptr)
+ {
+ int i;
+ char *d = inVal.dptr;
+
+ for (i = 0; i < inVal.dsize; i++, d++)
+ {
+ if (!isdigit (*d))
+ {
+ log_msg ("YP_LAST_MODIFIED entry \"%.*s\" in \"%s\" is not valid",
+ inVal.dsize, inVal.dptr, dbName_orig);
+ clnt_destroy (clnt_udp);
+ ypdb_close (dbm);
+ return YPXFR_SKEW;
+ }
+ }
+ d = alloca (inVal.dsize + 2);
+ strncpy (d, inVal.dptr, inVal.dsize);
+ d[inVal.dsize] = '\0';
+ localOrderNum = atoi (d);
+ }
+ ypdb_close (dbm);
+ }
+
+ if (debug_flag > 1)
+ log_msg ("masterOrderNum=%d, localOrderNum=%d",
+ masterOrderNum, localOrderNum);
+
+ if (localOrderNum >= masterOrderNum)
+ {
+ if (debug_flag)
+ log_msg("Map on Master \"%s\" is not newer", master_host);
+ clnt_destroy (clnt_udp);
+ return YPXFR_AGE;
+ }
+ }
+
+ /* Try to use ypxfrd for getting the new map. If it fails, use the old
+ method. */
+ if ((result = ypxfrd_transfer (master_host, map,
+ target_domain, dbName_temp)) != 0)
+ {
+ /* No success with ypxfrd, get the map entry by entry */
+ char orderNum[255];
+ CLIENT *clnt_tcp;
+
+#if defined(HAVE_COMPAT_LIBGDBM)
+ dbm = gdbm_open (dbName_temp, 0, GDBM_NEWDB, 0600, NULL);
+#elif defined(HAVE_NDBM)
+ dbm = dbm_open (dbName_temp, O_CREAT|O_RDWR, 0600);
+#elif defined(HAVE_LIBTC)
+ dbm = tcbdbnew ();
+ if (!tcbdbopen (dbm, dbName_temp, BDBOWRITER | BDBOCREAT | BDBOTRUNC))
+ {
+ tcbdbdel (dbm);
+ dbm = NULL;
+ }
+#endif
+ if (dbm == NULL)
+ {
+ log_msg ("Cannot open %s", dbName_temp);
+ clnt_destroy (clnt_udp);
+ return YPXFR_DBM;
+ }
+
+ outKey.dptr = "YP_MASTER_NAME";
+ outKey.dsize = strlen (outKey.dptr);
+ outData.dptr = master_host;
+ outData.dsize = strlen (outData.dptr);
+ if (ypdb_store (dbm, outKey, outData, YPDB_REPLACE) != 0)
+ {
+ ypdb_close (dbm);
+ unlink (dbName_temp);
+ clnt_destroy (clnt_udp);
+ return YPXFR_DBM;
+ }
+ snprintf (orderNum, sizeof (orderNum), "%ld", (long)masterOrderNum);
+ outKey.dptr = "YP_LAST_MODIFIED";
+ outKey.dsize = strlen (outKey.dptr);
+ outData.dptr = orderNum;
+ outData.dsize = strlen (outData.dptr);
+ if (ypdb_store (dbm, outKey, outData, YPDB_REPLACE) != 0)
+ {
+ ypdb_close (dbm);
+ unlink (dbName_temp);
+ clnt_destroy (clnt_udp);
+ return YPXFR_DBM;
+ }
+
+ /* Get the YP_INTERDOMAIN field. This is needed from the SunOS ypserv.
+ We ignore this, since we have the "dns" option. But a Sun could be
+ a NIS slave server and request the map from us. */
+ req_key.domain = source_domain;
+ req_key.map = map;
+ req_key.keydat.keydat_val = "YP_INTERDOMAIN";
+ req_key.keydat.keydat_len = strlen ("YP_INTERDOMAIN");
+ memset (&resp_val, 0, sizeof (resp_val));
+ if (ypproc_match_2 (&req_key, &resp_val, clnt_udp) != RPC_SUCCESS)
+ {
+ clnt_perror (clnt_udp, "ypproc_match(YP_INTERDOMAIN)");
+ clnt_destroy (clnt_udp);
+ ypdb_close (dbm);
+ unlink (dbName_temp);
+ return YPXFR_RPC;
+ }
+ else
+ {
+ if (resp_val.status == YP_TRUE)
+ {
+ outKey.dptr = "YP_INTERDOMAIN";
+ outKey.dsize = strlen (outKey.dptr);
+ outData.dptr = "";
+ outData.dsize = 0;
+ if (ypdb_store (dbm, outKey, outData, YPDB_REPLACE) != 0)
+ {
+ clnt_destroy (clnt_udp);
+ ypdb_close (dbm);
+ unlink (dbName_temp);
+ return YPXFR_DBM;
+ }
+ xdr_free ((xdrproc_t) xdr_ypresp_val,
+ (char *) &resp_val);
+ }
+ }
+
+ /* Get the YP_SECURE field. */
+ req_key.domain = source_domain;
+ req_key.map = map;
+ req_key.keydat.keydat_val = "YP_SECURE";
+ req_key.keydat.keydat_len = strlen ("YP_SECURE");
+ memset (&resp_val, 0, sizeof (resp_val));
+ if (ypproc_match_2 (&req_key, &resp_val, clnt_udp) != RPC_SUCCESS)
+ {
+ clnt_perror (clnt_udp, "yproc_match");
+ clnt_destroy (clnt_udp);
+ ypdb_close (dbm);
+ unlink (dbName_temp);
+ return YPXFR_RPC;
+ }
+ else
+ {
+ if (resp_val.status == YP_TRUE)
+ {
+ outKey.dptr = "YP_SECURE";
+ outKey.dsize = strlen (outKey.dptr);
+ outData.dptr = "";
+ outData.dsize = 0;
+ if (ypdb_store (dbm, outKey, outData, YPDB_REPLACE) != 0)
+ {
+ clnt_destroy (clnt_udp);
+ ypdb_close (dbm);
+ unlink (dbName_temp);
+ return YPXFR_DBM;
+ }
+ xdr_free ((xdrproc_t) xdr_ypresp_val,
+ (char *) &resp_val);
+ }
+ }
+
+ /* We don't need clnt_udp any longer, give it free */
+ clnt_destroy (clnt_udp);
+ /* Create a tcp socket to the server */
+ clnt_tcp = clnt_create (server, YPPROG, YPVERS, "tcp");
+ if (clnt_tcp == NULL)
+ {
+ clnt_pcreateerror ("YPXFR");
+ return YPXFR_RPC;
+ }
+
+ callback.foreach = ypxfr_foreach;
+ callback.data = NULL;
+ {
+ req_nokey.domain = source_domain;
+ req_nokey.map = map;
+ xdr_ypall_callback = &callback;
+ memset (&resp_all, 0, sizeof (resp_all));
+ if (ypproc_all_2 (&req_nokey, &resp_all, clnt_tcp) != RPC_SUCCESS)
+ {
+ clnt_perror (clnt_tcp, "ypall");
+ clnt_destroy (clnt_tcp);
+ ypdb_close (dbm);
+ return YPXFR_RPC;
+ }
+ else
+ {
+ switch (resp_all.ypresp_all_u.val.status)
+ {
+ case YP_TRUE:
+ case YP_NOMORE:
+ result = 0;
+ break;
+ default:
+ result = ypprot_err (resp_all.ypresp_all_u.val.status);
+ }
+ clnt_freeres (clnt_tcp, (xdrproc_t) ypxfr_xdr_ypresp_all,
+ (caddr_t) &resp_all);
+ }
+ }
+
+ clnt_destroy (clnt_tcp);
+ ypdb_close (dbm);
+ }
+
+ if (result == 0)
+ {
+#if defined(HAVE_LIBTC)
+ chmod(dbName_temp, S_IRUSR|S_IWUSR);
+#endif
+ rename (dbName_temp, dbName_orig);
+ }
+ else
+ unlink(dbName_temp);
+
+ if (!noclear) /* send the clear independing if an error occurs before */
+ {
+ char in = 0, *out = NULL;
+ int stat;
+
+ if ((stat = callrpc ("localhost", YPPROG, YPVERS, YPPROC_CLEAR,
+ (xdrproc_t) xdr_void, &in,
+ (xdrproc_t) xdr_void, out)) != RPC_SUCCESS)
+ {
+ log_msg ("failed to send 'clear' to local ypserv: %s",
+ clnt_sperrno ((enum clnt_stat) stat));
+ return YPXFR_CLEAR;
+ }
+ }
+
+ return result == 0 ? YPXFR_SUCC : YPXFR_YPERR;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *source_host = NULL, *target_domain = NULL, *source_domain = NULL;
+ const char *remote_addr = NULL;
+ unsigned int transid = 0;
+ unsigned short int remote_port = 0;
+ unsigned long program_number = 0;
+ int force = 0;
+ int noclear = 0;
+
+ if (argc < 2)
+ Usage (1);
+
+ if (!isatty (fileno (stderr)))
+ openlog ("ypxfr", LOG_PID, LOG_DAEMON);
+ else
+ debug_flag = 1;
+
+ while (1)
+ {
+ int c;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"version", no_argument, NULL, '\255'},
+ {"debug", no_argument, NULL, '\254'},
+ {"help", no_argument, NULL, 'u'},
+ {"usage", no_argument, NULL, 'u'},
+ {"path", required_argument, NULL, 'p'},
+ {NULL, 0, NULL, '\0'}
+ };
+
+ c = getopt_long (argc, argv, "ufcd:h:p:s:C:S", long_options, &option_index);
+ if (c == EOF)
+ break;
+ switch (c)
+ {
+ case 'p':
+ path_ypdb = optarg;
+ if (debug_flag)
+ log_msg ("Using database directory: %s", path_ypdb);
+ break;
+ case 'f':
+ force++;
+ break;
+ case 'c':
+ noclear++;
+ break;
+ case 'd':
+ if (strchr (optarg, '/'))
+ {
+ Usage (1);
+ break;
+ }
+ target_domain = optarg;
+ break;
+ case 'h':
+ source_host = optarg;
+ break;
+ case 's':
+ if (strchr (optarg, '/'))
+ {
+ Usage (1);
+ break;
+ }
+ source_domain = optarg;
+ break;
+ case 'C':
+ if (optind + 3 > argc)
+ {
+ Usage (1);
+ break;
+ }
+ transid = atoi (optarg);
+ program_number = atoi (argv[optind++]);
+ remote_addr = argv[optind++];
+ remote_port = atoi (argv[optind++]);
+ break;
+ case 'u':
+ Usage (0);
+ break;
+ case '\254':
+ debug_flag = 2;
+ break;
+ case '\255':
+ log_msg ("ypxfr (%s) %s", PACKAGE, VERSION);
+ return 0;
+ default:
+ Usage (1);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (target_domain == NULL)
+ {
+ if (yp_get_default_domain (&target_domain) != 0)
+ {
+ log_msg ("Cannot get default domain");
+ exit (1);
+ }
+
+ if (target_domain == NULL)
+ {
+ log_msg ("Please specify domainname");
+ exit (1);
+ }
+ }
+
+ if (source_domain == NULL)
+ source_domain = target_domain;
+
+ for (; *argv; argv++)
+ {
+ enum ypxfrstat res;
+
+ /* Start the map transfer */
+ if ((res = ypxfr (*argv, source_host, source_domain, target_domain,
+ noclear, force)) != YPXFR_SUCC)
+ {
+ /* Don't syslog "Master's version not newer" as that is
+ the common case. */
+ if (debug_flag || res != YPXFR_AGE)
+ log_msg ("ypxfr: %s", ypxfr_err_string (res));
+ }
+
+ /* Now send the status to the yppush program, so it can display a
+ message for the sysop and do not timeout. */
+ if (transid)
+ {
+ struct timeval tv = {10, 0};
+ CLIENT *clnt;
+ ypresp_xfr resp;
+
+ clnt = clnt_create (remote_addr, program_number, YPPUSHVERS, "datagram_n");
+ if (!clnt)
+ {
+ clnt_pcreateerror ("ypxfr_callback create");
+ if (debug_flag)
+ log_msg ("Remote host: %s, %x", remote_addr, program_number);
+ continue;
+ }
+ resp.transid = transid;
+ resp.xfrstat = res;
+
+ if (clnt_call (clnt, YPPUSHPROC_XFRRESP,
+ (xdrproc_t) xdr_ypresp_xfr, (caddr_t) &resp,
+ (xdrproc_t) xdr_void, (caddr_t)&res, tv)
+ != RPC_SUCCESS)
+ {
+ clnt_perror (clnt, "ypxfr_callback call");
+ if (debug_flag)
+ log_msg ("Remote host: %s, %x", remote_addr, program_number);
+ }
+
+ clnt_destroy (clnt);
+ }
+ }
+
+ return 0;
+}
diff --git a/ypxfr/ypxfr.h b/ypxfr/ypxfr.h
new file mode 100644
index 0000000..60c840d
--- /dev/null
+++ b/ypxfr/ypxfr.h
@@ -0,0 +1,7 @@
+
+#ifndef __YPXFR_H__
+#define __YPXFR_H__
+
+extern bool_t ypxfr_xdr_ypresp_all(XDR *, ypresp_all *);
+
+#endif
diff --git a/ypxfr/ypxfr_clnt.c b/ypxfr/ypxfr_clnt.c
new file mode 100644
index 0000000..731add4
--- /dev/null
+++ b/ypxfr/ypxfr_clnt.c
@@ -0,0 +1,49 @@
+/* Copyright (c) 2000, 2003 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <string.h>
+#include <memory.h>
+
+#include "yp.h"
+#include "ypxfr.h"
+
+static struct timeval TIMEOUT = { 25, 0 };
+
+enum clnt_stat
+ypproc_order_2 (ypreq_nokey *argp, ypresp_order *clnt_res, CLIENT *clnt)
+{
+ memset(clnt_res, 0, sizeof(ypresp_order));
+ return (clnt_call(clnt, YPPROC_ORDER,
+ (xdrproc_t) xdr_ypreq_nokey, (caddr_t) argp,
+ (xdrproc_t) xdr_ypresp_order, (caddr_t) clnt_res,
+ TIMEOUT));
+}
+
+enum clnt_stat
+ypproc_master_2 (ypreq_nokey *argp, ypresp_master *clnt_res, CLIENT *clnt)
+{
+ memset(clnt_res, 0, sizeof(ypresp_master));
+ return (clnt_call(clnt, YPPROC_MASTER,
+ (xdrproc_t) xdr_ypreq_nokey, (caddr_t) argp,
+ (xdrproc_t) xdr_ypresp_master, (caddr_t) clnt_res,
+ TIMEOUT));
+}
diff --git a/ypxfr/ypxfr_xdr.c b/ypxfr/ypxfr_xdr.c
new file mode 100644
index 0000000..5fd782b
--- /dev/null
+++ b/ypxfr/ypxfr_xdr.c
@@ -0,0 +1,124 @@
+/* Copyright (c) 1996, 1997, 1999, 2001, 2003, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The YP Server 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 the YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include "yp.h"
+
+struct {
+ union {
+ ypstat (*encoder) (char *, int, char **, int *, char **, int *);
+ int (*decoder) (int, char *, int, char *, int, char *);
+ }
+ foreach;
+ char *data;
+} *xdr_ypall_callback;
+
+bool_t
+ypxfr_xdr_ypresp_all (XDR *xdrs, ypresp_all *objp)
+{
+ int CallAgain = 0;
+
+ if (xdrs->x_op == XDR_DECODE)
+ {
+ while (1)
+ {
+ int s = objp->ypresp_all_u.val.status;
+ memset (objp, '\0', sizeof (*objp));
+ objp->ypresp_all_u.val.status = s;
+ if (!xdr_bool (xdrs, &objp->more))
+ return FALSE;
+
+ switch (objp->more)
+ {
+ case TRUE:
+ if (!xdr_ypresp_key_val (xdrs, &objp->ypresp_all_u.val))
+ {
+ printf ("xdr_ypresp_key_val failed\n");
+ return (FALSE);
+ }
+
+ if (CallAgain == 0)
+ {
+ CallAgain = (*(xdr_ypall_callback->foreach.decoder))
+ (objp->ypresp_all_u.val.status,
+ objp->ypresp_all_u.val.keydat.keydat_val,
+ objp->ypresp_all_u.val.keydat.keydat_len,
+ objp->ypresp_all_u.val.valdat.valdat_val,
+ objp->ypresp_all_u.val.valdat.valdat_len,
+ xdr_ypall_callback->data);
+ }
+ break;
+ case FALSE:
+ return TRUE;
+ }
+ xdr_free ((xdrproc_t) ypxfr_xdr_ypresp_all, (char *) objp);
+ }
+ }
+ else if (xdrs->x_op == XDR_ENCODE)
+ {
+ while (1)
+ {
+ if (!xdr_bool (xdrs, &(objp->more)))
+ return FALSE;
+
+ if (!xdr_ypresp_key_val (xdrs, &objp->ypresp_all_u.val))
+ {
+ printf ("xdr_ypresp_key_val failed\n");
+ return FALSE;
+ }
+ if (objp->ypresp_all_u.val.status != YP_TRUE)
+ {
+ objp->more = FALSE;
+ if (!xdr_bool (xdrs, &(objp->more)))
+ return FALSE;
+
+ return TRUE;
+ }
+ objp->ypresp_all_u.val.status =
+ (*(xdr_ypall_callback->foreach.encoder))
+ (objp->ypresp_all_u.val.keydat.keydat_val,
+ objp->ypresp_all_u.val.keydat.keydat_len,
+ &(objp->ypresp_all_u.val.keydat.keydat_val),
+ (int *) &(objp->ypresp_all_u.val.keydat.keydat_len),
+ &(objp->ypresp_all_u.val.valdat.valdat_val),
+ (int *) &(objp->ypresp_all_u.val.valdat.valdat_len));
+ }
+ }
+ else
+ return TRUE;
+}
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+enum clnt_stat
+ypproc_all_2 (ypreq_nokey *argp, ypresp_all *clnt_res, CLIENT *clnt)
+{
+ memset(clnt_res, 0, sizeof(ypresp_all));
+ return (clnt_call(clnt, YPPROC_ALL,
+ (xdrproc_t) xdr_ypreq_nokey, (caddr_t) argp,
+ (xdrproc_t) ypxfr_xdr_ypresp_all, (caddr_t) clnt_res,
+ TIMEOUT));
+}