diff options
author | Ulrich Drepper <drepper@redhat.com> | 1997-03-19 05:47:56 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1997-03-19 05:47:56 +0000 |
commit | e61abf83986463e263de965d487fac5cb083839a (patch) | |
tree | fa0a23e631c0c3e7f7b38c609e7fa808b1275933 | |
parent | Update (diff) | |
download | glibc-e61abf83986463e263de965d487fac5cb083839a.tar.gz glibc-e61abf83986463e263de965d487fac5cb083839a.tar.bz2 glibc-e61abf83986463e263de965d487fac5cb083839a.zip |
Update.cvs/libc-ud-970318
1997-03-19 01:40 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/sysv/sco3.2.4/Dist: New file.
* sysdeps/unix/sysv/sysv4/Dist: Add __getpgid.c and __setpgid.c.
* sysdeps/unix/bsd/Dist: Add bsdstat.h, setrgid.c, and setruid.c.
* sysdeps/unix/sysv/Dist: Add direct.h.
* sysdeps/unix/sysv/linux/Dist: Add netinet/tcp.h.
* Make-dist ($(tardir).tar): Prefer writing temporary file to
$TMPDIR is available. The default is /tmp.
* sysdeps/generic/ip.h: Move to...
* sysdeps/generic/netinet/ip.h: ...here.
* Makefile (tests): Quote $(CC) argument to isomac program.
Patch by H.J. Lu <hjl@gnu.ai.mit.edu>.
* sysdeps/i386/setjmp.S (__setjmp): Fix fatal bug where 0 argument
is placed in wrong place on the stack.
Reported by Marc Lehmann <mlehmann@hildesheim.sgh-net.de>.
* sysdeps/tst-setjmp.c: Add new test for above problem.
* sysdeps/libm-i387/e_pow.S: Compute PIC addres early.
* sysdeps/libm-i387/e_powf.S: Likewise.
* sysdeps/libm-i387/e_powl.S: Likewise.
1997-03-18 23:18 Ulrich Drepper <drepper@cygnus.com>
* time/offtime.c (__offtime): Change type of `yg' to long int.
Reported by a sun <asun@zoology.washington.edu>.
1997-03-18 23:08 a sun <asun@zoology.washington.edu>
* sysdeps/unix/sysv/linux/net/if_ppp.h (PPP_VERSION): Define to
2.2.0 to prevent version mismatch.
1997-03-17 19:26 Andreas Jaeger <aj@arthur.pfalz.de>
* stdio-common/printf_fphex.c (MIN): Only define MIN if not
already defined.
1997-03-14 23:34 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/unix/sysv/linux/powerpc/termbits.h: Leave ioctl numbers
in ioctls.h.
* elf/rtld.c (_dl_start): Call elf_machine_runtime_setup when the
loader first relocates itself.
* sysdeps/powerpc/elf/start.c (__start1): Fix bug for static objects.
* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Fix bugs in
jump slot relocation. Prefer relative branches (some PowerPC chips
don't predict absolute branches).
(elf_machine_runtime_setup): Simplify and correct expressions.
(RTLD_START): Fix bug changing _dl_starting_up.
* sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c: Added. Deal with
strange Linux/PPC padding of initial stack.
1997-03-11 04:14 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/unix/sysv/linux/powerpc/termbits.h: Increase NCCS to 39,
for future expansion.
* sysdeps/unix/sysv/linux/powerpc/sys/kernel_termios.h: Added.
* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Explain why it
can't have a switch statement.
* sysdeps/powerpc/elf/start.c (__start1): Explain why it can't be
static.
* sysdeps/powerpc/elf/start.c (_start): Use .previous to avoid
confusing gcc's idea of the current section.
* sysdeps/powerpc/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE,
RTLD_START): Likewise.
1997-03-08 09:10 Geoff Keating <geoffk@ozemail.com.au>
* sysdeps/powerpc/dl-machine.h (elf_machine_rela,
elf_machine_runtime_setup): Flush data & instruction caches when
necessary, for 603/604 support. Add better support for large PLTs.
(elf_machine_rela): Remove relocations that wouldn't work if
anyone ever used them. Use memcpy for copy reloc, it'll be safe.
Never target branch relocations at a PLT entry.
* sysdeps/powerpc/bsd-setjmp.S: Make jump to PLT entry if we are
generating PIC.
* sysdeps/powerpc/bsd-_setjmp.S: Likewise.
* sysdeps/powerpc/setjmp.S: Likewise.
* sysdeps/unix/sysv/linux/powerpc/clone.S: Likewise.
* sysdeps/unix/sysv/linux/powerpc/socket.S: Likewise.
* sysdeps/unix/sysv/linux/powerpc/syscall.S: Likewise.
* sysdeps/unix/sysv/linux/powerpc/sysdep.h: Likewise.
* sysdeps/powerpc/elf/start.c: Clean up.
* sysdeps/powerpc/__longjmp.S: Return 'value' as result from
setjmp call.
* sysdeps/unix/sysv/linux/powerpc/statbuf.h: New file.
1997-03-09 12:36 H.J. Lu <hjl@gnu.ai.mit.edu>
* Make-dist (srcs): Add $(test-srcs).
* MakeTAGS (all-sources): Likewise.
* Makerules (depfiles, common-mostlyclean): Likewise.
* Rules (tests): Likewise.
1997-03-18 05:28 Roland McGrath <roland@frob.com>
* elf/dl-reloc.c (RESOLVE): Don't try to resolve ocal symbols.
1997-03-17 21:39 Philip Blundell <phil@london.uk.eu.org>
* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Allow
protocol=NULL to match any protocol rather than returning an
error.
1997-03-17 19:00 Philip Blundell <phil@london.uk.eu.org>
* nss/nss_files/files-service.c (servbyname): Match any protocol
if proto==NULL.
1997-03-18 05:17 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/sysv/linux/alpha/fcntlbits.h: Don't define O_NORW.
* sysdeps/unix/sysv/linux/fcntlbits.h: Likewise.
Proposed by Thomas Bushnell, n/BSG.
1997-03-18 07:53 H.J. Lu <hjl@gnu.ai.mit.edu>
* sysdeps/generic/setenv.c (setenv): Don't copy name when we reuse
the buffer for replacement.
1997-03-16 19:30 H.J. Lu <hjl@gnu.ai.mit.edu>
* sysdeps/unix/sysv/linux/syscalls.list: Add sys_fstat,
sys_lstat and sys_stat.
1997-03-17 12:43 Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
Add NIS+ functions
* shlib-versions: Add libnss_nisplus.
* nis/Makefile: Add NIS+ source files.
* nis/nis_call.c: New file.
* nis/nis_clone.c: New file.
* nis/nis_error.c: New file.
* nis/nis_file.c: New file.
* nis/nis_free.c: New file.
* nis/nis_intern.c: New file.
* nis/nis_intern.h: New file.
* nis/nis_local_names.c: New file.
* nis/nis_names.c: New file.
* nis/nis_print.c: New file.
* nis/nis_server.c: New file.
* nis/nis_subr.c: New file.
* nis/nis_table.c: New file.
* nis/nis_xdr.c: New file.
* nis/nss-nisplus.h: New file.
* nis/nss_nisplus/nisplus-alias.c: New file.
* nis/nss_nisplus/nisplus-ethers.c: New file.
* nis/nss_nisplus/nisplus-grp.c: New file.
* nis/nss_nisplus/nisplus-hosts.c: New file.
* nis/nss_nisplus/nisplus-netgrp.c: New file.
* nis/nss_nisplus/nisplus-network.c: New file.
* nis/nss_nisplus/nisplus-proto.c: New file.
* nis/nss_nisplus/nisplus-publickey.c: New file.
* nis/nss_nisplus/nisplus-pwd.c: New file.
* nis/nss_nisplus/nisplus-rpc.c: New file.
* nis/nss_nisplus/nisplus-service.c: New file.
* nis/nss_nisplus/nisplus-spwd.c: New file.
* nis/rpcsvc/nis.h: New file.
* nis/rpcsvc/nis.x: New file.
* nis/rpcsvc/nis_object.x: New file.
* nis/rpcsvc/nis_tags.h: New file.
* nis/rpcsvc/nislib.h: New file.
1997-03-17 12:52 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* mach/devstream.c (output/write_some): Don't try and write more
than IO_INBAND_MAX in a single call to device_write_inband.
* sysdeps/libm-ieee754/w_atan2.c: Don't ignore exception if library
* sysdeps/libm-ieee754/w_atan2f.c: Likewise.
* sysdeps/libm-ieee754/w_atan2l.c: Likewise.
* sysdeps/unix/sysv/linux/sys/mman.h (msync): Add description for
* stdlib/atoll.c: Undefine atoll, not atol.
82 files changed, 10596 insertions, 367 deletions
diff --git a/.cvsignore b/.cvsignore index 606e7270bd..2cb16cdb10 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,4 +1,4 @@ -*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps +*.d *.o *.so *.po *.go *.bo stamp.* *.stamp *.ustamp *.udeps *.gz *.Z *.tar *.tgz =* TODO COPYING* AUTHORS copyr-* copying.* @@ -1,11 +1,193 @@ +1997-03-19 01:40 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/unix/sysv/sco3.2.4/Dist: New file. + + * sysdeps/unix/sysv/sysv4/Dist: Add __getpgid.c and __setpgid.c. + + * sysdeps/unix/bsd/Dist: Add bsdstat.h, setrgid.c, and setruid.c. + + * sysdeps/unix/sysv/Dist: Add direct.h. + + * sysdeps/unix/sysv/linux/Dist: Add netinet/tcp.h. + + * Make-dist ($(tardir).tar): Prefer writing temporary file to + $TMPDIR is available. The default is /tmp. + + * sysdeps/generic/ip.h: Move to... + * sysdeps/generic/netinet/ip.h: ...here. + + * Makefile (tests): Quote $(CC) argument to isomac program. + Patch by H.J. Lu <hjl@gnu.ai.mit.edu>. + + * sysdeps/i386/setjmp.S (__setjmp): Fix fatal bug where 0 argument + is placed in wrong place on the stack. + Reported by Marc Lehmann <mlehmann@hildesheim.sgh-net.de>. + * sysdeps/tst-setjmp.c: Add new test for above problem. + + * sysdeps/libm-i387/e_pow.S: Compute PIC addres early. + * sysdeps/libm-i387/e_powf.S: Likewise. + * sysdeps/libm-i387/e_powl.S: Likewise. + +1997-03-18 23:18 Ulrich Drepper <drepper@cygnus.com> + + * time/offtime.c (__offtime): Change type of `yg' to long int. + Reported by a sun <asun@zoology.washington.edu>. + +1997-03-18 23:08 a sun <asun@zoology.washington.edu> + + * sysdeps/unix/sysv/linux/net/if_ppp.h (PPP_VERSION): Define to + 2.2.0 to prevent version mismatch. + +1997-03-17 19:26 Andreas Jaeger <aj@arthur.pfalz.de> + + * stdio-common/printf_fphex.c (MIN): Only define MIN if not + already defined. + +1997-03-14 23:34 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/unix/sysv/linux/powerpc/termbits.h: Leave ioctl numbers + in ioctls.h. + + * elf/rtld.c (_dl_start): Call elf_machine_runtime_setup when the + loader first relocates itself. + * sysdeps/powerpc/elf/start.c (__start1): Fix bug for static objects. + * sysdeps/powerpc/dl-machine.h (elf_machine_rela): Fix bugs in + jump slot relocation. Prefer relative branches (some PowerPC chips + don't predict absolute branches). + (elf_machine_runtime_setup): Simplify and correct expressions. + (RTLD_START): Fix bug changing _dl_starting_up. + * sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c: Added. Deal with + strange Linux/PPC padding of initial stack. + +1997-03-11 04:14 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/unix/sysv/linux/powerpc/termbits.h: Increase NCCS to 39, + for future expansion. + * sysdeps/unix/sysv/linux/powerpc/sys/kernel_termios.h: Added. + * sysdeps/powerpc/dl-machine.h (elf_machine_rela): Explain why it + can't have a switch statement. + * sysdeps/powerpc/elf/start.c (__start1): Explain why it can't be + static. + + * sysdeps/powerpc/elf/start.c (_start): Use .previous to avoid + confusing gcc's idea of the current section. + * sysdeps/powerpc/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE, + RTLD_START): Likewise. + +1997-03-08 09:10 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/powerpc/dl-machine.h (elf_machine_rela, + elf_machine_runtime_setup): Flush data & instruction caches when + necessary, for 603/604 support. Add better support for large PLTs. + (elf_machine_rela): Remove relocations that wouldn't work if + anyone ever used them. Use memcpy for copy reloc, it'll be safe. + Never target branch relocations at a PLT entry. + + * sysdeps/powerpc/bsd-setjmp.S: Make jump to PLT entry if we are + generating PIC. + * sysdeps/powerpc/bsd-_setjmp.S: Likewise. + * sysdeps/powerpc/setjmp.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/clone.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/socket.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/syscall.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/sysdep.h: Likewise. + + * sysdeps/powerpc/elf/start.c: Clean up. + + * sysdeps/powerpc/__longjmp.S: Return 'value' as result from + setjmp call. + + * sysdeps/unix/sysv/linux/powerpc/statbuf.h: New file. + +1997-03-09 12:36 H.J. Lu <hjl@gnu.ai.mit.edu> + + * Make-dist (srcs): Add $(test-srcs). + * MakeTAGS (all-sources): Likewise. + * Makerules (depfiles, common-mostlyclean): Likewise. + * Rules (tests): Likewise. + +1997-03-18 05:28 Roland McGrath <roland@frob.com> + + * elf/dl-reloc.c (RESOLVE): Don't try to resolve ocal symbols. + +1997-03-17 21:39 Philip Blundell <phil@london.uk.eu.org> + + * nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Allow + protocol=NULL to match any protocol rather than returning an + error. + +1997-03-17 19:00 Philip Blundell <phil@london.uk.eu.org> + + * nss/nss_files/files-service.c (servbyname): Match any protocol + if proto==NULL. + +1997-03-18 05:17 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/unix/sysv/linux/alpha/fcntlbits.h: Don't define O_NORW. + * sysdeps/unix/sysv/linux/fcntlbits.h: Likewise. + Proposed by Thomas Bushnell, n/BSG. + +1997-03-18 07:53 H.J. Lu <hjl@gnu.ai.mit.edu> + + * sysdeps/generic/setenv.c (setenv): Don't copy name when we reuse + the buffer for replacement. + +1997-03-16 19:30 H.J. Lu <hjl@gnu.ai.mit.edu> + + * sysdeps/unix/sysv/linux/syscalls.list: Add sys_fstat, + sys_lstat and sys_stat. + +1997-03-17 12:43 Thorsten Kukuk <kukuk@vt.uni-paderborn.de> + + Add NIS+ functions + * shlib-versions: Add libnss_nisplus. + * nis/Makefile: Add NIS+ source files. + * nis/nis_call.c: New file. + * nis/nis_clone.c: New file. + * nis/nis_error.c: New file. + * nis/nis_file.c: New file. + * nis/nis_free.c: New file. + * nis/nis_intern.c: New file. + * nis/nis_intern.h: New file. + * nis/nis_local_names.c: New file. + * nis/nis_names.c: New file. + * nis/nis_print.c: New file. + * nis/nis_server.c: New file. + * nis/nis_subr.c: New file. + * nis/nis_table.c: New file. + * nis/nis_xdr.c: New file. + * nis/nss-nisplus.h: New file. + * nis/nss_nisplus/nisplus-alias.c: New file. + * nis/nss_nisplus/nisplus-ethers.c: New file. + * nis/nss_nisplus/nisplus-grp.c: New file. + * nis/nss_nisplus/nisplus-hosts.c: New file. + * nis/nss_nisplus/nisplus-netgrp.c: New file. + * nis/nss_nisplus/nisplus-network.c: New file. + * nis/nss_nisplus/nisplus-proto.c: New file. + * nis/nss_nisplus/nisplus-publickey.c: New file. + * nis/nss_nisplus/nisplus-pwd.c: New file. + * nis/nss_nisplus/nisplus-rpc.c: New file. + * nis/nss_nisplus/nisplus-service.c: New file. + * nis/nss_nisplus/nisplus-spwd.c: New file. + * nis/rpcsvc/nis.h: New file. + * nis/rpcsvc/nis.x: New file. + * nis/rpcsvc/nis_object.x: New file. + * nis/rpcsvc/nis_tags.h: New file. + * nis/rpcsvc/nislib.h: New file. + +1997-03-17 12:52 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * mach/devstream.c (output/write_some): Don't try and write more + than IO_INBAND_MAX in a single call to device_write_inband. + 1997-03-17 04:00 Ulrich Drepper <drepper@cygnus.com> - * sysdeps/libmieee754/w_atan2.c: Don't ignore exception if library + * sysdeps/libm-ieee754/w_atan2.c: Don't ignore exception if library type is SVID. - * sysdeps/libmieee754/w_atan2f.c: Likewise. - * sysdeps/libmieee754/w_atan2l.c: Likewise. + * sysdeps/libm-ieee754/w_atan2f.c: Likewise. + * sysdeps/libm-ieee754/w_atan2l.c: Likewise. - * sysdeps/unix/sysv/linux/sys/mman.h (msync): Add descrption for + * sysdeps/unix/sysv/linux/sys/mman.h (msync): Add description for FLAGS parameter. 1997-03-16 20:28 Philip Blundell <phil@london.uk.eu.org> @@ -2099,7 +2281,7 @@ 1997-02-11 14:49 Andreas Jaeger <jaeger@informatik.uni-kl.de> - * stdlib/atoll.c: Undefined atoll, not atol. + * stdlib/atoll.c: Undefine atoll, not atol. 1997-02-08 09:36 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> @@ -142,10 +142,10 @@ ifdef subdir foo:=$(shell echo subdir foo >&2) -+tsrcs := Makefile $(+tsrcs) \ - $(addsuffix .c,$(others) $(tests)) \ - $(wildcard $(addsuffix .input,$(tests)) \ - $(addsuffix .args,$(tests))) ++tsrcs := Makefile $(+tsrcs) \ + $(addsuffix .c,$(others) $(tests) $(test-srcs)) \ + $(wildcard $(addsuffix .input,$(tests) $(test-srcs)) \ + $(addsuffix .args,$(tests) $(test-srcs))) +tardeps := $(strip $(+tsrcs)) verbose = v @@ -87,8 +87,8 @@ sources += $(foreach lib,$(extra-libs),$($(lib)-routines:=.c)) # Files that are found in the current directory cannot occur in # sysdep directories, so don't bother searching them. sysdep-sources := $(filter-out $(wildcard $(sources)), $(sources)) -all-sources = $(wildcard $(sort $(sources) $(sources:.c=.S) $(sources:.c=.s) \ - $(others:=.c) $(tests:=.c))) \ +all-sources = $(wildcard $(sort $(sources) $(sources:.c=.S) $(sources:.c=.s) \ + $(others:=.c) $(tests:=.c) $(test-srcs:=.c))) \ $(foreach dir,$(all-dirs),\ $(wildcard \ $(addprefix $(dir)/,\ @@ -282,7 +282,7 @@ parent_echo-distinfo: # Run a test on the header files we use. tests: $(objpfx)isomac - $(objpfx)./isomac $(CC) '$(+sysdep-includes)' \ + $(objpfx)./isomac '$(CC)' '$(+sysdep-includes)' \ >$(common-objpfx)isomac.out $(objpfx)isomac: isomac.c @@ -857,9 +857,10 @@ mostlyclean: common-mostlyclean # Remove the object files. common-mostlyclean: - -rm -f $(addprefix $(objpfx),$(tests) $(others) \ - $(addsuffix .o,$(tests) $(others)) \ - $(addsuffix .out,$(tests))) + -rm -f $(addprefix $(objpfx),$(tests) $(test-srcs) $(others) \ + $(addsuffix .o,$(tests) $(test-srcs) \ + $(others)) \ + $(addsuffix .out,$(tests) $(test-srcs))) -rm -f $(addprefix $(objpfx),$(extra-objs) $(install-lib)) -rm -f core $(common-objpfx)stub-$(subdir) $(rmobjs) @@ -1,4 +1,4 @@ -GNU C Library NEWS -- history of user-visible changes. 1997-02-13 +GNU C Library NEWS -- history of user-visible changes. 1997-03-18 Copyright (C) 1992, 93, 94, 95, 96, 97 Free Software Foundation, Inc. See the end for copying conditions. @@ -24,6 +24,18 @@ Version 2.1 numbers * scanf recognizes the %A format for scanning floating point numbers + +* the new header <inttypes.h> from ISO C 9X provides information and + interfaces for the available integer types + +* the new header <complex.h> contains definitions of the complex math + functions from ISO C 9X + +* Thorsten Kukuk provided an implementation for NIS+, securelevel 0 and 1. + The implementation for securelevel 2 will follow as soon as the Diffie- + Hellman patent expired. + +* Andreas Jaeger provided a test suite for the math library Version 2.0.2 @@ -32,6 +44,8 @@ Version 2.0.2 * add atoll function * fix complex problems in Berkeley DB code + +* fix math functions Version 2.0.1 @@ -83,19 +83,19 @@ common-generated := $(common-generated) dummy.o dummy.c empty.c empty.o .PHONY: others tests others: $(addprefix $(objpfx),$(others) $(extra-objs)) ifeq ($(cross-compiling),yes) -tests: $(addprefix $(objpfx),$(tests)) +tests: $(addprefix $(objpfx),$(tests) $(test-srcs)) else tests: $(tests:%=$(objpfx)%.out) endif -ifneq "$(strip $(others) $(tests))" "" -$(addprefix $(objpfx),$(others) $(tests)): %: %.o \ +ifneq "$(strip $(others) $(tests) $(test-srcs))" "" +$(addprefix $(objpfx),$(others) $(tests) $(test-srcs)): %: %.o \ $(sort $(filter $(common-objpfx)libc%,$(link-libc))) \ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) $(+link) endif -ifneq "$(strip $(tests))" "" +ifneq "$(strip $(tests) $(test-srcs))" "" # These are the implicit rules for making test outputs # from the test programs and whatever input files are present. $(objpfx)%.out: %.args $(objpfx)% %.input diff --git a/csu/.cvsignore b/csu/.cvsignore index 3fc9f4cdf1..da6e41b953 100644 --- a/csu/.cvsignore +++ b/csu/.cvsignore @@ -4,3 +4,4 @@ TODO COPYING* AUTHORS copyr-* copying.* glibc-* distinfo +specs diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index f1c43ea174..d2122a8bdf 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -58,7 +58,10 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ #define RESOLVE(ref, version, flags) \ - ((version) != NULL && (version)->hash != 0 \ + ((*ref)->st_shndx != SHN_UNDEF && \ + ELFW(ST_BIND) ((*ref)->st_info) == STB_LOCAL \ + ? l->l_addr : \ + (version) != NULL && (version)->hash != 0 \ ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \ l->l_name, (version), (flags)) \ : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \ diff --git a/elf/rtld.c b/elf/rtld.c index 15df75fe8b..84ab37942b 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -106,6 +106,7 @@ _dl_start (void *arg) ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0); + elf_machine_runtime_setup (&bootstrap_map, 0); /* Now life is sane; we can call functions and access global data. Set up to use the operating system facilities, and find out from diff --git a/mach/devstream.c b/mach/devstream.c index db48307856..b54dcff60d 100644 --- a/mach/devstream.c +++ b/mach/devstream.c @@ -147,10 +147,16 @@ output (FILE *f, int c) { kern_return_t err; int wrote; + int thiswrite; + while (to_write > 0) { + thiswrite = to_write; + if (thiswrite > IO_INBAND_MAX) + thiswrite = IO_INBAND_MAX; + if (err = device_write_inband ((device_t) f->__cookie, 0, - f->__target, p, to_write, &wrote)) + f->__target, p, thiswrite, &wrote)) { errno = err; f->__error = 1; diff --git a/nis/Banner b/nis/Banner index 9ef1ded2d2..f03f4ea3f5 100644 --- a/nis/Banner +++ b/nis/Banner @@ -1 +1 @@ -NIS(YP) NSS modules 0.9 by Thorsten Kukuk +NIS(YP)/NIS+ NSS modules 0.10 by Thorsten Kukuk diff --git a/nis/Makefile b/nis/Makefile index 98ef4090a2..31fda25a45 100644 --- a/nis/Makefile +++ b/nis/Makefile @@ -22,15 +22,15 @@ subdir := nis headers := $(wildcard rpcsvc/*.[hx]) -distribute := nss-nis.h +distribute := nss-nis.h nss-nisplus.h # These are the databases available for the nis (and perhaps later nisplus) # service. This must be a superset of the services in nss. databases = proto service hosts network grp pwd rpc ethers \ spwd netgrp alias -# Specify rules for the nss_* modules. Later we may have nisplus as well. -services := nis compat +# Specify rules for the nss_* modules. +services := nis compat nisplus extra-libs = libnsl $(services:%=libnss_%) # These libraries will be built in the `others' pass rather than @@ -41,7 +41,10 @@ extra-libs-others = $(extra-libs) subdir-dirs = $(services:%=nss_%) vpath %.c $(subdir-dirs) -libnsl-routines = yp_xdr ypclnt ypupdate_xdr +libnsl-routines = yp_xdr ypclnt ypupdate_xdr \ + nis_subr nis_local_names nis_free nis_file \ + nis_print nis_error nis_call nis_names nis_clone\ + nis_table nis_xdr nis_intern nis_server libnss_compat-routines := $(addprefix compat-,grp pwd spwd) libnss_compat-inhibit-o = $(filter-out .so,$(object-suffixes)) @@ -49,6 +52,8 @@ libnss_compat-inhibit-o = $(filter-out .so,$(object-suffixes)) libnss_nis-routines := $(addprefix nis-,$(databases)) libnss_nis-inhibit-o = $(filter-out .so,$(object-suffixes)) +libnss_nisplus-routines := $(addprefix nisplus-,$(databases)) +libnss_nisplus-inhibit-o = $(filter-out .so,$(object-suffixes)) # Sun's header files are not too clean. CFLAGS-compat-pwd.c = -Wno-strict-prototypes @@ -69,6 +74,32 @@ CFLAGS-nis-spwd.c = -Wno-strict-prototypes CFLAGS-ypclnt.c = -Wno-strict-prototypes -Wno-write-strings -Irpcsvc CFLAGS-yp_xdr.c = -Wno-strict-prototypes -Irpcsvc CFLAGS-ypupdate_xdr.c = -Wno-strict-prototypes -Irpcsvc +# For the NIS+ Code +CFLAGS-nis_call.c = -DNO_DES_RPC -Wno-strict-prototypes +CFLAGS-nis_subr.c = -Wno-strict-prototypes +CFLAGS-nis_local_names.c = -Wno-strict-prototypes +CFLAGS-nis_free.c = -Wno-strict-prototypes +CFLAGS-nis_file.c = -Wno-strict-prototypes +CFLAGS-nis_print.c = -Wno-strict-prototypes +CFLAGS-nis_error.c = -Wno-strict-prototypes +CFLAGS-nis_names.c = -Wno-strict-prototypes +CFLAGS-nis_clone.c = -Wno-strict-prototypes +CFLAGS-nis_table.c = -Wno-strict-prototypes +CFLAGS-nis_server.c = -Wno-strict-prototypes +CFLAGS-nis_xdr.c = -Wno-strict-prototypes +CFLAGS-nis_intern.c = -Wno-strict-prototypes +CFLAGS-nisplus-alias.c = -Wno-strict-prototypes +CFLAGS-nisplus-ethers.c = -Wno-strict-prototypes +CFLAGS-nisplus-grp.c = -Wno-strict-prototypes +CFLAGS-nisplus-hosts.c = -Wno-strict-prototypes +CFLAGS-nisplus-netgrp.c = -Wno-strict-prototypes +CFLAGS-nisplus-network.c = -Wno-strict-prototypes +CFLAGS-nisplus-proto.c = -Wno-strict-prototypes +CFLAGS-nisplus-publickey.c = -Wno-strict-prototypes +CFLAGS-nisplus-pwd.c = -Wno-strict-prototypes +CFLAGS-nisplus-rpc.c = -Wno-strict-prototypes +CFLAGS-nisplus-service.c = -Wno-strict-prototypes +CFLAGS-nisplus-spwd.c = -Wno-strict-prototypes include ../Rules @@ -77,6 +108,7 @@ $(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version) \ $(common-objpfx)nss/libnss_files.so $(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \ $(common-objpfx)nss/libnss_files.so +$(objpfx)libnss_nisplus.so: $(objpfx)libnsl.so$(libnsl.so-version) # Depend on libc.so so a DT_NEEDED is generated in the shared objects. # This ensures they will load libc.so for needed symbols if loaded by diff --git a/nis/TODO b/nis/TODO new file mode 100644 index 0000000000..9b675dfbc6 --- /dev/null +++ b/nis/TODO @@ -0,0 +1,40 @@ + + * nss_nisplus: When using parser form nss_files, rewrite parser + + * compat could use data from nisplus, too. Implement this + + * nis_server: implement nis_getservlist, nis_stats, nis_servstate + + * nis_groups: implement it + + * nis_ping: implement it + + * __start_clock(), __stop_clock(): Test the interface and + implement it + + * What does nis_list give back, if rpc.nisd is not running or + if /var/nis/NIS_START_FILE does not exist ? + + * nis_table.c: nis_list(): + Missing flags: FOLLOW_PATH, ALL_RESULTS + callback: Don't simulate it, use server callback thread + + * Possible flags: + - FOLLOW_LINKS (nis_list, nis_lookup) + - FOLLOW_PATH (nis_list, not supported) + - HARD_LOOKUP (__do_niscall, not supported) + - ALL_RESULTS (nis_list, not supported, needs server callback) + - NO_CACHE (__do_niscall, cache not supported yet) + - MASTER_ONLY (__do_niscall, not supported) + - EXPAND_NAME (nis_lookup, nis_list) + - RETURN_RESULT (nis_table.c) + - ADD_OVERWRITE (nis_table.c) + - REM_MULTIPLE (nis_table.c) + - MOD_SAMEOBJ (nis_table.c) + - ADD_RESERVED (nis_table.c) + - REM_RESERVED (nis_table.c) + - MOD_EXCLUSIVE (nis_table.c) + - USE_DGRAM (__do_niscall) + - NO_AUTHINFO (__do_niscall) + + diff --git a/nis/nis_call.c b/nis/nis_call.c new file mode 100644 index 0000000000..cd1b6170d4 --- /dev/null +++ b/nis/nis_call.c @@ -0,0 +1,220 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <rpc/rpc.h> +#include <rpc/auth.h> +#include <rpcsvc/nis.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "nis_intern.h" + +static struct timeval TIMEOUT = {25, 0}; +static int const MAXTRIES = 3; + +static unsigned long +inetstr2int (const char *str) +{ + char buffer[strlen (str) + 3]; + size_t buflen; + size_t i, j; + + buflen = stpcpy (buffer, str) - buffer; + + j = 0; + for (i = 0; i < buflen; ++i) + if (buffer[i] == '.') + { + ++j; + if (j == 4) + { + buffer[i] = '\0'; + break; + } + } + + return inet_addr (buffer); +} + +static CLIENT * +__nis_dobind (const nis_server *server, u_long flags) +{ + struct sockaddr_in clnt_saddr; + int clnt_sock; + size_t i; + CLIENT *client = NULL; + /* XXX What is this variable for? */ + void *out = NULL; + + for (i = 0; i < server->ep.ep_len; i++) + { + memset (&clnt_saddr, '\0', sizeof clnt_saddr); + clnt_saddr.sin_family = AF_INET; + if (strcmp (server->ep.ep_val[i].family,"loopback") == 0) + { + if (server->ep.ep_val[i].uaddr[i] == '-') + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + else + if (strcmp (server->ep.ep_val[i].proto,"udp") == 0) + { + if ((flags & USE_DGRAM) == USE_DGRAM) + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + else + continue; + } + else + if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0) + { + if ((flags & USE_DGRAM) == USE_DGRAM) + continue; + else + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + } + } + else + if (strcmp (server->ep.ep_val[i].family,"inet") == 0) + { + if (server->ep.ep_val[i].uaddr[i] == '-') + clnt_saddr.sin_addr.s_addr = + inetstr2int (server->ep.ep_val[i].uaddr); + else + if (strcmp (server->ep.ep_val[i].proto,"udp") == 0) + { + if ((flags & USE_DGRAM) == USE_DGRAM) + clnt_saddr.sin_addr.s_addr = + inetstr2int (server->ep.ep_val[i].uaddr); + else + continue; + } + else + if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0) + { + if ((flags & USE_DGRAM) == USE_DGRAM) + continue; + else + clnt_saddr.sin_addr.s_addr = + inetstr2int (server->ep.ep_val[i].uaddr); + } + } + else + continue; + + clnt_sock = RPC_ANYSOCK; + if ((flags & USE_DGRAM) == USE_DGRAM) + client = clntudp_create (&clnt_saddr, NIS_PROG, NIS_VERSION, + TIMEOUT, &clnt_sock); + else + client = clnttcp_create (&clnt_saddr, NIS_PROG, NIS_VERSION, + &clnt_sock, 0, 0); + + if (client == NULL) + continue; +#if 1 + if (clnt_call (client, 0, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, out, TIMEOUT) != RPC_SUCCESS) + { + clnt_destroy (client); + continue; + } +#endif + if ((flags & NO_AUTHINFO) != NO_AUTHINFO) + { +#if !defined(NO_DES_RPC) + if (server->key_type == NIS_PK_DH) + { + char netname[MAXNETNAMELEN+1]; + char *p; + + strcpy (netname, "unix."); + strncat (netname, server->name,MAXNETNAMELEN-5); + netname[MAXNETNAMELEN-5] = '\0'; + p = strchr (netname, '.'); + *p = '@'; + client->cl_auth = + authdes_pk_create (netname, &server->pkey, 300, NULL, NULL); + if (!client->cl_auth) + client->cl_auth = authunix_create_default (); + } + else +#endif + client->cl_auth = authunix_create_default (); + } + return client; + } + + return NULL; +} + +nis_error +__do_niscall (const nis_server *serv, int serv_len, u_long prog, + xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp, + u_long flags) +{ + CLIENT *clnt; + directory_obj *dir = NULL; + const nis_server *server; + int try, result, server_len; + + if (serv == NULL || serv_len == 0) + { + dir = readColdStartFile (); + if (dir == NULL) + return NIS_UNAVAIL; + server = dir->do_servers.do_servers_val; + server_len = dir->do_servers.do_servers_len; + } + else + { + server = serv; + server_len = serv_len; + } + + try = 0; + result = NIS_NAMEUNREACHABLE; + + while (try < MAXTRIES && result != RPC_SUCCESS) + { + unsigned int i; + + ++try; + for (i = 0; i < server_len; i++) + { + if ((clnt = __nis_dobind (&server[i], flags)) == NULL) + continue; + + result = clnt_call (clnt, prog, xargs, req, xres, resp, TIMEOUT); + + if (result != RPC_SUCCESS) + { + /* XXX Grrr. The cast is needed for now since Sun code does + note know about `const'. */ + clnt_perror (clnt, (char *) "do_niscall: clnt_call"); + clnt_destroy (clnt); + result = NIS_RPCERROR; + } + else + clnt_destroy (clnt); + } + } + + if (dir != NULL) + nis_free_directory (dir); + return result; +} diff --git a/nis/nis_clone.c b/nis/nis_clone.c new file mode 100644 index 0000000000..860abb386c --- /dev/null +++ b/nis/nis_clone.c @@ -0,0 +1,551 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +directory_obj * +nis_clone_directory (const directory_obj *src, directory_obj *dest) +{ + directory_obj *res; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (directory_obj)); + if (res == NULL) + return NULL; + } + else + res = dest; + + if (src->do_name) + res->do_name = strdup (src->do_name); + else + res->do_name = NULL; + res->do_type = src->do_type; + if (src->do_servers.do_servers_len > 0) + { + size_t i; + + res->do_servers.do_servers_len = src->do_servers.do_servers_len; + if ((res->do_servers.do_servers_val = + malloc (src->do_servers.do_servers_len * sizeof (nis_server))) + == NULL) + return NULL; + + for (i = 0; i < src->do_servers.do_servers_len; ++i) + { + if (src->do_servers.do_servers_val[i].name != NULL) + res->do_servers.do_servers_val[i].name = + strdup (src->do_servers.do_servers_val[i].name); + else + res->do_servers.do_servers_val[i].name = NULL; + + res->do_servers.do_servers_val[i].ep.ep_len = + src->do_servers.do_servers_val[i].ep.ep_len; + if (res->do_servers.do_servers_val[i].ep.ep_len > 0) + { + size_t j; + + res->do_servers.do_servers_val[i].ep.ep_val = + malloc (src->do_servers.do_servers_val[i].ep.ep_len * + sizeof (endpoint)); + for (j = 0; j < res->do_servers.do_servers_val[i].ep.ep_len; ++j) + { + if (src->do_servers.do_servers_val[i].ep.ep_val[j].uaddr) + res->do_servers.do_servers_val[i].ep.ep_val[j].uaddr + = strdup (src->do_servers.do_servers_val[i].ep.ep_val[j].uaddr); + else + res->do_servers.do_servers_val[i].ep.ep_val[j].uaddr = NULL; + + if (src->do_servers.do_servers_val[i].ep.ep_val[j].family) + res->do_servers.do_servers_val[i].ep.ep_val[j].family + = strdup (src->do_servers.do_servers_val[i].ep.ep_val[j].family); + else + res->do_servers.do_servers_val[i].ep.ep_val[j].family = NULL; + + if (src->do_servers.do_servers_val[i].ep.ep_val[j].proto) + res->do_servers.do_servers_val[i].ep.ep_val[j].proto + = strdup (src->do_servers.do_servers_val[i].ep.ep_val[j].proto); + else + res->do_servers.do_servers_val[i].ep.ep_val[j].proto = NULL; + } + } + else + { + res->do_servers.do_servers_val[i].ep.ep_val = NULL; + } + res->do_servers.do_servers_val[i].key_type = + src->do_servers.do_servers_val[i].key_type; + res->do_servers.do_servers_val[i].pkey.n_len = + src->do_servers.do_servers_val[i].pkey.n_len; + if (res->do_servers.do_servers_val[i].pkey.n_len > 0) + { + res->do_servers.do_servers_val[i].pkey.n_bytes = + malloc (src->do_servers.do_servers_val[i].pkey.n_len); + if (res->do_servers.do_servers_val[i].pkey.n_bytes == NULL) + return NULL; + memcpy (res->do_servers.do_servers_val[i].pkey.n_bytes, + src->do_servers.do_servers_val[i].pkey.n_bytes, + src->do_servers.do_servers_val[i].pkey.n_len); + } + else + res->do_servers.do_servers_val[i].pkey.n_bytes = NULL; + } + } + else + { + res->do_servers.do_servers_len = 0; + res->do_servers.do_servers_val = NULL; + } + res->do_ttl = src->do_ttl; + res->do_armask.do_armask_len = src->do_armask.do_armask_len; + if (res->do_armask.do_armask_len > 0) + { + if ((res->do_armask.do_armask_val = + malloc (src->do_armask.do_armask_len * sizeof (oar_mask))) == NULL) + return NULL; + memcpy (res->do_armask.do_armask_val, src->do_armask.do_armask_val, + src->do_armask.do_armask_len * sizeof (oar_mask)); + } + else + { + res->do_armask.do_armask_val = NULL; + } + + return res; +} + +group_obj * +nis_clone_group (const group_obj *src, group_obj *dest) +{ + size_t i; + group_obj *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (group_obj)); + if (res == NULL) + return NULL; + } + else + res = dest; + + res->gr_flags = src->gr_flags; + + res->gr_members.gr_members_len = src->gr_members.gr_members_len; + if (res->gr_members.gr_members_len > 0) + { + if (res->gr_members.gr_members_val == NULL) + { + res->gr_members.gr_members_val = + malloc (res->gr_members.gr_members_len * sizeof (nis_name)); + if (res->gr_members.gr_members_val == NULL) + return NULL; + } + for (i = 0; i < res->gr_members.gr_members_len; ++i) + if (src->gr_members.gr_members_val[i] != NULL) + res->gr_members.gr_members_val[i] = + strdup (src->gr_members.gr_members_val[i]); + else + res->gr_members.gr_members_val[i] = NULL; + } + + return res; +} + +table_obj * +nis_clone_table (const table_obj *src, table_obj *dest) +{ + size_t i; + table_obj *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (table_obj)); + if (res == NULL) + return res; + } + else + res = dest; + + if (src->ta_type != NULL) + { + if ((res->ta_type = strdup (src->ta_type)) == NULL) + return NULL; + } + else + res->ta_type = NULL; + + res->ta_maxcol = src->ta_maxcol; + res->ta_sep = src->ta_sep; + res->ta_cols.ta_cols_len = src->ta_cols.ta_cols_len; + if (res->ta_cols.ta_cols_val == NULL) + { + res->ta_cols.ta_cols_val = + malloc (src->ta_cols.ta_cols_len * sizeof (table_col)); + if (res->ta_cols.ta_cols_val == NULL) + return NULL; + } + for (i = 0; i < res->ta_cols.ta_cols_len; i++) + { + if (src->ta_cols.ta_cols_val[i].tc_name == NULL) + res->ta_cols.ta_cols_val[i].tc_name = NULL; + else + res->ta_cols.ta_cols_val[i].tc_name = + strdup (src->ta_cols.ta_cols_val[i].tc_name); + res->ta_cols.ta_cols_val[i].tc_flags = + src->ta_cols.ta_cols_val[i].tc_flags; + res->ta_cols.ta_cols_val[i].tc_rights = + src->ta_cols.ta_cols_val[i].tc_rights; + } + + if (src->ta_path != NULL) + { + if ((res->ta_path = strdup (src->ta_path)) == NULL) + return NULL; + } + else + res->ta_path = NULL; + + return res; +} + +entry_obj * +nis_clone_entry (const entry_obj *src, entry_obj *dest) +{ + size_t i; + entry_obj *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (entry_obj)); + if (res == NULL) + return NULL; + } + else + res = dest; + + if (src->en_type) + res->en_type = strdup (src->en_type); + else + res->en_type = NULL; + + res->en_cols.en_cols_len = src->en_cols.en_cols_len; + if (res->en_cols.en_cols_val == NULL && src->en_cols.en_cols_len > 0) + { + res->en_cols.en_cols_val = + malloc (src->en_cols.en_cols_len * sizeof (entry_col)); + if (res->en_cols.en_cols_val == NULL) + return NULL; + } + for (i = 0; i < res->en_cols.en_cols_len; ++i) + { + res->en_cols.en_cols_val[i].ec_flags = + src->en_cols.en_cols_val[i].ec_flags; + res->en_cols.en_cols_val[i].ec_value.ec_value_len = + src->en_cols.en_cols_val[i].ec_value.ec_value_len; + if (res->en_cols.en_cols_val[i].ec_value.ec_value_val == NULL && + src->en_cols.en_cols_val[i].ec_value.ec_value_len > 0) + res->en_cols.en_cols_val[i].ec_value.ec_value_val = + malloc (src->en_cols.en_cols_val[i].ec_value.ec_value_len); + memcpy (res->en_cols.en_cols_val[i].ec_value.ec_value_val, + src->en_cols.en_cols_val[i].ec_value.ec_value_val, + res->en_cols.en_cols_val[i].ec_value.ec_value_len); + } + + return res; +} + +nis_attr * +nis_clone_nis_attr (const nis_attr *src, nis_attr *dest) +{ + nis_attr *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (nis_attr)); + if (res == NULL) + return NULL; + } + else + res = dest; + + if (src->zattr_ndx != NULL) + { + if ((res->zattr_ndx = strdup (src->zattr_ndx)) == NULL) + return NULL; + } + else + res->zattr_ndx = NULL; + + res->zattr_val.zattr_val_len = src->zattr_val.zattr_val_len; + if (res->zattr_val.zattr_val_val == NULL) + { + res->zattr_val.zattr_val_val = + malloc (src->zattr_val.zattr_val_len); + if (res->zattr_val.zattr_val_val == NULL) + return NULL; + } + memcpy (res->zattr_val.zattr_val_val, src->zattr_val.zattr_val_val, + src->zattr_val.zattr_val_len); + + return res; +} + +static nis_attr * +__nis_clone_attrs (const nis_attr *src, nis_attr *dest, u_int len) +{ + unsigned int i; + nis_attr *res; + + if (len == 0) + return dest; + + if (dest == NULL) + { + res = calloc (len, sizeof (nis_attr)); + if (res == NULL) + return NULL; + } + else + res = dest; + + for (i = 0; i < len; i++) + nis_clone_nis_attr(&src[i], &res[i]); + + return res; +} + +link_obj * +nis_clone_link (const link_obj *src, link_obj *dest) +{ + link_obj *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (link_obj)); + if (res == NULL) + return NULL; + } + else + res = dest; + + res->li_rtype = src->li_rtype; + + res->li_attrs.li_attrs_len = src->li_attrs.li_attrs_len; + res->li_attrs.li_attrs_val = + __nis_clone_attrs (src->li_attrs.li_attrs_val, + res->li_attrs.li_attrs_val, + src->li_attrs.li_attrs_len); + + if ((res->li_name = strdup (src->li_name)) == NULL) + return NULL; + + return res; +} + +objdata * +nis_clone_objdata (const objdata *src, objdata *dest) +{ + objdata *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (objdata)); + if (res == NULL) + return res; + } + else + res = dest; + + res->zo_type = src->zo_type; + + switch (src->zo_type) + { + case BOGUS_OBJ: + break; + case NO_OBJ: + break; + case DIRECTORY_OBJ: + if (nis_clone_directory (&src->objdata_u.di_data, + &res->objdata_u.di_data) == NULL) + return NULL; + break; + case GROUP_OBJ: + if (nis_clone_group (&src->objdata_u.gr_data, + &res->objdata_u.gr_data) == NULL) + return NULL; + break; + case TABLE_OBJ: + if (nis_clone_table (&src->objdata_u.ta_data, + &res->objdata_u.ta_data) == NULL) + return NULL; + break; + case ENTRY_OBJ: + if (nis_clone_entry (&src->objdata_u.en_data, + &res->objdata_u.en_data) == NULL) + return NULL; + break; + case LINK_OBJ: + if (nis_clone_link (&src->objdata_u.li_data, + &res->objdata_u.li_data) == NULL) + return NULL; + break; + case PRIVATE_OBJ: + res->objdata_u.po_data.po_data_len = + src->objdata_u.po_data.po_data_len; + if (src->objdata_u.po_data.po_data_val) + { + res->objdata_u.po_data.po_data_val = + malloc (res->objdata_u.po_data.po_data_len); + if (res->objdata_u.po_data.po_data_val == NULL) + return NULL; + memcpy (res->objdata_u.po_data.po_data_val, + src->objdata_u.po_data.po_data_val, + src->objdata_u.po_data.po_data_len); + if (res->objdata_u.po_data.po_data_val == NULL) + return NULL; + } + else + { + res->objdata_u.po_data.po_data_val = NULL; + res->objdata_u.po_data.po_data_len = 0; + } + break; + default: + return NULL; + } + + return res; +} + +nis_object * +nis_clone_object (const nis_object *src, nis_object *dest) +{ + nis_object *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (nis_object)); + if (res == NULL) + return NULL; + } + else + res = dest; + + res->zo_oid = src->zo_oid; + + if ((res->zo_name = strdup (src->zo_name)) == NULL) + return NULL; + if ((res->zo_owner = strdup (src->zo_owner)) == NULL) + return NULL; + if ((res->zo_group = strdup (src->zo_group)) == NULL) + return NULL; + if ((res->zo_domain = strdup (src->zo_domain)) == NULL) + return NULL; + + res->zo_access = src->zo_access; + res->zo_ttl = src->zo_ttl; + + if (nis_clone_objdata (&src->zo_data, &res->zo_data) == NULL) + return NULL; + + return res; +} + +static nis_object * +__nis_clone_objects (const nis_object *src, nis_object *dest, u_int len) +{ + unsigned int i; + nis_object *res; + + if (len == 0) + return dest; + + if (dest == NULL) + { + res = calloc (len, sizeof (nis_object)); + if (res == NULL) + return NULL; + } + else + res = dest; + + for (i = 0; i < len; ++i) + nis_clone_object(&src[i], &res[i]); + + return res; +} + +nis_result * +nis_clone_result (const nis_result *src, nis_result *dest) +{ + nis_result *res = NULL; + + if (src == NULL) + return NULL; + + if (dest == NULL) + { + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + return NULL; + } + else + res = dest; + + res->status = src->status; + res->objects.objects_len = src->objects.objects_len; + res->objects.objects_val = + __nis_clone_objects (src->objects.objects_val, + res->objects.objects_val, + src->objects.objects_len); + res->zticks = src->zticks; + res->dticks = src->dticks; + res->aticks = src->aticks; + res->cticks = src->cticks; + + return res; +} diff --git a/nis/nis_error.c b/nis/nis_error.c new file mode 100644 index 0000000000..760dc518ab --- /dev/null +++ b/nis/nis_error.c @@ -0,0 +1,124 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <syslog.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + + +static const char *nis_errlist[] = +{ + N_("Success"), + N_("Probable success"), + N_("Not found"), + N_("Probably not found"), + N_("Cache expired"), + N_("NIS+ servers unreachable"), + N_("Unknown object"), + N_("Server busy, try again"), + N_("Generic system error"), + N_("First/Next chain broken"), + N_("Permission denied"), + N_("Not owner"), + N_("Name not served by this server"), + N_("Server out of memory"), + N_("Object with same name exists"), + N_("Not master server for this domain"), + N_("Invalid Object for operation"), + N_("Malformed Name, or illegal name"), + N_("Unable to create callback"), + N_("Results Sent to callback proc"), + N_("Not Found, no such name"), + N_("Name/entry isn't unique"), + N_("Modification failed"), + N_("Database for table does not exist"), + N_("Entry/Table type mismatch"), + N_("Link Points to illegal name"), + N_("Partial Success"), + N_("Too Many Attributes"), + N_("Error in RPC subsystem"), + N_("Missing or malformed attribute"), + N_("Named object is not searchable"), + N_("Error while talking to callback proc"), + N_("Non NIS+ namespace encountered"), + N_("Illegal object type for operation"), + N_("Passed object is not the same object on server"), + N_("Modify operation failed"), + N_("Query illegal for named table"), + N_("Attempt to remove a non-empty table"), + N_("Error in accessing NIS+ cold start file. Is NIS+ installed?"), + N_("Full resync required for directory"), + N_("NIS+ operation failed"), + N_("NIS+ service is unavailable or not installed"), + N_("Yes, 42 is the meaning of life"), + N_("Unable to authenticate NIS+ server"), + N_("Unable to authenticate NIS+ client"), + N_("No file space on server"), + N_("Unable to create process on server"), + N_("Master server busy, full dump rescheduled.") +}; + +const char * +nis_sperrno (const nis_error status) +{ + if (status >= (sizeof (nis_errlist) / sizeof (nis_errlist[0]))) + return "???"; + else + return gettext (nis_errlist[status]); +} + +void +nis_perror (const nis_error status, const char *label) +{ + fprintf (stderr, "%s: %s\n", label, nis_sperrno (status)); +} + +void +nis_lerror (const nis_error status, const char *label) +{ + syslog (LOG_ERR, "%s: %s", label, nis_sperrno (status)); +} + +char * +nis_sperror_r (const nis_error status, const char *label, + char *buffer, size_t buflen) +{ + const char *cptr; + + cptr = nis_sperrno (status); + + if ((strlen (cptr) + strlen (label) + 3) > buflen) + { + errno = ERANGE; + return NULL; + } + + sprintf (buffer, "%s: %s", label, cptr); + + return buffer; +} + +char * +nis_sperror (const nis_error status, const char *label) +{ + static char buffer[NIS_MAXNAMELEN +1]; + + return nis_sperror_r (status, label, buffer, sizeof (buffer)); +} diff --git a/nis/nis_file.c b/nis/nis_file.c new file mode 100644 index 0000000000..002e72ed20 --- /dev/null +++ b/nis/nis_file.c @@ -0,0 +1,108 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +directory_obj * +readColdStartFile (void) +{ + XDR xdrs; + FILE *in; + directory_obj obj; + + in = fopen ("/var/nis/NIS_COLD_START", "rb"); + if (in == NULL) + { + fputs (_("Error: Could not open /var/nis/NIS_COLD_START!\n"), stdout); + return NULL; + } + memset (&obj, '\0', sizeof (obj)); + xdrstdio_create (&xdrs, in, XDR_DECODE); + if (!xdr_directory_obj (&xdrs, &obj)) + { + fputs (("Error while reading /var/nis/NIS_COLD_START!\n"), stdout); + return NULL; + } + + return nis_clone_directory (&obj, NULL); +} + +bool_t +writeColdStartFile (const directory_obj *obj) +{ + XDR xdrs; + FILE *out; + + out = fopen ("/var/nis/NIS_COLD_START", "wb"); + if (out == NULL) + return FALSE; + + xdrstdio_create (&xdrs, out, XDR_ENCODE); + /* XXX The following cast is bad! Shouldn't the XDR functions take + pointers to const objects? */ + if (!xdr_directory_obj (&xdrs, (directory_obj *) obj)) + { + fputs (_("Error while reading /var/nis/NIS_COLD_START!\n"), stdout); + return FALSE; + } + + return TRUE; +} + +nis_object * +nis_read_obj (const char *name) +{ + XDR xdrs; + FILE *in; + nis_object obj; + + in = fopen (name, "rb"); + if (in == NULL) + return NULL; + + memset (&obj, '\0', sizeof (obj)); + xdrstdio_create (&xdrs, in, XDR_DECODE); + if (!xdr_nis_object (&xdrs, &obj)) + return NULL; + + return nis_clone_object (&obj, NULL); +} + +bool_t +nis_write_obj (const char *name, const nis_object *obj) +{ + XDR xdrs; + FILE *out; + + out = fopen (name, "wb"); + if (out == NULL) + return FALSE; + + xdrstdio_create (&xdrs, out, XDR_ENCODE); + /* XXX The following cast is bad! Shouldn't the XDR functions take + pointers to const objects? */ + if (!xdr_nis_object (&xdrs, (nis_object *) obj)) + return FALSE; + + return TRUE; +} diff --git a/nis/nis_free.c b/nis/nis_free.c new file mode 100644 index 0000000000..35b7331372 --- /dev/null +++ b/nis/nis_free.c @@ -0,0 +1,334 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +void +nis_free_attr (nis_attr *obj) +{ + if (obj == NULL) + return; + + if (obj->zattr_ndx) + { + free (obj->zattr_ndx); + obj->zattr_ndx = NULL; + } + + if (obj->zattr_val.zattr_val_val) + { + free (obj->zattr_val.zattr_val_val); + obj->zattr_val.zattr_val_val = NULL; + obj->zattr_val.zattr_val_len = 0; + } +} + +void +nis_free_request (ib_request *ibreq) +{ + unsigned int i; + + for (i = 0; i < ibreq->ibr_srch.ibr_srch_len; ++i) + { + nis_free_attr (&(ibreq->ibr_srch.ibr_srch_val)[i]); + ibreq->ibr_srch.ibr_srch_val = NULL; + ibreq->ibr_srch.ibr_srch_len = 0; + } + + if (ibreq->ibr_name) + { + free (ibreq->ibr_name); + ibreq->ibr_name = NULL; + } + + if (ibreq->ibr_cookie.n_bytes) + { + free (ibreq->ibr_cookie.n_bytes); + ibreq->ibr_cookie.n_bytes = NULL; + ibreq->ibr_cookie.n_len = 0; + } +} + +void +nis_free_endpoints (endpoint *ep, int len) +{ + int i; + + if (ep == NULL) + return; + + for (i = 0; i < len; ++i) + { + if (ep[i].uaddr) + { + free (ep[i].uaddr); + ep[i].uaddr = NULL; + } + if (ep[i].family) + { + free (ep[i].family); + ep[i].family = NULL; + } + if (ep[i].proto) + { + free (ep[i].proto); + ep[i].proto = NULL; + } + } +} + +void +nis_free_servers (nis_server *obj, int len) +{ + int i; + + if (obj == NULL) + return; + + for (i = 0; i < len; i++) + { + if (obj[i].name) + { + free (obj[i].name); + obj[i].name = NULL; + } + if (obj[i].ep.ep_len > 0) + { + nis_free_endpoints (obj[i].ep.ep_val, obj[i].ep.ep_len); + free (obj[i].ep.ep_val); + obj[i].ep.ep_val = NULL; + obj[i].ep.ep_len = 0; + } + if (obj[i].pkey.n_bytes && obj[i].pkey.n_len > 0) + { + free (obj[i].pkey.n_bytes); + obj[i].pkey.n_bytes = NULL; + obj[i].pkey.n_len = 0; + } + } +} + +void +nis_free_directory (directory_obj *obj) +{ + if (obj == NULL) + return; + if (obj->do_name) + { + free (obj->do_name); + obj->do_name = NULL; + } + if (obj->do_servers.do_servers_len > 0) + { + nis_free_servers (obj->do_servers.do_servers_val, + obj->do_servers.do_servers_len); + free (obj->do_servers.do_servers_val); + obj->do_servers.do_servers_val = NULL; + obj->do_servers.do_servers_len = 0; + } + if (obj->do_armask.do_armask_len > 0) + { + free (obj->do_armask.do_armask_val); + obj->do_armask.do_armask_val = NULL; + obj->do_armask.do_armask_len = 0; + } +} + +void +nis_free_group (group_obj *obj) +{ + unsigned int i; + + if (obj->gr_members.gr_members_len > 0) + { + for (i = 0; i < obj->gr_members.gr_members_len; ++i) + if (obj->gr_members.gr_members_val[i]) + free (obj->gr_members.gr_members_val[i]); + free (obj->gr_members.gr_members_val); + obj->gr_members.gr_members_val = NULL; + obj->gr_members.gr_members_len = 0; + } +} + +void +nis_free_table (table_obj *obj) +{ + if (obj == NULL) + return; + + if (obj->ta_type) + { + free (obj->ta_type); + obj->ta_type = NULL; + } + + if (obj->ta_cols.ta_cols_val) + { + unsigned int i; + + for (i = 0; i < obj->ta_cols.ta_cols_len; ++i) + if (obj->ta_cols.ta_cols_val[i].tc_name) + free (obj->ta_cols.ta_cols_val[i].tc_name); + free (obj->ta_cols.ta_cols_val); + obj->ta_cols.ta_cols_val = NULL; + obj->ta_cols.ta_cols_len = 0; + } + + if (obj->ta_path) + { + free (obj->ta_path); + obj->ta_path = NULL; + } +} + +void +nis_free_entry (entry_obj *obj) +{ + if (obj == NULL) + return; + + if (obj->en_type) + { + free (obj->en_type); + obj->en_type = 0; + } + + if (obj->en_cols.en_cols_val) + { + unsigned int i; + + for (i = 0; i < obj->en_cols.en_cols_len; ++i) + if (obj->en_cols.en_cols_val[i].ec_value.ec_value_val) + free (obj->en_cols.en_cols_val[i].ec_value.ec_value_val); + free (obj->en_cols.en_cols_val); + obj->en_cols.en_cols_val = NULL; + obj->en_cols.en_cols_len = 0; + } +} + +void +nis_free_link (link_obj *obj) +{ + if (obj == NULL) + return; + + if (obj->li_attrs.li_attrs_val) + { + unsigned int i; + + for (i = 0; i < obj->li_attrs.li_attrs_len; ++i) + { + if (obj->li_attrs.li_attrs_val[i].zattr_ndx) + free (obj->li_attrs.li_attrs_val[i].zattr_ndx); + if (obj->li_attrs.li_attrs_val[i].zattr_val.zattr_val_val) + free (obj->li_attrs.li_attrs_val[i].zattr_val.zattr_val_val); + } + free (obj->li_attrs.li_attrs_val); + obj->li_attrs.li_attrs_val = NULL; + obj->li_attrs.li_attrs_len = 0; + } + + if (obj->li_name) + { + free (obj->li_name); + obj->li_name = NULL; + } +} + +void +nis_free_object (nis_object *obj) +{ + + if (obj == NULL) + return; + + if (obj->zo_name) + { + free (obj->zo_name); + obj->zo_name = NULL; + } + if (obj->zo_owner) + { + free (obj->zo_owner); + obj->zo_owner = NULL; + } + if (obj->zo_group) + { + free (obj->zo_group); + obj->zo_group = NULL; + } + if (obj->zo_domain) + { + free (obj->zo_domain); + obj->zo_domain = NULL; + } + switch (obj->zo_data.zo_type) + { + case BOGUS_OBJ: + break; + case NO_OBJ: + break; + case DIRECTORY_OBJ: + nis_free_directory (&obj->zo_data.objdata_u.di_data); + break; + case GROUP_OBJ: + nis_free_group (&obj->zo_data.objdata_u.gr_data); + break; + case TABLE_OBJ: + nis_free_table (&obj->zo_data.objdata_u.ta_data); + break; + case ENTRY_OBJ: + nis_free_entry (&obj->zo_data.objdata_u.en_data); + break; + case LINK_OBJ: + nis_free_link (&obj->zo_data.objdata_u.li_data); + break; + case PRIVATE_OBJ: + if (obj->zo_data.objdata_u.po_data.po_data_val) + { + free (obj->zo_data.objdata_u.po_data.po_data_val); + obj->zo_data.objdata_u.po_data.po_data_val = NULL; + } + break; + default: + break; + } + obj->zo_data.zo_type = NO_OBJ; +} + +void +nis_freeresult (nis_result *res) +{ + unsigned int i; + + if (res == NULL) + return; + + for (i = 0; i < res->objects.objects_len; i++) + nis_free_object (&(res->objects.objects_val)[i]); + + if (res->objects.objects_val != NULL) + free (res->objects.objects_val); + + if (res->cookie.n_bytes != NULL && res->cookie.n_len > 0) + free (res->cookie.n_bytes); + + free (res); +} diff --git a/nis/nis_intern.c b/nis/nis_intern.c new file mode 100644 index 0000000000..57019b3cfa --- /dev/null +++ b/nis/nis_intern.c @@ -0,0 +1,169 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> +#include "nis_intern.h" + +/* Nearly the same as nis_getnames, but nis_getnames stopped + when 2 points left */ +nis_name * +__nis_expandname (const nis_name name) +{ + nis_name *getnames = NULL; + char local_domain[NIS_MAXNAMELEN + 1]; + char *path, *cp; + int count, pos; + + strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN); + local_domain[NIS_MAXNAMELEN] = '\0'; + + count = 1; + if ((getnames = malloc ((count + 1) * sizeof (char *))) == NULL) + return NULL; + + /* Do we have a fully qualified NIS+ name ? If yes, give it back */ + if (name[strlen (name) - 1] == '.') + { + if ((getnames[0] = strdup (name)) == NULL) + { + free (getnames); + return NULL; + } + getnames[1] = NULL; + + return getnames; + } + + /* Get the search path, where we have to search "name" */ + path = getenv ("NIS_PATH"); + if (path == NULL) + path = strdupa ("$"); + else + path = strdupa (path); + + pos = 0; + + cp = strtok (path, ":"); + while (cp) + { + if (strcmp (cp, "$") == 0) + { + char *cptr = local_domain; + char *tmp; + + while (*cptr != '\0') + { + if (pos >= count) + { + count += 5; + getnames = realloc (getnames, (count + 1) * sizeof (char *)); + } + tmp = malloc (strlen (cptr) + strlen (local_domain) + + strlen (name) + 2); + if (tmp == NULL) + return NULL; + + getnames[pos] = tmp; + tmp = stpcpy (tmp, name); + if (*cptr != '.') + *tmp++ = '.'; + stpcpy (tmp, cptr); + + ++pos; + + ++cptr; + while ((*cptr != '\0') && (*cptr != '.')) + ++cptr; + + if ((*cptr == '.') && (cptr[1] != '\0')) + ++cptr; + } + } + else + { + char *tmp; + + if (cp[strlen (cp) - 1] == '$') + { + tmp = malloc (strlen (cp) + strlen (local_domain) + + strlen (name) + 2); + if (tmp == NULL) + return NULL; + + getnames[pos] = tmp; + tmp = stpcpy (tmp, name); + *tmp++ = '.'; + tmp = stpcpy (tmp, cp); + --tmp; + if (tmp[- 1] != '.') + *tmp++ = '.'; + stpcpy (tmp, local_domain); + } + else + { + tmp = malloc (strlen (cp) + strlen (name) + 2); + if (tmp == NULL) + return NULL; + + tmp = stpcpy (tmp, name); + *tmp++ = '.'; + stpcpy (tmp, cp); + } + + if (pos > count) + { + count += 5; + getnames = realloc (getnames, (count + 1) * sizeof (char *)); + } + getnames[pos] = tmp; + pos++; + } + cp = strtok (NULL, ":"); + } + + getnames[pos] = NULL; + + return getnames; +} + +fd_result * +__nis_finddirectoy (nis_name dir_name) +{ + fd_args args; + nis_error status; + fd_result *res; + + args.dir_name = dir_name; + args.requester = nis_local_principal (); + + res = calloc (1, sizeof (fd_result)); + if (res == NULL) + return NULL; + + if ((status = __do_niscall (NULL, 0, NIS_FINDDIRECTORY, + (xdrproc_t) xdr_fd_args, + (caddr_t) & args, + (xdrproc_t) xdr_fd_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + return res; +} diff --git a/nis/nis_intern.h b/nis/nis_intern.h new file mode 100644 index 0000000000..b5fb605506 --- /dev/null +++ b/nis/nis_intern.h @@ -0,0 +1,39 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef __NIS_INTERN_H + +#define __NIS_INTERN_H +#include <features.h> + +__BEGIN_DECLS + +extern nis_error __do_niscall (__const nis_server *server, int server_len, + u_long prog, xdrproc_t xargs, caddr_t req, + xdrproc_t xres, caddr_t resp, u_long flags); +#if !defined(NO_DES_RPC) +extern AUTH *authdes_pk_create (char *, netobj *, u_int, + struct sockaddr *, des_block *); +#endif + +extern nis_name *__nis_expandname (__const nis_name); + +__END_DECLS + +#endif diff --git a/nis/nis_local_names.c b/nis/nis_local_names.c new file mode 100644 index 0000000000..50120a6f73 --- /dev/null +++ b/nis/nis_local_names.c @@ -0,0 +1,184 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +nis_name +nis_local_group (void) +{ + static char __nisgroup[NIS_MAXNAMELEN + 1]; + + if (__nisgroup[0] == '\0') + { + char *cptr; + + if ((cptr = getenv ("NIS_GROUP")) == NULL) + return __nisgroup; + + if (strlen (cptr) >= NIS_MAXNAMELEN) + return __nisgroup; + + strcpy (__nisgroup, cptr); + + if (__nisgroup[strlen (__nisgroup) - 1] != '.') + { + cptr = nis_local_directory (); + if (strlen (__nisgroup) + strlen (cptr) + 1 < NIS_MAXNAMELEN) + { + strcat (__nisgroup, "."); + strcat (__nisgroup, cptr); + } + else + { + __nisgroup[0] = '\0'; + return __nisgroup; + } + } + } + + return __nisgroup; +} + + +nis_name +nis_local_directory (void) +{ + static char __nisdomainname[NIS_MAXNAMELEN + 1]; + int len; + + if (__nisdomainname[0] == '\0') + { + if (getdomainname (__nisdomainname, NIS_MAXNAMELEN) < 0) + strcpy (__nisdomainname, "\0"); + else + { + len = strlen (__nisdomainname); + + /* Missing trailing dot? */ + if (__nisdomainname[len - 1] != '.') + { + __nisdomainname[len] = '.'; + __nisdomainname[len + 1] = '\0'; + } + } + } + + return __nisdomainname; +} + +nis_name +nis_local_principal (void) +{ + static char __principal[NIS_MAXNAMELEN + 1]; + + if (__principal[0] == '\0') + { + char buf[NIS_MAXNAMELEN + 1]; + nis_result *res; + uid_t uid = geteuid (); + + if (uid != 0) + { + snprintf (buf, NIS_MAXNAMELEN - 1, + "[auth_name=%d,auth_type=LOCAL],cred.org_dir.%s", + uid, nis_local_directory ()); + + if (buf[strlen (buf) - 1] != '.') + strcat (buf, "."); + + res = nis_list (buf, USE_DGRAM + NO_AUTHINFO + FOLLOW_LINKS + + FOLLOW_PATH, NULL, NULL); + + if (res == NULL) + { + strcpy (__principal, "nobody"); + return __principal; + } + + if (res->status == NIS_SUCCESS) + { + if (res->objects.objects_len > 1) + { + /* More than one principal with same uid? something + wrong with cred table. Should be unique Warn user + and continue. */ + printf (_("\ +LOCAL entry for UID %d in directory %s not unique\n"), + uid, nis_local_directory ()); + } + strcpy (__principal, ENTRY_VAL (res->objects.objects_val, 0)); + nis_freeresult (res); + return __principal; + } + else + { + nis_freeresult (res); + strcpy (__principal, "nobody"); + return __principal; + } + } + else + { + strcpy (__principal, nis_local_host ()); + return __principal; + } + + /* Should be never reached */ + strcpy (__principal, "nobody"); + return __principal; + } + return __principal; +} + +nis_name +nis_local_host (void) +{ + static char __nishostname[NIS_MAXNAMELEN + 1]; + int len; + + if (__nishostname[0] == '\0') + { + char *cp = __nishostname; + + if (gethostname (__nishostname, NIS_MAXNAMELEN) < 0) + cp = stpcpy (cp, "\0"); + + len = cp - __nishostname; + + /* Hostname already fully qualified? */ + if (__nishostname[len - 1] == '.') + return __nishostname; + + if (strlen (__nishostname + strlen (nis_local_directory ()) + 1) > + NIS_MAXNAMELEN) + { + __nishostname[0] = '\0'; + return __nishostname; + } + + *cp++ = '.'; + stpcpy (cp, nis_local_directory ()); + } + + return __nishostname; +} diff --git a/nis/nis_names.c b/nis/nis_names.c new file mode 100644 index 0000000000..92f8040b3d --- /dev/null +++ b/nis/nis_names.c @@ -0,0 +1,238 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <rpc/rpc.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nis_intern.h" + +nis_result * +nis_lookup (const nis_name name, const u_long flags) +{ + nis_result *res; + struct ns_request req; + nis_name *names; + nis_error status; + int is_link = 1; /* We should go at least once in the while loop */ + int count_links = 0; /* We will follow only 16 links in the deep */ + int i; + + res = calloc (1, sizeof (nis_result)); + + if (flags & EXPAND_NAME) + { + names = __nis_expandname (name); + if (names == NULL) + { + res->status = NIS_NAMEUNREACHABLE; + return res; + } + + i = 0; + while (names[i] != NULL && (i == 0 || res->status > 1)) + { + req.ns_name = names[i]; + + while (is_link) + { + req.ns_object.ns_object_len = 0; + req.ns_object.ns_object_val = NULL; + memset (res, '\0', sizeof (nis_result)); + + if ((status = __do_niscall (NULL, 0, NIS_LOOKUP, + (xdrproc_t) xdr_ns_request, + (caddr_t) & req, + (xdrproc_t) xdr_nis_result, + (caddr_t) res, flags)) != RPC_SUCCESS) + { + res->status = status; + nis_freenames (names); + return res; + } + + if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS) + && (res->objects.objects_len > 0 && + res->objects.objects_val->zo_data.zo_type == LINK_OBJ)) + is_link = 1; + else + is_link = 0; + + if (is_link) + { + if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS) + { + if (count_links == 16) + { + res->status = NIS_LINKNAMEERROR; + return res; + } + else + ++count_links; + + req.ns_name = res->objects.objects_val->LI_data.li_name; + } + else + { + res->status = NIS_NOTSEARCHABLE; + return res; + } + } + } + + ++i; + if (res->status == NIS_NOT_ME) + res->status = NIS_NOSUCHNAME; + } + + nis_freenames (names); + } + else + { + req.ns_name = name; + + while (is_link) + { + req.ns_object.ns_object_len = 0; + req.ns_object.ns_object_val = NULL; + memset (res, '\0', sizeof (nis_result)); + + if ((status = __do_niscall (NULL, 0, NIS_LOOKUP, + (xdrproc_t) xdr_ns_request, + (caddr_t) & req, + (xdrproc_t) xdr_nis_result, + (caddr_t) res, flags)) != RPC_SUCCESS) + { + res->status = status; + return res; + } + + if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS) && + (res->objects.objects_len > 0 && + res->objects.objects_val->zo_data.zo_type == LINK_OBJ)) + is_link = 1; + else + is_link = 0; + + if (is_link) + { + if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS) + { + if (count_links == 16) + { + res->status = NIS_LINKNAMEERROR; + return res; + } + else + ++count_links; + + req.ns_name = res->objects.objects_val->LI_data.li_name; + } + else + { + res->status = NIS_NOTSEARCHABLE; + return res; + } + } + } + } + + return res; +} + +nis_result * +nis_add (const nis_name name, const nis_object *obj) +{ + nis_result *res; + nis_error status; + struct ns_request req; + + res = calloc (1, sizeof (nis_result)); + + req.ns_name = name; + + req.ns_object.ns_object_len = 1; + req.ns_object.ns_object_val = nis_clone_object (obj, NULL); + + if ((status = __do_niscall (NULL, 0, NIS_ADD, (xdrproc_t) xdr_ns_request, + (caddr_t) & req, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_destroy_object (req.ns_object.ns_object_val); + + return res; +} + +nis_result * +nis_remove (const nis_name name, const nis_object *obj) +{ + nis_result *res; + nis_error status; + struct ns_request req; + + res = calloc (1, sizeof (nis_result)); + + req.ns_name = name; + + if (obj != NULL) + { + req.ns_object.ns_object_len = 1; + req.ns_object.ns_object_val = nis_clone_object (obj, NULL); + } + else + { + req.ns_object.ns_object_len = 0; + req.ns_object.ns_object_val = NULL; + } + + if ((status = __do_niscall (NULL, 0, NIS_REMOVE, (xdrproc_t) xdr_ns_request, + (caddr_t) & req, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_destroy_object (req.ns_object.ns_object_val); + + return res; +} + +nis_result * +nis_modify (const nis_name name, const nis_object *obj) +{ + nis_result *res; + nis_error status; + struct ns_request req; + + res = calloc (1, sizeof (nis_result)); + + req.ns_name = name; + + req.ns_object.ns_object_len = 1; + req.ns_object.ns_object_val = nis_clone_object (obj, NULL); + + if ((status = __do_niscall (NULL, 0, NIS_REMOVE, (xdrproc_t) xdr_ns_request, + (caddr_t) & req, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_destroy_object (req.ns_object.ns_object_val); + + return res; +} diff --git a/nis/nis_print.c b/nis/nis_print.c new file mode 100644 index 0000000000..e6eb264ae7 --- /dev/null +++ b/nis/nis_print.c @@ -0,0 +1,308 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <time.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +static const char * +nis_nstype2str (const nstype type) +{ + switch (type) + { + case NIS: + return N_("NIS"); + case SUNYP: + return N_("SUNYP"); + case IVY: + return N_("IVY"); + case DNS: + return N_("DNS"); + case X500: + return N_("X500"); + case DNANS: + return N_("DNANS"); + case XCHS: + return N_("XCHS"); + case CDS: + return N_("CDS"); + default: + return N_("UNKNOWN"); + } +} + +static char * +nis_ttl2str (const u_long ttl) +{ + static char buf[64]; + unsigned long int time, s, m, h; + + time = ttl; + + h = time / (60 * 60); + time %= (60 * 60); + m = time / 60; + time %= 60; + s = time; + snprintf (buf, 63, "%lu:%02lu:%02lu", h, m, s); + + return buf; +} + +static char * +nis_flags2str (const u_long flags) +{ + static char buf[1024]; + + snprintf (buf, 1023, "%lu", flags); + + return buf; +} + +void +nis_print_rights (const u_long access) +{ + char result[17]; + u_long acc; + int i; + + acc = access; /* Parameter is const ! */ + result[i = 16] = '\0'; + while (i > 0) + { + i -= 4; + result[i + 0] = (acc & NIS_READ_ACC) ? 'r' : '-'; + result[i + 1] = (acc & NIS_MODIFY_ACC) ? 'm' : '-'; + result[i + 2] = (acc & NIS_CREATE_ACC) ? 'c' : '-'; + result[i + 3] = (acc & NIS_DESTROY_ACC) ? 'd' : '-'; + + acc >>= 8; + } + printf ("%s", result); +} + +void +nis_print_directory (const directory_obj *dir) +{ + nis_server *sptr; + unsigned int i; + + printf (_("Name : '%s'\n"), dir->do_name); + printf (_("Type : %s\n"), gettext (nis_nstype2str (dir->do_type))); + sptr = dir->do_servers.do_servers_val; + for (i = 0; i < dir->do_servers.do_servers_len; i++) + { + if (i == 0) + fputs (_("Master Server :\n"), stdout); + else + fputs (_("Replicate :\n"), stdout); + printf (_("\tName : %s\n"), sptr->name); + fputs (_("\tPublic Key : "), stdout); + switch (sptr->key_type) + { + case NIS_PK_NONE: + fputs (_("None.\n"), stdout); + break; + case NIS_PK_DH: + fputs (_("DH.\n"), stdout); + break; + case NIS_PK_RSA: + fputs (_("RSA.\n"), stdout); + break; + case NIS_PK_KERB: + fputs (_("Kerberous.\n"), stdout); + break; + default: + fputs (_("Unknown.\n"), stdout); + break; + } + + if (sptr->ep.ep_len != 0) + { + unsigned int j; + + endpoint *ptr; + ptr = sptr->ep.ep_val; + printf (_("\tUniversal addresses (%u)\n"), sptr->ep.ep_len); + for (j = 0; j < sptr->ep.ep_len; j++) + { + printf ("\t[%d] - ", j + 1); + if (ptr->proto != NULL && strlen (ptr->proto) > 0) + printf ("%s, ", ptr->proto); + else + printf ("-, "); + if (ptr->family != NULL && strlen (ptr->family) > 0) + printf ("%s, ", ptr->family); + else + printf ("-, "); + if (ptr->uaddr != NULL && strlen (ptr->uaddr) > 0) + printf ("%s\n", ptr->uaddr); + else + printf ("-\n"); + ptr++; + } + } + sptr++; + } + + printf (_("Time to live : %s\n"), nis_ttl2str (dir->do_ttl)); + if (dir->do_armask.do_armask_len != 0) + { + oar_mask *ptr; + + ptr = dir->do_armask.do_armask_val; + for (i = 0; i < dir->do_armask.do_armask_len; i++) + { + fputs (_("Default Access rights: "), stdout); + nis_print_rights (ptr->oa_rights); + printf (_("\nDirect Type : %d\n"), ptr->oa_otype); + ptr++; + } + } +} + +void +nis_print_group (const group_obj *obj) +{ + unsigned int i; + + fputs (_("Group Flags :"), stdout); + if (obj->gr_flags) + printf ("0x%08lX", obj->gr_flags); + fputs (_("\nGroup Members :\n"), stdout); + + for (i = 0; i < obj->gr_members.gr_members_len; i++) + printf ("\t%s\n", obj->gr_members.gr_members_val[i]); +} + +void +nis_print_table (const table_obj *obj) +{ + unsigned int i; + + printf (_("Table Type : %s\n"), obj->ta_type); + printf (_("Number of Columns : %d\n"), obj->ta_maxcol); + printf (_("Character Separator : %c\n"), obj->ta_sep); + printf (_("Search Path : %s\n"), obj->ta_path); + fputs (_("Columns :\n"), stdout); + for (i = 0; i < obj->ta_cols.ta_cols_len; i++) + { + printf (_("\t[%d]\tName : %s\n"), i, + obj->ta_cols.ta_cols_val[i].tc_name); + printf (_("\t\tAttributes : %s\n"), + nis_flags2str (obj->ta_cols.ta_cols_val[i].tc_flags)); + fputs (_("\t\tAccess Rights : "), stdout); + nis_print_rights (obj->ta_cols.ta_cols_val[i].tc_rights); + fputc ('\n', stdout); + } +} + +void +nis_print_link (const link_obj *obj) +{ + printf (_("Type : %d\n"), obj->li_rtype); + printf (_("Name : %s\n"), obj->li_name); + printf (_("Attributes : %d\n"), obj->li_attrs.li_attrs_len); +} + +void +nis_print_entry (const entry_obj *obj) +{ + unsigned int i; + + printf (_("\tEntry data of type %s\n"), obj->en_type); + for (i = 0; i < obj->en_cols.en_cols_len; i++) + { + printf (_("\t[%u] - [%u bytes] "), i, + obj->en_cols.en_cols_val[i].ec_value.ec_value_len); + if ((obj->en_cols.en_cols_val[i].ec_flags & EN_CRYPT) == EN_CRYPT) + fputs (_("Encrypted data\n"), stdout); + else if ((obj->en_cols.en_cols_val[i].ec_flags & EN_BINARY) == EN_BINARY) + fputs (_("Binary data\n"), stdout); + else + printf ("%s\n", obj->en_cols.en_cols_val[i].ec_value.ec_value_val); + } +} + +void +nis_print_object (const nis_object * obj) +{ + printf (_("Object Name : %s\n"), obj->zo_name); + printf (_("Directory : %s\n"), obj->zo_domain); + printf (_("Owner : %s\n"), obj->zo_owner); + printf (_("Group : %s\n"), obj->zo_group); + fputs (_("Access Rights : "), stdout); + nis_print_rights (obj->zo_access); + printf (_("\nTime to Live : %lu (seconds)\n"), obj->zo_ttl); + printf (_("Creation Time : %s"), ctime (&obj->zo_oid.ctime)); + printf (_("Mod. Time : %s"), ctime (&obj->zo_oid.mtime)); + fputs (_("Object Type : "), stdout); + switch (obj->zo_data.zo_type) + { + case BOGUS_OBJ: + fputs (_("BOGUS OBJECT\n"), stdout); + break; + case NO_OBJ: + fputs (_("NO OBJECT\n"), stdout); + break; + case DIRECTORY_OBJ: + fputs (_("DIRECTORY\n"), stdout); + nis_print_directory (&obj->zo_data.objdata_u.di_data); + break; + case GROUP_OBJ: + fputs (_("GROUP\n"), stdout); + nis_print_group (&obj->zo_data.objdata_u.gr_data); + break; + case TABLE_OBJ: + fputs (_("TABLE\n"), stdout); + nis_print_table (&obj->zo_data.objdata_u.ta_data); + break; + case ENTRY_OBJ: + fputs (_("ENTRY\n"), stdout); + nis_print_entry (&obj->zo_data.objdata_u.en_data); + break; + case LINK_OBJ: + fputs (_("LINK\n"), stdout); + nis_print_link (&obj->zo_data.objdata_u.li_data); + break; + case PRIVATE_OBJ: + fputs (_("PRIVATE\n"), stdout); + printf (_(" Data Length = %u\n"), + obj->zo_data.objdata_u.po_data.po_data_len); + break; + default: + fputs (_("(Unknown object)\n"), stdout); + break; + } +} + +void +nis_print_result (const nis_result *res) +{ + unsigned int i; + + printf (_("Status : %s\n"), nis_sperrno (res->status)); + printf (_("Number of objects : %u\n"), res->objects.objects_len); + + for (i = 0; i < res->objects.objects_len; i++) + { + printf (_("Object #%d:\n"), i); + nis_print_object (&res->objects.objects_val[i]); + } +} diff --git a/nis/nis_server.c b/nis/nis_server.c new file mode 100644 index 0000000000..48d2144c78 --- /dev/null +++ b/nis/nis_server.c @@ -0,0 +1,143 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> +#include "nis_intern.h" + +nis_error +nis_mkdir (const nis_name dir, const nis_server *server) +{ + nis_error res; + + if (server == NULL) + { + int result; + if ((result = __do_niscall (NULL, 0, NIS_MKDIR, (xdrproc_t) xdr_nis_name, + (caddr_t) dir, (xdrproc_t) xdr_nis_error, + (caddr_t) & res, 0)) != RPC_SUCCESS) + { + fprintf (stderr, _("__do_niscall: Error #%d\n"), result); + return NIS_RPCERROR; + } + } + else + { + int result; + if ((result = __do_niscall (server, 1, NIS_MKDIR, + (xdrproc_t) xdr_nis_name, + (caddr_t) dir, (xdrproc_t) xdr_nis_error, + (caddr_t) & res, 0)) != RPC_SUCCESS) + { + fprintf (stderr, _("__do_niscall: Error #%d\n"), result); + return NIS_RPCERROR; + } + } + + return res; +} + +nis_error +nis_rmdir (const nis_name dir, const nis_server *server) +{ + nis_error res; + + if (server == NULL) + { + int result; + if ((result = __do_niscall (NULL, 0, NIS_RMDIR, (xdrproc_t) xdr_nis_name, + (caddr_t) dir, (xdrproc_t) xdr_nis_error, + (caddr_t) & res, 0)) != RPC_SUCCESS) + { + fprintf (stderr, _("__do_niscall: Error #%d\n"), result); + return NIS_RPCERROR; + } + } + else + { + int result; + if ((result = __do_niscall (server, 1, NIS_RMDIR, + (xdrproc_t) xdr_nis_name, + (caddr_t) dir, (xdrproc_t) xdr_nis_error, + (caddr_t) & res, 0)) != RPC_SUCCESS) + { + fprintf (stderr, _("__do_niscall: Error #%d\n"), result); + return NIS_RPCERROR; + } + } + + return res; +} + +nis_error +nis_servstate (const nis_server *serv, const nis_tag *tags, + const int numtags, nis_tag **result) +{ + *result = NULL; + return NIS_FAIL; +} +stub_warning (nis_servstate) + +nis_error +nis_stats (const nis_server *serv, const nis_tag *tags, + const int numtags, nis_tag **result) +{ + result = malloc (sizeof (nis_tag *)); + if (result != NULL) + result[0] = NULL; + return NIS_FAIL; +} +stub_warning (nis_stats); + +void +nis_freetags (nis_tag *tags, const int numtags) +{ + int i; + + for (i = 0; i < numtags; ++i) + free (tags->tag_val); + free (tags); +} + +nis_server ** +nis_getservlist (const nis_name dir) +{ + nis_server **serv; + + serv = malloc (sizeof (nis_server *)); + if (serv != NULL) + serv[0] = NULL; + + return serv; +} +stub_warning (nis_getservlist); + +void +nis_freeservlist (nis_server **serv) +{ + int i; + + if (serv == NULL) + return; + + i = 0; + while (serv[i] != NULL) + nis_free_servers (serv[i], 1); + free (serv); +} diff --git a/nis/nis_subr.c b/nis/nis_subr.c new file mode 100644 index 0000000000..74eb0b5c77 --- /dev/null +++ b/nis/nis_subr.c @@ -0,0 +1,310 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <string.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +nis_name +nis_leaf_of (const nis_name name) +{ + static char result[NIS_MAXNAMELEN + 1]; + + return nis_leaf_of_r (name, result, NIS_MAXNAMELEN); +} + +nis_name +nis_leaf_of_r (const nis_name name, char *buffer, size_t buflen) +{ + size_t i = 0; + + buffer[0] = '\0'; + + while (name[i] != '.' && name[i] != '\0') + i++; + + if (i > buflen - 1) + { + errno = ERANGE; + return NULL; + } + + if (i > 1) + strncpy (buffer, name, i - 1); + + return buffer; +} + +nis_name +nis_name_of (const nis_name name) +{ + static char result[NIS_MAXNAMELEN + 1]; + + return nis_name_of_r (name, result, NIS_MAXNAMELEN); +} + +nis_name +nis_name_of_r (const nis_name name, char *buffer, size_t buflen) +{ + char *local_domain; + int diff; + + local_domain = nis_local_directory (); + + diff = strlen (name) - strlen (local_domain); + if (diff <= 0) + return NULL; + + if (strcmp (&name[diff], local_domain) != 0) + return NULL; + + if ((size_t) diff >= buflen) + { + errno = ERANGE; + return NULL; + } + memcpy (buffer, name, diff - 1); + buffer[diff - 1] = '\0'; + + if (diff - 1 == 0) + return NULL; + + return buffer; +} + +nis_name +nis_domain_of (const nis_name name) +{ + static char result[NIS_MAXNAMELEN + 1]; + + return nis_domain_of_r (name, result, NIS_MAXNAMELEN); +} + +nis_name +nis_domain_of_r (const nis_name name, char *buffer, size_t buflen) +{ + char *cptr; + size_t cptr_len; + + cptr = strchr (name, '.'); /* XXX What happens if the NIS name + does not contain a `.'? */ + ++cptr; + cptr_len = strlen (cptr); + + if (cptr_len == 0) + strcpy (buffer, "."); + else if (cptr_len >= buflen) + { + errno = ERANGE; + return NULL; + } + else + memcpy (buffer, cptr, cptr_len + 1); + + return buffer; +} + +static int +count_dots (const nis_name str) +{ + int count = 0; + size_t i; + + for (i = 0; i < strlen (str); ++i) + if (str[i] == '.') + ++count; + + return count; +} + +nis_name * +nis_getnames (const nis_name name) +{ + nis_name *getnames = NULL; + char local_domain[NIS_MAXNAMELEN + 1]; + char *path, *cp; + int count, pos; + + + strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN); + local_domain[NIS_MAXNAMELEN] = '\0'; + + count = 1; + if ((getnames = malloc ((count + 1) * sizeof (char *))) == NULL) + return NULL; + + /* Do we have a fully qualified NIS+ name ? If yes, give it back */ + if (name[strlen (name) - 1] == '.') + { + if ((getnames[0] = strdup (name)) == NULL) + { + free (getnames); + return NULL; + } + getnames[1] = NULL; + + return getnames; + } + + /* Get the search path, where we have to search "name" */ + path = getenv ("NIS_PATH"); + if (path == NULL) + path = strdupa ("$"); + else + path = strdupa (path); + + pos = 0; + + cp = strtok (path, ":"); + while (cp) + { + if (strcmp (cp, "$") == 0) + { + char *cptr = local_domain; + char *tmp; + + while (count_dots (cptr) >= 2) + { + if (pos >= count) + { + count += 5; + getnames = realloc (getnames, (count + 1) * sizeof (char *)); + } + tmp = malloc (strlen (cptr) + strlen (local_domain) + + strlen (name) + 2); + if (tmp == NULL) + return NULL; + + getnames[pos] = tmp; + tmp = stpcpy (tmp, name); + *tmp++ = '.'; + stpcpy (tmp, cptr); + + ++pos; + + while (*cptr != '.') + ++cptr; + ++cptr; + } + } + else + { + char *tmp; + + if (cp[strlen (cp) - 1] == '$') + { + tmp = malloc (strlen (cp) + strlen (local_domain) + + strlen (name) + 2); + if (tmp == NULL) + return NULL; + + tmp = stpcpy (tmp, name); + *tmp++ = '.'; + tmp = stpcpy (tmp, cp); + --tmp; + if (tmp[-1] != '.') + *tmp++ = '.'; + stpcpy (tmp, local_domain); + } + else + { + tmp = malloc (strlen (cp) + strlen (name) + 2); + if (tmp == NULL) + return NULL; + + tmp = stpcpy (tmp, name); + *tmp++ = '.'; + stpcpy (tmp, cp); + } + + if (pos > count) + { + count += 5; + getnames = realloc (getnames, (count + 1) * sizeof (char *)); + if (getnames == NULL) + return NULL; + } + getnames[pos] = tmp; + ++pos; + } + cp = strtok (NULL, ":"); + } + + getnames[pos] = NULL; + + return getnames; +} + +void +nis_freenames (nis_name *names) +{ + int i = 0; + + while (names[i] != NULL) + { + free (names[i]); + ++i; + } + + free (names); +} + +name_pos +nis_dir_cmp (const nis_name n1, const nis_name n2) +{ + int len1, len2; + + len1 = strlen (n1); + len2 = strlen (n2); + + if (len1 == len2) + { + if (strcmp (n1, n2) == 0) + return SAME_NAME; + else + return NOT_SEQUENTIAL; + } + + if (len1 < len2) + { + if (n2[len2 - len1 - 1] != '.') + return NOT_SEQUENTIAL; + else if (strcmp (&n2[len2 - len1], n1) == 0) + return HIGHER_NAME; + else + return NOT_SEQUENTIAL; + } + else + { + if (n1[len1 - len2 - 1] != '.') + return NOT_SEQUENTIAL; + else if (strcmp (&n1[len1 - len2], n2) == 0) + return LOWER_NAME; + else + return NOT_SEQUENTIAL; + + } +} + +void +nis_destroy_object (nis_object *obj) +{ + nis_free_object (obj); +} diff --git a/nis/nis_table.c b/nis/nis_table.c new file mode 100644 index 0000000000..a3061e1d94 --- /dev/null +++ b/nis/nis_table.c @@ -0,0 +1,417 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> +#include "nis_intern.h" + +static void +splitname (const nis_name name, nis_name *ibr_name, int *srch_len, + nis_attr **srch_val) +{ + char *cptr, *key, *val, *next; + int size; + + if (name == NULL) + return; + + cptr = strdup (name); + if (srch_len) + *srch_len = 0; + if (srch_val) + *srch_val = NULL; + size = 0; + + /* Not of "[key=value,key=value,...],foo.." format? */ + if (cptr[0] != '[') + { + *ibr_name = cptr; + return; + } + + *ibr_name = strchr (cptr, ']'); + if (*ibr_name == NULL || (*ibr_name)[1] != ',') + { + free (cptr); + *ibr_name = NULL; + return; + } + + *ibr_name[0] = '\0'; + *ibr_name += 2; + *ibr_name = strdup (*ibr_name); + + if (srch_len == NULL || srch_val == NULL) + { + free (cptr); + return; + } + + key = (cptr) + 1; + do + { + next = strchr (key, ','); + if (next) + { + next[0] = '\0'; + ++next; + } + + val = strchr (key, '='); + if (!val) + { + free (cptr); + *srch_val = malloc (sizeof (char *)); + if (*srch_val == NULL) + { + free (cptr); + free (*ibr_name); + *ibr_name = NULL; + return; + } + (*srch_val)[*srch_len].zattr_val.zattr_val_len = 0; + (*srch_val)[*srch_len].zattr_val.zattr_val_val = NULL; + return; + } + + val[0] = '\0'; + ++val; + + if ((*srch_len) + 1 >= size) + { + size += 10; + if (size == 10) + *srch_val = malloc (size * sizeof (char *)); + else + *srch_val = realloc (val, size * sizeof (char *)); + if (*srch_val == NULL) + { + free (cptr); + free (*ibr_name); + *ibr_name = NULL; + return; + } + } + + (*srch_val)[*srch_len].zattr_ndx = strdup (key); + if (((*srch_val)[*srch_len].zattr_ndx) == NULL) + { + free (cptr); + free (*ibr_name); + *ibr_name = NULL; + return; + } + (*srch_val)[*srch_len].zattr_val.zattr_val_len = strlen (val) + 1; + (*srch_val)[*srch_len].zattr_val.zattr_val_val = strdup (val); + if ((*srch_val)[*srch_len].zattr_val.zattr_val_val == NULL) + { + free (cptr); + free (*ibr_name); + *ibr_name = NULL; + return; + } + ++(*srch_len); + + key = next; + + } + while (next); + + free (cptr); +} + +static struct ib_request * +__create_ib_request (const nis_name name, struct ib_request *ibreq, + u_long flags) +{ + splitname (name, &ibreq->ibr_name, &ibreq->ibr_srch.ibr_srch_len, + &ibreq->ibr_srch.ibr_srch_val); + if (ibreq->ibr_name == NULL) + return NULL; + if ((flags & EXPAND_NAME) == EXPAND_NAME) + { + nis_name *names; + + names = __nis_expandname (ibreq->ibr_name); + free (ibreq->ibr_name); + ibreq->ibr_name = NULL; + if (names == NULL) + return NULL; + ibreq->ibr_name = strdup (names[0]); + nis_freenames (names); + } + + ibreq->ibr_flags = (flags & (RETURN_RESULT | ADD_OVERWRITE | REM_MULTIPLE | + MOD_SAMEOBJ | ADD_RESERVED | REM_RESERVED | + MOD_EXCLUSIVE)); + ibreq->ibr_obj.ibr_obj_len = 0; + ibreq->ibr_obj.ibr_obj_val = NULL; + ibreq->ibr_cbhost.ibr_cbhost_len = 0; + ibreq->ibr_cbhost.ibr_cbhost_val = NULL; + ibreq->ibr_bufsize = 0; + ibreq->ibr_cookie.n_len = 0; + ibreq->ibr_cookie.n_bytes = NULL; + + return ibreq; +} + +nis_result * +nis_list (const nis_name name, const u_long flags, + int (*callback) (const nis_name name, + const nis_object *object, + const void *userdata), + const void *userdata) +{ + nis_result *res = NULL; + struct ib_request ibreq; + int result; + int count_links = 0; /* We will only follow 16 links! */ + int is_link = 1; /* We should go at least once in the while loop */ + + res = calloc (1, sizeof (nis_result)); + + if (__create_ib_request (name, &ibreq, flags) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + + while (is_link) + { + memset (res, '\0', sizeof (nis_result)); + + if ((result = __do_niscall (NULL, 0, NIS_IBLIST, + (xdrproc_t) xdr_ib_request, + (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result, + (caddr_t) res, flags)) != RPC_SUCCESS) + { + res->status = result; + nis_free_request (&ibreq); + return res; + } + + nis_free_request (&ibreq); + + if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS) && + (res->objects.objects_len > 0 && + res->objects.objects_val->zo_data.zo_type == LINK_OBJ)) + is_link = 1; + else + is_link = 0; + + if (is_link) + { + if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS) + { + if (count_links == 16) + { + res->status = NIS_LINKNAMEERROR; + return res; + } + else + ++count_links; + + if (__create_ib_request (res->objects.objects_val->LI_data.li_name, + &ibreq, flags) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + } + else + { + res->status = NIS_NOTSEARCHABLE; + return res; + } + } + } + + if (callback != NULL && + (res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS)) + { + unsigned int i; + + for (i = 0; i < res->objects.objects_len; ++i) + if ((*callback) (name, &(res->objects.objects_val)[i], userdata) != 0) + break; + } + + return res; +} + +nis_result * +nis_add_entry (const nis_name name, const nis_object *obj, + const u_long flags) +{ + nis_result *res; + struct ib_request ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + + if (__create_ib_request (name, &ibreq, flags) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + + ibreq.ibr_flags = flags; + ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL); + ibreq.ibr_obj.ibr_obj_len = 1; + + if ((status = __do_niscall (NULL, 0, NIS_IBADD, + (xdrproc_t) xdr_ib_request, + (caddr_t) & ibreq, + (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_free_request (&ibreq); + + return res; +} + +nis_result * +nis_modify_entry (const nis_name name, const nis_object *obj, + const u_long flags) +{ + nis_result *res; + struct ib_request ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + + if (__create_ib_request (name, &ibreq, flags) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + + ibreq.ibr_flags = flags; + ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL); + ibreq.ibr_obj.ibr_obj_len = 1; + + if ((status = __do_niscall (NULL, 0, NIS_IBMODIFY, + (xdrproc_t) xdr_ib_request, + (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_free_request (&ibreq); + + return res; +} + +nis_result * +nis_remove_entry (const nis_name name, const nis_object *obj, + const u_long flags) +{ + nis_result *res; + struct ib_request ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + + if (__create_ib_request (name, &ibreq, flags) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + + ibreq.ibr_flags = flags; + if (obj != NULL) + { + ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL); + ibreq.ibr_obj.ibr_obj_len = 1; + } + + if ((status = __do_niscall (NULL, 0, NIS_IBREMOVE, + (xdrproc_t) xdr_ib_request, + (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_free_request (&ibreq); + + return res; +} + +nis_result * +nis_first_entry (const nis_name name) +{ + nis_result *res; + struct ib_request ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + + if (__create_ib_request (name, &ibreq, 0) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + + if ((status = __do_niscall (NULL, 0, NIS_IBFIRST, (xdrproc_t) xdr_ib_request, + (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_free_request (&ibreq); + + return res; +} + +nis_result * +nis_next_entry (const nis_name name, const netobj *cookie) +{ + nis_result *res; + struct ib_request ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + + if (__create_ib_request (name, &ibreq, 0) == NULL) + { + res->status = NIS_BADNAME; + return res; + } + + if (cookie != NULL) + { + ibreq.ibr_cookie.n_bytes = malloc (cookie->n_len); + if (ibreq.ibr_cookie.n_bytes == NULL) + { + res->status = NIS_NOMEMORY; + free (res); + return NULL; + } + memcpy (ibreq.ibr_cookie.n_bytes, cookie->n_bytes, cookie->n_len); + ibreq.ibr_cookie.n_len = cookie->n_len; + } + + if ((status = __do_niscall (NULL, 0, NIS_IBNEXT, (xdrproc_t) xdr_ib_request, + (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result, + (caddr_t) res, 0)) != RPC_SUCCESS) + res->status = status; + + nis_free_request (&ibreq); + + return res; +} diff --git a/nis/nis_xdr.c b/nis/nis_xdr.c new file mode 100644 index 0000000000..82df04e449 --- /dev/null +++ b/nis/nis_xdr.c @@ -0,0 +1,572 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <rpcsvc/nis.h> + +bool_t +xdr_nis_attr (XDR *xdrs, nis_attr *objp) +{ + if (!xdr_string (xdrs, &objp->zattr_ndx, ~0)) + return FALSE; + if (!xdr_bytes (xdrs, (char **) &objp->zattr_val.zattr_val_val, + (u_int *) & objp->zattr_val.zattr_val_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nis_name (XDR *xdrs, nis_name *objp) +{ + if (!xdr_string (xdrs, objp, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_zotypes (XDR *xdrs, zotypes *objp) +{ + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nstype (XDR *xdrs, nstype *objp) +{ + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_oar_mask (XDR *xdrs, oar_mask *objp) +{ + if (!xdr_u_long (xdrs, &objp->oa_rights)) + return FALSE; + if (!xdr_zotypes (xdrs, &objp->oa_otype)) + return FALSE; + return TRUE; +} + +bool_t +xdr_endpoint (XDR *xdrs, endpoint *objp) +{ + if (!xdr_string (xdrs, &objp->uaddr, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->family, ~0)) + return FALSE; + if (!xdr_string (xdrs, &objp->proto, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nis_server (XDR *xdrs, nis_server *objp) +{ + if (!xdr_nis_name (xdrs, &objp->name)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->ep.ep_val, (u_int *) &objp->ep.ep_len, + ~0, sizeof (endpoint), (xdrproc_t) xdr_endpoint)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->key_type)) + return FALSE; + if (!xdr_netobj (xdrs, &objp->pkey)) + return FALSE; + return TRUE; +} + +bool_t +xdr_directory_obj (XDR *xdrs, directory_obj *objp) +{ + if (!xdr_nis_name (xdrs, &objp->do_name)) + return FALSE; + if (!xdr_nstype (xdrs, &objp->do_type)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->do_servers.do_servers_val, + (u_int *) & objp->do_servers.do_servers_len, ~0, + sizeof (nis_server), (xdrproc_t) xdr_nis_server)) + return FALSE; + + if (!xdr_u_long (xdrs, &objp->do_ttl)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->do_armask.do_armask_val, + (u_int *) & objp->do_armask.do_armask_len, ~0, + sizeof (oar_mask), (xdrproc_t) xdr_oar_mask)) + return FALSE; + return TRUE; +} + +bool_t +xdr_entry_col (XDR *xdrs, entry_col *objp) +{ + if (!xdr_u_long (xdrs, &objp->ec_flags)) + return FALSE; + if (!xdr_bytes (xdrs, (char **) &objp->ec_value.ec_value_val, + (u_int *) &objp->ec_value.ec_value_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_entry_obj (XDR *xdrs, entry_obj *objp) +{ + if (!xdr_string (xdrs, &objp->en_type, ~0)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->en_cols.en_cols_val, + (u_int *) &objp->en_cols.en_cols_len, ~0, + sizeof (entry_col), (xdrproc_t) xdr_entry_col)) + return FALSE; + return TRUE; +} + +bool_t +xdr_group_obj (XDR *xdrs, group_obj *objp) +{ + if (!xdr_u_long (xdrs, &objp->gr_flags)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->gr_members.gr_members_val, + (u_int *) &objp->gr_members.gr_members_len, ~0, + sizeof (nis_name), (xdrproc_t) xdr_nis_name)) + return FALSE; + return TRUE; +} + +bool_t +xdr_link_obj (XDR *xdrs, link_obj *objp) +{ + if (!xdr_zotypes (xdrs, &objp->li_rtype)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->li_attrs.li_attrs_val, + (u_int *) &objp->li_attrs.li_attrs_len, ~0, + sizeof (nis_attr), (xdrproc_t) xdr_nis_attr)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->li_name)) + return FALSE; + return TRUE; +} + +bool_t +xdr_table_col (XDR *xdrs, table_col *objp) +{ + if (!xdr_string (xdrs, &objp->tc_name, 64)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->tc_flags)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->tc_rights)) + return FALSE; + return TRUE; +} + +bool_t +xdr_table_obj (XDR *xdrs, table_obj *objp) +{ + if (!xdr_string (xdrs, &objp->ta_type, 64)) + return FALSE; + if (!xdr_int (xdrs, &objp->ta_maxcol)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->ta_sep)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->ta_cols.ta_cols_val, + (u_int *) &objp->ta_cols.ta_cols_len, ~0, + sizeof (table_col), (xdrproc_t) xdr_table_col)) + return FALSE; + if (!xdr_string (xdrs, &objp->ta_path, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_objdata (XDR *xdrs, objdata *objp) +{ + if (!xdr_zotypes (xdrs, &objp->zo_type)) + return FALSE; + switch (objp->zo_type) + { + case DIRECTORY_OBJ: + if (!xdr_directory_obj (xdrs, &objp->objdata_u.di_data)) + return FALSE; + break; + case GROUP_OBJ: + if (!xdr_group_obj (xdrs, &objp->objdata_u.gr_data)) + return FALSE; + break; + case TABLE_OBJ: + if (!xdr_table_obj (xdrs, &objp->objdata_u.ta_data)) + return FALSE; + break; + case ENTRY_OBJ: + if (!xdr_entry_obj (xdrs, &objp->objdata_u.en_data)) + return FALSE; + break; + case LINK_OBJ: + if (!xdr_link_obj (xdrs, &objp->objdata_u.li_data)) + return FALSE; + break; + case PRIVATE_OBJ: + if (!xdr_bytes (xdrs, (char **) &objp->objdata_u.po_data.po_data_val, + (u_int *) & objp->objdata_u.po_data.po_data_len, ~0)) + return FALSE; + break; + case NO_OBJ: + break; + case BOGUS_OBJ: + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_nis_oid (XDR *xdrs, nis_oid *objp) +{ + if (!xdr_u_long (xdrs, &objp->ctime)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->mtime)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nis_object (XDR *xdrs, nis_object *objp) +{ + if (!xdr_nis_oid (xdrs, &objp->zo_oid)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->zo_name)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->zo_owner)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->zo_group)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->zo_domain)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->zo_access)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->zo_ttl)) + return FALSE; + if (!xdr_objdata (xdrs, &objp->zo_data)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nis_error (XDR *xdrs, nis_error *objp) +{ + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nis_result (XDR *xdrs, nis_result *objp) +{ + register long *buf; + + if (xdrs->x_op == XDR_ENCODE) + { + if (!xdr_nis_error (xdrs, &objp->status)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->objects.objects_val, + (u_int *) &objp->objects.objects_len, ~0, + sizeof (nis_object), (xdrproc_t) xdr_nis_object)) + return FALSE; + if (!xdr_netobj (xdrs, &objp->cookie)) + return FALSE; + buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); + if (buf == NULL) + { + if (!xdr_u_long (xdrs, &objp->zticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->dticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->aticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->cticks)) + { + return FALSE; + } + + } + else + { + IXDR_PUT_U_LONG (buf, objp->zticks); + IXDR_PUT_U_LONG (buf, objp->dticks); + IXDR_PUT_U_LONG (buf, objp->aticks); + IXDR_PUT_U_LONG (buf, objp->cticks); + } + + return TRUE; + } + else if (xdrs->x_op == XDR_DECODE) + { + if (!xdr_nis_error (xdrs, &objp->status)) + { + return FALSE; + } + if (!xdr_array (xdrs, (char **) &objp->objects.objects_val, + (u_int *) &objp->objects.objects_len, ~0, + sizeof (nis_object), (xdrproc_t) xdr_nis_object)) + { + return FALSE; + } + if (!xdr_netobj (xdrs, &objp->cookie)) + { + return FALSE; + } + buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); + if (buf == NULL) + { + if (!xdr_u_long (xdrs, &objp->zticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->dticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->aticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->cticks)) + { + return FALSE; + } + + } + else + { + objp->zticks = IXDR_GET_U_LONG (buf); + objp->dticks = IXDR_GET_U_LONG (buf); + objp->aticks = IXDR_GET_U_LONG (buf); + objp->cticks = IXDR_GET_U_LONG (buf); + } + return TRUE; + } + + if (!xdr_nis_error (xdrs, &objp->status)) + { + return FALSE; + } + if (!xdr_array (xdrs, (char **) &objp->objects.objects_val, + (u_int *) &objp->objects.objects_len, ~0, + sizeof (nis_object), (xdrproc_t) xdr_nis_object)) + { + return FALSE; + } + if (!xdr_netobj (xdrs, &objp->cookie)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->zticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->dticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->aticks)) + { + return FALSE; + } + if (!xdr_u_long (xdrs, &objp->cticks)) + { + return FALSE; + } + return TRUE; +} + +bool_t +xdr_ns_request (XDR *xdrs, ns_request *objp) +{ + if (!xdr_nis_name (xdrs, &objp->ns_name)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->ns_object.ns_object_val, + (u_int *) &objp->ns_object.ns_object_len, 1, + sizeof (nis_object), (xdrproc_t) xdr_nis_object)) + return FALSE; + return TRUE; +} + +bool_t +xdr_ib_request (XDR *xdrs, ib_request *objp) +{ + if (!xdr_nis_name (xdrs, &objp->ibr_name)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->ibr_srch.ibr_srch_val, + (u_int *) &objp->ibr_srch.ibr_srch_len, ~0, + sizeof (nis_attr), (xdrproc_t) xdr_nis_attr)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->ibr_flags)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->ibr_obj.ibr_obj_val, + (u_int *) &objp->ibr_obj.ibr_obj_len, 1, + sizeof (nis_object), (xdrproc_t) xdr_nis_object)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->ibr_cbhost.ibr_cbhost_val, + (u_int *) &objp->ibr_cbhost.ibr_cbhost_len, 1, + sizeof (nis_server), (xdrproc_t) xdr_nis_server)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->ibr_bufsize)) + return FALSE; + if (!xdr_netobj (xdrs, &objp->ibr_cookie)) + return FALSE; + return TRUE; +} + +bool_t +xdr_ping_args (XDR *xdrs, ping_args *objp) +{ + if (!xdr_nis_name (xdrs, &objp->dir)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->stamp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_log_entry_t (XDR *xdrs, log_entry_t *objp) +{ + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_log_entry (XDR *xdrs, log_entry *objp) +{ + if (!xdr_u_long (xdrs, &objp->le_time)) + return FALSE; + if (!xdr_log_entry_t (xdrs, &objp->le_type)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->le_princp)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->le_name)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->le_attrs.le_attrs_val, + (u_int *) &objp->le_attrs.le_attrs_len, ~0, + sizeof (nis_attr), (xdrproc_t) xdr_nis_attr)) + return FALSE; + if (!xdr_nis_object (xdrs, &objp->le_object)) + return FALSE; + return TRUE; +} + +bool_t +xdr_log_result (XDR *xdrs, log_result *objp) +{ + if (!xdr_nis_error (xdrs, &objp->lr_status)) + { + return FALSE; + } + if (!xdr_netobj (xdrs, &objp->lr_cookie)) + { + return FALSE; + } + if (!xdr_array (xdrs, (char **) &objp->lr_entries.lr_entries_val, + (u_int *) &objp->lr_entries.lr_entries_len, ~0, + sizeof (log_entry), (xdrproc_t) xdr_log_entry)) + { + return FALSE; + } + return TRUE; +} + +bool_t +xdr_cp_result (XDR *xdrs, cp_result *objp) +{ + if (!xdr_nis_error (xdrs, &objp->cp_status)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->cp_zticks)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->cp_dticks)) + return FALSE; + return TRUE; +} + +bool_t +xdr_nis_tag (XDR *xdrs, nis_tag *objp) +{ + if (!xdr_u_long (xdrs, &objp->tag_type)) + { + return FALSE; + } + if (!xdr_string (xdrs, &objp->tag_val, 1024)) + { + return FALSE; + } + return TRUE; +} + +bool_t +xdr_nis_taglist (XDR *xdrs, nis_taglist *objp) +{ + if (!xdr_array (xdrs, (char **) &objp->tags.tags_val, + (u_int *) &objp->tags.tags_len, ~0, sizeof (nis_tag), + (xdrproc_t) xdr_nis_tag)) + return FALSE; + return TRUE; +} + +bool_t +xdr_dump_args (XDR *xdrs, dump_args *objp) +{ + if (!xdr_nis_name (xdrs, &objp->da_dir)) + return FALSE; + if (!xdr_u_long (xdrs, &objp->da_time)) + return FALSE; + if (!xdr_array (xdrs, (char **) &objp->da_cbhost.da_cbhost_val, + (u_int *) &objp->da_cbhost.da_cbhost_len, 1, + sizeof (nis_server), (xdrproc_t) xdr_nis_server)) + return FALSE; + return TRUE; +} + +bool_t +xdr_fd_args (XDR *xdrs, fd_args *objp) +{ + if (!xdr_nis_name (xdrs, &objp->dir_name)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->requester)) + return FALSE; + return TRUE; +} + +bool_t +xdr_fd_result (XDR *xdrs, fd_result *objp) +{ + if (!xdr_nis_error (xdrs, &objp->status)) + return FALSE; + if (!xdr_nis_name (xdrs, &objp->source)) + return FALSE; + if (!xdr_bytes (xdrs, (char **) &objp->dir_data.dir_data_val, + (u_int *) &objp->dir_data.dir_data_len, ~0)) + return FALSE; + if (!xdr_bytes (xdrs, (char **) &objp->signature.signature_val, + (u_int *) &objp->signature.signature_len, ~0)) + return FALSE; + return TRUE; +} diff --git a/nis/nss-nisplus.h b/nis/nss-nisplus.h new file mode 100644 index 0000000000..ff497f1ca4 --- /dev/null +++ b/nis/nss-nisplus.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _NIS_NSS_NISPLUS_H +#define _NIS_NSS_NISPLUS_H 1 + +#include <rpcsvc/nis.h> + +#include "nsswitch.h" + + +/* Convert NIS+ error number to NSS error number. */ +static enum nss_status niserr2nss_tab[] = +{ + [NIS_SUCCESS] = NSS_STATUS_SUCCESS, + [NIS_S_SUCCESS] = NSS_STATUS_SUCCESS, + [NIS_NOTFOUND] = NSS_STATUS_NOTFOUND, + [NIS_S_NOTFOUND] = NSS_STATUS_TRYAGAIN, + [NIS_CACHEEXPIRED] = NSS_STATUS_UNAVAIL, + [NIS_NAMEUNREACHABLE] = NSS_STATUS_TRYAGAIN, + [NIS_UNKNOWNOBJ] = NSS_STATUS_NOTFOUND, + [NIS_TRYAGAIN] = NSS_STATUS_TRYAGAIN, + [NIS_SYSTEMERROR] = NSS_STATUS_UNAVAIL, /* Maybe TRYAGAIN ? */ + [NIS_CHAINBROKEN] = NSS_STATUS_UNAVAIL, + [NIS_PERMISSION] = NSS_STATUS_UNAVAIL, + [NIS_NOTOWNER] = NSS_STATUS_UNAVAIL, + [NIS_NOT_ME] = NSS_STATUS_UNAVAIL, + [NIS_NOMEMORY] = NSS_STATUS_TRYAGAIN, + [NIS_NAMEEXISTS] = NSS_STATUS_UNAVAIL, + [NIS_NOTMASTER] = NSS_STATUS_UNAVAIL, + [NIS_INVALIDOBJ] = NSS_STATUS_UNAVAIL, + [NIS_BADNAME] = NSS_STATUS_UNAVAIL, + [NIS_NOCALLBACK] = NSS_STATUS_UNAVAIL, + [NIS_CBRESULTS] = NSS_STATUS_UNAVAIL, + [NIS_NOSUCHNAME] = NSS_STATUS_NOTFOUND, + [NIS_NOTUNIQUE] = NSS_STATUS_UNAVAIL, + [NIS_IBMODERROR] = NSS_STATUS_UNAVAIL, + [NIS_NOSUCHTABLE] = NSS_STATUS_UNAVAIL, + [NIS_TYPEMISMATCH] = NSS_STATUS_UNAVAIL, + [NIS_LINKNAMEERROR] = NSS_STATUS_UNAVAIL, + [NIS_PARTIAL] = NSS_STATUS_NOTFOUND, + [NIS_TOOMANYATTRS] = NSS_STATUS_UNAVAIL, + [NIS_RPCERROR] = NSS_STATUS_UNAVAIL, + [NIS_BADATTRIBUTE] = NSS_STATUS_UNAVAIL, + [NIS_NOTSEARCHABLE] = NSS_STATUS_UNAVAIL, + [NIS_CBERROR] = NSS_STATUS_UNAVAIL, + [NIS_FOREIGNNS] = NSS_STATUS_UNAVAIL, + [NIS_BADOBJECT] = NSS_STATUS_UNAVAIL, + [NIS_NOTSAMEOBJ] = NSS_STATUS_UNAVAIL, + [NIS_MODFAIL] = NSS_STATUS_UNAVAIL, + [NIS_BADREQUEST] = NSS_STATUS_UNAVAIL, + [NIS_NOTEMPTY] = NSS_STATUS_UNAVAIL, + [NIS_COLDSTART_ERR] = NSS_STATUS_UNAVAIL, + [NIS_RESYNC] = NSS_STATUS_UNAVAIL, + [NIS_FAIL] = NSS_STATUS_UNAVAIL, + [NIS_UNAVAIL] = NSS_STATUS_UNAVAIL, + [NIS_RES2BIG] = NSS_STATUS_UNAVAIL, + [NIS_SRVAUTH] = NSS_STATUS_UNAVAIL, + [NIS_CLNTAUTH] = NSS_STATUS_UNAVAIL, + [NIS_NOFILESPACE] = NSS_STATUS_UNAVAIL, + [NIS_NOPROC] = NSS_STATUS_TRYAGAIN, + [NIS_DUMPLATER] = NSS_STATUS_UNAVAIL +}; +#define NISERR_COUNT (sizeof (niserr2nss_tab) / sizeof (niserr2nss_tab[0])) + +static inline enum nss_status +niserr2nss (int errval) +{ + if ((unsigned int) errval > NISERR_COUNT) + return NSS_STATUS_UNAVAIL; + return niserr2nss_tab[errval]; +} + +#endif /* nis/nss-nisplus.h */ diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c index fe189b161b..ae7667f231 100644 --- a/nis/nss_nis/nis-service.c +++ b/nis/nss_nis/nis-service.c @@ -204,7 +204,7 @@ _nss_nis_getservbyname_r (const char *name, char *protocol, enum nss_status status; int found; - if (name == NULL || protocol == NULL) + if (name == NULL) { __set_errno (EINVAL); return NSS_STATUS_UNAVAIL; @@ -219,7 +219,7 @@ _nss_nis_getservbyname_r (const char *name, char *protocol, ((status = internal_nis_getservent_r (serv, buffer, buflen, &data)) == NSS_STATUS_SUCCESS)) { - if (strcmp (serv->s_proto, protocol) == 0) + if (protocol == NULL || strcmp (serv->s_proto, protocol) == 0) { char **cp; diff --git a/nis/nss_nisplus/nisplus-alias.c b/nis/nss_nisplus/nisplus-alias.c new file mode 100644 index 0000000000..b0f035178e --- /dev/null +++ b/nis/nss_nisplus/nisplus-alias.c @@ -0,0 +1,251 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <aliases.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_aliasent (nis_result *result, struct aliasent *alias, + char *buffer, size_t buflen) +{ + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "mail_aliases") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 2) + return -1; + else + { + char *first_unused = buffer + NISENTRYLEN(0, 1, result) + 1; + size_t room_left = + buflen - (buflen % __alignof__ (char *)) - + NISENTRYLEN(0, 1, result) - 2; + char *line; + char *cp; + + if (NISENTRYLEN(0, 1, result) >= buflen) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return -1; + } + else + { + strncpy (buffer, NISENTRYVAL(0, 1, result), NISENTRYLEN(0, 1, result)); + buffer[NISENTRYLEN(0, 1, result)] = '\0'; + } + + if (NISENTRYLEN(0, 0, result) >= room_left) + goto no_more_room; + + alias->alias_local = 0; + alias->alias_members_len = 0; + *first_unused = '\0'; + ++first_unused; + strcpy (first_unused, NISENTRYVAL(0, 0, result)); + first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + alias->alias_name = first_unused; + + /* Terminate the line for any case. */ + cp = strpbrk (alias->alias_name, "#\n"); + if (cp != NULL) + *cp = '\0'; + + first_unused += strlen (alias->alias_name) +1; + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + alias->alias_members = (char **) first_unused; + + line = buffer; + + while (*line != '\0') + { + /* Skip leading blanks. */ + while (isspace (*line)) + line++; + + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= sizeof (char *); + alias->alias_members[alias->alias_members_len] = line; + + while (*line != '\0' && *line != ',') + line++; + + if (line != alias->alias_members[alias->alias_members_len]) + { + *line = '\0'; + line++; + alias->alias_members_len++; + } + } + + return alias->alias_members_len == 0 ? 0 : 1; + } +} + +enum nss_status +_nss_nisplus_setaliasent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endaliasent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getaliasent_r (struct aliasent *alias, + char *buffer, size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames("mail_aliases.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry(names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res2; + + res2 = nis_next_entry(names[0], &result->cookie); + nis_freeresult (result); + result = res2; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_aliasent (result, alias, buffer, buflen); + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getaliasent_r (struct aliasent *result, char *buffer, + size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getaliasent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getaliasbyname_r (const char *name, struct aliasent *alias, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL || strlen(name) > 8) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 30]; + + sprintf(buf, "[name=%s],mail_aliases.org_dir", name); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + + parse_res = _nss_nisplus_parse_aliasent (result, alias, buffer, buflen); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} diff --git a/nis/nss_nisplus/nisplus-ethers.c b/nis/nss_nisplus/nisplus-ethers.c new file mode 100644 index 0000000000..ac3e06960a --- /dev/null +++ b/nis/nss_nisplus/nisplus-ethers.c @@ -0,0 +1,278 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <libc-lock.h> +#include <netdb.h> +#include <netinet/ether.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> +#include <netinet/if_ether.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +/* Because the `ethers' lookup does not fit so well in the scheme so + we define a dummy struct here which helps us to use the available + functions. */ +struct etherent +{ + const char *e_name; + struct ether_addr e_addr; +}; +struct etherent_data {}; + +#define ENTNAME etherent +#define DATABASE "ethers" +#include "../../nss/nss_files/files-parse.c" +LINE_PARSER +("#", + /* Read the ethernet address: 6 x 8bit hexadecimal number. */ + { + size_t cnt; + + for (cnt = 0; cnt < 6; ++cnt) + { + unsigned int number; + + if (cnt < 5) + INT_FIELD (number, ISCOLON , 0, 16, (unsigned int)) + else + INT_FIELD (number, isspace, 0, 16, (unsigned int)) + + if (number > 0xff) + return 0; + result->e_addr.ether_addr_octet[cnt] = number; + } + }; + STRING_FIELD (result->e_name, isspace, 1); + ) + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_etherent (nis_result *result, struct etherent *ether, + char *buffer, size_t buflen) +{ + char *p = buffer; + size_t room_left = buflen; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "ethers_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 2) + return -1; + + memset (p, '\0', room_left); + + /* Generate the ether entry format and use the normal parser */ + if (NISENTRYLEN (0, 0, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) +1); + + if (NISENTRYLEN (0, 1, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "\t"); + strncat (p, NISENTRYVAL (0, 1, result), NISENTRYLEN (0, 1, result)); + room_left -= (NISENTRYLEN (0, 1, result) + 1); + + return _nss_files_parse_etherent (p,ether, data, buflen); +} + +enum nss_status +_nss_nisplus_setetherent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endetherent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getetherent_r (struct etherent *ether, char *buffer, + size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames("ethers.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry(names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res2; + + res2 = nis_next_entry(names[0], &result->cookie); + nis_freeresult (result); + result = res2; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_etherent (result, ether, buffer, buflen); + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getetherent_r (struct etherent *result, char *buffer, + size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getetherent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_gethostton_r (const char *name, struct etherent *eth, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 255]; + + sprintf(buf, "[name=%s],ethers.org_dir", name); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + + parse_res = _nss_nisplus_parse_etherent (result, eth, buffer, buflen); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_getntohost_r (const struct ether_addr *addr, + struct etherent *eth, + char *buffer, size_t buflen) +{ + int parse_res; + nis_result *result; + char buf[255]; + + if (addr == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + memset (&buf, '\0', sizeof (buf)); + snprintf(buf, sizeof (buf), "[addr=%x:%x:%x:%x:%x:%x],ethers.org_dir", + addr->ether_addr_octet[0], addr->ether_addr_octet[1], + addr->ether_addr_octet[2], addr->ether_addr_octet[3], + addr->ether_addr_octet[4], addr->ether_addr_octet[5]); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + + parse_res = _nss_nisplus_parse_etherent (result, eth, buffer, buflen); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-grp.c b/nis/nss_nisplus/nisplus-grp.c new file mode 100644 index 0000000000..2e56afa6fc --- /dev/null +++ b/nis/nss_nisplus/nisplus-grp.c @@ -0,0 +1,387 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <grp.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock); + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define NISENTRYVAL(idx,col,res) \ +((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +#define STRUCTURE group +#define ENTNAME grent +struct grent_data {}; + +#define TRAILING_LIST_MEMBER gr_mem +#define TRAILING_LIST_SEPARATOR_P(c) ((c) == ',') +#include "../../nss/nss_files/files-parse.c" +LINE_PARSER +(, + STRING_FIELD (result->gr_name, ISCOLON, 0); + if (line[0] == '\0' + && (result->gr_name[0] == '+' || result->gr_name[0] == '-')) + { + result->gr_passwd = NULL; + result->gr_gid = 0; + } + else + { + STRING_FIELD (result->gr_passwd, ISCOLON, 0); + if (result->gr_name[0] == '+' || result->gr_name[0] == '-') + INT_FIELD_MAYBE_NULL (result->gr_gid, ISCOLON, 0, 10, , 0) + else + INT_FIELD (result->gr_gid, ISCOLON, 0, 10,) + } + ) + +static int +_nss_nisplus_parse_grent (nis_result * result, struct group *gr, + char *buffer, size_t buflen) +{ +#if 0 + /* XXX here is a bug, sometimes we get some special characters at the + end of a line */ + char *first_unused = buffer; + size_t room_left = buflen; + char *line; + int count; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "group_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + return -1; + + if (NISENTRYLEN (0, 0, result) >= room_left) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return -1; + } + + strncpy (first_unused, NISENTRYVAL (0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN (0, 0, result)] = '\0'; + gr->gr_name = first_unused; + room_left -= (strlen (first_unused) + 1); + first_unused += strlen (first_unused) + 1; + + if (NISENTRYLEN (0, 1, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 1, result), + NISENTRYLEN (0, 1, result)); + first_unused[NISENTRYLEN (0, 1, result)] = '\0'; + gr->gr_passwd = first_unused; + room_left -= (strlen (first_unused) + 1); + first_unused += strlen (first_unused) + 1; + + if (NISENTRYLEN (0, 2, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 2, result), + NISENTRYLEN (0, 2, result)); + first_unused[NISENTRYLEN (0, 2, result)] = '\0'; + gr->gr_gid = atoi (first_unused); + room_left -= (strlen (first_unused) + 1); + first_unused += strlen (first_unused) + 1; + + if (NISENTRYLEN (0, 3, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 3, result), + NISENTRYLEN (0, 3, result)); + first_unused[NISENTRYLEN (0, 3, result)] = '\0'; + line = first_unused; + room_left -= (strlen (line) + 1); + first_unused += strlen (line) + 1; + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + gr->gr_mem = (char **) first_unused; + + count = 0; + while (*line != '\0') + { + /* Skip leading blanks. */ + while (isspace (*line)) + ++line; + + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= sizeof (char *); + gr->gr_mem[count] = line; + + while (*line != '\0' && *line != ',' && !isspace(*line)) + ++line; + + if (line != gr->gr_mem[count]) + { + *line = '\0'; + ++line; + ++count; + } + else + gr->gr_mem[count] = NULL; + } + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= sizeof (char *); + gr->gr_mem[count] = NULL; + + return 1; +#else + char *p = buffer; + size_t room_left = buflen; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "group_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + return -1; + + memset (p, '\0', room_left); + + if (NISENTRYLEN (0, 0, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) + 1); + strcat (p, ":"); + + if (NISENTRYLEN (0, 1, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncat (p, NISENTRYVAL (0, 1, result), NISENTRYLEN (0, 1, result)); + room_left -= (NISENTRYLEN (0, 1, result) + 1); + strcat (p, ":"); + if (NISENTRYLEN (0, 2, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); + room_left -= (NISENTRYLEN (0, 2, result) + 1); + strcat (p, ":"); + if (NISENTRYLEN (0, 3, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncat (p, NISENTRYVAL (0, 3, result), NISENTRYLEN (0, 3, result)); + room_left -= (NISENTRYLEN (0, 3, result) + 1); + + return _nss_files_parse_grent (p, gr, data, buflen); +#endif +} + +enum nss_status +_nss_nisplus_setgrent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endgrent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames ("group.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry (names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res; + + res = nis_next_entry (names[0], &result->cookie); + nis_freeresult (result); + result = res; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen); + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getgrent_r (struct group *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getgrent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getgrnam_r (const char *name, struct group *gr, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL || strlen (name) > 8) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 24]; + + sprintf (buf, "[name=%s],group.org_dir", name); + + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr, + char *buffer, size_t buflen) +{ + int parse_res; + nis_result *result; + char buf[36]; + + sprintf (buf, "[gid=%d],group.org_dir", gid); + + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-hosts.c b/nis/nss_nisplus/nisplus-hosts.c new file mode 100644 index 0000000000..0a486411de --- /dev/null +++ b/nis/nss_nisplus/nisplus-hosts.c @@ -0,0 +1,412 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <netdb.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +/* Get implementation for some internal functions. */ +#include "../../resolv/mapv4v6addr.h" +#include "../../resolv/mapv4v6hostent.h" + +#define ENTNAME hostent +#define DATABASE "hosts" +#define NEED_H_ERRNO + +#define ENTDATA hostent_data +struct hostent_data + { + unsigned char host_addr[16]; /* IPv4 or IPv6 address. */ + char *h_addr_ptrs[2]; /* Points to that and null terminator. */ + }; + +#define TRAILING_LIST_MEMBER h_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "../../nss/nss_files/files-parse.c" +LINE_PARSER +("#", + { + char *addr; + + STRING_FIELD (addr, isspace, 1); + + /* Parse address. */ + if ((_res.options & RES_USE_INET6) + && inet_pton (AF_INET6, addr, entdata->host_addr) > 0) + { + result->h_addrtype = AF_INET6; + result->h_length = IN6ADDRSZ; + } + else + if (inet_pton (AF_INET, addr, entdata->host_addr) > 0) + { + if (_res.options & RES_USE_INET6) + { + map_v4v6_address ((char *) entdata->host_addr, + (char *) entdata->host_addr); + result->h_addrtype = AF_INET6; + result->h_length = IN6ADDRSZ; + } + else + { + result->h_addrtype = AF_INET; + result->h_length = INADDRSZ; + } + } + else + /* Illegal address: ignore line. */ + return 0; + + /* Store a pointer to the address in the expected form. */ + entdata->h_addr_ptrs[0] = entdata->host_addr; + entdata->h_addr_ptrs[1] = NULL; + result->h_addr_list = entdata->h_addr_ptrs; + + /* If we need the host entry in IPv6 form change it now. */ + if (_res.options & RES_USE_INET6) + { + char *bufptr = data->linebuffer; + size_t buflen = (char *) data + datalen - bufptr; + map_v4v6_hostent (result, &bufptr, &buflen); + } + + STRING_FIELD (result->h_name, isspace, 1); + } +) + + +static int +_nss_nisplus_parse_hostent (nis_result *result, struct hostent *host, + char *buffer, size_t buflen) +{ + char *p = buffer; + size_t room_left = buflen; + int parse_res, i; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "hosts_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + return -1; + + memset (p, '\0', room_left); + + /* Generate the hosts entry format and use the normal parser */ + if (NISENTRYLEN (0, 2, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncpy (p, NISENTRYVAL (0, 2, result), + NISENTRYLEN (0, 2, result)); + room_left -= (NISENTRYLEN (0, 2, result) + 1); + + if (NISENTRYLEN (0, 0, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "\t"); + strncat (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) + 1); + /* + 1: We overwrite the last \0 */ + + for (i = 1; i < result->objects.objects_len; i++) + { + if (NISENTRYLEN (i, 1, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, " "); + strcat (p, NISENTRYVAL (i, 1, result)); + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } + + parse_res = parse_line (p, host, data, buflen); + + return parse_res; +} + +enum nss_status +_nss_nisplus_sethostent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endhostent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_gethostent_r (struct hostent *host, char *buffer, + size_t buflen, int *herrnop) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames("hosts.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry(names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + int retval; + + retval = niserr2nss (result->status); + if (retval == NSS_STATUS_TRYAGAIN) + { + *herrnop = NETDB_INTERNAL; + __set_errno (EAGAIN); + } + return retval; + } + + } + else + { + nis_result *res2; + + res2 = nis_next_entry(names[0], &result->cookie); + nis_freeresult (result); + result = res2; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + int retval; + + retval = niserr2nss (result->status); + if (retval == NSS_STATUS_TRYAGAIN) + { + *herrnop = NETDB_INTERNAL; + __set_errno (EAGAIN); + } + return retval; + } + } + + parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen); + if (!parse_res && errno == ERANGE) + { + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_gethostent_r (struct hostent *result, char *buffer, + size_t buflen, int *herrnop) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_gethostent_r (result, buffer, buflen, herrnop); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host, + char *buffer, size_t buflen, int *herrnop) +{ + int parse_res, retval; + + if (name == NULL) + { + __set_errno (EINVAL); + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_NOTFOUND; + } + else + { + nis_result *result; + char buf[strlen (name) + 255]; + + /* Search at first in the alias list, and use the correct name + for the next search */ + sprintf(buf, "[name=%s],hosts.org_dir", name); + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + /* If we do not find it, try it as original name. But if the + database is correct, we should find it in the first case, too */ + if ((result->status != NIS_SUCCESS && + result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "hosts_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len + < 3) + sprintf(buf, "[cname=%s],hosts.org_dir", name); + else + sprintf(buf, "[cname=%s],hosts.org_dir", NISENTRYVAL(0, 0, result)); + + nis_freeresult (result); + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + retval = niserr2nss (result->status); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + __set_errno (EAGAIN); + *herrnop = NETDB_INTERNAL; + } + nis_freeresult (result); + return retval; + } + + parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + *herrnop = NETDB_INTERNAL; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_gethostbyname_r (const char *name, struct hostent *host, + char *buffer, size_t buflen, int *h_errnop) +{ + if (_res.options & RES_USE_INET6) + { + enum nss_status status; + + status = _nss_nisplus_gethostbyname2_r (name, AF_INET6, host, buffer, + buflen, h_errnop); + if (status == NSS_STATUS_SUCCESS) + return status; + } + + return _nss_nisplus_gethostbyname2_r (name, AF_INET, host, buffer, + buflen, h_errnop); +} + +enum nss_status +_nss_nisplus_gethostbyaddr_r (const char *addr, struct hostent *host, + char *buffer, size_t buflen, int *herrnop) +{ + if (addr == NULL) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[24 + strlen (addr)]; + int retval, parse_res; + + sprintf(buf, "[addr=%s],hosts.org_dir", addr); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + retval = niserr2nss (result->status); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + __set_errno (EAGAIN); + *herrnop = NETDB_INTERNAL; + } + nis_freeresult (result); + return retval; + } + + parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + *herrnop = NETDB_INTERNAL; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} diff --git a/nis/nss_nisplus/nisplus-netgrp.c b/nis/nss_nisplus/nisplus-netgrp.c new file mode 100644 index 0000000000..766d2bc773 --- /dev/null +++ b/nis/nss_nisplus/nisplus-netgrp.c @@ -0,0 +1,141 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <netdb.h> +#include <string.h> +#include <netgroup.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static char *data = NULL; +static size_t data_size = 0; +static char *cursor = NULL;; + +extern enum nss_status +_nss_netgroup_parseline (char **cursor, struct __netgrent *result, + char *buffer, size_t buflen); + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +enum nss_status +_nss_nisplus_setnetgrent (char *group) + +{ + enum nss_status status; + nis_result *result; + char buf[strlen (group) + 30]; + int i; + size_t len; + + if (group == NULL || group[0] == '\0') + return NSS_STATUS_UNAVAIL; + + status = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + if (data != NULL) + { + free (data); + data = NULL; + data_size = 0; + cursor = NULL; + } + + sprintf(buf, "[name=%s],netgroup.org_dir", group); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + status = niserr2nss (result->status); + + len = 0; + for (i = 0; i < result->objects.objects_len; i++) + len += 1 + NISENTRYLEN (i, 1, result) + 1 + NISENTRYLEN(i,2,result) + + 1 + NISENTRYLEN(i,3,result) + 1 + NISENTRYLEN(i,4,result) + 2; + + data = malloc (len+1); + memset (data, '\0', len+1); + + for (i = 0; i < result->objects.objects_len; i++) + { + strncat (data, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); + strcat (data," ("); + strncat (data, NISENTRYVAL(i,2,result), NISENTRYLEN (i, 2, result)); + strcat (data, ","); + strncat (data, NISENTRYVAL(i,3,result), NISENTRYLEN (i, 3, result)); + strcat (data, ","); + strncat (data, NISENTRYVAL(i,4,result), NISENTRYLEN (i, 4, result)); + strcat (data, ") "); + } + + nis_freeresult (result); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_endnetgrent (void) +{ + __libc_lock_lock (lock); + + if (data != NULL) + { + free (data); + data = NULL; + data_size = 0; + cursor = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getnetgrent_r (struct __netgrent *result, + char *buffer, size_t buflen) +{ + enum nss_status status; + + if (cursor == NULL) + return NSS_STATUS_NOTFOUND; + + __libc_lock_lock (lock); + + status = _nss_netgroup_parseline (&cursor, result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} diff --git a/nis/nss_nisplus/nisplus-network.c b/nis/nss_nisplus/nisplus-network.c new file mode 100644 index 0000000000..28580b6bc9 --- /dev/null +++ b/nis/nss_nisplus/nisplus-network.c @@ -0,0 +1,340 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <netdb.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <arpa/inet.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +/* Get the declaration of the parser function. */ +#define ENTNAME netent +#define DATABASE "networks" +#define TRAILING_LIST_MEMBER n_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "../nss/nss_files/files-parse.c" +LINE_PARSER +("#", + { + char *addr; + + STRING_FIELD (result->n_name, isspace, 1); + + STRING_FIELD (addr, isspace, 1); + result->n_net = inet_network (addr); + + }) + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + + +static int +_nss_nisplus_parse_netent (nis_result *result, struct netent *network, + char *buffer, size_t buflen) +{ + char *p = buffer; + size_t room_left = buflen; + int i; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "networks_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + return -1; + + /* Generate the network entry format and use the normal parser */ + if (NISENTRYLEN (0, 0, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + + memset (p, '\0', room_left); + + strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) +1); + + if (NISENTRYLEN (0, 2, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "\t"); + strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); + room_left -= (NISENTRYLEN (0, 2, result) + 1); + /* + 1: We overwrite the last \0 */ + + for (i = 1; i < result->objects.objects_len; i++) + /* XXX should we start with i = 0 or with i = 1 ? */ + { + if (NISENTRYLEN (i, 1, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, " "); + strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } + + return _nss_files_parse_netent (p, network, data, buflen); +} + +enum nss_status +_nss_nisplus_setnetent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endnetent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getnetent_r (struct netent *network, char *buffer, + size_t buflen, int *herrnop) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames("networks.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry(names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + int retval; + + retval = niserr2nss (result->status); + if (retval == NSS_STATUS_TRYAGAIN) + { + *herrnop = NETDB_INTERNAL; + __set_errno (EAGAIN); + } + return retval; + } + } + else + { + nis_result *res; + + res = nis_next_entry(names[0], &result->cookie); + nis_freeresult (result); + result = res; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + int retval; + + retval = niserr2nss (result->status); + if (retval == NSS_STATUS_TRYAGAIN) + { + *herrnop = NETDB_INTERNAL; + __set_errno (EAGAIN); + } + return retval; + } + } + + parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen); + if (!parse_res && errno == ERANGE) + { + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getnetent_r (struct netent *result, char *buffer, + size_t buflen, int *herrnop) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getnetent_r (result, buffer, buflen, herrnop); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getnetbyname_r (const char *name, struct netent *network, + char *buffer, size_t buflen, int *herrnop) +{ + int parse_res, retval; + + if (name == NULL) + { + __set_errno (EINVAL); + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + else + { + nis_result *result; + char buf[strlen (name) + 255]; + + + /* Search at first in the alias list, and use the correct name + for the next search */ + sprintf(buf, "[name=%s],networks.org_dir", name); + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + /* If we do not find it, try it as original name. But if the + database is correct, we should find it in the first case, too */ + if ((result->status != NIS_SUCCESS && + result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "networks_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + sprintf(buf, "[cname=%s],networks.org_dir", name); + else + sprintf(buf, "[cname=%s],networks.org_dir", NISENTRYVAL(0, 0, result)); + + nis_freeresult (result); + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + retval = niserr2nss (result->status); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + __set_errno (EAGAIN); + *herrnop = NETDB_INTERNAL; + } + nis_freeresult (result); + return retval; + } + + parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + *herrnop = NETDB_INTERNAL; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +/* XXX type is ignored, SUN's NIS+ table doesn't support it */ +enum nss_status +_nss_nisplus_getnetbyaddr_r (const unsigned long addr, const int type, + struct netent *network, + char *buffer, size_t buflen, int *herrnop) +{ + int parse_res, retval; + nis_result *result; + char buf[1024]; + struct in_addr in; + + in = inet_makeaddr (addr, 0); + snprintf(buf, sizeof (buf) - 1, "[addr=%s],networks.org_dir", + inet_ntoa (in)); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + retval = niserr2nss (result->status); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + __set_errno (EAGAIN); + *herrnop = NETDB_INTERNAL; + } + nis_freeresult (result); + return retval; + } + + parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + *herrnop = NETDB_INTERNAL; + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-proto.c b/nis/nss_nisplus/nisplus-proto.c new file mode 100644 index 0000000000..b26cb8230e --- /dev/null +++ b/nis/nss_nisplus/nisplus-proto.c @@ -0,0 +1,284 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <netdb.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define ENTNAME protoent +#define DATABASE "protocols" +#define TRAILING_LIST_MEMBER p_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "../../nss/nss_files/files-parse.c" +LINE_PARSER +("#", + STRING_FIELD (result->p_name, isspace, 1); + INT_FIELD (result->p_proto, isspace, 1, 10,); +) + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_protoent (nis_result * result, struct protoent *proto, + char *buffer, size_t buflen) +{ + char *p = buffer; + size_t room_left = buflen; + int i; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "protocols_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + return -1; + + memset (p, '\0', room_left); + + /* Generate the protocols entry format and use the normal parser */ + if (NISENTRYLEN (0, 0, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) + 1); + + if (NISENTRYLEN (0, 2, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "\t"); + strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); + room_left -= (NISENTRYLEN (0, 2, result) + 1); + /* + 1: We overwrite the last \0 */ + + for (i = 1; i < result->objects.objects_len; i++) + { + if (NISENTRYLEN (i, 1, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, " "); + strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } + + return _nss_files_parse_protoent (p, proto, data, buflen); +} + +enum nss_status +_nss_nisplus_setprotoent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endprotoent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getprotoent_r (struct protoent *proto, char *buffer, + size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames ("protocols.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry (names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res; + + res = nis_next_entry (names[0], &result->cookie); + nis_freeresult (result); + result = res; + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen); + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getprotoent_r (struct protoent *result, char *buffer, + size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getprotoent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getprotobyname_r (const char *name, struct protoent *proto, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 255]; + + /* Search at first in the alias list, and use the correct name + for the next search */ + sprintf (buf, "[name=%s],protocols.org_dir", name); + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + /* If we do not find it, try it as original name. But if the + database is correct, we should find it in the first case, too */ + if ((result->status != NIS_SUCCESS && + result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "protocols_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + sprintf (buf, "[cname=%s],protocols.org_dir", name); + else + sprintf (buf, "[cname=%s],protocols.org_dir", NISENTRYVAL (0, 0, result)); + + nis_freeresult (result); + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_getprotobynumber_r (const int number, struct protoent *proto, + char *buffer, size_t buflen) +{ + int parse_res; + nis_result *result; + char buf[46]; + + snprintf (buf, sizeof (buf), "[number=%d],protocols.org_dir", number); + + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen); + + nis_freeresult (result); + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-publickey.c b/nis/nss_nisplus/nisplus-publickey.c new file mode 100644 index 0000000000..7312c91229 --- /dev/null +++ b/nis/nss_nisplus/nisplus-publickey.c @@ -0,0 +1,347 @@ +/* Copyright (c) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <rpc/key_prot.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include <nss-nisplus.h> + +extern int xdecrypt (char *, char *); + +/* If we found the entry, we give a SUCCESS and an empty key back. */ +enum nss_status +_nss_nisplus_getpublickey (const char *netname, char *pkey) +{ + nis_result *res; + enum nss_status retval; + char buf[NIS_MAXNAMELEN+2]; + char *domain, *cptr; + int len; + + pkey[0] = 0; + + if (netname == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + domain = strchr (netname, '@'); + if (!domain) + return NSS_STATUS_UNAVAIL; + domain++; + + snprintf (buf, NIS_MAXNAMELEN, + "[auth_name=%s,auth_type=DES],cred.org_dir.%s", + netname, domain); + + if (buf[strlen (buf)-1] != '.') + strcat(buf, "."); + + res = nis_list(buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, + NULL, NULL); + + retval = niserr2nss (res->status); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + nis_freeresult (res); + return retval; + } + + if (res->objects.objects_len > 1) + { + /* + * More than one principal with same uid? + * something wrong with cred table. Should be unique + * Warn user and continue. + */ + printf (_("DES entry for netname %s not unique\n"), netname); + nis_freeresult (res); + return NSS_STATUS_SUCCESS; + } + + len = ENTRY_LEN (res->objects.objects_val, 3); + memcpy (pkey, ENTRY_VAL (res->objects.objects_val,3), len); + pkey[len] = 0; + cptr = strchr (pkey, ':'); + if (cptr) + cptr[0] = '\0'; + nis_freeresult (res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd) +{ + nis_result *res; + enum nss_status retval; + char buf[NIS_MAXNAMELEN+2]; + char *domain, *cptr; + int len; + + skey[0] = 0; + + if (netname == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + domain = strchr (netname, '@'); + if (!domain) + return NSS_STATUS_UNAVAIL; + domain++; + + snprintf (buf, NIS_MAXNAMELEN, + "[auth_name=%s,auth_type=DES],cred.org_dir.%s", + netname, domain); + + if (buf[strlen(buf)-1] != '.') + strcat(buf, "."); + + res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, + NULL, NULL); + + retval = niserr2nss (res->status); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + nis_freeresult (res); + return retval; + } + + if (res->objects.objects_len > 1) + { + /* + * More than one principal with same uid? + * something wrong with cred table. Should be unique + * Warn user and continue. + */ + printf (_("DES entry for netname %s not unique\n"), netname); + nis_freeresult (res); + return NSS_STATUS_SUCCESS; + } + + len = ENTRY_LEN (res->objects.objects_val, 4); + memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len); + skey[len] = 0; + cptr = strchr (skey, ':'); + if (cptr) + cptr[0] = '\0'; + nis_freeresult (res); + + if (!xdecrypt (buf, passwd)) + return NSS_STATUS_SUCCESS; + + if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0) + return NSS_STATUS_SUCCESS; + + buf[HEXKEYBYTES] = 0; + strcpy (skey, buf); + + return NSS_STATUS_SUCCESS; +} + +/* Parse information from the passed string. + The format of the string passed is gid,grp,grp, ... */ +static enum nss_status +parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist) +{ + int gidlen; + + if (!s || (!isdigit (*s))) + { + syslog (LOG_ERR, "netname2user: missing group id list in '%s'.", s); + return NSS_STATUS_NOTFOUND; + } + + *gidp = (atoi (s)); + + gidlen = 0; + + while ((s = strchr (s, ',')) != NULL) + { + s++; + gidlist[gidlen++] = atoi (s); + } + *gidlenp = gidlen; + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, + gid_t *gidp, int *gidlenp, gid_t *gidlist) +{ + char *domain; + nis_result *res; + char sname[NIS_MAXNAMELEN+1]; /* search criteria + table name */ + char principal[NIS_MAXNAMELEN+1]; + int len; + + /* 1. Get home domain of user. */ + domain = strchr (netname, '@'); + if (! domain) + return NSS_STATUS_UNAVAIL; + + domain++; /* skip '@' */ + + /* 2. Get user's nisplus principal name. */ + if ((strlen (netname) + strlen (domain)+45) > + (size_t) NIS_MAXNAMELEN) + return NSS_STATUS_UNAVAIL; + + snprintf (sname, NIS_MAXNAMELEN, + "[auth_name=%s,auth_type=DES],cred.org_dir.%s", + netname, domain); + if (sname[strlen (sname) - 1] != '.') + strcat(sname, "."); + + /* must use authenticated call here */ + /* XXX but we cant, for now. XXX */ + res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, + NULL, NULL); + switch(res->status) + { + case NIS_SUCCESS: + case NIS_S_SUCCESS: + break; /* go and do something useful */ + case NIS_NOTFOUND: + case NIS_PARTIAL: + case NIS_NOSUCHNAME: + case NIS_NOSUCHTABLE: + nis_freeresult (res); + return NSS_STATUS_NOTFOUND; + case NIS_S_NOTFOUND: + case NIS_TRYAGAIN: + syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n", + nis_sperrno (res->status)); + nis_freeresult (res); + return NSS_STATUS_TRYAGAIN; + default: + syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n", + nis_sperrno (res->status)); + nis_freeresult (res); + return NSS_STATUS_UNAVAIL; + } + + if (res->objects.objects_len > 1) + { + /* + * A netname belonging to more than one principal? + * Something wrong with cred table. should be unique. + * Warn user and continue. + */ + syslog (LOG_ALERT, + _("netname2user: DES entry for %s in directory %s not unique"), + netname, domain); + } + + len = ENTRY_LEN(res->objects.objects_val, 0); + strncpy(principal, ENTRY_VAL(res->objects.objects_val, 0), len); + principal[len] = '\0'; + nis_freeresult(res); + + if (principal[0] == '\0') + return NSS_STATUS_UNAVAIL; + + /* + * 3. Use principal name to look up uid/gid information in + * LOCAL entry in **local** cred table. + */ + domain = nis_local_directory (); + if ((strlen(principal)+strlen(domain)+45) > + (size_t) NIS_MAXNAMELEN) + { + syslog (LOG_ERR, _("netname2user: principal name '%s' too long"), + principal); + return NSS_STATUS_UNAVAIL; + } + sprintf(sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s", + principal, domain); + if (sname[strlen(sname) - 1] != '.') + strcat(sname, "."); + + /* must use authenticated call here */ + /* XXX but we cant, for now. XXX */ + res = nis_list(sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, + NULL, NULL); + switch(res->status) { + case NIS_NOTFOUND: + case NIS_PARTIAL: + case NIS_NOSUCHNAME: + case NIS_NOSUCHTABLE: + nis_freeresult (res); + return NSS_STATUS_NOTFOUND; + case NIS_S_NOTFOUND: + case NIS_TRYAGAIN: + syslog (LOG_ERR, + "netname2user: (nis+ lookup): %s\n", + nis_sperrno (res->status)); + nis_freeresult (res); + return NSS_STATUS_TRYAGAIN; + case NIS_SUCCESS: + case NIS_S_SUCCESS: + break; /* go and do something useful */ + default: + syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n", + nis_sperrno (res->status)); + nis_freeresult (res); + return NSS_STATUS_UNAVAIL; + } + + if (res->objects.objects_len > 1) + { + /* + * A principal can have more than one LOCAL entry? + * Something wrong with cred table. + * Warn user and continue. + */ + syslog(LOG_ALERT, + _("netname2user: LOCAL entry for %s in directory %s not unique"), + netname, domain); + } + /* Fetch the uid */ + *uidp = (atoi (ENTRY_VAL (res->objects.objects_val, 2))); + + if (*uidp == 0) + { + syslog (LOG_ERR, _("netname2user: should not have uid 0")); + return NSS_STATUS_NOTFOUND; + } + + parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3), + gidp, gidlenp, gidlist); + + nis_freeresult (res); + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nisplus/nisplus-pwd.c b/nis/nss_nisplus/nisplus-pwd.c new file mode 100644 index 0000000000..3717d5e98a --- /dev/null +++ b/nis/nss_nisplus/nisplus-pwd.c @@ -0,0 +1,293 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <pwd.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw, + char *buffer, size_t buflen) +{ + char *first_unused = buffer; + size_t room_left = buflen; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "passwd_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 7) + return -1; + + if (NISENTRYLEN(0, 0, result) >= room_left) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return -1; + } + + strncpy (first_unused, NISENTRYVAL(0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + pw->pw_name = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 1, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL(0, 1, result), + NISENTRYLEN (0, 1, result)); + first_unused[NISENTRYLEN(0, 1, result)] = '\0'; + pw->pw_passwd = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 2, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 2, result), + NISENTRYLEN (0, 2, result)); + first_unused[NISENTRYLEN(0, 2, result)] = '\0'; + pw->pw_uid = atoi (first_unused); + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 3, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL(0, 3, result), + NISENTRYLEN (0, 3, result)); + first_unused[NISENTRYLEN(0, 3, result)] = '\0'; + pw->pw_gid = atoi (first_unused); + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 4, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL(0, 4, result), + NISENTRYLEN (0, 4, result)); + first_unused[NISENTRYLEN(0, 4, result)] = '\0'; + pw->pw_gecos = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 5, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 5, result), + NISENTRYLEN (0, 5, result)); + first_unused[NISENTRYLEN(0, 5, result)] = '\0'; + pw->pw_dir = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 6, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 6, result), + NISENTRYLEN (0, 6, result)); + first_unused[NISENTRYLEN (0, 6, result)] = '\0'; + pw->pw_shell = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + return 1; +} + +enum nss_status +_nss_nisplus_setpwent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endpwent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames ("passwd.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry(names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res; + + res = nis_next_entry(names[0], &result->cookie); + nis_freeresult (result); + result = res; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen); + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getpwent_r (struct passwd *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getpwent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getpwnam_r (const char *name, struct passwd *pw, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL || strlen (name) > 8) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 24]; + + sprintf(buf, "[name=%s],passwd.org_dir", name); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw, + char *buffer, size_t buflen) +{ + int parse_res; + nis_result *result; + char buf[100]; + + sprintf(buf, "[uid=%d],passwd.org_dir", uid); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen); + + nis_freeresult (result); + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-rpc.c b/nis/nss_nisplus/nisplus-rpc.c new file mode 100644 index 0000000000..326f262749 --- /dev/null +++ b/nis/nss_nisplus/nisplus-rpc.c @@ -0,0 +1,284 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <libc-lock.h> +#include <rpc/netdb.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define ENTNAME rpcent +#define DATABASE "rpc" +#define TRAILING_LIST_MEMBER r_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "../../nss/nss_files/files-parse.c" +LINE_PARSER +("#", + STRING_FIELD (result->r_name, isspace, 1); + INT_FIELD (result->r_number, isspace, 1, 10,); + ) + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_rpcent (nis_result *result, struct rpcent *rpc, + char *buffer, size_t buflen) +{ + char *p = buffer; + size_t room_left = buflen; + int i; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "rpc_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + return -1; + + memset (p, '\0', room_left); + + /* Generate the rpc entry format and use the normal parser */ + if (NISENTRYLEN (0, 0, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) +1); + + if (NISENTRYLEN (0, 2, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "\t"); + strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); + room_left -= (NISENTRYLEN (0, 2, result) + 1); + /* + 1: We overwrite the last \0 */ + + for (i = 0; i < result->objects.objects_len; i++) + /* XXX should we start with i = 0 or with i = 1 ? */ + { + if (NISENTRYLEN (i, 1, result) +1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, " "); + strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result)); + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } + + return _nss_files_parse_rpcent (p, rpc, data, buflen); +} + +enum nss_status +_nss_nisplus_setrpcent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endrpcent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer, + size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames ("rpc.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry(names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res; + + res = nis_next_entry (names[0], &result->cookie); + nis_freeresult (result); + result = res; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen); + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getrpcent_r (struct rpcent *result, char *buffer, + size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getrpcent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getrpcbyname_r (const char *name, struct rpcent *rpc, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 255]; + + /* Search at first in the alias list, and use the correct name + for the next search */ + sprintf (buf, "[name=%s],rpc.org_dir", name); + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + /* If we do not find it, try it as original name. But if the + database is correct, we should find it in the first case, too */ + if ((result->status != NIS_SUCCESS && + result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "rpc_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3) + sprintf (buf, "[cname=%s],rpc.org_dir", name); + else + sprintf (buf, "[cname=%s],rpc.org_dir", NISENTRYVAL(0, 0, result)); + + nis_freeresult (result); + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_getrpcbynumber_r (const int number, struct rpcent *rpc, + char *buffer, size_t buflen) +{ + int parse_res; + nis_result *result; + char buf[100]; + + snprintf (buf, sizeof (buf), "[number=%d],rpc.org_dir", number); + + result = nis_list(buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-service.c b/nis/nss_nisplus/nisplus-service.c new file mode 100644 index 0000000000..54f4f876c7 --- /dev/null +++ b/nis/nss_nisplus/nisplus-service.c @@ -0,0 +1,308 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <netdb.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock); + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define ENTNAME servent +#define DATABASE "services" +#define TRAILING_LIST_MEMBER s_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "../../nss/nss_files/files-parse.c" +#define ISSLASH(c) ((c) == '/') +LINE_PARSER +("#", + STRING_FIELD (result->s_name, isspace, 1); + INT_FIELD (result->s_port, ISSLASH, 10, 0, htons); + STRING_FIELD (result->s_proto, isspace, 1); + ) + + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_servent (nis_result *result, struct servent *serv, + char *buffer, size_t buflen) +{ + char *p = buffer; + size_t room_left = buflen; + int i; + struct parser_data *data = (void *) buffer; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "services_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + return -1; + + memset (p, '\0', room_left); + + /* Generate the services entry format and use the normal parser */ + if (NISENTRYLEN (0, 0, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result)); + room_left -= (NISENTRYLEN (0, 0, result) + 1); + + if (NISENTRYLEN (0, 3, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "\t"); + strncat (p, NISENTRYVAL (0, 3, result), NISENTRYLEN (0, 3, result)); + room_left -= (NISENTRYLEN (0, 3, result) + 1); + if (NISENTRYLEN (0, 2, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, "/"); + strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result)); + room_left -= (NISENTRYLEN (0, 2, result) + 1); + + for (i = 1; i < result->objects.objects_len; i++) + { + if (NISENTRYLEN (i, 1, result) + 1 > room_left) + { + __set_errno (ERANGE); + return -1; + } + strcat (p, " "); + strcat (p, NISENTRYVAL (i, 1, result)); + room_left -= (NISENTRYLEN (i, 1, result) + 1); + } + + return _nss_files_parse_servent (p, serv, data, buflen); +} + +enum nss_status +_nss_nisplus_setservent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endservent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getservent_r (struct servent *serv, char *buffer, + size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames ("services.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry (names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res; + + res = nis_next_entry (names[0], &result->cookie); + nis_freeresult (result); + result = res; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen); + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getservent_r (struct servent *result, char *buffer, + size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getservent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getservbyname_r (const char *name, const char *protocol, + struct servent *serv, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL || protocol == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_NOTFOUND; + } + else + { + nis_result *result; + char buf[strlen (name) + 255]; + + /* Search at first in the alias list, and use the correct name + for the next search */ + sprintf (buf, "[name=%s,proto=%s],services.org_dir", name, + protocol); + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + /* If we do not find it, try it as original name. But if the + database is correct, we should find it in the first case, too */ + if ((result->status != NIS_SUCCESS && + result->status != NIS_S_SUCCESS) || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "services_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4) + sprintf (buf, "[cname=%s,proto=%s],services.org_dir", name, protocol); + else + sprintf (buf, "[cname=%s,proto=%s],services.org_dir", + NISENTRYVAL (0, 0, result), protocol); + + nis_freeresult (result); + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} + +enum nss_status +_nss_nisplus_getservbynumber_r (const int number, const char *protocol, + struct servent *serv, + char *buffer, size_t buflen) +{ + int parse_res; + nis_result *result; + char buf[60 + strlen (protocol)]; + + if (protocol == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_NOTFOUND; + } + + snprintf (buf, sizeof (buf), "[number=%d,proto=%s],services.org_dir", + number, protocol); + + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; +} diff --git a/nis/nss_nisplus/nisplus-spwd.c b/nis/nss_nisplus/nisplus-spwd.c new file mode 100644 index 0000000000..ec4b5b3340 --- /dev/null +++ b/nis/nss_nisplus/nisplus-spwd.c @@ -0,0 +1,262 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <shadow.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/nis.h> +#include <rpcsvc/nislib.h> + +#include "nss-nisplus.h" + +__libc_lock_define_initialized (static, lock) + +static nis_result *result = NULL; +static nis_name *names = NULL; + +#define NISENTRYVAL(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) + +#define NISENTRYLEN(idx,col,res) \ + ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) + +static int +_nss_nisplus_parse_spent (nis_result *result, struct spwd *sp, + char *buffer, size_t buflen) +{ + char *first_unused = buffer; + size_t room_left = buflen; + char *line, *cp; + + if (result == NULL) + return -1; + + if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) || + result->objects.objects_len != 1 || + result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ || + strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type, + "passwd_tbl") != 0 || + result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 8) + return -1; + + if (NISENTRYLEN(0, 0, result) >= room_left) + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return -1; + } + + strncpy (first_unused, NISENTRYVAL (0, 0, result), + NISENTRYLEN (0, 0, result)); + first_unused[NISENTRYLEN(0, 0, result)] = '\0'; + sp->sp_namp = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + if (NISENTRYLEN(0, 1, result) >= room_left) + goto no_more_room; + + strncpy (first_unused, NISENTRYVAL (0, 1, result), + NISENTRYLEN (0, 1, result)); + first_unused[NISENTRYLEN(0, 1, result)] = '\0'; + sp->sp_pwdp = first_unused; + room_left -= (strlen (first_unused) +1); + first_unused += strlen (first_unused) +1; + + sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact = + sp->sp_expire = sp->sp_flag = -1; + + line = NISENTRYVAL (0, 7, result); + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_lstchg = atoi (line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_min = atoi(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_max = atoi(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_warn = atoi(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_inact = atoi(line); + + line = cp; + cp = strchr (line, ':'); + if (cp == NULL) + return 0; + *cp++ = '\0'; + sp->sp_expire = atoi(line); + + line = cp; + if (line == NULL) + return 0; + sp->sp_flag = atoi(line); + + return 1; +} + +enum nss_status +_nss_nisplus_setspent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_endspent (void) +{ + __libc_lock_lock (lock); + + if (result) + nis_freeresult (result); + result = NULL; + if (names) + { + nis_freenames (names); + names = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nisplus_getspent_r (struct spwd *sp, char *buffer, size_t buflen) +{ + int parse_res; + + /* Get the next entry until we found a correct one. */ + do + { + if (result == NULL) + { + names = nis_getnames ("passwd.org_dir"); + if (names == NULL || names[0] == NULL) + return NSS_STATUS_UNAVAIL; + + result = nis_first_entry (names[0]); + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + else + { + nis_result *res; + + res = nis_next_entry (names[0], &result->cookie); + nis_freeresult (result); + result = res; + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + return niserr2nss (result->status); + } + + parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen); + } while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nisplus_getspent_r (struct spwd *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nisplus_getspent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nisplus_getspnam_r (const char *name, struct spwd *sp, + char *buffer, size_t buflen) +{ + int parse_res; + + if (name == NULL || strlen (name) > 8) + return NSS_STATUS_NOTFOUND; + else + { + nis_result *result; + char buf[strlen (name) + 24]; + + sprintf (buf, "[name=%s],passwd.org_dir", name); + + result = nis_list (buf, EXPAND_NAME, NULL, NULL); + + if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) + { + enum nss_status status = niserr2nss (result->status); + + nis_freeresult (result); + return status; + } + + parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen); + + nis_freeresult (result); + + if (parse_res) + return NSS_STATUS_SUCCESS; + + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } +} diff --git a/nis/rpcsvc/nis.h b/nis/rpcsvc/nis.h new file mode 100644 index 0000000000..c2c5319abd --- /dev/null +++ b/nis/rpcsvc/nis.h @@ -0,0 +1,1008 @@ +/* + * 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 or with the express written consent of + * Sun Microsystems, Inc. + * + * 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 + */ + +#ifndef _NIS_H_RPCGEN +#define _NIS_H_RPCGEN + +#include <rpc/rpc.h> + +/* + * nis.h + * + * This file is the main include file for NIS clients. It contains + * both the client library function defines and the various data + * structures used by the NIS service. It includes the file nis_tags.h + * which defines the tag values. This allows the tags to change without + * having to change the nis.x file. + * + * NOTE : DO NOT EDIT THIS FILE! It is automatically generated when + * rpcgen is run on the nis.x file. Note that there is a + * simple sed script to remove some unneeded lines. (See the + * Makefile target nis.h) + * + */ +#include <rpcsvc/nis_tags.h> +#include <rpc/xdr.h> +#pragma ident "@(#)nis_object.x 1.7 92/07/14 SMI" + +#ifndef __nis_object_h +#define __nis_object_h + +#define NIS_MAXSTRINGLEN 255 +#define NIS_MAXNAMELEN 1024 +#define NIS_MAXATTRNAME 32 +#define NIS_MAXATTRVAL 2048 +#define NIS_MAXCOLUMNS 64 +#define NIS_MAXATTR 16 +#define NIS_MAXPATH 1024 +#define NIS_MAXREPLICAS 128 +#define NIS_MAXLINKS 16 +#define NIS_PK_NONE 0 +#define NIS_PK_DH 1 +#define NIS_PK_RSA 2 +#define NIS_PK_KERB 3 + +struct nis_attr { + char *zattr_ndx; + struct { + u_int zattr_val_len; + char *zattr_val_val; + } zattr_val; +}; +typedef struct nis_attr nis_attr; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_attr(XDR *, nis_attr*); +#elif __STDC__ +extern bool_t xdr_nis_attr(XDR *, nis_attr*); +#else /* Old Style C */ +bool_t xdr_nis_attr(); +#endif /* Old Style C */ + + +typedef char *nis_name; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_name(XDR *, nis_name*); +#elif __STDC__ +extern bool_t xdr_nis_name(XDR *, nis_name*); +#else /* Old Style C */ +bool_t xdr_nis_name(); +#endif /* Old Style C */ + + +enum zotypes { + BOGUS_OBJ = 0, + NO_OBJ = 1, + DIRECTORY_OBJ = 2, + GROUP_OBJ = 3, + TABLE_OBJ = 4, + ENTRY_OBJ = 5, + LINK_OBJ = 6, + PRIVATE_OBJ = 7, +}; +typedef enum zotypes zotypes; +#ifdef __cplusplus +extern "C" bool_t xdr_zotypes(XDR *, zotypes*); +#elif __STDC__ +extern bool_t xdr_zotypes(XDR *, zotypes*); +#else /* Old Style C */ +bool_t xdr_zotypes(); +#endif /* Old Style C */ + + +enum nstype { + UNKNOWN = 0, + NIS = 1, + SUNYP = 2, + IVY = 3, + DNS = 4, + X500 = 5, + DNANS = 6, + XCHS = 7, + CDS = 8, +}; +typedef enum nstype nstype; +#ifdef __cplusplus +extern "C" bool_t xdr_nstype(XDR *, nstype*); +#elif __STDC__ +extern bool_t xdr_nstype(XDR *, nstype*); +#else /* Old Style C */ +bool_t xdr_nstype(); +#endif /* Old Style C */ + + +struct oar_mask { + u_long oa_rights; + zotypes oa_otype; +}; +typedef struct oar_mask oar_mask; +#ifdef __cplusplus +extern "C" bool_t xdr_oar_mask(XDR *, oar_mask*); +#elif __STDC__ +extern bool_t xdr_oar_mask(XDR *, oar_mask*); +#else /* Old Style C */ +bool_t xdr_oar_mask(); +#endif /* Old Style C */ + + +struct endpoint { + char *uaddr; + char *family; + char *proto; +}; +typedef struct endpoint endpoint; +#ifdef __cplusplus +extern "C" bool_t xdr_endpoint(XDR *, endpoint*); +#elif __STDC__ +extern bool_t xdr_endpoint(XDR *, endpoint*); +#else /* Old Style C */ +bool_t xdr_endpoint(); +#endif /* Old Style C */ + + +struct nis_server { + nis_name name; + struct { + u_int ep_len; + endpoint *ep_val; + } ep; + u_long key_type; + netobj pkey; +}; +typedef struct nis_server nis_server; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_server(XDR *, nis_server*); +#elif __STDC__ +extern bool_t xdr_nis_server(XDR *, nis_server*); +#else /* Old Style C */ +bool_t xdr_nis_server(); +#endif /* Old Style C */ + + +struct directory_obj { + nis_name do_name; + nstype do_type; + struct { + u_int do_servers_len; + nis_server *do_servers_val; + } do_servers; + u_long do_ttl; + struct { + u_int do_armask_len; + oar_mask *do_armask_val; + } do_armask; +}; +typedef struct directory_obj directory_obj; +#ifdef __cplusplus +extern "C" bool_t xdr_directory_obj(XDR *, directory_obj*); +#elif __STDC__ +extern bool_t xdr_directory_obj(XDR *, directory_obj*); +#else /* Old Style C */ +bool_t xdr_directory_obj(); +#endif /* Old Style C */ + +#define EN_BINARY 1 +#define EN_CRYPT 2 +#define EN_XDR 4 +#define EN_MODIFIED 8 +#define EN_ASN1 64 + +struct entry_col { + u_long ec_flags; + struct { + u_int ec_value_len; + char *ec_value_val; + } ec_value; +}; +typedef struct entry_col entry_col; +#ifdef __cplusplus +extern "C" bool_t xdr_entry_col(XDR *, entry_col*); +#elif __STDC__ +extern bool_t xdr_entry_col(XDR *, entry_col*); +#else /* Old Style C */ +bool_t xdr_entry_col(); +#endif /* Old Style C */ + + +struct entry_obj { + char *en_type; + struct { + u_int en_cols_len; + entry_col *en_cols_val; + } en_cols; +}; +typedef struct entry_obj entry_obj; +#ifdef __cplusplus +extern "C" bool_t xdr_entry_obj(XDR *, entry_obj*); +#elif __STDC__ +extern bool_t xdr_entry_obj(XDR *, entry_obj*); +#else /* Old Style C */ +bool_t xdr_entry_obj(); +#endif /* Old Style C */ + + +struct group_obj { + u_long gr_flags; + struct { + u_int gr_members_len; + nis_name *gr_members_val; + } gr_members; +}; +typedef struct group_obj group_obj; +#ifdef __cplusplus +extern "C" bool_t xdr_group_obj(XDR *, group_obj*); +#elif __STDC__ +extern bool_t xdr_group_obj(XDR *, group_obj*); +#else /* Old Style C */ +bool_t xdr_group_obj(); +#endif /* Old Style C */ + + +struct link_obj { + zotypes li_rtype; + struct { + u_int li_attrs_len; + nis_attr *li_attrs_val; + } li_attrs; + nis_name li_name; +}; +typedef struct link_obj link_obj; +#ifdef __cplusplus +extern "C" bool_t xdr_link_obj(XDR *, link_obj*); +#elif __STDC__ +extern bool_t xdr_link_obj(XDR *, link_obj*); +#else /* Old Style C */ +bool_t xdr_link_obj(); +#endif /* Old Style C */ + +#define TA_BINARY 1 +#define TA_CRYPT 2 +#define TA_XDR 4 +#define TA_SEARCHABLE 8 +#define TA_CASE 16 +#define TA_MODIFIED 32 +#define TA_ASN1 64 + +struct table_col { + char *tc_name; + u_long tc_flags; + u_long tc_rights; +}; +typedef struct table_col table_col; +#ifdef __cplusplus +extern "C" bool_t xdr_table_col(XDR *, table_col*); +#elif __STDC__ +extern bool_t xdr_table_col(XDR *, table_col*); +#else /* Old Style C */ +bool_t xdr_table_col(); +#endif /* Old Style C */ + + +struct table_obj { + char *ta_type; + int ta_maxcol; + u_char ta_sep; + struct { + u_int ta_cols_len; + table_col *ta_cols_val; + } ta_cols; + char *ta_path; +}; +typedef struct table_obj table_obj; +#ifdef __cplusplus +extern "C" bool_t xdr_table_obj(XDR *, table_obj*); +#elif __STDC__ +extern bool_t xdr_table_obj(XDR *, table_obj*); +#else /* Old Style C */ +bool_t xdr_table_obj(); +#endif /* Old Style C */ + + +struct objdata { + zotypes zo_type; + union { + struct directory_obj di_data; + struct group_obj gr_data; + struct table_obj ta_data; + struct entry_obj en_data; + struct link_obj li_data; + struct { + u_int po_data_len; + char *po_data_val; + } po_data; + } objdata_u; +}; +typedef struct objdata objdata; +#ifdef __cplusplus +extern "C" bool_t xdr_objdata(XDR *, objdata*); +#elif __STDC__ +extern bool_t xdr_objdata(XDR *, objdata*); +#else /* Old Style C */ +bool_t xdr_objdata(); +#endif /* Old Style C */ + + +struct nis_oid { + u_long ctime; + u_long mtime; +}; +typedef struct nis_oid nis_oid; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_oid(XDR *, nis_oid*); +#elif __STDC__ +extern bool_t xdr_nis_oid(XDR *, nis_oid*); +#else /* Old Style C */ +bool_t xdr_nis_oid(); +#endif /* Old Style C */ + + +struct nis_object { + nis_oid zo_oid; + nis_name zo_name; + nis_name zo_owner; + nis_name zo_group; + nis_name zo_domain; + u_long zo_access; + u_long zo_ttl; + objdata zo_data; +}; +typedef struct nis_object nis_object; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_object(XDR *, nis_object*); +#elif __STDC__ +extern bool_t xdr_nis_object(XDR *, nis_object*); +#else /* Old Style C */ +bool_t xdr_nis_object(); +#endif /* Old Style C */ + + +#endif /* if __nis_object_h */ + + +enum nis_error { + NIS_SUCCESS = 0, + NIS_S_SUCCESS = 1, + NIS_NOTFOUND = 2, + NIS_S_NOTFOUND = 3, + NIS_CACHEEXPIRED = 4, + NIS_NAMEUNREACHABLE = 5, + NIS_UNKNOWNOBJ = 6, + NIS_TRYAGAIN = 7, + NIS_SYSTEMERROR = 8, + NIS_CHAINBROKEN = 9, + NIS_PERMISSION = 10, + NIS_NOTOWNER = 11, + NIS_NOT_ME = 12, + NIS_NOMEMORY = 13, + NIS_NAMEEXISTS = 14, + NIS_NOTMASTER = 15, + NIS_INVALIDOBJ = 16, + NIS_BADNAME = 17, + NIS_NOCALLBACK = 18, + NIS_CBRESULTS = 19, + NIS_NOSUCHNAME = 20, + NIS_NOTUNIQUE = 21, + NIS_IBMODERROR = 22, + NIS_NOSUCHTABLE = 23, + NIS_TYPEMISMATCH = 24, + NIS_LINKNAMEERROR = 25, + NIS_PARTIAL = 26, + NIS_TOOMANYATTRS = 27, + NIS_RPCERROR = 28, + NIS_BADATTRIBUTE = 29, + NIS_NOTSEARCHABLE = 30, + NIS_CBERROR = 31, + NIS_FOREIGNNS = 32, + NIS_BADOBJECT = 33, + NIS_NOTSAMEOBJ = 34, + NIS_MODFAIL = 35, + NIS_BADREQUEST = 36, + NIS_NOTEMPTY = 37, + NIS_COLDSTART_ERR = 38, + NIS_RESYNC = 39, + NIS_FAIL = 40, + NIS_UNAVAIL = 41, + NIS_RES2BIG = 42, + NIS_SRVAUTH = 43, + NIS_CLNTAUTH = 44, + NIS_NOFILESPACE = 45, + NIS_NOPROC = 46, + NIS_DUMPLATER = 47, +}; +typedef enum nis_error nis_error; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_error(XDR *, nis_error*); +#elif __STDC__ +extern bool_t xdr_nis_error(XDR *, nis_error*); +#else /* Old Style C */ +bool_t xdr_nis_error(); +#endif /* Old Style C */ + + +struct nis_result { + nis_error status; + struct { + u_int objects_len; + nis_object *objects_val; + } objects; + netobj cookie; + u_long zticks; + u_long dticks; + u_long aticks; + u_long cticks; +}; +typedef struct nis_result nis_result; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_result(XDR *, nis_result*); +#elif __STDC__ +extern bool_t xdr_nis_result(XDR *, nis_result*); +#else /* Old Style C */ +bool_t xdr_nis_result(); +#endif /* Old Style C */ + + +struct ns_request { + nis_name ns_name; + struct { + u_int ns_object_len; + nis_object *ns_object_val; + } ns_object; +}; +typedef struct ns_request ns_request; +#ifdef __cplusplus +extern "C" bool_t xdr_ns_request(XDR *, ns_request*); +#elif __STDC__ +extern bool_t xdr_ns_request(XDR *, ns_request*); +#else /* Old Style C */ +bool_t xdr_ns_request(); +#endif /* Old Style C */ + + +struct ib_request { + nis_name ibr_name; + struct { + u_int ibr_srch_len; + nis_attr *ibr_srch_val; + } ibr_srch; + u_long ibr_flags; + struct { + u_int ibr_obj_len; + nis_object *ibr_obj_val; + } ibr_obj; + struct { + u_int ibr_cbhost_len; + nis_server *ibr_cbhost_val; + } ibr_cbhost; + u_long ibr_bufsize; + netobj ibr_cookie; +}; +typedef struct ib_request ib_request; +#ifdef __cplusplus +extern "C" bool_t xdr_ib_request(XDR *, ib_request*); +#elif __STDC__ +extern bool_t xdr_ib_request(XDR *, ib_request*); +#else /* Old Style C */ +bool_t xdr_ib_request(); +#endif /* Old Style C */ + + +struct ping_args { + nis_name dir; + u_long stamp; +}; +typedef struct ping_args ping_args; +#ifdef __cplusplus +extern "C" bool_t xdr_ping_args(XDR *, ping_args*); +#elif __STDC__ +extern bool_t xdr_ping_args(XDR *, ping_args*); +#else /* Old Style C */ +bool_t xdr_ping_args(); +#endif /* Old Style C */ + + +enum log_entry_t { + LOG_NOP = 0, + ADD_NAME = 1, + REM_NAME = 2, + MOD_NAME_OLD = 3, + MOD_NAME_NEW = 4, + ADD_IBASE = 5, + REM_IBASE = 6, + MOD_IBASE = 7, + UPD_STAMP = 8, +}; +typedef enum log_entry_t log_entry_t; +#ifdef __cplusplus +extern "C" bool_t xdr_log_entry_t(XDR *, log_entry_t*); +#elif __STDC__ +extern bool_t xdr_log_entry_t(XDR *, log_entry_t*); +#else /* Old Style C */ +bool_t xdr_log_entry_t(); +#endif /* Old Style C */ + + +struct log_entry { + u_long le_time; + log_entry_t le_type; + nis_name le_princp; + nis_name le_name; + struct { + u_int le_attrs_len; + nis_attr *le_attrs_val; + } le_attrs; + nis_object le_object; +}; +typedef struct log_entry log_entry; +#ifdef __cplusplus +extern "C" bool_t xdr_log_entry(XDR *, log_entry*); +#elif __STDC__ +extern bool_t xdr_log_entry(XDR *, log_entry*); +#else /* Old Style C */ +bool_t xdr_log_entry(); +#endif /* Old Style C */ + + +struct log_result { + nis_error lr_status; + netobj lr_cookie; + struct { + u_int lr_entries_len; + log_entry *lr_entries_val; + } lr_entries; +}; +typedef struct log_result log_result; +#ifdef __cplusplus +extern "C" bool_t xdr_log_result(XDR *, log_result*); +#elif __STDC__ +extern bool_t xdr_log_result(XDR *, log_result*); +#else /* Old Style C */ +bool_t xdr_log_result(); +#endif /* Old Style C */ + + +struct cp_result { + nis_error cp_status; + u_long cp_zticks; + u_long cp_dticks; +}; +typedef struct cp_result cp_result; +#ifdef __cplusplus +extern "C" bool_t xdr_cp_result(XDR *, cp_result*); +#elif __STDC__ +extern bool_t xdr_cp_result(XDR *, cp_result*); +#else /* Old Style C */ +bool_t xdr_cp_result(); +#endif /* Old Style C */ + + +struct nis_tag { + u_long tag_type; + char *tag_val; +}; +typedef struct nis_tag nis_tag; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_tag(XDR *, nis_tag*); +#elif __STDC__ +extern bool_t xdr_nis_tag(XDR *, nis_tag*); +#else /* Old Style C */ +bool_t xdr_nis_tag(); +#endif /* Old Style C */ + + +struct nis_taglist { + struct { + u_int tags_len; + nis_tag *tags_val; + } tags; +}; +typedef struct nis_taglist nis_taglist; +#ifdef __cplusplus +extern "C" bool_t xdr_nis_taglist(XDR *, nis_taglist*); +#elif __STDC__ +extern bool_t xdr_nis_taglist(XDR *, nis_taglist*); +#else /* Old Style C */ +bool_t xdr_nis_taglist(); +#endif /* Old Style C */ + + +struct dump_args { + nis_name da_dir; + u_long da_time; + struct { + u_int da_cbhost_len; + nis_server *da_cbhost_val; + } da_cbhost; +}; +typedef struct dump_args dump_args; +#ifdef __cplusplus +extern "C" bool_t xdr_dump_args(XDR *, dump_args*); +#elif __STDC__ +extern bool_t xdr_dump_args(XDR *, dump_args*); +#else /* Old Style C */ +bool_t xdr_dump_args(); +#endif /* Old Style C */ + + +struct fd_args { + nis_name dir_name; + nis_name requester; +}; +typedef struct fd_args fd_args; +#ifdef __cplusplus +extern "C" bool_t xdr_fd_args(XDR *, fd_args*); +#elif __STDC__ +extern bool_t xdr_fd_args(XDR *, fd_args*); +#else /* Old Style C */ +bool_t xdr_fd_args(); +#endif /* Old Style C */ + + +struct fd_result { + nis_error status; + nis_name source; + struct { + u_int dir_data_len; + char *dir_data_val; + } dir_data; + struct { + u_int signature_len; + char *signature_val; + } signature; +}; +typedef struct fd_result fd_result; +#ifdef __cplusplus +extern "C" bool_t xdr_fd_result(XDR *, fd_result*); +#elif __STDC__ +extern bool_t xdr_fd_result(XDR *, fd_result*); +#else /* Old Style C */ +bool_t xdr_fd_result(); +#endif /* Old Style C */ + +/* + * Generic "hash" datastructures, used by all types of hashed data. + */ +struct nis_hash_data { + nis_name name; /* NIS name of hashed item */ + int keychain; /* It's hash key (for pop) */ + struct nis_hash_data *next; /* Hash collision pointer */ + struct nis_hash_data *prv_item; /* A serial, doubly linked list */ + struct nis_hash_data *nxt_item; /* of items in the hash table */ +}; +typedef struct nis_hash_data NIS_HASH_ITEM; + +struct nis_hash_table { + NIS_HASH_ITEM *keys[64]; /* A hash table of items */ + NIS_HASH_ITEM *first; /* The first "item" in serial list */ +}; +typedef struct nis_hash_table NIS_HASH_TABLE; + +/* Structure for storing dynamically allocated static data */ +struct nis_sdata { + void *buf; /* Memory allocation pointer */ + u_long size; /* Buffer size */ +}; + +/* Generic client creating flags */ +#define ZMH_VC 1 +#define ZMH_DG 2 +#define ZMH_AUTH 4 + +/* Testing Access rights for objects */ + +#define NIS_READ_ACC 1 +#define NIS_MODIFY_ACC 2 +#define NIS_CREATE_ACC 4 +#define NIS_DESTROY_ACC 8 +/* Test macros. a == access rights, m == desired rights. */ +#define WORLD(a, m) (((a) & (m)) != 0) +#define GROUP(a, m) (((a) & ((m) << 8)) != 0) +#define OWNER(a, m) (((a) & ((m) << 16)) != 0) +#define NOBODY(a, m) (((a) & ((m) << 24)) != 0) + +#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype) +#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights) +#define WORLD_DEFAULT (NIS_READ_ACC) +#define GROUP_DEFAULT (NIS_READ_ACC << 8) +#define OWNER_DEFAULT ((NIS_READ_ACC + NIS_MODIFY_ACC + NIS_CREATE_ACC +\ + NIS_DESTROY_ACC) << 16) +#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT) + +/* Result manipulation defines ... */ +#define NIS_RES_NUMOBJ(x) ((x)->objects.objects_len) +#define NIS_RES_OBJECT(x) ((x)->objects.objects_val) +#define NIS_RES_COOKIE(x) ((x)->cookie) +#define NIS_RES_STATUS(x) ((x)->status) + +/* These defines make getting at the variant part of the object easier. */ +#define TA_data zo_data.objdata_u.ta_data +#define EN_data zo_data.objdata_u.en_data +#define DI_data zo_data.objdata_u.di_data +#define LI_data zo_data.objdata_u.li_data +#define GR_data zo_data.objdata_u.gr_data + +#define __type_of(o) ((o)->zo_data.zo_type) + +/* Declarations for the internal subroutines in nislib.c */ +enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME}; +typedef enum name_pos name_pos; + +/* + * Defines for getting at column data in entry objects. Because RPCGEN + * generates some rather wordy structures, we create some defines that + * collapse the needed keystrokes to access a particular value using + * these definitions they take an nis_object *, and an int and return + * a u_char * for Value, and an int for length. + */ +#define ENTRY_VAL(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val +#define ENTRY_LEN(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len + +#ifdef __cplusplus +} +#endif + +/* Prototypes, and extern declarations for the NIS library functions. */ +#include <rpcsvc/nislib.h> +#endif /* __NIS_RPCGEN_H */ +/* EDIT_START */ + +/* + * nis_3.h + * + * This file contains definitions that are only of interest to the actual + * service daemon and client stubs. Normal users of NIS will not include + * this file. + * + * NOTE : This include file is automatically created by a combination + * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead + * and then remake this file. + */ +#ifndef __nis_3_h +#define __nis_3_h +#ifdef __cplusplus +extern "C" { +#endif + +#define NIS_PROG ((u_long)100300) +extern struct rpcgen_table nis_prog_3_table[]; +extern int nis_prog_3_nproc; +#define NIS_VERSION ((u_long)3) + +#ifdef __cplusplus +#define NIS_LOOKUP ((u_long)1) +extern "C" nis_result * nis_lookup_3(ns_request *, CLIENT *); +extern "C" nis_result * nis_lookup_3_svc(ns_request *, struct svc_req *); +#define NIS_ADD ((u_long)2) +extern "C" nis_result * nis_add_3(ns_request *, CLIENT *); +extern "C" nis_result * nis_add_3_svc(ns_request *, struct svc_req *); +#define NIS_MODIFY ((u_long)3) +extern "C" nis_result * nis_modify_3(ns_request *, CLIENT *); +extern "C" nis_result * nis_modify_3_svc(ns_request *, struct svc_req *); +#define NIS_REMOVE ((u_long)4) +extern "C" nis_result * nis_remove_3(ns_request *, CLIENT *); +extern "C" nis_result * nis_remove_3_svc(ns_request *, struct svc_req *); +#define NIS_IBLIST ((u_long)5) +extern "C" nis_result * nis_iblist_3(ib_request *, CLIENT *); +extern "C" nis_result * nis_iblist_3_svc(ib_request *, struct svc_req *); +#define NIS_IBADD ((u_long)6) +extern "C" nis_result * nis_ibadd_3(ib_request *, CLIENT *); +extern "C" nis_result * nis_ibadd_3_svc(ib_request *, struct svc_req *); +#define NIS_IBMODIFY ((u_long)7) +extern "C" nis_result * nis_ibmodify_3(ib_request *, CLIENT *); +extern "C" nis_result * nis_ibmodify_3_svc(ib_request *, struct svc_req *); +#define NIS_IBREMOVE ((u_long)8) +extern "C" nis_result * nis_ibremove_3(ib_request *, CLIENT *); +extern "C" nis_result * nis_ibremove_3_svc(ib_request *, struct svc_req *); +#define NIS_IBFIRST ((u_long)9) +extern "C" nis_result * nis_ibfirst_3(ib_request *, CLIENT *); +extern "C" nis_result * nis_ibfirst_3_svc(ib_request *, struct svc_req *); +#define NIS_IBNEXT ((u_long)10) +extern "C" nis_result * nis_ibnext_3(ib_request *, CLIENT *); +extern "C" nis_result * nis_ibnext_3_svc(ib_request *, struct svc_req *); +#define NIS_FINDDIRECTORY ((u_long)12) +extern "C" fd_result * nis_finddirectory_3(fd_args *, CLIENT *); +extern "C" fd_result * nis_finddirectory_3_svc(fd_args *, struct svc_req *); +#define NIS_STATUS ((u_long)14) +extern "C" nis_taglist * nis_status_3(nis_taglist *, CLIENT *); +extern "C" nis_taglist * nis_status_3_svc(nis_taglist *, struct svc_req *); +#define NIS_DUMPLOG ((u_long)15) +extern "C" log_result * nis_dumplog_3(dump_args *, CLIENT *); +extern "C" log_result * nis_dumplog_3_svc(dump_args *, struct svc_req *); +#define NIS_DUMP ((u_long)16) +extern "C" log_result * nis_dump_3(dump_args *, CLIENT *); +extern "C" log_result * nis_dump_3_svc(dump_args *, struct svc_req *); +#define NIS_CALLBACK ((u_long)17) +extern "C" bool_t * nis_callback_3(netobj *, CLIENT *); +extern "C" bool_t * nis_callback_3_svc(netobj *, struct svc_req *); +#define NIS_CPTIME ((u_long)18) +extern "C" u_long * nis_cptime_3(nis_name *, CLIENT *); +extern "C" u_long * nis_cptime_3_svc(nis_name *, struct svc_req *); +#define NIS_CHECKPOINT ((u_long)19) +extern "C" cp_result * nis_checkpoint_3(nis_name *, CLIENT *); +extern "C" cp_result * nis_checkpoint_3_svc(nis_name *, struct svc_req *); +#define NIS_PING ((u_long)20) +extern "C" void * nis_ping_3(ping_args *, CLIENT *); +extern "C" void * nis_ping_3_svc(ping_args *, struct svc_req *); +#define NIS_SERVSTATE ((u_long)21) +extern "C" nis_taglist * nis_servstate_3(nis_taglist *, CLIENT *); +extern "C" nis_taglist * nis_servstate_3_svc(nis_taglist *, struct svc_req *); +#define NIS_MKDIR ((u_long)22) +extern "C" nis_error * nis_mkdir_3(nis_name *, CLIENT *); +extern "C" nis_error * nis_mkdir_3_svc(nis_name *, struct svc_req *); +#define NIS_RMDIR ((u_long)23) +extern "C" nis_error * nis_rmdir_3(nis_name *, CLIENT *); +extern "C" nis_error * nis_rmdir_3_svc(nis_name *, struct svc_req *); +#define NIS_UPDKEYS ((u_long)24) +extern "C" nis_error * nis_updkeys_3(nis_name *, CLIENT *); +extern "C" nis_error * nis_updkeys_3_svc(nis_name *, struct svc_req *); + +#elif __STDC__ +#define NIS_LOOKUP ((u_long)1) +extern nis_result * nis_lookup_3(ns_request *, CLIENT *); +extern nis_result * nis_lookup_3_svc(ns_request *, struct svc_req *); +#define NIS_ADD ((u_long)2) +extern nis_result * nis_add_3(ns_request *, CLIENT *); +extern nis_result * nis_add_3_svc(ns_request *, struct svc_req *); +#define NIS_MODIFY ((u_long)3) +extern nis_result * nis_modify_3(ns_request *, CLIENT *); +extern nis_result * nis_modify_3_svc(ns_request *, struct svc_req *); +#define NIS_REMOVE ((u_long)4) +extern nis_result * nis_remove_3(ns_request *, CLIENT *); +extern nis_result * nis_remove_3_svc(ns_request *, struct svc_req *); +#define NIS_IBLIST ((u_long)5) +extern nis_result * nis_iblist_3(ib_request *, CLIENT *); +extern nis_result * nis_iblist_3_svc(ib_request *, struct svc_req *); +#define NIS_IBADD ((u_long)6) +extern nis_result * nis_ibadd_3(ib_request *, CLIENT *); +extern nis_result * nis_ibadd_3_svc(ib_request *, struct svc_req *); +#define NIS_IBMODIFY ((u_long)7) +extern nis_result * nis_ibmodify_3(ib_request *, CLIENT *); +extern nis_result * nis_ibmodify_3_svc(ib_request *, struct svc_req *); +#define NIS_IBREMOVE ((u_long)8) +extern nis_result * nis_ibremove_3(ib_request *, CLIENT *); +extern nis_result * nis_ibremove_3_svc(ib_request *, struct svc_req *); +#define NIS_IBFIRST ((u_long)9) +extern nis_result * nis_ibfirst_3(ib_request *, CLIENT *); +extern nis_result * nis_ibfirst_3_svc(ib_request *, struct svc_req *); +#define NIS_IBNEXT ((u_long)10) +extern nis_result * nis_ibnext_3(ib_request *, CLIENT *); +extern nis_result * nis_ibnext_3_svc(ib_request *, struct svc_req *); +#define NIS_FINDDIRECTORY ((u_long)12) +extern fd_result * nis_finddirectory_3(fd_args *, CLIENT *); +extern fd_result * nis_finddirectory_3_svc(fd_args *, struct svc_req *); +#define NIS_STATUS ((u_long)14) +extern nis_taglist * nis_status_3(nis_taglist *, CLIENT *); +extern nis_taglist * nis_status_3_svc(nis_taglist *, struct svc_req *); +#define NIS_DUMPLOG ((u_long)15) +extern log_result * nis_dumplog_3(dump_args *, CLIENT *); +extern log_result * nis_dumplog_3_svc(dump_args *, struct svc_req *); +#define NIS_DUMP ((u_long)16) +extern log_result * nis_dump_3(dump_args *, CLIENT *); +extern log_result * nis_dump_3_svc(dump_args *, struct svc_req *); +#define NIS_CALLBACK ((u_long)17) +extern bool_t * nis_callback_3(netobj *, CLIENT *); +extern bool_t * nis_callback_3_svc(netobj *, struct svc_req *); +#define NIS_CPTIME ((u_long)18) +extern u_long * nis_cptime_3(nis_name *, CLIENT *); +extern u_long * nis_cptime_3_svc(nis_name *, struct svc_req *); +#define NIS_CHECKPOINT ((u_long)19) +extern cp_result * nis_checkpoint_3(nis_name *, CLIENT *); +extern cp_result * nis_checkpoint_3_svc(nis_name *, struct svc_req *); +#define NIS_PING ((u_long)20) +extern void * nis_ping_3(ping_args *, CLIENT *); +extern void * nis_ping_3_svc(ping_args *, struct svc_req *); +#define NIS_SERVSTATE ((u_long)21) +extern nis_taglist * nis_servstate_3(nis_taglist *, CLIENT *); +extern nis_taglist * nis_servstate_3_svc(nis_taglist *, struct svc_req *); +#define NIS_MKDIR ((u_long)22) +extern nis_error * nis_mkdir_3(nis_name *, CLIENT *); +extern nis_error * nis_mkdir_3_svc(nis_name *, struct svc_req *); +#define NIS_RMDIR ((u_long)23) +extern nis_error * nis_rmdir_3(nis_name *, CLIENT *); +extern nis_error * nis_rmdir_3_svc(nis_name *, struct svc_req *); +#define NIS_UPDKEYS ((u_long)24) +extern nis_error * nis_updkeys_3(nis_name *, CLIENT *); +extern nis_error * nis_updkeys_3_svc(nis_name *, struct svc_req *); + +#else /* Old Style C */ +#define NIS_LOOKUP ((u_long)1) +extern nis_result * nis_lookup_3(); +extern nis_result * nis_lookup_3_svc(); +#define NIS_ADD ((u_long)2) +extern nis_result * nis_add_3(); +extern nis_result * nis_add_3_svc(); +#define NIS_MODIFY ((u_long)3) +extern nis_result * nis_modify_3(); +extern nis_result * nis_modify_3_svc(); +#define NIS_REMOVE ((u_long)4) +extern nis_result * nis_remove_3(); +extern nis_result * nis_remove_3_svc(); +#define NIS_IBLIST ((u_long)5) +extern nis_result * nis_iblist_3(); +extern nis_result * nis_iblist_3_svc(); +#define NIS_IBADD ((u_long)6) +extern nis_result * nis_ibadd_3(); +extern nis_result * nis_ibadd_3_svc(); +#define NIS_IBMODIFY ((u_long)7) +extern nis_result * nis_ibmodify_3(); +extern nis_result * nis_ibmodify_3_svc(); +#define NIS_IBREMOVE ((u_long)8) +extern nis_result * nis_ibremove_3(); +extern nis_result * nis_ibremove_3_svc(); +#define NIS_IBFIRST ((u_long)9) +extern nis_result * nis_ibfirst_3(); +extern nis_result * nis_ibfirst_3_svc(); +#define NIS_IBNEXT ((u_long)10) +extern nis_result * nis_ibnext_3(); +extern nis_result * nis_ibnext_3_svc(); +#define NIS_FINDDIRECTORY ((u_long)12) +extern fd_result * nis_finddirectory_3(); +extern fd_result * nis_finddirectory_3_svc(); +#define NIS_STATUS ((u_long)14) +extern nis_taglist * nis_status_3(); +extern nis_taglist * nis_status_3_svc(); +#define NIS_DUMPLOG ((u_long)15) +extern log_result * nis_dumplog_3(); +extern log_result * nis_dumplog_3_svc(); +#define NIS_DUMP ((u_long)16) +extern log_result * nis_dump_3(); +extern log_result * nis_dump_3_svc(); +#define NIS_CALLBACK ((u_long)17) +extern bool_t * nis_callback_3(); +extern bool_t * nis_callback_3_svc(); +#define NIS_CPTIME ((u_long)18) +extern u_long * nis_cptime_3(); +extern u_long * nis_cptime_3_svc(); +#define NIS_CHECKPOINT ((u_long)19) +extern cp_result * nis_checkpoint_3(); +extern cp_result * nis_checkpoint_3_svc(); +#define NIS_PING ((u_long)20) +extern void * nis_ping_3(); +extern void * nis_ping_3_svc(); +#define NIS_SERVSTATE ((u_long)21) +extern nis_taglist * nis_servstate_3(); +extern nis_taglist * nis_servstate_3_svc(); +#define NIS_MKDIR ((u_long)22) +extern nis_error * nis_mkdir_3(); +extern nis_error * nis_mkdir_3_svc(); +#define NIS_RMDIR ((u_long)23) +extern nis_error * nis_rmdir_3(); +extern nis_error * nis_rmdir_3_svc(); +#define NIS_UPDKEYS ((u_long)24) +extern nis_error * nis_updkeys_3(); +extern nis_error * nis_updkeys_3_svc(); +#endif /* Old Style C */ +struct rpcgen_table { + char *(*proc)(); + xdrproc_t xdr_arg; + unsigned len_arg; + xdrproc_t xdr_res; + unsigned len_res; +}; + +#endif /* !_NIS_H_RPCGEN */ diff --git a/nis/rpcsvc/nis.x b/nis/rpcsvc/nis.x new file mode 100644 index 0000000000..625ed57f10 --- /dev/null +++ b/nis/rpcsvc/nis.x @@ -0,0 +1,446 @@ +%/* +% * 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 or with the express written consent of +% * Sun Microsystems, Inc. +% * +% * 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 +% */ + +/* + * From 4.1 : @(#)nis.x 1.61 Copyright 1989 Sun Microsystems + * + * RPC Language Protocol description file for NIS Plus + * This version : 1.61 + * Last Modified : 3/19/91 + */ +#ifdef RPC_HDR +%/* +% * nis.h +% * +% * This file is the main include file for NIS clients. It contains +% * both the client library function defines and the various data +% * structures used by the NIS service. It includes the file nis_tags.h +% * which defines the tag values. This allows the tags to change without +% * having to change the nis.x file. +% * +% * NOTE : DO NOT EDIT THIS FILE! It is automatically generated when +% * rpcgen is run on the nis.x file. Note that there is a +% * simple sed script to remove some unneeded lines. (See the +% * Makefile target nis.h) +% * +% */ +%#include <rpcsvc/nis_tags.h> +#endif + +/* This gets stuffed into the source files. */ +#if RPC_HDR +%#include <rpc/xdr.h> +#endif +#if RPC_SVC +%#include "nis_svc.h" +#endif + +/* Include the RPC Language description of NIS objects */ +#include "nis_object.x" + +/* Errors that can be returned by the service */ +enum nis_error { + NIS_SUCCESS = 0, /* A-ok, let's rock n roll */ + NIS_S_SUCCESS = 1, /* Name found (maybe) */ + NIS_NOTFOUND = 2, /* Name definitely not found */ + NIS_S_NOTFOUND = 3, /* Name maybe not found */ + NIS_CACHEEXPIRED = 4, /* Name exists but cache out of date */ + NIS_NAMEUNREACHABLE = 5, /* Can't get there from here */ + NIS_UNKNOWNOBJ = 6, /* Object type is bogus */ + NIS_TRYAGAIN = 7, /* I'm busy, call back */ + NIS_SYSTEMERROR = 8, /* Out of band failure */ + NIS_CHAINBROKEN = 9, /* First/Next warning */ + NIS_PERMISSION = 10, /* Not enough permission to access */ + NIS_NOTOWNER = 11, /* You don't own it, sorry */ + NIS_NOT_ME = 12, /* I don't serve this name */ + NIS_NOMEMORY = 13, /* Outta VM! Help! */ + NIS_NAMEEXISTS = 14, /* Can't create over another name */ + NIS_NOTMASTER = 15, /* I'm justa secondaray, don't ask me */ + NIS_INVALIDOBJ = 16, /* Object is broken somehow */ + NIS_BADNAME = 17, /* Unparsable name */ + NIS_NOCALLBACK = 18, /* Couldn't talk to call back proc */ + NIS_CBRESULTS = 19, /* Results being called back to you */ + NIS_NOSUCHNAME = 20, /* Name unknown */ + NIS_NOTUNIQUE = 21, /* Value is not uniques (entry) */ + NIS_IBMODERROR = 22, /* Inf. Base. Modify error. */ + NIS_NOSUCHTABLE = 23, /* Name for table was wrong */ + NIS_TYPEMISMATCH = 24, /* Entry and table type mismatch */ + NIS_LINKNAMEERROR = 25, /* Link points to bogus name */ + NIS_PARTIAL = 26, /* Partial success, found table */ + NIS_TOOMANYATTRS = 27, /* Too many attributes */ + NIS_RPCERROR = 28, /* RPC error encountered */ + NIS_BADATTRIBUTE = 29, /* Bad or invalid attribute */ + NIS_NOTSEARCHABLE = 30, /* Non-searchable object searched */ + NIS_CBERROR = 31, /* Error during callback (svc crash) */ + NIS_FOREIGNNS = 32, /* Foreign Namespace */ + NIS_BADOBJECT = 33, /* Malformed object structure */ + NIS_NOTSAMEOBJ = 34, /* Object swapped during deletion */ + NIS_MODFAIL = 35, /* Failure during a Modify. */ + NIS_BADREQUEST = 36, /* Illegal query for table */ + NIS_NOTEMPTY = 37, /* Attempt to remove a non-empty tbl */ + NIS_COLDSTART_ERR = 38, /* Error accesing the cold start file */ + NIS_RESYNC = 39, /* Transaction log too far out of date */ + NIS_FAIL = 40, /* NIS operation failed. */ + NIS_UNAVAIL = 41, /* NIS+ service is unavailable (client) */ + NIS_RES2BIG = 42, /* NIS+ result too big for datagram */ + NIS_SRVAUTH = 43, /* NIS+ server wasn't authenticated. */ + NIS_CLNTAUTH = 44, /* NIS+ Client wasn't authenticated. */ + NIS_NOFILESPACE = 45, /* NIS+ server ran out of disk space */ + NIS_NOPROC = 46, /* NIS+ server couldn't create new proc */ + NIS_DUMPLATER = 47 /* NIS+ server already has dump child */ +}; + + +/* + * Structure definitions for the parameters and results of the actual + * NIS RPC calls. + * + * This is the standard result (in the protocol) of most of the nis + * requests. + */ + +struct nis_result { + nis_error status; /* Status of the response */ + nis_object objects<>; /* objects found */ + netobj cookie; /* Cookie Data */ + u_long zticks; /* server ticks */ + u_long dticks; /* DBM ticks. */ + u_long aticks; /* Cache (accel) ticks */ + u_long cticks; /* Client ticks */ +}; + +/* + * A Name Service request + * This request is used to access the name space, ns_name is the name + * of the object within the namespace and the object is it's value, for + * add/modify, a copy of the original for remove. + */ + +struct ns_request { + nis_name ns_name; /* Name in the NIS name space */ + nis_object ns_object<1>; /* Optional Object (add/remove) */ +}; + +/* + * An information base request + * This request includes the NIS name of the table we wish to search, the + * search criteria in the form of attribute/value pairs and an optional + * callback program number. If the callback program number is provided + * the server will send back objects one at a time, otherwise it will + * return them all in the response. + */ + +struct ib_request { + nis_name ibr_name; /* The name of the Table */ + nis_attr ibr_srch<>; /* The search critereia */ + u_long ibr_flags; /* Optional flags */ + nis_object ibr_obj<1>; /* optional object (add/modify) */ + nis_server ibr_cbhost<1>; /* Optional callback info */ + u_long ibr_bufsize; /* Optional first/next bufsize */ + netobj ibr_cookie; /* The first/next cookie */ +}; + +/* + * This argument to the PING call notifies the replicas that something in + * a directory has changed and this is it's timestamp. The replica will use + * the timestamp to determine if its resync operation was successful. + */ +struct ping_args { + nis_name dir; /* Directory that had the change */ + u_long stamp; /* timestamp of the transaction */ +}; + +/* + * These are the type of entries that are stored in the transaction log, + * note that modifications will appear as two entries, for names, they have + * a "OLD" entry followed by a "NEW" entry. For entries in tables, there + * is a remove followed by an add. It is done this way so that we can read + * the log backwards to back out transactions and forwards to propogate + * updated. + */ +enum log_entry_t { + LOG_NOP = 0, + ADD_NAME = 1, /* Name Added to name space */ + REM_NAME = 2, /* Name removed from name space */ + MOD_NAME_OLD = 3, /* Name was modified in the name space */ + MOD_NAME_NEW = 4, /* Name was modified in the name space */ + ADD_IBASE = 5, /* Entry added to information base */ + REM_IBASE = 6, /* Entry removed from information base */ + MOD_IBASE = 7, /* Entry was modified in information base */ + UPD_STAMP = 8 /* Update timestamp (used as fenceposts) */ +}; + +/* + * This result is returned from the name service when it is requested to + * dump logged entries from its transaction log. Information base updates + * will have the name of the information base in the le_name field and + * a canonical set of attribute/value pairs to fully specify the entry's + * 'name'. + */ +struct log_entry { + u_long le_time; /* Time in seconds */ + log_entry_t le_type; /* Type of log entry */ + nis_name le_princp; /* Principal making the change */ + nis_name le_name; /* Name of table/dir involved */ + nis_attr le_attrs<>; /* List of AV pairs. */ + nis_object le_object; /* Actual object value */ +}; + +struct log_result { + nis_error lr_status; /* The status itself */ + netobj lr_cookie; /* Used by the dump callback */ + log_entry lr_entries<>; /* zero or more entries */ +}; + +struct cp_result { + nis_error cp_status; /* Status of the checkpoint */ + u_long cp_zticks; /* Service 'ticks' */ + u_long cp_dticks; /* Database 'ticks' */ +}; + +/* + * This structure defines a generic NIS tag list. The taglist contains + * zero or tags, each of which is a type and a value. (u_long). + * These are used to report statistics (see tag definitions below) + * and to set or reset state variables. + */ +struct nis_tag { + u_long tag_type; /* Statistic tag (may vary) */ + string tag_val<1024>; /* Statistic value may also vary */ +}; + +struct nis_taglist { + nis_tag tags<>; /* List of tags */ +}; + +struct dump_args { + nis_name da_dir; /* Directory to dump */ + u_long da_time; /* From this timestamp */ + nis_server da_cbhost<1>; /* Callback to use. */ +}; + +struct fd_args { + nis_name dir_name; /* The directory we're looking for */ + nis_name requester; /* Host principal name for signature */ +}; + +struct fd_result { + nis_error status; /* Status returned by function */ + nis_name source; /* Source of this answer */ + opaque dir_data<>; /* Directory Data (XDR'ed) */ + opaque signature<>; /* Signature of the source */ +}; + + +/* + * What's going on here? Well, it's like this. When the service + * is being compiled it wants to have the service definition specific + * info included, and when the client is being compiled it wants that + * info. This includes the appropriate file which was generated by + * make in the protocols directory (probably /usr/include/rpcsvc). + */ +#ifdef RPC_SVC +%#include "nis_svc.h" +#endif +#ifdef RPC_CLNT +%#include "nis_clnt.h" +#endif + +program NIS_PROG { + + /* RPC Language description of the NIS+ protocol */ + version NIS_VERSION { + /* The name service functions */ + nis_result NIS_LOOKUP(ns_request) = 1; + nis_result NIS_ADD(ns_request) = 2; + nis_result NIS_MODIFY(ns_request) = 3; + nis_result NIS_REMOVE(ns_request) = 4; + + /* The information base functions */ + nis_result NIS_IBLIST(ib_request) = 5; + nis_result NIS_IBADD(ib_request) = 6; + nis_result NIS_IBMODIFY(ib_request) = 7; + nis_result NIS_IBREMOVE(ib_request) = 8; + nis_result NIS_IBFIRST(ib_request) = 9; + nis_result NIS_IBNEXT(ib_request) = 10; + + /* NIS Administrative functions */ + fd_result NIS_FINDDIRECTORY(fd_args) = 12; + + /* If fetch and optionally reset statistics */ + nis_taglist NIS_STATUS(nis_taglist) = 14; + + /* Dump changes to directory since time in da_time */ + log_result NIS_DUMPLOG(dump_args) = 15; + + /* Dump contents of directory named */ + log_result NIS_DUMP(dump_args) = 16; + + /* Check status of callback thread */ + bool NIS_CALLBACK(netobj) = 17; + + /* Return last update time for named dir */ + u_long NIS_CPTIME(nis_name) = 18; + + /* Checkpoint directory or table named */ + cp_result NIS_CHECKPOINT(nis_name) = 19; + + /* Send 'status changed' ping to replicates */ + void NIS_PING(ping_args) = 20; + + /* Modify server behaviour (such as debugging) */ + nis_taglist NIS_SERVSTATE(nis_taglist) = 21; + + /* Create a Directory */ + nis_error NIS_MKDIR(nis_name) = 22; + + /* Remove a Directory */ + nis_error NIS_RMDIR(nis_name) = 23; + + /* Update public keys of a directory object */ + nis_error NIS_UPDKEYS(nis_name) = 24; + } = 3; +} = 100300; + +/* + * Included below are the defines that become part of nis.h, + * they are technically not part of the protocol, but do define + * key aspects of the implementation and are therefore useful + * in building a conforming server or client. + */ +#if RPC_HDR +%/* +% * Generic "hash" datastructures, used by all types of hashed data. +% */ +%struct nis_hash_data { +% nis_name name; /* NIS name of hashed item */ +% int keychain; /* It's hash key (for pop) */ +% struct nis_hash_data *next; /* Hash collision pointer */ +% struct nis_hash_data *prv_item; /* A serial, doubly linked list */ +% struct nis_hash_data *nxt_item; /* of items in the hash table */ +%}; +%typedef struct nis_hash_data NIS_HASH_ITEM; +% +%struct nis_hash_table { +% NIS_HASH_ITEM *keys[64]; /* A hash table of items */ +% NIS_HASH_ITEM *first; /* The first "item" in serial list */ +%}; +%typedef struct nis_hash_table NIS_HASH_TABLE; +% +%/* Structure for storing dynamically allocated static data */ +%struct nis_sdata { +% void *buf; /* Memory allocation pointer */ +% u_long size; /* Buffer size */ +%}; +% +%/* Generic client creating flags */ +%#define ZMH_VC 1 +%#define ZMH_DG 2 +%#define ZMH_AUTH 4 +% +%/* Testing Access rights for objects */ +% +%#define NIS_READ_ACC 1 +%#define NIS_MODIFY_ACC 2 +%#define NIS_CREATE_ACC 4 +%#define NIS_DESTROY_ACC 8 +%/* Test macros. a == access rights, m == desired rights. */ +%#define WORLD(a, m) (((a) & (m)) != 0) +%#define GROUP(a, m) (((a) & ((m) << 8)) != 0) +%#define OWNER(a, m) (((a) & ((m) << 16)) != 0) +%#define NOBODY(a, m) (((a) & ((m) << 24)) != 0) +% +%#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype) +%#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights) +%#define WORLD_DEFAULT (NIS_READ_ACC) +%#define GROUP_DEFAULT (NIS_READ_ACC << 8) +%#define OWNER_DEFAULT ((NIS_READ_ACC +\ + NIS_MODIFY_ACC +\ + NIS_CREATE_ACC +\ + NIS_DESTROY_ACC) << 16) +%#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT) +% +%/* Result manipulation defines ... */ +%#define NIS_RES_NUMOBJ(x) ((x)->objects.objects_len) +%#define NIS_RES_OBJECT(x) ((x)->objects.objects_val) +%#define NIS_RES_COOKIE(x) ((x)->cookie) +%#define NIS_RES_STATUS(x) ((x)->status) +% +%/* These defines make getting at the variant part of the object easier. */ +%#define TA_data zo_data.objdata_u.ta_data +%#define EN_data zo_data.objdata_u.en_data +%#define DI_data zo_data.objdata_u.di_data +%#define LI_data zo_data.objdata_u.li_data +%#define GR_data zo_data.objdata_u.gr_data +% +%#define __type_of(o) ((o)->zo_data.zo_type) +% +%/* Declarations for the internal subroutines in nislib.c */ +%enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME}; +%typedef enum name_pos name_pos; +% +%/* +% * Defines for getting at column data in entry objects. Because RPCGEN +% * generates some rather wordy structures, we create some defines that +% * collapse the needed keystrokes to access a particular value using +% * these definitions they take an nis_object *, and an int and return +% * a u_char * for Value, and an int for length. +% */ +%#define ENTRY_VAL(obj, col) \ +% (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val +%#define ENTRY_LEN(obj, col) \ +% (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len +% +%#ifdef __cplusplus +%} +%#endif +% +%/* Prototypes, and extern declarations for the NIS library functions. */ +%#include <rpcsvc/nislib.h> +%#endif /* __NIS_RPCGEN_H */ +%/* EDIT_START */ +% +%/* +% * nis_3.h +% * +% * This file contains definitions that are only of interest to the actual +% * service daemon and client stubs. Normal users of NIS will not include +% * this file. +% * +% * NOTE : This include file is automatically created by a combination +% * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead +% * and then remake this file. +% */ +%#ifndef __nis_3_h +%#define __nis_3_h +%#ifdef __cplusplus +%extern "C" { +%#endif +#endif diff --git a/nis/rpcsvc/nis_object.x b/nis/rpcsvc/nis_object.x new file mode 100644 index 0000000000..e13ae47b70 --- /dev/null +++ b/nis/rpcsvc/nis_object.x @@ -0,0 +1,287 @@ +/* + * nis_object.x + * + * Copyright (c) 1988-1992 Sun Microsystems Inc + * All Rights Reserved. + */ + +%#pragma ident "@(#)nis_object.x 1.7 92/07/14 SMI" + +#if RPC_HDR +% +%#ifndef __nis_object_h +%#define __nis_object_h +% +#endif +/* + * This file defines the format for a NIS object in RPC language. + * It is included by the main .x file and the database access protocol + * file. It is common because both of them need to deal with the same + * type of object. Generating the actual code though is a bit messy because + * the nis.x file and the nis_dba.x file will generate xdr routines to + * encode/decode objects when only one set is needed. Such is life when + * one is using rpcgen. + * + * Note, the protocol doesn't specify any limits on such things as + * maximum name length, number of attributes, etc. These are enforced + * by the database backend. When you hit them you will no. Also see + * the db_getlimits() function for fetching the limit values. + * + */ + +/* Some manifest constants, chosen to maximize flexibility without + * plugging the wire full of data. + */ +const NIS_MAXSTRINGLEN = 255; +const NIS_MAXNAMELEN = 1024; +const NIS_MAXATTRNAME = 32; +const NIS_MAXATTRVAL = 2048; +const NIS_MAXCOLUMNS = 64; +const NIS_MAXATTR = 16; +const NIS_MAXPATH = 1024; +const NIS_MAXREPLICAS = 128; +const NIS_MAXLINKS = 16; + +const NIS_PK_NONE = 0; /* no public key (unix/sys auth) */ +const NIS_PK_DH = 1; /* Public key is Diffie-Hellman type */ +const NIS_PK_RSA = 2; /* Public key if RSA type */ +const NIS_PK_KERB = 3; /* Use kerberos style authentication */ + +/* + * The fundamental name type of NIS. The name may consist of two parts, + * the first being the fully qualified name, and the second being an + * optional set of attribute/value pairs. + */ +struct nis_attr { + string zattr_ndx<>; /* name of the index */ + opaque zattr_val<>; /* Value for the attribute. */ +}; + +typedef string nis_name<>; /* The NIS name itself. */ + +/* NIS object types are defined by the following enumeration. The numbers + * they use are based on the following scheme : + * 0 - 1023 are reserved for Sun, + * 1024 - 2047 are defined to be private to a particular tree. + * 2048 - 4095 are defined to be user defined. + * 4096 - ... are reserved for future use. + */ + +enum zotypes { + BOGUS_OBJ = 0, /* Uninitialized object structure */ + NO_OBJ = 1, /* NULL object (no data) */ + DIRECTORY_OBJ = 2, /* Directory object describing domain */ + GROUP_OBJ = 3, /* Group object (a list of names) */ + TABLE_OBJ = 4, /* Table object (a database schema) */ + ENTRY_OBJ = 5, /* Entry object (a database record) */ + LINK_OBJ = 6, /* A name link. */ + PRIVATE_OBJ = 7 /* Private object (all opaque data) */ +}; + +/* + * The types of Name services NIS knows about. They are enumerated + * here. The Binder code will use this type to determine if it has + * a set of library routines that will access the indicated name service. + */ +enum nstype { + UNKNOWN = 0, + NIS = 1, /* Nis Plus Service */ + SUNYP = 2, /* Old NIS Service */ + IVY = 3, /* Nis Plus Plus Service */ + DNS = 4, /* Domain Name Service */ + X500 = 5, /* ISO/CCCIT X.500 Service */ + DNANS = 6, /* Digital DECNet Name Service */ + XCHS = 7, /* Xerox ClearingHouse Service */ + CDS= 8 +}; + +/* + * DIRECTORY - The name service object. These objects identify other name + * servers that are serving some portion of the name space. Each has a + * type associated with it. The resolver library will note whether or not + * is has the needed routines to access that type of service. + * The oarmask structure defines an access rights mask on a per object + * type basis for the name spaces. The only bits currently used are + * create and destroy. By enabling or disabling these access rights for + * a specific object type for a one of the accessor entities (owner, + * group, world) the administrator can control what types of objects + * may be freely added to the name space and which require the + * administrator's approval. + */ +struct oar_mask { + u_long oa_rights; /* Access rights mask */ + zotypes oa_otype; /* Object type */ +}; + +struct endpoint { + string uaddr<>; + string family<>; /* Transport family (INET, OSI, etc) */ + string proto<>; /* Protocol (TCP, UDP, CLNP, etc) */ +}; + +/* + * Note: pkey is a netobj which is limited to 1024 bytes which limits the + * keysize to 8192 bits. This is consider to be a reasonable limit for + * the expected lifetime of this service. + */ +struct nis_server { + nis_name name; /* Principal name of the server */ + endpoint ep<>; /* Universal addr(s) for server */ + u_long key_type; /* Public key type */ + netobj pkey; /* server's public key */ +}; + +struct directory_obj { + nis_name do_name; /* Name of the directory being served */ + nstype do_type; /* one of NIS, DNS, IVY, YP, or X.500 */ + nis_server do_servers<>; /* <0> == Primary name server */ + u_long do_ttl; /* Time To Live (for caches) */ + oar_mask do_armask<>; /* Create/Destroy rights by object type */ +}; + +/* + * ENTRY - This is one row of data from an information base. + * The type value is used by the client library to convert the entry to + * it's internal structure representation. The Table name is a back pointer + * to the table where the entry is stored. This allows the client library + * to determine where to send a request if the client wishes to change this + * entry but got to it through a LINK rather than directly. + * If the entry is a "standalone" entry then this field is void. + */ +const EN_BINARY = 1; /* Indicates value is binary data */ +const EN_CRYPT = 2; /* Indicates the value is encrypted */ +const EN_XDR = 4; /* Indicates the value is XDR encoded */ +const EN_MODIFIED = 8; /* Indicates entry is modified. */ +const EN_ASN1 = 64; /* Means contents use ASN.1 encoding */ + +struct entry_col { + u_long ec_flags; /* Flags for this value */ + opaque ec_value<>; /* It's textual value */ +}; + +struct entry_obj { + string en_type<>; /* Type of entry such as "passwd" */ + entry_col en_cols<>; /* Value for the entry */ +}; + +/* + * GROUP - The group object contains a list of NIS principal names. Groups + * are used to authorize principals. Each object has a set of access rights + * for members of its group. Principal names in groups are in the form + * name.directory and recursive groups are expressed as @groupname.directory + */ +struct group_obj { + u_long gr_flags; /* Flags controlling group */ + nis_name gr_members<>; /* List of names in group */ +}; + +/* + * LINK - This is the LINK object. It is quite similar to a symbolic link + * in the UNIX filesystem. The attributes in the main object structure are + * relative to the LINK data and not what it points to (like the file system) + * "modify" privleges here indicate the right to modify what the link points + * at and not to modify that actual object pointed to by the link. + */ +struct link_obj { + zotypes li_rtype; /* Real type of the object */ + nis_attr li_attrs<>; /* Attribute/Values for tables */ + nis_name li_name; /* The object's real NIS name */ +}; + +/* + * TABLE - This is the table object. It implements a simple + * data base that applications and use for configuration or + * administration purposes. The role of the table is to group together + * a set of related entries. Tables are the simple database component + * of NIS. Like many databases, tables are logically divided into columns + * and rows. The columns are labeled with indexes and each ENTRY makes + * up a row. Rows may be addressed within the table by selecting one + * or more indexes, and values for those indexes. Each row which has + * a value for the given index that matches the desired value is returned. + * Within the definition of each column there is a flags variable, this + * variable contains flags which determine whether or not the column is + * searchable, contains binary data, and access rights for the entry objects + * column value. + */ + +const TA_BINARY = 1; /* Means table data is binary */ +const TA_CRYPT = 2; /* Means value should be encrypted */ +const TA_XDR = 4; /* Means value is XDR encoded */ +const TA_SEARCHABLE = 8; /* Means this column is searchable */ +const TA_CASE = 16; /* Means this column is Case Sensitive */ +const TA_MODIFIED = 32; /* Means this columns attrs are modified*/ +const TA_ASN1 = 64; /* Means contents use ASN.1 encoding */ + +struct table_col { + string tc_name<64>; /* Column Name */ + u_long tc_flags; /* control flags */ + u_long tc_rights; /* Access rights mask */ +}; + +struct table_obj { + string ta_type<64>; /* Table type such as "passwd" */ + int ta_maxcol; /* Total number of columns */ + u_char ta_sep; /* Separator character */ + table_col ta_cols<>; /* The number of table indexes */ + string ta_path<>; /* A search path for this table */ +}; + +/* + * This union joins together all of the currently known objects. + */ +union objdata switch (zotypes zo_type) { + case DIRECTORY_OBJ : + struct directory_obj di_data; + case GROUP_OBJ : + struct group_obj gr_data; + case TABLE_OBJ : + struct table_obj ta_data; + case ENTRY_OBJ: + struct entry_obj en_data; + case LINK_OBJ : + struct link_obj li_data; + case PRIVATE_OBJ : + opaque po_data<>; + case NO_OBJ : + void; + case BOGUS_OBJ : + void; + default : + void; +}; + +/* + * This is the basic NIS object data type. It consists of a generic part + * which all objects contain, and a specialized part which varies depending + * on the type of the object. All of the specialized sections have been + * described above. You might have wondered why they all start with an + * integer size, followed by the useful data. The answer is, when the + * server doesn't recognize the type returned it treats it as opaque data. + * And the definition for opaque data is {int size; char *data;}. In this + * way, servers and utility routines that do not understand a given type + * may still pass it around. One has to be careful in setting + * this variable accurately, it must take into account such things as + * XDR padding of structures etc. The best way to set it is to note one's + * position in the XDR encoding stream, encode the structure, look at the + * new position and calculate the size. + */ +struct nis_oid { + u_long ctime; /* Time of objects creation */ + u_long mtime; /* Time of objects modification */ +}; + +struct nis_object { + nis_oid zo_oid; /* object identity verifier. */ + nis_name zo_name; /* The NIS name for this object */ + nis_name zo_owner; /* NIS name of object owner. */ + nis_name zo_group; /* NIS name of access group. */ + nis_name zo_domain; /* The administrator for the object */ + u_long zo_access; /* Access rights (owner, group, world) */ + u_long zo_ttl; /* Object's time to live in seconds. */ + objdata zo_data; /* Data structure for this type */ +}; +#if RPC_HDR +% +%#endif /* if __nis_object_h */ +% +#endif diff --git a/nis/rpcsvc/nis_tags.h b/nis/rpcsvc/nis_tags.h new file mode 100644 index 0000000000..30bdff6d1a --- /dev/null +++ b/nis/rpcsvc/nis_tags.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1991, Sun Microsystems Inc. + */ + +/* + * nis_tags.h + * + * This file contains the tags and statistics definitions. It is + * automatically included by nis.h + */ + +#ifndef _RPCSVC_NIS_TAGS_H +#define _RPCSVC_NIS_TAGS_H + +#pragma ident "@(#)nis_tags.h 1.13 95/02/17 SMI" +/* from file: zns_tags.h 1.7 Copyright (c) 1990 Sun Microsystems */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NIS_DIR "data" + +/* Lookup and List function flags */ +#define FOLLOW_LINKS (1<<0) /* Follow link objects */ +#define FOLLOW_PATH (1<<1) /* Follow the path in a table */ +#define HARD_LOOKUP (1<<2) /* Block until successful */ +#define ALL_RESULTS (1<<3) /* Retrieve all results */ +#define NO_CACHE (1<<4) /* Do not return 'cached' results */ +#define MASTER_ONLY (1<<5) /* Get value only from master server */ +#define EXPAND_NAME (1<<6) /* Expand partitially qualified names */ + +/* Semantic modification for table operations flags */ +#define RETURN_RESULT (1<<7) /* Return resulting object to client */ +#define ADD_OVERWRITE (1<<8) /* Allow overwrites on ADD */ +#define REM_MULTIPLE (1<<9) /* Allow wildcard deletes */ +#define MOD_SAMEOBJ (1<<10) /* Check modified object before write */ +#define ADD_RESERVED (1<<11) /* Spare ADD semantic */ +#define REM_RESERVED (1<<12) /* Spare REM semantic */ +#define MOD_EXCLUSIVE (1<<13) /* Modify no overwrite on modified keys */ + +/* Transport specific modifications to the operation */ +#define USE_DGRAM (1<<16) /* Use a datagram transport */ +#define NO_AUTHINFO (1<<17) /* Don't bother attaching auth info */ + +/* + * Declarations for "standard" NIS+ tags + * State variable tags have values 0 - 2047 + * Statistic tags have values 2048 - 65535 + * User Tags have values >2^16 + */ +#define TAG_DEBUG 1 /* set debug level */ +#define TAG_STATS 2 /* Enable/disable statistics */ +#define TAG_GCACHE 3 /* Flush the Group Cache */ +#define TAG_GCACHE_ALL TAG_GCACHE +#define TAG_DCACHE 4 /* Flush the directory cache */ +#define TAG_DCACHE_ONE TAG_DCACHE +#define TAG_OCACHE 5 /* Flush the Object Cache */ +#define TAG_SECURE 6 /* Set the security level */ +#define TAG_TCACHE_ONE 7 /* Flush the table cache */ +#define TAG_DCACHE_ALL 8 /* Flush entire directory cache */ +#define TAG_TCACHE_ALL 9 /* Flush entire table cache */ +#define TAG_GCACHE_ONE 10 /* Flush one group object */ +#define TAG_DCACHE_ONE_REFRESH 11 /* Flush and refresh one DO */ + +#define TAG_OPSTATS 2048 /* NIS+ operations statistics */ +#define TAG_THREADS 2049 /* Child process/thread status */ +#define TAG_HEAP 2050 /* Heap usage statistics */ +#define TAG_UPDATES 2051 /* Updates to this service */ +#define TAG_VISIBLE 2052 /* First update that isn't replicated */ +#define TAG_S_DCACHE 2053 /* Directory cache statistics */ +#define TAG_S_OCACHE 2054 /* Object cache statistics */ +#define TAG_S_GCACHE 2055 /* Group cache statistics */ +#define TAG_S_STORAGE 2056 /* Group cache statistics */ +#define TAG_UPTIME 2057 /* Time that server has been up */ +#define TAG_DIRLIST 2058 /* Dir served by this server */ +#define TAG_NISCOMPAT 2059 /* Whether supports NIS compat mode */ +#define TAG_DNSFORWARDING 2060 /* Whether DNS forwarding supported */ +#define TAG_SECURITY_LEVEL 2061 /* Security level of the server */ +#define TAG_ROOTSERVER 2062 /* Whether root server */ + +/* + * Declarations for the Group object flags. Currently + * there are only 3. + */ +#define IMPMEM_GROUPS 1 /* Implicit Membership allowed */ +#define RECURS_GROUPS 2 /* Recursive Groups allowed */ +#define NEGMEM_GROUPS 4 /* Negative Groups allowed */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RPCSVC_NIS_TAGS_H */ diff --git a/nis/rpcsvc/nislib.h b/nis/rpcsvc/nislib.h new file mode 100644 index 0000000000..2ad38ef9c8 --- /dev/null +++ b/nis/rpcsvc/nislib.h @@ -0,0 +1,165 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef __RPCSVC_NISLIB_H__ +#define __RPCSVC_NISLIB_H__ + +#include <features.h> + +__BEGIN_DECLS + +/* +** nis_names +*/ +extern nis_result *nis_lookup __P ((__const nis_name, const u_long)); +extern nis_result *nis_add __P ((__const nis_name, const nis_object *)); +extern nis_result *nis_remove __P ((__const nis_name, const nis_object *)); +extern nis_result *nis_modify __P ((__const nis_name, const nis_object *)); +/* +** nis_table +*/ +extern nis_result *nis_list __P ((__const nis_name, const u_long, + int (*)(__const nis_name, + __const nis_object *, + __const void *), __const void *)); +extern nis_result *nis_add_entry __P ((__const nis_name, __const nis_object *, + __const u_long)); +extern nis_result *nis_modify_entry __P ((__const nis_name, + __const nis_object *, + __const u_long)); +extern nis_result *nis_remove_entry __P ((__const nis_name, + __const nis_object *, + __const u_long)); +extern nis_result *nis_first_entry __P ((__const nis_name)); +extern nis_result *nis_next_entry __P ((__const nis_name, __const netobj *)); +/* +** nis_server +*/ +extern nis_error nis_mkdir __P ((__const nis_name, __const nis_server *)); +extern nis_error nis_rmdir __P ((__const nis_name, __const nis_server *)); +extern nis_error nis_servstate __P ((__const nis_server *, __const nis_tag *, + __const int, nis_tag **)); +extern nis_error nis_stats __P ((__const nis_server *, __const nis_tag *, + __const int, nis_tag **)); +extern void nis_freetags __P ((nis_tag *, __const int)); +extern nis_server **nis_getservlist __P ((__const nis_name)); +extern void nis_freeservlist __P ((nis_server **)); +/* +** nis_subr +*/ +extern nis_name nis_leaf_of __P ((__const nis_name)); +extern nis_name nis_leaf_of_r __P ((__const nis_name, char *, size_t)); +extern nis_name nis_name_of __P ((__const nis_name)); +extern nis_name nis_name_of_r __P ((__const nis_name, char *, size_t)); +extern nis_name nis_domain_of __P ((__const nis_name)); +extern nis_name nis_domain_of_r __P ((__const nis_name, char *, size_t)); +extern nis_name *nis_getnames __P ((__const nis_name)); +extern void nis_freenames __P ((nis_name *)); +extern name_pos nis_dir_cmp __P ((nis_name, nis_name)); +extern nis_object *nis_clone_object __P ((__const nis_object *, nis_object *)); +extern void nis_destroy_object __P ((nis_object *)); +extern void nis_print_object __P ((__const nis_object *)); +/* +** nis_local_names +*/ +extern nis_name nis_local_group __P ((void)); +extern nis_name nis_local_directory __P ((void)); +extern nis_name nis_local_principal __P ((void)); +extern nis_name nis_local_host __P ((void)); +/* +** nis_error +*/ +extern const char *nis_sperrno __P ((__const nis_error)); +extern void nis_perror __P ((__const nis_error, __const char *)); +extern void nis_lerror __P ((__const nis_error, __const char *)); +extern char *nis_sperror __P ((__const nis_error, __const char *)); +extern char *nis_sperror_r __P ((__const nis_error, __const char *, + char *, size_t)); +/* +** nis_groups +*/ +extern bool_t nis_ismember __P ((__const nis_name, __const nis_name)); +extern nis_error nis_addmember __P ((__const nis_name, __const nis_name)); +extern nis_error nis_removemember __P ((__const nis_name, __const nis_name)); +extern nis_error nis_creategroup __P ((__const nis_name, __const u_long)); +extern nis_error nis_destroygroup __P ((__const nis_name)); +extern void nis_print_group_entry __P ((__const nis_name)); +extern nis_error nis_verifygroup __P ((__const nis_name)); +/* +** nis_ping +*/ +extern void nis_ping __P ((__const nis_name, __const u_long, + __const nis_object *)); +extern nis_result *nis_checkpoint __P ((__const nis_name)); + +/* +** nis_print (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) +*/ +extern void nis_print_result __P ((__const nis_result *)); +extern void nis_print_rights __P ((__const u_long)); +extern void nis_print_directory __P ((__const directory_obj *)); +extern void nis_print_group __P ((__const group_obj *)); +extern void nis_print_table __P ((__const table_obj *)); +extern void nis_print_link __P ((__const link_obj *)); +extern void nis_print_entry __P ((__const entry_obj *)); +/* +** nis_file (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) +*/ +extern directory_obj *readColdStartFile __P ((void)); +extern bool_t writeColdStartFile __P ((__const directory_obj *)); +extern nis_object *nis_read_obj __P ((__const char *)); +extern bool_t nis_write_obj __P ((__const char *, __const nis_object *)); +/* +** nis_clone - (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) +*/ + +extern directory_obj *nis_clone_directory __P ((__const directory_obj *, + directory_obj *)); +extern group_obj *nis_clone_group __P ((__const group_obj *, group_obj *)); +extern table_obj *nis_clone_table __P ((__const table_obj *, table_obj *)); +extern entry_obj *nis_clone_entry __P ((__const entry_obj *, entry_obj *)); +extern link_obj *nis_clone_link __P ((__const link_obj *, link_obj *)); +extern objdata *nis_clone_objdata __P ((__const objdata *, objdata *)); +extern nis_result *nis_clone_result __P ((__const nis_result *, nis_result *)); +/* +** nis_free - nis_freeresult +*/ +extern void nis_freeresult __P ((nis_result *)); +/* (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) */ +extern void nis_free_attr __P ((nis_attr *)); +extern void nis_free_request __P ((ib_request *)); +extern void nis_free_endpoints __P ((endpoint *, int)); +extern void nis_free_servers __P ((nis_server *, int)); +extern void nis_free_directory __P ((directory_obj *)); +extern void nis_free_group __P ((group_obj *)); +extern void nis_free_table __P ((table_obj *)); +extern void nis_free_entry __P ((entry_obj *)); +extern void nis_free_link __P ((link_obj *)); +extern void nis_free_object __P ((nis_object *)); + +/* This is the SUN definition, but I don't know for what we need + the directory_obj parameter */ +/* extern fd_result *nis_finddirectory __P ((directory_obj *, nis_name)); */ +extern fd_result *__nis_finddirectory __P ((nis_name)); +extern int __start_clock(int); +extern u_long __stop_clock(int); + +__END_DECLS + +#endif /* __RPCSVC_NISLIB_H__ */ diff --git a/nss/nss_files/files-service.c b/nss/nss_files/files-service.c index 5fb38e2058..317b4fa9cc 100644 --- a/nss/nss_files/files-service.c +++ b/nss/nss_files/files-service.c @@ -41,8 +41,8 @@ LINE_PARSER DB_LOOKUP (servbyname, 1 + strlen (name), (".%s/%s", name, proto), { - /* Must match both protocol and name. */ - if (strcmp (result->s_proto, proto)) + /* Must match both protocol (if specified) and name. */ + if (proto != NULL && strcmp (result->s_proto, proto)) continue; LOOKUP_NAME (s_name, s_aliases) }, diff --git a/setjmp/tst-setjmp.c b/setjmp/tst-setjmp.c index 53fee89864..6147ae9567 100644 --- a/setjmp/tst-setjmp.c +++ b/setjmp/tst-setjmp.c @@ -52,6 +52,29 @@ main (void) jump (value + 1); } + if (!lose && value == 10) + { + /* Do a second test, this time without `setjmp' being a macro. */ +#undef setjmp + value = setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + } + if (lose || value != 10) puts ("Test FAILED!"); else diff --git a/shlib-versions b/shlib-versions index 3ad220d625..145de21e0f 100644 --- a/shlib-versions +++ b/shlib-versions @@ -56,13 +56,15 @@ alpha-.*-linux.* libnss_dns=1.1 alpha-.*-linux.* libnss_db=1.1 alpha-.*-linux.* libnss_compat=1.1 alpha-.*-linux.* libnss_nis=1.1 +alpha-.*-linux.* libnss_nisplus=1.1 .*-.*-.* libnss_files=1 .*-.*-.* libnss_dns=1 .*-.*-.* libnss_db=1 .*-.*-.* libnss_compat=1 .*-.*-.* libnss_nis=1 +.*-.*-.* libnss_nisplus=1 -# Version for libnsl with YP functions. +# Version for libnsl with YP and NIS+ functions. alpha-.*-linux.* libnsl=1.1 .*-.*-.* libnsl=1 diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c index 6d0c23114c..94dc7472ec 100644 --- a/sysdeps/generic/setenv.c +++ b/sysdeps/generic/setenv.c @@ -132,9 +132,9 @@ setenv (name, value, replace) return -1; } *ep = new; + memcpy (*ep, name, namelen); + (*ep)[namelen] = '='; } - memcpy (*ep, name, namelen); - (*ep)[namelen] = '='; memcpy (&(*ep)[namelen + 1], value, vallen); } diff --git a/sysdeps/i386/setjmp.S b/sysdeps/i386/setjmp.S index 23e2b74401..203c2d16d0 100644 --- a/sysdeps/i386/setjmp.S +++ b/sysdeps/i386/setjmp.S @@ -1,21 +1,21 @@ /* setjmp for i386. -Copyright (C) 1995, 1996 Free Software Foundation, Inc. -This file is part of the GNU C Library. + Copyright (C) 1995, 1996, 1997 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 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. + 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., 675 Mass Ave, -Cambridge, MA 02139, USA. */ + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ #include <sysdep.h> #define _ASM @@ -24,7 +24,9 @@ Cambridge, MA 02139, USA. */ /* Binary compatibility entry point. */ ENTRY (__setjmp) popl %eax /* Pop return address. */ + popl %ecx /* Pop jmp_buf. */ pushl $0 /* Push zero argument. */ + pushl %ecx /* Push jmp_buf. */ pushl %eax /* Push back return address. */ ENTRY (__sigsetjmp) diff --git a/sysdeps/libm-i387/e_pow.S b/sysdeps/libm-i387/e_pow.S index efe184168b..ab6b454339 100644 --- a/sysdeps/libm-i387/e_pow.S +++ b/sysdeps/libm-i387/e_pow.S @@ -64,6 +64,13 @@ nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f ENTRY(__ieee754_pow) fldl 12(%esp) // y fxam + +#ifdef PIC + call 1f +1: popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx +#endif + fnstsw movb %ah, %dl andb $0x45, %ah @@ -76,12 +83,6 @@ ENTRY(__ieee754_pow) cmpb $0x01, %ah // is y == NaN ? je 30f -#ifdef PIC - call 1f -1: popl %ecx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx -#endif - fldl 4(%esp) // x : y subl $8,%esp diff --git a/sysdeps/libm-i387/e_powf.S b/sysdeps/libm-i387/e_powf.S index 54af93c961..48316464ef 100644 --- a/sysdeps/libm-i387/e_powf.S +++ b/sysdeps/libm-i387/e_powf.S @@ -64,6 +64,13 @@ nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f ENTRY(__ieee754_powf) flds 8(%esp) // y fxam + +#ifdef PIC + call 1f +1: popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx +#endif + fnstsw movb %ah, %dl andb $0x45, %ah @@ -76,12 +83,6 @@ ENTRY(__ieee754_powf) cmpb $0x01, %ah // is y == NaN ? je 30f -#ifdef PIC - call 1f -1: popl %ecx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx -#endif - flds 4(%esp) // x : y subl $4, %esp diff --git a/sysdeps/libm-i387/e_powl.S b/sysdeps/libm-i387/e_powl.S index 3cfb96b213..dba725aa77 100644 --- a/sysdeps/libm-i387/e_powl.S +++ b/sysdeps/libm-i387/e_powl.S @@ -64,6 +64,13 @@ nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f ENTRY(__ieee754_powl) fldt 16(%esp) // y fxam + +#ifdef PIC + call 1f +1: popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx +#endif + fnstsw movb %ah, %dl andb $0x45, %ah @@ -76,12 +83,6 @@ ENTRY(__ieee754_powl) cmpb $0x01, %ah // is y == NaN ? je 30f -#ifdef PIC - call 1f -1: popl %ecx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx -#endif - fldt 4(%esp) // x : y subl $8,%esp diff --git a/sysdeps/powerpc/__longjmp.S b/sysdeps/powerpc/__longjmp.S index 928b5c540a..da621e22c0 100644 --- a/sysdeps/powerpc/__longjmp.S +++ b/sysdeps/powerpc/__longjmp.S @@ -62,5 +62,6 @@ ENTRY (__longjmp) lfd 30,((JB_FPRS+16*2)*4)(3) lwz 31,((JB_GPRS+17)*4)(3) lfd 31,((JB_FPRS+17*2)*4)(3) + mr 3,4 blr END (__longjmp) diff --git a/sysdeps/powerpc/bsd-_setjmp.S b/sysdeps/powerpc/bsd-_setjmp.S index 90171ea616..a9aefcc977 100644 --- a/sysdeps/powerpc/bsd-_setjmp.S +++ b/sysdeps/powerpc/bsd-_setjmp.S @@ -25,5 +25,9 @@ ENTRY (_setjmp) li 4,0 /* Set second argument to 0. */ - b C_SYMBOL_NAME(__sigsetjmp) +#ifdef PIC + b __sigsetjmp@plt +#else + b __sigsetjmp +#endif END (_setjmp) diff --git a/sysdeps/powerpc/bsd-setjmp.S b/sysdeps/powerpc/bsd-setjmp.S new file mode 100644 index 0000000000..19c2fe308c --- /dev/null +++ b/sysdeps/powerpc/bsd-setjmp.S @@ -0,0 +1,33 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. PowerPC version. + Copyright (C) 1994, 1997 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include <sysdep.h> + +ENTRY (setjmp) + li 4,1 /* Set second argument to 1. */ +#ifdef PIC + b __sigsetjmp@plt +#else + b __sigsetjmp +#endif +END (setjmp) diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h index a60a29723d..541892cdfc 100644 --- a/sysdeps/powerpc/dl-machine.h +++ b/sysdeps/powerpc/dl-machine.h @@ -26,6 +26,14 @@ /* stuff for the PLT */ #define PLT_INITIAL_ENTRY_WORDS 18 #define PLT_LONGBRANCH_ENTRY_WORDS 10 +#define PLT_DOUBLE_SIZE (1<<13) +#define PLT_ENTRY_START_WORDS(entry_number) \ + (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2 + \ + ((entry_number) > PLT_DOUBLE_SIZE ? \ + ((entry_number) - PLT_DOUBLE_SIZE)*2 : \ + 0)) +#define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries) + #define OPCODE_ADDI(rd,ra,simm) \ (0x38000000 | (rd) << 21 | (ra) << 16 | (simm) & 0xffff) #define OPCODE_ADDIS(rd,ra,simm) \ @@ -44,6 +52,19 @@ #define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm) #define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh) +#define PPC_DCBST(where) asm __volatile__ ("dcbst 0,%0" : : "r"(where)) ++#define PPC_SYNC asm __volatile__ ("sync") ++#define PPC_ISYNC asm __volatile__ ("sync; isync") ++#define PPC_ICBI(where) asm __volatile__ ("icbi 0,%0" : : "r"(where)) + +/* Use this when you've modified some code, but it won't be in the + instruction fetch queue (or when it doesn't matter if it is). */ +#define MODIFIED_CODE_NOQUEUE(where) \ + do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0) +/* Use this when it might be in the instruction queue. */ +#define MODIFIED_CODE(where) \ + do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0) + /* Return nonzero iff E_MACHINE is compatible with the running host. */ static inline int @@ -53,7 +74,8 @@ elf_machine_matches_host (Elf32_Half e_machine) } -/* Return the link-time address of _DYNAMIC, the first value in the GOT. */ +/* Return the link-time address of _DYNAMIC, stored as + the first value in the GOT. */ static inline Elf32_Addr elf_machine_dynamic (void) { @@ -79,11 +101,11 @@ elf_machine_load_address (void) get confused. asm ("bcl 20,31,0f ;" - "0: mflr 0 ;" - "lis %0,0b@ha;" - "addi %0,%0,0b@l;" - "subf %0,%0,0" - : "=b" (addr) : : "r0", "lr"); + "0: mflr 0 ;" + "lis %0,0b@ha;" + "addi %0,%0,0b@l;" + "subf %0,%0,0" + : "=b" (addr) : : "r0", "lr"); doesn't work, because the linker doesn't have to (and in fact doesn't) update the @ha and @l references; the loader (which runs after this @@ -134,7 +156,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, if (rinfo == R_PPC_NONE) return; - if (sym && ELF32_ST_TYPE (sym->st_info) == STT_SECTION || + assert (sym != NULL); + if (ELF32_ST_TYPE (sym->st_info) == STT_SECTION || rinfo == R_PPC_RELATIVE) { /* Has already been relocated. */ @@ -143,133 +166,124 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, } else { - assert (sym != NULL); - if (rinfo == R_PPC_JMP_SLOT) - loadbase = (Elf32_Word) (char *) RESOLVE (&sym, - version, DL_LOOKUP_NOPLT); + int flags; + + /* We never want to use a PLT entry as the destination of a + reloc, when what is being relocated is a branch. This is + partly for efficiency, but mostly so we avoid loops. */ + if (rinfo == R_PPC_REL24 || + rinfo == R_PPC_ADDR24 || + rinfo == R_PPC_JMP_SLOT) + flags = DL_LOOKUP_NOPLT; + else if (rinfo == R_PPC_COPY) + flags = DL_LOOKUP_NOEXEC; else - loadbase = (Elf32_Word) (char *) RESOLVE (&sym, version, 0); + flags = 0; + + loadbase = (Elf32_Word) (char *) (RESOLVE (&sym, version, flags)); if (sym == NULL) { /* Weak symbol that wasn't actually defined anywhere. */ - assert (loadbase == 0); + assert(loadbase == 0); finaladdr = reloc->r_addend; } else - finaladdr = (loadbase + (Elf32_Word)(char *)sym->st_value - + reloc->r_addend); + finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value + + reloc->r_addend); } - switch (rinfo) + /* This is an if/else if chain because GCC 2.7.2.[012] turns case + statements into non-PIC table lookups. When a later version + comes out that fixes this, this should be changed. */ + if (rinfo == R_PPC_ADDR16_LO) { - case R_PPC_UADDR16: - case R_PPC_ADDR16_LO: - case R_PPC_ADDR16: *(Elf32_Half*) reloc_addr = finaladdr; - break; - - case R_PPC_ADDR16_HI: + } + else if (rinfo == R_PPC_ADDR16_HI) + { *(Elf32_Half*) reloc_addr = finaladdr >> 16; - break; - - case R_PPC_ADDR16_HA: + } + else if (rinfo == R_PPC_ADDR16_HA) + { *(Elf32_Half*) reloc_addr = finaladdr + 0x8000 >> 16; - break; - - case R_PPC_REL24: - { - Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; - assert (delta << 6 >> 6 == delta); - *reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc; - } - break; - - case R_PPC_UADDR32: - case R_PPC_GLOB_DAT: - case R_PPC_ADDR32: - case R_PPC_RELATIVE: + } + else if (rinfo == R_PPC_REL24) + { + Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; + assert (delta << 6 >> 6 == delta); + *reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc; + } + else if (rinfo == R_PPC_UADDR32 || + rinfo == R_PPC_GLOB_DAT || + rinfo == R_PPC_ADDR32 || + rinfo == R_PPC_RELATIVE) + { *reloc_addr = finaladdr; - break; - - case R_PPC_ADDR24: + } + else if (rinfo == R_PPC_ADDR24) + { + assert (finaladdr << 6 >> 6 == finaladdr); *reloc_addr = *reloc_addr & 0xfc000003 | finaladdr & 0x3fffffc; - break; - - case R_PPC_REL14_BRTAKEN: - case R_PPC_REL14_BRNTAKEN: - case R_PPC_REL14: - { - Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; - *reloc_addr = *reloc_addr & 0xffdf0003 | delta & 0xfffc; - if (rinfo == R_PPC_REL14_BRTAKEN && delta >= 0 || - rinfo == R_PPC_REL14_BRNTAKEN && delta < 0) - *reloc_addr |= 0x00200000; - } - break; - - case R_PPC_COPY: - { - /* Can't use memcpy (because we can't call any functions here). */ - int i; - for (i = 0; i < sym->st_size; ++i) - ((unsigned char *) reloc_addr)[i] = - ((unsigned char *)finaladdr)[i]; - } - break; - - case R_PPC_REL32: + } + else if (rinfo == R_PPC_COPY) + { + /* Memcpy is safe to use here, because ld.so doesn't have any + COPY relocs (it's self-contained). */ + memcpy (reloc_addr, (char *) finaladdr, sym->st_size); + } + else if (rinfo == R_PPC_REL32) + { *reloc_addr = finaladdr - (Elf32_Word) (char *) reloc_addr; - break; - - case R_PPC_JMP_SLOT: - if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) - *reloc_addr = OPCODE_BA (finaladdr); + } + else if (rinfo == R_PPC_JMP_SLOT) + { + Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; + if (delta << 6 >> 6 == delta) + *reloc_addr = OPCODE_B(delta); + else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) + *reloc_addr = OPCODE_BA(finaladdr); else { - Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr; - if (delta <= 0x01fffffc && delta >= 0xfe000000) - *reloc_addr = OPCODE_B (delta); + Elf32_Word *plt = (Elf32_Word *)((char *)map->l_addr + + map->l_info[DT_PLTGOT]->d_un.d_val); + Elf32_Word index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2; + Elf32_Word offset = index * 2 + PLT_INITIAL_ENTRY_WORDS; + + if (index >= PLT_DOUBLE_SIZE) + { + /* Slots greater than or equal to 2^13 have 4 words + available instead of two. */ + plt[offset ] = OPCODE_LI (11,finaladdr); + plt[offset+1] = OPCODE_ADDIS (11,11,finaladdr + 0x8000 >> 16); + plt[offset+2] = OPCODE_MTCTR (11); + plt[offset+3] = OPCODE_BCTR (); + } else { - Elf32_Word *plt = - (Elf32_Word *) ((char *) map->l_addr - + map->l_info[DT_PLTGOT]->d_un.d_val); - Elf32_Word index =((reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS) - / 2); - int num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val - / sizeof (Elf32_Rela)); - int rel_offset_words = (PLT_INITIAL_ENTRY_WORDS - + num_plt_entries * 2); - - if (index >= (1 << 13)) - { - /* Indexes greater than or equal to 2^13 have 4 - words available instead of two. */ - plt[index * 2 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_LI (11, finaladdr); - plt[index * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16); - plt[index * 2 + 2 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_MTCTR (11); - plt[index * 2 + 2 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_BCTR (); - } - else - { - plt[index * 2 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_LI (11, index * 4); - plt[index * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_B(-(4 * (index * 2 + 1 + PLT_INITIAL_ENTRY_WORDS - + PLT_LONGBRANCH_ENTRY_WORDS))); - plt[index + rel_offset_words] = finaladdr; - } + Elf32_Word num_plt_entries; + Elf32_Word rel_offset_words; + + num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val + / sizeof(Elf32_Rela)); + rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries); + + plt[offset ] = OPCODE_LI (11,index * 4); + plt[offset+1] = OPCODE_B (-(4 * (offset + 1 + - PLT_LONGBRANCH_ENTRY_WORDS))); + plt[index + rel_offset_words] = finaladdr; } } - break; - - default: - assert (! "unexpected dynamic reloc type"); + MODIFIED_CODE(reloc_addr); } + else + assert (! "unexpected dynamic reloc type"); + + if (rinfo == R_PPC_ADDR16_LO || + rinfo == R_PPC_ADDR16_HI || + rinfo == R_PPC_ADDR16_HA || + rinfo == R_PPC_REL24 || + rinfo == R_PPC_ADDR24) + MODIFIED_CODE_NOQUEUE (reloc_addr); } #define ELF_MACHINE_NO_REL 1 @@ -282,64 +296,58 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, /* Set up the loaded object described by L so its unrelocated PLT entries will jump to the on-demand fixup code in dl-runtime.c. */ - -/* This code does not presently work if there are more than 2^13 PLT - entries. */ static inline void elf_machine_runtime_setup (struct link_map *map, int lazy) { - Elf32_Word *plt; - int i; - Elf32_Word num_plt_entries; - Elf32_Word rel_offset_words; - extern void _dl_runtime_resolve (void); - if (map->l_info[DT_JMPREL]) { + int i; /* Fill in the PLT. Its initial contents are directed to a function earlier in the PLT which arranges for the dynamic linker to be called back. */ - plt = (Elf32_Word *) ((char *) map->l_addr + - map->l_info[DT_PLTGOT]->d_un.d_val); - num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val - / sizeof (Elf32_Rela)); - rel_offset_words = PLT_INITIAL_ENTRY_WORDS + num_plt_entries * 2; + Elf32_Word *plt = (Elf32_Word *) ((char *) map->l_addr + + map->l_info[DT_PLTGOT]->d_un.d_val); + Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val + / sizeof (Elf32_Rela)); + Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries); + extern void _dl_runtime_resolve (void); + Elf32_Word size_modified; if (lazy) for (i = 0; i < num_plt_entries; i++) - if (i >= (1 << 13)) - { - plt[i * 2 + (i - (1 << 13)) * 2 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_LI (11, i * 4); - plt[i * 2 + (i - (1 << 13)) * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_ADDIS (11, 11, i * 4 + 0x8000 >> 16); - plt[i * 2 + (i - (1 << 13)) * 2 + 2 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_B (-(4 * ( i * 2 + 1 + PLT_INITIAL_ENTRY_WORDS))); - } - else - { - plt[i * 2 + PLT_INITIAL_ENTRY_WORDS] = OPCODE_LI (11, i * 4); - plt[i * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] = - OPCODE_B (-(4 * (i * 2 + 1 + PLT_INITIAL_ENTRY_WORDS))); - } - - /* Multiply index of entry, by 0xC. */ - plt[0] = OPCODE_SLWI (12, 11, 1); - plt[1] = OPCODE_ADD (11, 12, 11); - if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc || - (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000) { - plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map); - plt[3] = OPCODE_ADDIS (12, 12, - (Elf32_Word) (char *) map + 0x8000 >> 16); - plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve); + Elf32_Word offset = PLT_ENTRY_START_WORDS(i); + + if (i >= PLT_DOUBLE_SIZE) + { + plt[offset ] = OPCODE_LI (11, i * 4); + plt[offset+1] = OPCODE_ADDIS (11, 11, i * 4 + 0x8000 >> 16); + plt[offset+2] = OPCODE_B (-(4 * (offset + 2))); + } + else + { + plt[offset ] = OPCODE_LI (11, i * 4); + plt[offset+1] = OPCODE_B(-(4 * (offset + 1))); + } + + /* Multiply index of entry, by 0xC. */ + plt[0] = OPCODE_SLWI (12, 11, 1); + plt[1] = OPCODE_ADD (11, 12, 11); + if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc + || (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000) + { + plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map); + plt[3] = OPCODE_ADDIS (12, 12, + (Elf32_Word) (char *) map + 0x8000 >> 16); + plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve); + } } else { plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) _dl_runtime_resolve); - plt[3] = OPCODE_ADDIS (12, 12, 0x8000 + - ((Elf32_Word) (char *) _dl_runtime_resolve - >> 16)); + plt[3] = OPCODE_ADDIS(12, 12, 0x8000 + + ((Elf32_Word) (char *) _dl_runtime_resolve + >> 16)); plt[4] = OPCODE_MTCTR (12); plt[5] = OPCODE_LI (12, (Elf32_Word) (char *) map); plt[6] = OPCODE_ADDIS (12, 12, ((Elf32_Word) (char *) map @@ -347,21 +355,28 @@ elf_machine_runtime_setup (struct link_map *map, int lazy) plt[7] = OPCODE_BCTR (); } plt[PLT_LONGBRANCH_ENTRY_WORDS] = - OPCODE_ADDIS (11, 11, ((Elf32_Word) (char*) (plt+rel_offset_words) - + 0x8000 >> 16)); + OPCODE_ADDIS (11, 11, (Elf32_Word) (char*) (plt + rel_offset_words) + + 0x8000 >> 16); plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = - OPCODE_LWZ (11, (Elf32_Word) (char*) (plt + rel_offset_words), 11); + OPCODE_LWZ(11,(Elf32_Word)(char*)(plt+rel_offset_words),11); plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR (11); plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR (); + + size_modified = lazy ? rel_offset_words : PLT_INITIAL_ENTRY_WORDS; + /* Now we need to keep the caches in sync. */ + for (i = 0; i < size_modified; i+=8) + PPC_DCBST (plt + i); + PPC_SYNC; + for (i = 0; i < size_modified; i+=8) + PPC_ICBI (plt + i); + PPC_ISYNC; } } static inline void elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) { - if (ELF32_R_TYPE (reloc->r_info) != R_PPC_JMP_SLOT) - assert (! "unexpected PLT reloc type"); - + assert (ELF32_R_TYPE (reloc->r_info) == R_PPC_JMP_SLOT); /* elf_machine_runtime_setup handles this. */ } @@ -369,17 +384,23 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) #define elf_machine_relplt elf_machine_rela /* This code is used in dl-runtime.c to call the `fixup' function - and then redirect to the address it returns. */ + and then redirect to the address it returns. It is called + from code built in the PLT by elf_machine_runtime_setup. */ #define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ .section \".text\" + .align 2 .globl _dl_runtime_resolve + .type _dl_runtime_resolve,@function _dl_runtime_resolve: + # We need to save the registers used to pass parameters. + # We build a stack frame to put them in. stwu 1,-48(1) mflr 0 stw 3,16(1) stw 4,20(1) stw 0,52(1) stw 5,24(1) + # We also need to save some of the condition register fields. mfcr 0 stw 6,28(1) stw 7,32(1) @@ -387,10 +408,13 @@ _dl_runtime_resolve: stw 9,40(1) stw 10,44(1) stw 0,12(1) + # The code that calls this has put parameters for `fixup' in r12 and r11. mr 3,12 mr 4,11 bl fixup + # 'fixup' returns the address we want to branch to. mtctr 3 + # Put the registers back... lwz 0,52(1) lwz 10,44(1) lwz 9,40(1) @@ -403,37 +427,40 @@ _dl_runtime_resolve: lwz 5,24(1) lwz 4,20(1) lwz 3,16(1) + # ...unwind the stack frame, and jump to the PLT entry we updated. addi 1,1,48 bctr +0: + .size _dl_runtime_resolve,0b-_dl_runtime_resolve + # undo '.section text'. + .previous "); /* Initial entry point code for the dynamic linker. The C function `_dl_start' is the real entry point; - its return value is the user program's entry point. */ - -/* FIXME! We don't make provision for calling _dl_fini, - because Linux/PPC is somewhat broken. */ + its return value is the user program's entry point. */ #define RTLD_START \ asm ("\ .text - .align 2 + .align 2 .globl _start - .type _start,@function + .type _start,@function _start: # We start with the following on the stack, from top: # argc (4 bytes) # arguments for program (terminated by NULL) # environment variables (terminated by NULL) # arguments for the program loader + # FIXME: perhaps this should do the same trick as elf/start.c? # Call _dl_start with one parameter pointing at argc - mr 3,1 + mr 3,1 # (we have to frob the stack pointer a bit to allow room for # _dl_start to save the link register) - li 4,0 - addi 1,1,-16 - stw 4,0(1) - bl _dl_start@local + li 4,0 + addi 1,1,-16 + stw 4,0(1) + bl _dl_start@local # Now, we do our main work of calling initialisation procedures. # The ELF ABI doesn't say anything about parameters for these, @@ -442,10 +469,10 @@ _start: # passed by value!). # put our GOT pointer in r31 - bl _GLOBAL_OFFSET_TABLE_-4@local - mflr 31 + bl _GLOBAL_OFFSET_TABLE_-4@local + mflr 31 # the address of _start in r30 - mr 30,3 + mr 30,3 # &_dl_argc in 29, &_dl_argv in 27, and _dl_default_scope in 28 lwz 28,_dl_default_scope@got(31) lwz 29,_dl_argc@got(31) @@ -499,13 +526,19 @@ _start: mtlr 0 # and also clear _dl_starting_up lwz 26,_dl_starting_up@got(31) - stw 0,0(3) + stw 0,0(26) # go do it! bctr +0: + .size _start,0b-_start + # undo '.section text'. + .previous "); -#define ELF_PREFERRED_ADDRESS_DATA static ElfW(Addr) _dl_preferred_address = 0; -#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \ +#define ELF_PREFERRED_ADDRESS_DATA \ +static ElfW(Addr) _dl_preferred_address = 0; + +#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \ ( { \ ElfW(Addr) prefd; \ if (mapstartpref != 0 && _dl_preferred_address == 0) \ @@ -516,13 +549,14 @@ _start: prefd = 0; \ else \ prefd = _dl_preferred_address = \ - (_dl_preferred_address - maplength - 0x10000) & \ - ~(_dl_pagesize - 1); \ + ((_dl_preferred_address - maplength - 0x10000) \ + & ~(_dl_pagesize - 1)); \ prefd; \ } ) -#define ELF_FIXED_ADDRESS(loader, mapstart) \ + +#define ELF_FIXED_ADDRESS(loader, mapstart) \ ( { \ - if (mapstart != 0 && _dl_preferred_address == 0) \ + if (mapstart != 0 && _dl_preferred_address < mapstart) \ _dl_preferred_address = mapstart; \ } ) diff --git a/sysdeps/powerpc/elf/start.c b/sysdeps/powerpc/elf/start.c index 9b1cf1c026..001d6aa97c 100644 --- a/sysdeps/powerpc/elf/start.c +++ b/sysdeps/powerpc/elf/start.c @@ -26,22 +26,27 @@ /* Just a little assembler stub before gcc gets its hands on our stack pointer... */ asm ("\ - .text + .section \".text\" + .align 2 .globl _start _start: # save the stack pointer, in case we're statically linked under Linux - mr 8,1 + mr 8,1 # set up an initial stack frame, and clear the LR - addi 1,1,-16 - clrrwi 1,1,4 - li 0,0 - stw 0,0(1) - mtlr 0 + addi 1,1,-16 + clrrwi 1,1,4 + li 0,0 + stw 0,0(1) + mtlr 0 # set r13 to point at the 'small data area' - lis 13,_SDA_BASE_@ha - addi 13,13,_SDA_BASE_@l + lis 13,_SDA_BASE_@ha + addi 13,13,_SDA_BASE_@l # and continue below. - b __start1 + b __start1 +0: + .size _start,0b-_start + # undo '.section text'. + .previous "); /* Define a symbol for the first piece of initialized data. */ @@ -53,38 +58,46 @@ weak_alias (__data_start, data_start) void (*_mach_init_routine) (void); void (*_thread_init_routine) (void); -void __libc_init_first (int argc, char **argv, char **envp); -int main (int argc, char **argv, char **envp, void *auxvec); +extern void __libc_init_first (int argc, char **argv, char **envp); +extern int main (int argc, char **argv, char **envp, void *auxvec); #ifdef HAVE_INITFINI -void _init (void); -void _fini (void); +extern void _init (void); +extern void _fini (void); #endif - +#if 0 +/* I'd like to say this, but it causes GCC to strip the whole procedure + from the object file (this is sort of reasonable, because you've told + GCC that the procedure is unused). :-( */ static void __start1(int argc, char **argv, char **envp, - void *auxvec, void (*exitfn) (void), char **arguments) + void *auxvec, void (*exitfn) (void), + char **stack_on_entry) __attribute__ ((unused)); -static void + +static +#endif +void __start1(int argc, char **argv, char **envp, void *auxvec, void (*exitfn) (void), - char **arguments) + char **stack_on_entry) { /* the PPC SVR4 ABI says that the top thing on the stack will be a NULL pointer, so if not we assume that we're being called - as a statically-linked program by Linux. */ - int abi_compliant_startup = *arguments == NULL; - - if (!abi_compliant_startup) - { - argc = *(int *) arguments; - argv = arguments+1; - envp = argv+argc+1; - auxvec = envp; - while (auxvec != NULL) - auxvec++; - auxvec++; - exitfn = NULL; - } + as a statically-linked program by Linux... */ + if (*stack_on_entry != NULL) + { + /* ...in which case, we have argc as the top thing on the + stack, followed by argv (NULL-terminated), envp (likewise), + and the auxilary vector. */ + argc = *(int *) stack_on_entry; + argv = stack_on_entry + 1; + envp = argv + argc + 1; + auxvec = envp; + while (*(char **) auxvec != NULL) + ++auxvec; + ++auxvec; + exitfn = NULL; + } if (exitfn != NULL) atexit (exitfn); diff --git a/sysdeps/powerpc/setjmp.S b/sysdeps/powerpc/setjmp.S index a2c0b8c53d..755ef6504c 100644 --- a/sysdeps/powerpc/setjmp.S +++ b/sysdeps/powerpc/setjmp.S @@ -62,5 +62,9 @@ ENTRY (__sigsetjmp) stfd 30,((JB_FPRS+16*2)*4)(3) stw 31,((JB_GPRS+17)*4)(3) stfd 31,((JB_FPRS+17*2)*4)(3) +#ifdef PIC + b __sigjmp_save@plt +#else b __sigjmp_save +#endif END (__sigsetjmp) diff --git a/sysdeps/unix/bsd/Dist b/sysdeps/unix/bsd/Dist index 9e0e553aa7..ab3c4f491e 100644 --- a/sysdeps/unix/bsd/Dist +++ b/sysdeps/unix/bsd/Dist @@ -1 +1,4 @@ -bsdtty.h +setrgid.c +setruid.c +bsdstat.h +bsdtty.h diff --git a/sysdeps/unix/sysv/Dist b/sysdeps/unix/sysv/Dist index 14343b6b6f..6ad8e0f653 100644 --- a/sysdeps/unix/sysv/Dist +++ b/sysdeps/unix/sysv/Dist @@ -1 +1,2 @@ +direct.h sysv_termio.h diff --git a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist index 7b94300c6a..d4b6bac217 100644 --- a/sysdeps/unix/sysv/linux/Dist +++ b/sysdeps/unix/sysv/linux/Dist @@ -21,6 +21,7 @@ netinet/igmp.h netinet/in_systm.h netinet/ip_fw.h netinet/ip_icmp.h +netinet/tcp.h netinet/udp.h netipx/ipx.h nfs/nfs.h diff --git a/sysdeps/unix/sysv/linux/alpha/fcntlbits.h b/sysdeps/unix/sysv/linux/alpha/fcntlbits.h index faf198393f..6e1c843ccb 100644 --- a/sysdeps/unix/sysv/linux/alpha/fcntlbits.h +++ b/sysdeps/unix/sysv/linux/alpha/fcntlbits.h @@ -27,7 +27,6 @@ #ifdef __USE_GNU #define O_READ O_RDONLY /* Open for reading. */ #define O_WRITE O_WRONLY /* Open for writing. */ -#define O_NORW 0 /* Open without R/W access. */ #endif /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ diff --git a/sysdeps/unix/sysv/linux/fcntlbits.h b/sysdeps/unix/sysv/linux/fcntlbits.h index fdc67ce4eb..f6ba880459 100644 --- a/sysdeps/unix/sysv/linux/fcntlbits.h +++ b/sysdeps/unix/sysv/linux/fcntlbits.h @@ -27,7 +27,6 @@ #ifdef __USE_GNU #define O_READ O_RDONLY /* Open for reading. */ #define O_WRITE O_WRONLY /* Open for writing. */ -#define O_NORW 0 /* Open without R/W access. */ #endif /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ diff --git a/sysdeps/unix/sysv/linux/net/if_ppp.h b/sysdeps/unix/sysv/linux/net/if_ppp.h index 567dccebe3..0f2a979cd6 100644 --- a/sysdeps/unix/sysv/linux/net/if_ppp.h +++ b/sysdeps/unix/sysv/linux/net/if_ppp.h @@ -51,7 +51,7 @@ __BEGIN_DECLS #define PPP_MTU 1500 /* Default MTU (size of Info field) */ #define PPP_MAXMRU 65000 /* Largest MRU we allow */ -#define PPP_VERSION "2.3.0" +#define PPP_VERSION "2.2.0" #define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ #define PROTO_IPX 0x002b /* protocol numbers */ #define PROTO_DNA_RT 0x0027 /* DNA Routing */ diff --git a/sysdeps/unix/sysv/linux/powerpc/clone.S b/sysdeps/unix/sysv/linux/powerpc/clone.S index e5fa16d8c5..0afd0717f4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/clone.S @@ -71,4 +71,8 @@ child: badargs: li 3,-EINVAL error: +#ifdef PIC + b __syscall_error@plt +#else b __syscall_error +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c new file mode 100644 index 0000000000..eb732d6fb1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c @@ -0,0 +1,237 @@ +/* Operating system support for run-time dynamic linker. Linux/PPC version. + Copyright (C) 1995, 1996, 1997 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <elf.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <link.h> +#include <unistd.h> +#include <stdarg.h> +#include <string.h> + + +extern int _dl_argc; +extern char **_dl_argv; +extern char **_environ; +extern size_t _dl_pagesize; +extern void _end; +extern void _start (void); + +int __libc_enable_secure; +int __libc_multiple_libcs; /* Defining this here avoids the inclusion + of init-first. */ + +ElfW(Addr) +_dl_sysdep_start (void **start_argptr, + void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum, + ElfW(Addr) *user_entry)) +{ + const ElfW(Phdr) *phdr = NULL; + ElfW(Word) phnum = 0; + ElfW(Addr) user_entry; + ElfW(auxv_t) *av; + uid_t uid = 0; + uid_t euid = 0; + gid_t gid = 0; + gid_t egid = 0; + unsigned int seen; + + user_entry = (ElfW(Addr)) &_start; + _dl_argc = *(long *) start_argptr; + _dl_argv = (char **) start_argptr + 1; + _environ = &_dl_argv[_dl_argc + 1]; + start_argptr = (void **) _environ; + while (*start_argptr) + ++start_argptr; + ++start_argptr; + + if (*start_argptr == 0 && + ((unsigned)(char *)start_argptr & 0xF) != 0) + { + unsigned test_sap = (int)(char *)start_argptr; + test_sap = test_sap + 0xF & ~0xF; + if (*(long *)(char *)test_sap == AT_PHDR) + start_argptr = (void **)(char *)test_sap; + } + + seen = 0; +#define M(type) (1 << (type)) + + for (av = (void *) start_argptr; + av->a_type != AT_NULL; + seen |= M ((++av)->a_type)) + switch (av->a_type) + { + case AT_PHDR: + phdr = av->a_un.a_ptr; + break; + case AT_PHNUM: + phnum = av->a_un.a_val; + break; + case AT_PAGESZ: + _dl_pagesize = av->a_un.a_val; + break; + case AT_ENTRY: + user_entry = av->a_un.a_val; + break; + case AT_UID: + uid = av->a_un.a_val; + break; + case AT_GID: + gid = av->a_un.a_val; + break; + case AT_EUID: + euid = av->a_un.a_val; + break; + case AT_EGID: + egid = av->a_un.a_val; + break; + } + + /* Linux doesn't provide us with any of these values on the stack + when the dynamic linker is run directly as a program. */ + +#define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid () + SEE (UID, uid); + SEE (GID, gid); + SEE (EUID, euid); + SEE (EGID, egid); + + + __libc_enable_secure = uid != euid || gid != egid; + + __brk (0); /* Initialize the break. */ + + if (__sbrk (0) == &_end) + { + /* The dynamic linker was run as a program, and so the initial break + starts just after our bss, at &_end. The malloc in dl-minimal.c + will consume the rest of this page, so tell the kernel to move the + break up that far. When the user program examines its break, it + will see this new value and not clobber our data. */ + size_t pg = __getpagesize (); + + __sbrk (pg - ((&_end - (void *) 0) & pg)); + __sbrk (pg - ((&_end - (void *) 0) & (pg - 1))); + } + + (*dl_main) (phdr, phnum, &user_entry); + return user_entry; +} + +void +_dl_sysdep_start_cleanup (void) +{ +} + +#ifndef MAP_ANON +/* This is only needed if the system doesn't support MAP_ANON. */ + +int +_dl_sysdep_open_zero_fill (void) +{ + return __open ("/dev/zero", O_RDONLY); +} +#endif + +/* Read the whole contents of FILE into new mmap'd space with given + protections. *SIZEP gets the size of the file. */ + +void * +_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) +{ + void *result; + struct stat st; + int fd = __open (file, O_RDONLY); + if (fd < 0) + return NULL; + if (__fstat (fd, &st) < 0) + result = NULL; + else + { + /* Map a copy of the file contents. */ + result = __mmap (0, st.st_size, prot, +#ifdef MAP_COPY + MAP_COPY +#else + MAP_PRIVATE +#endif +#ifdef MAP_FILE + | MAP_FILE +#endif + , fd, 0); + if (result == (void *) -1) + result = NULL; + else + *sizep = st.st_size; + } + __close (fd); + return result; +} + +void +_dl_sysdep_fatal (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + do + { + size_t len = strlen (msg); + __write (STDERR_FILENO, msg, len); + msg = va_arg (ap, const char *); + } while (msg); + va_end (ap); + + _exit (127); +} + + +void +_dl_sysdep_error (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + do + { + size_t len = strlen (msg); + __write (STDERR_FILENO, msg, len); + msg = va_arg (ap, const char *); + } while (msg); + va_end (ap); +} + + +void +_dl_sysdep_message (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + do + { + size_t len = strlen (msg); + __write (STDOUT_FILENO, msg, len); + msg = va_arg (ap, const char *); + } while (msg); + va_end (ap); +} diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h new file mode 100644 index 0000000000..acf62a42ca --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h @@ -0,0 +1,25 @@ +#ifndef _SYS_KERNEL_TERMIOS_H +#define _SYS_KERNEL_TERMIOS_H 1 +/* The following corresponds to the values from the Linux 2.0.28 kernel. */ + +/* We need the definition of tcflag_t, cc_t, and speed_t. */ +#include <termbits.h> + +#define __KERNEL_NCCS 19 + +struct __kernel_termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + int c_ispeed; /* input speed */ + int c_ospeed; /* output speed */ + }; + +#define _HAVE_C_ISPEED 1 +#define _HAVE_C_OSPEED 1 + +#endif /* sys/kernel_termios.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/socket.S b/sysdeps/unix/sysv/linux/powerpc/socket.S index 32bb8f64cd..12417faac6 100644 --- a/sysdeps/unix/sysv/linux/powerpc/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/socket.S @@ -76,7 +76,11 @@ ENTRY(P(__,socket)) DO_CALL(SYS_ify(socketcall)) addi 1,1,48 bnslr +#ifdef PIC + b __syscall_error@plt +#else b __syscall_error +#endif PSEUDO_END (P(__,socket)) diff --git a/sysdeps/unix/sysv/linux/powerpc/statbuf.h b/sysdeps/unix/sysv/linux/powerpc/statbuf.h new file mode 100644 index 0000000000..5be5736931 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/statbuf.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1992, 1995, 1996, 1997 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _STATBUF_H +#define _STATBUF_H 1 + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + unsigned int st_dev; /* Device. */ + unsigned int st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned short int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group.*/ + unsigned int st_rdev; /* Device number, if device. */ + long int st_size; /* Size of file, in bytes. */ + unsigned long int st_blksize; /* Optimal block size for I/O. */ +#define _STATBUF_ST_BLKSIZE /* Tell code we have this member. */ + + unsigned long int st_blocks; /* Number of 512-byte blocks allocated. */ + unsigned long int st_atime; /* Time of last access. */ + unsigned long int __unused1; + unsigned long int st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + unsigned long int st_ctime; /* Time of last status change. */ + unsigned long int __unused3; + unsigned long int __unused4; + unsigned long int __unused5; + }; + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#endif /* statbuf.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S index 9b3f66682e..441dd5d433 100644 --- a/sysdeps/unix/sysv/linux/powerpc/syscall.S +++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S @@ -28,5 +28,9 @@ ENTRY (syscall) mr 7,8 sc bnslr +#ifdef PIC + b __syscall_error@plt +#else b __syscall_error +#endif PSEUDO_END (syscall) diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h index c08e3d8060..d6d33bf7af 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h @@ -41,13 +41,21 @@ li 0,syscall; \ sc +#ifdef PIC +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); \ + bnslr; \ + b __syscall_error@plt +#else #define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (SYS_ify (syscall_name)); \ - bnslr; \ + bnslr; \ b __syscall_error - +#endif #define ret /* Nothing (should be 'blr', but never reached). */ #endif /* ASSEMBLER */ diff --git a/sysdeps/unix/sysv/linux/powerpc/termbits.h b/sysdeps/unix/sysv/linux/powerpc/termbits.h index d1b0a3e3cb..4c6073bfc2 100644 --- a/sysdeps/unix/sysv/linux/powerpc/termbits.h +++ b/sysdeps/unix/sysv/linux/powerpc/termbits.h @@ -17,9 +17,7 @@ Boston, MA 02111-1307, USA. */ #ifndef _TERMBITS_H -#define _TERMBITS_H - -#include <linux/posix_types.h> +#define _TERMBITS_H 1 typedef unsigned char cc_t; typedef unsigned int speed_t; @@ -31,14 +29,14 @@ typedef unsigned int tcflag_t; * concerning namespace pollution. */ -#define NCCS 19 +#define NCCS 32 struct termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ - cc_t c_cc[NCCS]; /* control characters */ cc_t c_line; /* line discipline (== c_cc[19]) */ + cc_t c_cc[NCCS]; /* control characters */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */ }; @@ -219,80 +217,6 @@ struct ltchars { char t_lnextc; }; -#define FIOCLEX _IO('f', 1) -#define FIONCLEX _IO('f', 2) -#define FIOASYNC _IOW('f', 125, int) -#define FIONBIO _IOW('f', 126, int) -#define FIONREAD _IOR('f', 127, int) -#define TIOCINQ FIONREAD - -#define TIOCGETP _IOR('t', 8, struct sgttyb) -#define TIOCSETP _IOW('t', 9, struct sgttyb) -#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ - -#define TIOCSETC _IOW('t', 17, struct tchars) -#define TIOCGETC _IOR('t', 18, struct tchars) -#define TCGETS _IOR('t', 19, struct termios) -#define TCSETS _IOW('t', 20, struct termios) -#define TCSETSW _IOW('t', 21, struct termios) -#define TCSETSF _IOW('t', 22, struct termios) - -#define TCGETA _IOR('t', 23, struct termio) -#define TCSETA _IOW('t', 24, struct termio) -#define TCSETAW _IOW('t', 25, struct termio) -#define TCSETAF _IOW('t', 28, struct termio) - -#define TCSBRK _IO('t', 29) -#define TCXONC _IO('t', 30) -#define TCFLSH _IO('t', 31) - -#define TIOCSWINSZ _IOW('t', 103, struct winsize) -#define TIOCGWINSZ _IOR('t', 104, struct winsize) -#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ -#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ -#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ - -#define TIOCGLTC _IOR('t', 116, struct ltchars) -#define TIOCSLTC _IOW('t', 117, struct ltchars) -#define TIOCSPGRP _IOW('t', 118, int) -#define TIOCGPGRP _IOR('t', 119, int) - -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E - -#define TIOCSTI 0x5412 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 - -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ - -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 diff --git a/sysdeps/unix/sysv/linux/readv.c b/sysdeps/unix/sysv/linux/readv.c new file mode 100644 index 0000000000..458e8ffb38 --- /dev/null +++ b/sysdeps/unix/sysv/linux/readv.c @@ -0,0 +1,71 @@ +/* readv supports all Linux kernels >= 2.0. + Copyright (C) 1997 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, + read to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/param.h> +#include <sys/uio.h> + +extern ssize_t __syscall_readv __P ((int, __const struct iovec *, int)); + + +/* Not all versions of the kernel support the large number of records. */ +#undef MAX_IOVEC +#ifdef UIO_FASTIOV +# define MAX_IOVEC UIO_FASTIOV +#else +# define MAX_IOVEC 8 /* 8 is a safe number. */ +#endif + + +/* We should deal with kernel which have a smaller UIO_MAXIOV as well + as a very big count. */ +ssize_t +readv (fd, vector, count) + int fd; + const struct iovec *vector; + int count; +{ + int errno_saved = errno; + ssize_t bytes_read; + + bytes_read = __syscall_readv (fd, vector, count); + + if (bytes_read < 0 && errno == EINVAL && count > MAX_IOVEC) + { + int i; + + /* Restore the old error value as if nothing happened. */ + __set_errno (errno_saved); + + bytes_read = 0; + for (i = 0; i < count; i += MAX_IOVEC) + { + ssize_t bytes = __syscall_readv (fd, vector + i, + MIN (count - i, MAX_IOVEC)); + + if (bytes < 0) + return bytes; + + bytes_read += bytes; + } + } + + return bytes_read; +} diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 4e92f6d35c..f8644c2705 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -56,7 +56,12 @@ setresuid EXTRA setresuid 3 setresuid sigpending - sigpending 1 sigpending sigprocmask - sigprocmask 3 __sigprocmask sigprocmask sigreturn - sigreturn 1 __sigreturn sigreturn +sys_fstat fxstat fstat 2 __syscall_fstat sys_mknod xmknod mknod 3 __syscall_mknod +sys_lstat lxstat lstat 2 __syscall_lstat +sys_readv readv readv 3 __syscall_readv +sys_stat xstat stat 2 __syscall_stat +sys_writev writev writev 3 __syscall_writev sysinfo EXTRA sysinfo 1 sysinfo swapon - swapon 2 swapon umount EXTRA umount 1 __umount umount diff --git a/sysdeps/unix/sysv/linux/writev.c b/sysdeps/unix/sysv/linux/writev.c new file mode 100644 index 0000000000..11afd81d2e --- /dev/null +++ b/sysdeps/unix/sysv/linux/writev.c @@ -0,0 +1,68 @@ +/* writev supports all Linux kernels >= 2.0. + Copyright (C) 1997 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/param.h> +#include <sys/uio.h> + +extern ssize_t __syscall_writev __P ((int, const struct iovec *, int)); + +/* Not all versions of the kernel support the large number of records. */ +#undef MAX_IOVEC +#ifdef UIO_FASTIOV +# define MAX_IOVEC UIO_FASTIOV +#else +# define MAX_IOVEC 8 /* 8 is a safe number. */ +#endif + + +/* We should deal with kernel which have a smaller UIO_MAXIOV as well + as a very big count. */ +ssize_t +writev (fd, vector, count) + int fd; + const struct iovec *vector; + int count; +{ + int errno_saved = errno; + ssize_t bytes_written; + + bytes_written = __syscall_writev (fd, vector, count); + + if (bytes_written < 0 && errno == EINVAL && count > MAX_IOVEC) + { + int i; + + /* Restore the old error value as if nothing happened. */ + __set_errno (errno_saved); + + bytes_written = 0; + for (i = 0; i < count; i += MAX_IOVEC) + { + ssize_t bytes = __syscall_writev (fd, vector + i, + MIN (count - i, MAX_IOVEC)); + + if (bytes < 0) + return bytes_written > 0 ? bytes_written : bytes; + } + } + + return bytes_written; +} diff --git a/sysdeps/unix/sysv/sco3.2.4/Dist b/sysdeps/unix/sysv/sco3.2.4/Dist new file mode 100644 index 0000000000..984b473349 --- /dev/null +++ b/sysdeps/unix/sysv/sco3.2.4/Dist @@ -0,0 +1 @@ +__setpgid.c diff --git a/sysdeps/unix/sysv/sysv4/Dist b/sysdeps/unix/sysv/sysv4/Dist index da3d7e58e1..6395064504 100644 --- a/sysdeps/unix/sysv/sysv4/Dist +++ b/sysdeps/unix/sysv/sysv4/Dist @@ -1,2 +1,4 @@ +__getpgid.c +__setpgid.c sysconfig.h siginfo.h diff --git a/time/offtime.c b/time/offtime.c index 1469029bc0..f13c8a38ae 100644 --- a/time/offtime.c +++ b/time/offtime.c @@ -64,7 +64,7 @@ __offtime (t, offset, tp) while (days < 0 || days >= (__isleap (y) ? 366 : 365)) { /* Guess a corrected year, assuming 365 days per year. */ - int yg = y + days / 365 - (days % 365 < 0); + long int yg = y + days / 365 - (days % 365 < 0); /* Adjust DAYS and Y to match the guessed year. */ days -= ((yg - y) * 365 |