mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
update from main archive 960814
This commit is contained in:
parent
046e3001f9
commit
706074a5bb
13
MakeTAGS
13
MakeTAGS
@ -132,8 +132,8 @@ endif
|
|||||||
|
|
||||||
define extract
|
define extract
|
||||||
@rm -f $@.new
|
@rm -f $@.new
|
||||||
$(XGETTEXT) --keyword=_ --keyword=N_ --add-comments=TRANS --sort-output -d - \
|
$(XGETTEXT) --keyword=_ --keyword=N_ --add-comments=TRANS --sort-output \
|
||||||
$(XGETTEXTFLAGS-$(@F)) > $@.new $^
|
--omit-header -n -d - $(XGETTEXTFLAGS-$(@F)) > $@.new $^
|
||||||
mv -f $@.new $@
|
mv -f $@.new $@
|
||||||
endef
|
endef
|
||||||
|
|
||||||
@ -146,15 +146,12 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
$P/siglist.pot: $(common-objpfx)siglist.c; $(extract)
|
$P/siglist.pot: $(common-objpfx)siglist.c; $(extract)
|
||||||
$P/errlist.pot: $(..)sysdeps/gnu/errlist.c; $(extract)
|
|
||||||
|
|
||||||
# Extract all strings from these files; their strings are not marked.
|
# Extract all strings from this file; its strings are not marked.
|
||||||
# Their surroundings are also not interesting.
|
# Their surroundings are also not interesting.
|
||||||
XGETTEXTFLAGS-siglist.pot = -a --no-location
|
XGETTEXTFLAGS-siglist.pot = -a --no-location
|
||||||
XGETTEXTFLAGS-errlist.pot = -a --no-location
|
|
||||||
|
|
||||||
all-pot = $P/libc-top.pot $P/subdirs.pot \
|
all-pot = $P/libc-top.pot $P/subdirs.pot $P/siglist.pot
|
||||||
$P/siglist.pot $P/errlist.pot
|
|
||||||
|
|
||||||
ifndef subdir
|
ifndef subdir
|
||||||
# Collect all the subdir messages, massaging the file names in comments
|
# Collect all the subdir messages, massaging the file names in comments
|
||||||
@ -173,7 +170,7 @@ $P/SYS_libc.pot: $(all-pot)
|
|||||||
@rm -f $@.new
|
@rm -f $@.new
|
||||||
sed -e 's/VERSION/$(version)/' -e "s/DATE/`date +'%Y-%m-%d %k:%M'`/" \
|
sed -e 's/VERSION/$(version)/' -e "s/DATE/`date +'%Y-%m-%d %k:%M'`/" \
|
||||||
po/header.pot > $@.new
|
po/header.pot > $@.new
|
||||||
$(XGETTEXT) -d - -n -s --omit-header $^ >> $@.new
|
$(XGETTEXT) -d - --omit-header -n -s $^ >> $@.new
|
||||||
mv -f $@.new $@
|
mv -f $@.new $@
|
||||||
test ! -d CVS || cvs ci -m'Regenerated from source files' $@
|
test ! -d CVS || cvs ci -m'Regenerated from source files' $@
|
||||||
|
|
||||||
|
@ -454,9 +454,10 @@ endef
|
|||||||
object-suffixes-left := $(object-suffixes)
|
object-suffixes-left := $(object-suffixes)
|
||||||
include $(o-iterator)
|
include $(o-iterator)
|
||||||
define do-ar
|
define do-ar
|
||||||
|
topdir=`cd $(..).; pwd`; \
|
||||||
$(patsubst %,cd %;,$(objdir)) \
|
$(patsubst %,cd %;,$(objdir)) \
|
||||||
$(AUTOLOCK) ${O%-lib}.lck $(AR) cru$(verbose) ${O%-lib} \
|
$$topdir/autolock.sh ${O%-lib}.lck $(AR) cru$(verbose) ${O%-lib} \
|
||||||
$(patsubst $(objpfx)%,%,$^)
|
$(patsubst $(objpfx)%,%,$^)
|
||||||
rm -f $@
|
rm -f $@
|
||||||
touch $@
|
touch $@
|
||||||
endef
|
endef
|
||||||
@ -474,7 +475,9 @@ define o-iterator-doit
|
|||||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)($(ar-symtab-name)): \
|
$(common-objpfx)$(patsubst %,$(libtype$o),c)($(ar-symtab-name)): \
|
||||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)(\
|
$(common-objpfx)$(patsubst %,$(libtype$o),c)(\
|
||||||
$(patsubst $(objpfx)%,%,$(o-objects))) $(subdirs-stamp-o); \
|
$(patsubst $(objpfx)%,%,$(o-objects))) $(subdirs-stamp-o); \
|
||||||
$(AUTOLOCK) $$(common-objpfx)$$(patsubst %,$$(libtype$o),c).lck \
|
topdir=`cd $(..).; pwd`; \
|
||||||
|
$$$$topdir/autolock.sh \
|
||||||
|
$$(common-objpfx)$$(patsubst %,$$(libtype$o),c).lck \
|
||||||
$$(RANLIB) $$(common-objpfx)$$(patsubst %,$$(libtype$o),c)
|
$$(RANLIB) $$(common-objpfx)$$(patsubst %,$$(libtype$o),c)
|
||||||
endef
|
endef
|
||||||
ifndef subdir
|
ifndef subdir
|
||||||
|
@ -34,7 +34,6 @@ CC = @CC@
|
|||||||
BUILD_CC = @BUILD_CC@
|
BUILD_CC = @BUILD_CC@
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
AR = @AR@
|
AR = @AR@
|
||||||
AUTOLOCK = @AUTOLOCK@
|
|
||||||
RANLIB = @RANLIB@
|
RANLIB = @RANLIB@
|
||||||
AS = $(CC) -c
|
AS = $(CC) -c
|
||||||
|
|
||||||
|
@ -308,8 +308,6 @@ fi
|
|||||||
AC_PROG_CPP
|
AC_PROG_CPP
|
||||||
AC_CHECK_TOOL(AR, ar)
|
AC_CHECK_TOOL(AR, ar)
|
||||||
AC_CHECK_TOOL(RANLIB, ranlib, :)
|
AC_CHECK_TOOL(RANLIB, ranlib, :)
|
||||||
AUTOLOCK="`(cd $srcdir; pwd)`/autolock.sh"
|
|
||||||
AC_SUBST(AUTOLOCK)
|
|
||||||
|
|
||||||
AC_CACHE_CHECK(for signed size_t type, libc_cv_signed_size_t, [dnl
|
AC_CACHE_CHECK(for signed size_t type, libc_cv_signed_size_t, [dnl
|
||||||
echo '#include <stddef.h>
|
echo '#include <stddef.h>
|
||||||
|
@ -70,11 +70,25 @@ int _dl_zerofd = -1;
|
|||||||
size_t _dl_pagesize;
|
size_t _dl_pagesize;
|
||||||
|
|
||||||
|
|
||||||
|
/* Local version of `strdup' function. */
|
||||||
|
static inline char *
|
||||||
|
local_strdup (const char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen (s) + 1;
|
||||||
|
void *new = malloc (len);
|
||||||
|
|
||||||
|
if (new == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (char *) memcpy (new, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||||
opened on FD. */
|
opened on FD. */
|
||||||
|
|
||||||
struct link_map *
|
struct link_map *
|
||||||
_dl_map_object_from_fd (const char *name, int fd, char *realname,
|
_dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||||
struct link_map *loader, int l_type)
|
struct link_map *loader, int l_type)
|
||||||
{
|
{
|
||||||
struct link_map *l = NULL;
|
struct link_map *l = NULL;
|
||||||
@ -96,6 +110,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
|
|||||||
l->l_next->l_prev = l->l_prev;
|
l->l_next->l_prev = l->l_prev;
|
||||||
free (l);
|
free (l);
|
||||||
}
|
}
|
||||||
|
free (name);
|
||||||
free (realname);
|
free (realname);
|
||||||
_dl_signal_error (code, name, msg);
|
_dl_signal_error (code, name, msg);
|
||||||
}
|
}
|
||||||
@ -142,6 +157,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
|
|||||||
/* The object is already loaded.
|
/* The object is already loaded.
|
||||||
Just bump its reference count and return it. */
|
Just bump its reference count and return it. */
|
||||||
__close (fd);
|
__close (fd);
|
||||||
|
free (name);
|
||||||
free (realname);
|
free (realname);
|
||||||
++l->l_opencount;
|
++l->l_opencount;
|
||||||
return l;
|
return l;
|
||||||
@ -524,11 +540,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type)
|
|||||||
fd = __open (cached, O_RDONLY);
|
fd = __open (cached, O_RDONLY);
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
{
|
{
|
||||||
size_t cl = strlen (cached) + 1;
|
realname = local_strdup (cached);
|
||||||
realname = malloc (cl);
|
if (realname == NULL)
|
||||||
if (realname)
|
|
||||||
memcpy (realname, cached, cl);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
__close (fd);
|
__close (fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
@ -548,11 +561,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type)
|
|||||||
fd = __open (name, O_RDONLY);
|
fd = __open (name, O_RDONLY);
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
{
|
{
|
||||||
size_t len = strlen (name) + 1;
|
realname = local_strdup (name);
|
||||||
realname = malloc (len);
|
if (realname == NULL)
|
||||||
if (realname)
|
|
||||||
memcpy (realname, name, len);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
__close (fd);
|
__close (fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
@ -560,6 +570,16 @@ _dl_map_object (struct link_map *loader, const char *name, int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
name = local_strdup (name);
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
__close (fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
_dl_signal_error (errno, name, "cannot open shared object file");
|
_dl_signal_error (errno, name, "cannot open shared object file");
|
||||||
|
|
||||||
|
@ -45,16 +45,16 @@ _dl_elf_hash (const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||||
UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero,
|
UNDEF_NAME. FLAGS is a set of flags. If DL_LOOKUP_NOEXEC is set,
|
||||||
then a PLT entry cannot satisfy the reference; some different binding
|
then don't search the executable for a definition; this used for
|
||||||
must be found. */
|
copy relocs. If DL_LOOKUP_NOPLT is set, then a PLT entry cannot
|
||||||
|
satisfy the reference; some different binding must be found. */
|
||||||
|
|
||||||
ElfW(Addr)
|
ElfW(Addr)
|
||||||
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
struct link_map *symbol_scope[],
|
struct link_map *symbol_scope[],
|
||||||
const char *reference_name,
|
const char *reference_name,
|
||||||
ElfW(Addr) reloc_addr,
|
int flags)
|
||||||
int noplt)
|
|
||||||
{
|
{
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct
|
struct
|
||||||
@ -75,6 +75,10 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
|||||||
|
|
||||||
map = (*scope)->l_searchlist[i];
|
map = (*scope)->l_searchlist[i];
|
||||||
|
|
||||||
|
/* Don't search the executable when resolving a copy reloc. */
|
||||||
|
if (flags & DL_LOOKUP_NOEXEC && map->l_type == lt_executable)
|
||||||
|
continue;
|
||||||
|
|
||||||
symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||||
strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
|
strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||||
|
|
||||||
@ -87,9 +91,8 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
|||||||
const ElfW(Sym) *sym = &symtab[symidx];
|
const ElfW(Sym) *sym = &symtab[symidx];
|
||||||
|
|
||||||
if (sym->st_value == 0 || /* No value. */
|
if (sym->st_value == 0 || /* No value. */
|
||||||
/* Cannot resolve to the location being filled in. */
|
((flags & DL_LOOKUP_NOPLT) != 0 /* Reject PLT entry. */
|
||||||
reloc_addr == map->l_addr + sym->st_value ||
|
&& sym->st_shndx == SHN_UNDEF))
|
||||||
(noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (ELFW(ST_TYPE) (sym->st_info))
|
switch (ELFW(ST_TYPE) (sym->st_info))
|
||||||
|
@ -57,9 +57,9 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
|
|||||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||||
|
|
||||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||||
#define RESOLVE(ref, reloc_addr, noplt) \
|
#define RESOLVE(ref, flags) \
|
||||||
(_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
|
(_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
|
||||||
l->l_name, reloc_addr, noplt))
|
l->l_name, flags))
|
||||||
|
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
ELF_DYNAMIC_RELOCATE (l, lazy);
|
ELF_DYNAMIC_RELOCATE (l, lazy);
|
||||||
|
@ -122,9 +122,9 @@ fixup (
|
|||||||
|
|
||||||
{
|
{
|
||||||
/* This macro is used as a callback from the elf_machine_relplt code. */
|
/* This macro is used as a callback from the elf_machine_relplt code. */
|
||||||
#define RESOLVE(ref, reloc_addr, noplt) \
|
#define RESOLVE(ref, flags) \
|
||||||
(_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
|
(_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
|
||||||
l->l_name, reloc_addr, noplt))
|
l->l_name, flags))
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
/* Perform the specified relocation. */
|
/* Perform the specified relocation. */
|
||||||
|
@ -28,6 +28,6 @@ _dl_symbol_value (struct link_map *map, const char *name)
|
|||||||
ElfW(Addr) loadbase;
|
ElfW(Addr) loadbase;
|
||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
struct link_map *scope[2] = { map, NULL };
|
struct link_map *scope[2] = { map, NULL };
|
||||||
loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0);
|
loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0);
|
||||||
return loadbase + ref->st_value;
|
return loadbase + ref->st_value;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ dlsym (void *handle, const char *name)
|
|||||||
scope = &(_dl_global_scope ?: _dl_default_scope)[2];
|
scope = &(_dl_global_scope ?: _dl_default_scope)[2];
|
||||||
owner = NULL;
|
owner = NULL;
|
||||||
}
|
}
|
||||||
loadbase = _dl_lookup_symbol (name, &ref, scope, owner, 0, 0);
|
loadbase = _dl_lookup_symbol (name, &ref, scope, owner, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
|
return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
|
||||||
|
14
elf/link.h
14
elf/link.h
@ -224,16 +224,18 @@ extern void _dl_close (struct link_map *map);
|
|||||||
null-terminated list of object scopes to search; each object's
|
null-terminated list of object scopes to search; each object's
|
||||||
l_searchlist (i.e. the segment of the dependency tree starting at that
|
l_searchlist (i.e. the segment of the dependency tree starting at that
|
||||||
object) is searched in turn. REFERENCE_NAME should name the object
|
object) is searched in turn. REFERENCE_NAME should name the object
|
||||||
containing the reference; it is used in error messages. RELOC_ADDR is
|
containing the reference; it is used in error messages. FLAGS is a
|
||||||
the address being fixed up and the chosen symbol cannot be one with this
|
set of flags: */
|
||||||
value. If NOPLT is nonzero, then the reference must not be resolved to
|
#define DL_LOOKUP_NOEXEC 1 /* Don't search the executable for a
|
||||||
a PLT entry. */
|
definition; this is used for copy
|
||||||
|
relocs. */
|
||||||
|
#define DL_LOOKUP_NOPLT 2 /* The reference must not be resolved
|
||||||
|
to a PLT entry. */
|
||||||
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct link_map *symbol_scope[],
|
struct link_map *symbol_scope[],
|
||||||
const char *reference_name,
|
const char *reference_name,
|
||||||
ElfW(Addr) reloc_addr,
|
int flags);
|
||||||
int noplt);
|
|
||||||
|
|
||||||
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
||||||
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name);
|
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name);
|
||||||
|
@ -62,7 +62,7 @@ _dl_start (void *arg)
|
|||||||
/* This #define produces dynamic linking inline functions for
|
/* This #define produces dynamic linking inline functions for
|
||||||
bootstrap relocation instead of general-purpose relocation. */
|
bootstrap relocation instead of general-purpose relocation. */
|
||||||
#define RTLD_BOOTSTRAP
|
#define RTLD_BOOTSTRAP
|
||||||
#define RESOLVE(sym, reloc_addr, noplt) bootstrap_map.l_addr
|
#define RESOLVE(sym, flags) bootstrap_map.l_addr
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
/* Figure out the run-time load address of the dynamic linker itself. */
|
/* Figure out the run-time load address of the dynamic linker itself. */
|
||||||
@ -369,7 +369,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||||
&_dl_default_scope[2],
|
&_dl_default_scope[2],
|
||||||
"argument", 0, 0);
|
"argument", 0);
|
||||||
char buf[20], *bp;
|
char buf[20], *bp;
|
||||||
buf[sizeof buf - 1] = '\0';
|
buf[sizeof buf - 1] = '\0';
|
||||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||||
|
19
manual/examples/strdupa.c
Normal file
19
manual/examples/strdupa.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include <paths.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
const char path[] = _PATH_STDPATH;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
char *wr_path = strdupa (path);
|
||||||
|
char *cp = strtok (wr_path, ":");
|
||||||
|
|
||||||
|
while (cp != NULL)
|
||||||
|
{
|
||||||
|
puts (cp);
|
||||||
|
cp = strtok (NULL, ":");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -137,6 +137,7 @@ of the GNU C Library.
|
|||||||
* Process Startup:: Writing the beginning and end of your program.
|
* Process Startup:: Writing the beginning and end of your program.
|
||||||
* Processes:: How to create processes and run other programs.
|
* Processes:: How to create processes and run other programs.
|
||||||
* Job Control:: All about process groups and sessions.
|
* Job Control:: All about process groups and sessions.
|
||||||
|
* Name Service Switch:: Accessing the various system databases.
|
||||||
* Users and Groups:: How users are identified and classified.
|
* Users and Groups:: How users are identified and classified.
|
||||||
* System Information:: Getting information about the
|
* System Information:: Getting information about the
|
||||||
hardware and software configuration
|
hardware and software configuration
|
||||||
@ -806,6 +807,13 @@ Functions for Job Control
|
|||||||
* Process Group Functions:: Functions for manipulating process groups.
|
* Process Group Functions:: Functions for manipulating process groups.
|
||||||
* Terminal Access Functions:: Functions for controlling terminal access.
|
* Terminal Access Functions:: Functions for controlling terminal access.
|
||||||
|
|
||||||
|
Name Service Switch
|
||||||
|
|
||||||
|
* NSS Basics:: What is this NSS good for.
|
||||||
|
* NSS Configuration File:: Configuring NSS.
|
||||||
|
* NSS Module Internals:: How does it work internally.
|
||||||
|
* Extending NSS:: What to do to add services or databases.
|
||||||
|
|
||||||
Users and Groups
|
Users and Groups
|
||||||
|
|
||||||
* User and Group IDs:: Each user and group has a unique numeric ID.
|
* User and Group IDs:: Each user and group has a unique numeric ID.
|
||||||
@ -961,6 +969,7 @@ Porting the GNU C Library
|
|||||||
@include startup.texi
|
@include startup.texi
|
||||||
@include process.texi
|
@include process.texi
|
||||||
@include job.texi
|
@include job.texi
|
||||||
|
@include nss.texi
|
||||||
@include users.texi
|
@include users.texi
|
||||||
@include sysinfo.texi
|
@include sysinfo.texi
|
||||||
@include conf.texi
|
@include conf.texi
|
||||||
|
586
manual/nss.texi
Normal file
586
manual/nss.texi
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
@c each section should have index entries corresponding to the section title
|
||||||
|
|
||||||
|
@node Name Service Switch
|
||||||
|
@chapter System Databases and Name Service Switch
|
||||||
|
|
||||||
|
Various functions in the C Library need to be configured to work
|
||||||
|
correctly in the local environment. Traditionally, this was done by
|
||||||
|
using files (e.g., @file{/etc/passwd}), but other nameservices (line the
|
||||||
|
Network Information Service (NIS) and the Domain Name Service (DNS))
|
||||||
|
became popular, and were hacked into the C library, usually with a fixed
|
||||||
|
search order @pxref{frobnicate, frobnicate, ,jargon}.
|
||||||
|
|
||||||
|
The GNU C Library contains a cleaner solution of this problem. It is
|
||||||
|
designed after a method used by Sun Microsystems in the C library of
|
||||||
|
@w{Solaris 2}. GNU C Library follows their name and calls this
|
||||||
|
scheme @dfn{Name Service Switch} (NSS).
|
||||||
|
|
||||||
|
Though the interface might be similar to Sun's version there is no
|
||||||
|
common code. We never saw any source code of Sun's implementation and
|
||||||
|
so the internal interface are incompatible. This is also manifest in the
|
||||||
|
file names we use as we will see later.
|
||||||
|
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* NSS Basics:: What is this NSS good for.
|
||||||
|
* NSS Configuration File:: Configuring NSS.
|
||||||
|
* NSS Module Internals:: How does it work internally.
|
||||||
|
* Extending NSS:: What to do to add services or databases.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node NSS Basics, NSS Configuration File, Name Service Switch, Name Service Switch
|
||||||
|
@section NSS Basics
|
||||||
|
|
||||||
|
The basic idea is to put the implementation of the different services
|
||||||
|
offered to access the databases in separate modules. This has some
|
||||||
|
advantages:
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
@item
|
||||||
|
Contributors can add new services without adding them to GNU C Library.
|
||||||
|
@item
|
||||||
|
The modules can be updated separately.
|
||||||
|
@item
|
||||||
|
The C library image is smaller.
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
To fulfill the first goal above the ABI of the modules will be described
|
||||||
|
below. For getting the implementation of a new service right it is
|
||||||
|
important to understand how the functions in the modules get called.
|
||||||
|
They are in no way designed to be used by the programmer directly.
|
||||||
|
Instead the programmer should only use the documented and standardized
|
||||||
|
functions to access the databases.
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
The databases available in the NSS are
|
||||||
|
|
||||||
|
@cindex ethers
|
||||||
|
@cindex group
|
||||||
|
@cindex hosts
|
||||||
|
@cindex network
|
||||||
|
@cindex protocols
|
||||||
|
@cindex passwd
|
||||||
|
@cindex rpc
|
||||||
|
@cindex services
|
||||||
|
@cindex shadow
|
||||||
|
@vtable @code
|
||||||
|
@item ethers
|
||||||
|
Ethernet numbers,
|
||||||
|
@comment @pxref{Ethernet Numbers}.
|
||||||
|
@item group
|
||||||
|
Groups of users, @pxref{Group Database}.
|
||||||
|
@item hosts
|
||||||
|
Host names and numbers, @pxref{Host Names}.
|
||||||
|
@item network
|
||||||
|
Network names and numbers, @pxref{Networks Database}.
|
||||||
|
@item protocols
|
||||||
|
Network protocols, @pxref{Protocols Database}.
|
||||||
|
@item passwd
|
||||||
|
User passwords, @pxref{User Database}.
|
||||||
|
@item rpc
|
||||||
|
Remote procedure call names and numbers,
|
||||||
|
@comment @pxref{RPC Database}.
|
||||||
|
@item services
|
||||||
|
Network services, @pxref{Services Database}.
|
||||||
|
@item shadow
|
||||||
|
Shadow user passwords,
|
||||||
|
@comment @pxref{Shadow Password Database}.
|
||||||
|
@end vtable
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
There will be some more added later (@code{aliases}, @code{automount},
|
||||||
|
@code{bootparams}, @code{netgroup}, @code{netmasks}, and
|
||||||
|
@code{publickey}).
|
||||||
|
|
||||||
|
@node NSS Configuration File, NSS Module Internals, NSS Basics, Name Service Switch
|
||||||
|
@section The NSS Configuration File
|
||||||
|
|
||||||
|
@cindex @file{/etc/nsswitch.conf}
|
||||||
|
@cindex @file{nsswitch.conf}
|
||||||
|
Somehow the NSS code must be told about the wishes of the user. For
|
||||||
|
this reason there is the file @file{/etc/nsswitch.conf}. For each
|
||||||
|
database this file contain a specification how the lookup process should
|
||||||
|
work. The file could look like this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@include nsswitch.texi
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The first column is the database as you can guess from the table above.
|
||||||
|
The rest of the line specifies how the lookup process works. Please
|
||||||
|
note that you specify the way it works for each database individually.
|
||||||
|
This cannot be done with the old way of a monolithic implementation.
|
||||||
|
|
||||||
|
The configuration specification for each database can contain two
|
||||||
|
different items:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
the service specification like @code{files}, @code{db}, or @code{nis}.
|
||||||
|
@item
|
||||||
|
the reaction on lookup result line @code{[NOTFOUND=return]}.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Services in the NSS configuration:: Service names in the NSS configuratin.
|
||||||
|
* Actions in the NSS configuration:: React approprite on the lookup result.
|
||||||
|
* Notes on NSS Configuration File:: Things to take care about while
|
||||||
|
configuring NSS.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node Services in the NSS configuration, Actions in the NSS configuration, NSS Configuration File, NSS Configuration File
|
||||||
|
@subsection Services in the NSS configuration File
|
||||||
|
|
||||||
|
The above example file mentions four different services: @code{files},
|
||||||
|
@code{db}, @code{nis}, and @code{nisplus}. This does not mean these
|
||||||
|
services are available on all sites and it does also not mean these are
|
||||||
|
all the services which will ever be available.
|
||||||
|
|
||||||
|
In fact, these names are simply strings which the NSS code uses to find
|
||||||
|
the implicitly addressed functions. The internal interface will be
|
||||||
|
described later. Visible to the user are the modules which implement an
|
||||||
|
individual service.
|
||||||
|
|
||||||
|
Assume the service @var{name} shall be used for a lookup. The code for
|
||||||
|
this service is implemented in a module called @file{libnss_@var{name}}.
|
||||||
|
On a system supporting shared libraries this is in fact a shared library
|
||||||
|
with the name (for example) @file{libnss_@var{name}.so.1}. The number
|
||||||
|
at the end is the currently used version of the interface which will not
|
||||||
|
change frequently. Normally the user should not have to be cognizant of
|
||||||
|
these files since they should be placed in a directory where they are
|
||||||
|
found automatically. Only the names of all available services are
|
||||||
|
important.
|
||||||
|
|
||||||
|
@node Actions in the NSS configuration, Notes on NSS Configuration File, Services in the NSS configuration, NSS Configuration File
|
||||||
|
@subsection Actions in the NSS configuration
|
||||||
|
|
||||||
|
The second item in the specification gives the user much finer control
|
||||||
|
on the lookup process. Action items are placed between two service
|
||||||
|
names and are written within brackets. The general form is
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
[ @r{(}!@r{?} @var{status} = @var{action}@r{)+} ]
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
where
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
@var{status} @result{} success | notfound | unavail | tryagain
|
||||||
|
@var{action} @result{} return | continue
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
The case of the keywords is insignificant. The @var{status}
|
||||||
|
values are the results of a call to a lookup function of a specific
|
||||||
|
service. They mean
|
||||||
|
|
||||||
|
@ftable @samp
|
||||||
|
@item success
|
||||||
|
No error occured an the wanted entry is returned. The default action
|
||||||
|
for this is @code{return}.
|
||||||
|
|
||||||
|
@item notfound
|
||||||
|
The lookup process works ok but the needed value was not found. The
|
||||||
|
default action is @code{continue}.
|
||||||
|
|
||||||
|
@item unavail
|
||||||
|
@cindex DNS server unavailable
|
||||||
|
The service is permanently unavailable. This can either mean the needed
|
||||||
|
file is not available, or, for DNS, the server is not available or does
|
||||||
|
not allow queries. The default action is @code{continue}.
|
||||||
|
|
||||||
|
@item tryagain
|
||||||
|
The service is temporarily unavailable. This could mean a file is
|
||||||
|
locked or a server currently cannot accept more connections. The
|
||||||
|
default action is @code{continue}.
|
||||||
|
@end ftable
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
If we have a line like
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
ethers: nisplus [NOTFOUND=return] db files
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
this is equivalent to
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
ethers: nisplus [SUCCESS=return NOTFOUND=return UNAVAIL=continue
|
||||||
|
TRYAGAIN=continue]
|
||||||
|
db [SUCCESS=return NOTFOUND=continue UNAVAIL=continue
|
||||||
|
TRYAGAIN=continue]
|
||||||
|
files
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
(except that it would have to be written on one line). The default
|
||||||
|
value for the actions are normally what you want, and only need to be
|
||||||
|
changed in exceptional cases.
|
||||||
|
|
||||||
|
If the optional @code{!} is placed before the @var{status} this means
|
||||||
|
the following action is used for all statii but @var{status} itself.
|
||||||
|
I.e., @code{!} is negation as in the C language (and others).
|
||||||
|
|
||||||
|
Before we explain the exception which makes this action item necessary
|
||||||
|
one more remark: obviously it makes no sense to add another action
|
||||||
|
item after the @code{files} service. Since there is no other service
|
||||||
|
following the action @emph{always} is @code{return}.
|
||||||
|
|
||||||
|
@cindex nisplus, and completeness
|
||||||
|
Now, why is this @code{[NOTFOUND=return]} action useful? To understand
|
||||||
|
this we should know that the @code{nisplus} service is often
|
||||||
|
complete; i.e., if an entry is not available in the NIS+ tables it is
|
||||||
|
not available anywhere else. This is what is expressed by this action
|
||||||
|
item: it is useless to examine further services since they will not give
|
||||||
|
us a result.
|
||||||
|
|
||||||
|
@cindex nisplus, and booting
|
||||||
|
@cindex bootstrapping, and services
|
||||||
|
The situation would be different if the NIS+ service is not available
|
||||||
|
because the machine is booting. In this case the return value of the
|
||||||
|
lookup function is not @code{notfound} but instead @code{unavail}. And
|
||||||
|
as you can see in the complete form above: in this situation the
|
||||||
|
@code{db} and @code{files} services are used. Neat, isn't it? The
|
||||||
|
system administrator need not pay special care for the time the system
|
||||||
|
is not completely ready to work (while booting or shutdown or
|
||||||
|
network problems).
|
||||||
|
|
||||||
|
|
||||||
|
@node Notes on NSS Configuration File, , Actions in the NSS configuration, NSS Configuration File
|
||||||
|
@subsection Notes on the NSS Configuration File
|
||||||
|
|
||||||
|
Finally a few more hints. The NSS implementation is not completely
|
||||||
|
helpless if @file{/etc/nsswitch.conf} does not exist. For
|
||||||
|
all supported databases there is a default value so it should normally
|
||||||
|
be possible to get the system running even if the file is corrupted or
|
||||||
|
missing.
|
||||||
|
|
||||||
|
A second point is that the user should try to optimize the lookup
|
||||||
|
process. The different service have different response times. A simple
|
||||||
|
file look up on a local file could be fast, but if the file is long and the
|
||||||
|
needed entry is near the end of the file this may take quite some time.
|
||||||
|
In this case it might be better to use the @code{db} service which
|
||||||
|
allows fast local access to large data sets.
|
||||||
|
|
||||||
|
Often the situation is that some global information like NIS must be
|
||||||
|
used. So it is unavoidable to use service entries like @code{nis} etc.
|
||||||
|
But one should avoid slow services like this if possible.
|
||||||
|
|
||||||
|
|
||||||
|
@node NSS Module Internals, Extending NSS, NSS Configuration File, Name Service Switch
|
||||||
|
@section NSS Module Internals
|
||||||
|
|
||||||
|
Now it is time to described how the modules look like. The functions
|
||||||
|
contained in a module are identified by their names. I.e., there is no
|
||||||
|
jump table or the like. How this is done is of no interest here; those
|
||||||
|
interested in this topic should read about Dynamic Linking.
|
||||||
|
@comment @ref{Dynamic Linking}.
|
||||||
|
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* NSS Module Names:: Construction of the interface function of
|
||||||
|
the NSS modules.
|
||||||
|
* NSS Modules Interface:: Programming interface in the NSS module
|
||||||
|
functions.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node NSS Module Names, NSS Modules Interface, NSS Module Internals, NSS Module Internals
|
||||||
|
@subsection The Naming Scheme of the NSS Modules
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
The name of each function consist of various parts:
|
||||||
|
|
||||||
|
@quotation
|
||||||
|
_nss_@var{service}_@var{function}
|
||||||
|
@end quotation
|
||||||
|
|
||||||
|
@var{service} of course corresponds to the name of the module this
|
||||||
|
function is found in.@footnote{Now you might ask why to duplicate this
|
||||||
|
information. The answer is that we want to keep the possibility to link
|
||||||
|
directly with these shared objects.} The @var{function} part is derived
|
||||||
|
from the interface function in the C library itself. If the user calls
|
||||||
|
the function @code{gethostbyname} and the service used is @code{files}
|
||||||
|
the function
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
_nss_files_gethostbyname_r
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
in the module
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
libnss_files.so.1
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
@cindex reentrant NSS functions
|
||||||
|
is used. You see, what is explained above in not the whole truth. In
|
||||||
|
fact the NSS modules only contain reentrant versions of the lookup
|
||||||
|
functions. I.e., if the user would call the @code{gethostbyname_r}
|
||||||
|
function this also would end in the above function. For all user
|
||||||
|
interface functions the C library maps this call to a call to the
|
||||||
|
reentrant function. For reentrant functions this is trivial since the
|
||||||
|
interface is (nearly) the same. For the non-reentrant version pointers
|
||||||
|
to static buffers are used to replace the user supplied buffers.
|
||||||
|
|
||||||
|
I.e., the reentrant functions @emph{can} have counterparts. No service
|
||||||
|
module is forced to have functions for all databases and all kinds to
|
||||||
|
access them. If a function is not available it is simply treated as if
|
||||||
|
the function would return @code{unavail}
|
||||||
|
(@pxref{Actions in the NSS configuration}).
|
||||||
|
|
||||||
|
|
||||||
|
@node NSS Modules Interface, , NSS Module Names, NSS Module Internals
|
||||||
|
@subsection The Interface of the Function in NSS Modules
|
||||||
|
|
||||||
|
Now we know about the functions contained in the modules. It is now
|
||||||
|
time to describe the types. When we mentioned the reentrant versions of
|
||||||
|
the functions above, this means there are some additional arguments
|
||||||
|
(compared with the standard, non-reentrant version). The prototypes for
|
||||||
|
the non-reentrant and reentrant versions of our function above are:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
struct hostent *gethostbyname (const char *name)
|
||||||
|
|
||||||
|
struct hostent *gethostbyname_r (const char *name,
|
||||||
|
struct hostent *result_buf, char *buf,
|
||||||
|
int buflen, int *h_errnop)
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
The actual prototype of the function is the NSS modules in this case is
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
int _nss_files_gethostbyname_r (const char *name,
|
||||||
|
struct hostent *result_buf, char *buf,
|
||||||
|
int buflen, int *h_errnop)
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
I.e., the interface function is in fact the reentrant function with
|
||||||
|
the change of the return value. While the user-level function returns a
|
||||||
|
pointer to the result the reentrant function return an @code{int} value:
|
||||||
|
|
||||||
|
@cindex NSS_STATUS_TRYAGAIN
|
||||||
|
@cindex NSS_STATUS_UNAVAIL
|
||||||
|
@cindex NSS_STATUS_NOTFOUND
|
||||||
|
@cindex NSS_STATUS_SUCCESS
|
||||||
|
@ftable @code
|
||||||
|
@item NSS_STATUS_TRYAGAIN
|
||||||
|
numeric value @code{-2}
|
||||||
|
|
||||||
|
@item NSS_STATUS_UNAVAIL
|
||||||
|
numeric value @code{-1}
|
||||||
|
|
||||||
|
@item NSS_STATUS_NOTFOUND
|
||||||
|
numeric value @code{0}
|
||||||
|
|
||||||
|
@item NSS_STATUS_SUCCESS
|
||||||
|
numeric value @code{1}
|
||||||
|
@end ftable
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
Now you see where the action items of the @file{/etc/nsswitch.conf} file
|
||||||
|
are used.
|
||||||
|
|
||||||
|
The above function has somthing special which is missing for almost all
|
||||||
|
the other module functions. There is an argument @var{h_errnop}. This
|
||||||
|
points to a variable which will be filled with the error code in case
|
||||||
|
the execution of the function fails for some reason. The reentrant
|
||||||
|
function cannot use the global variable @var{h_errno};
|
||||||
|
@code{gethostbyname} calls @code{gethostbyname_r} with the
|
||||||
|
last argument set to @code{&h_errno}.
|
||||||
|
|
||||||
|
The @code{get@var{XXX}by@var{YYY}} functions are the most important
|
||||||
|
functions in the NSS modules. But there are others which implement
|
||||||
|
the other ways to access system databases (say for the
|
||||||
|
password database, there are @code{setpwent}, @code{getpwent}, and
|
||||||
|
@code{endpwent}). These will be described in more detail later.
|
||||||
|
Here we give a general way to determine the
|
||||||
|
signature of the module function:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
the return value is @code{int};
|
||||||
|
@item
|
||||||
|
the name is as explain in @pxref{NSS Module Names};
|
||||||
|
@item
|
||||||
|
the first arguments are identical to the arguments of the non-reentrant
|
||||||
|
function;
|
||||||
|
@item
|
||||||
|
the next three arguments are:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item STRUCT_TYPE result_buf
|
||||||
|
pointer to buffer where the result is stored. @code{STRUCT_TYPE} is
|
||||||
|
normally a struct which corresponds to the database.
|
||||||
|
@item char *buffer
|
||||||
|
pointer to a buffer where the function can store additional adata for
|
||||||
|
the result etc.
|
||||||
|
@item int buflen
|
||||||
|
length of the buffer pointed to by @var{buffer}.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@item
|
||||||
|
possibly a last argument @var{h_errnop}, for the host name and network
|
||||||
|
name lookup functions.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
This table is correct for all functions but the @code{set@dots{}ent}
|
||||||
|
and @code{end@dots{}ent} functions.
|
||||||
|
|
||||||
|
|
||||||
|
@node Extending NSS, , NSS Module Internals, Name Service Switch
|
||||||
|
@section Extending NSS
|
||||||
|
|
||||||
|
One of the advantages of NSS mentioned above is that it can be extended
|
||||||
|
quite easily. There are two ways in which the extension can happen:
|
||||||
|
adding another database or adding another service. The former is
|
||||||
|
normally done only by the C library developers. It is
|
||||||
|
here only important to remember that adding another database is
|
||||||
|
independent from adding another service because a service need not
|
||||||
|
support all databases or lookup functions.
|
||||||
|
|
||||||
|
A designer/implementor of a new service is therefore free to choose the
|
||||||
|
databases s/he is interested in and leave the rest for later (or
|
||||||
|
completely aside).
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Adding another Service to NSS:: What is to do to add a new service.
|
||||||
|
* NSS Module Function Internals:: Guidelines for writing new NSS
|
||||||
|
service functions.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node Adding another Service to NSS, NSS Module Function Internals, Extending NSS, Extending NSS
|
||||||
|
@subsection Adding another Service to NSS
|
||||||
|
|
||||||
|
The sources for a new service need not (and should not) be part of the
|
||||||
|
GNU C Library itself. The developer retains complete control over the
|
||||||
|
sources and its development. The links between the C library and the
|
||||||
|
new service module consists solely of the interface functions.
|
||||||
|
|
||||||
|
Each module is designed following a specific interface specification.
|
||||||
|
For now the version is 1 and this manifests in the version number of the
|
||||||
|
shared library object of the NSS modules: they have the extension
|
||||||
|
@code{.1}. If the interface ever changes in an incompatible way,
|
||||||
|
this number will be increased---hopefully this will never be necessary.
|
||||||
|
Modules using the old interface will still be usable.
|
||||||
|
|
||||||
|
Developers of a new service will have to make sure that their module is
|
||||||
|
created using the correct interface number. This means the file itself
|
||||||
|
must have the correct name and on ElF systems the @dfn{soname} (Shared
|
||||||
|
Object Name) must also have this number. Building a module from a bunch
|
||||||
|
of object files on an ELF system using GNU CC could be done like this:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
gcc -shared -o libnss_NAME.so.1 -Wl,-soname,libnss_NAME.so.1 OBJECTS
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
@ref{Link Options, Options for Linking, , gcc, GNU CC}, to learn
|
||||||
|
more about this command line.
|
||||||
|
|
||||||
|
To use the new module the library must be able to find it. This can be
|
||||||
|
achieved by using options for the dynamic linker so that it will search
|
||||||
|
directory where the binary is placed. For an ELF system this could be
|
||||||
|
done by adding the wanted directory to the value of
|
||||||
|
@code{LD_LIBRARY_PATH}.
|
||||||
|
|
||||||
|
But this is not always possible since some program (those which run
|
||||||
|
under IDs which do not belong to the user) ignore this variable.
|
||||||
|
Therefore the stable version of the module should be placed into a
|
||||||
|
directory which is searched by the dynamic linker. Normally this should
|
||||||
|
be the directory @file{$prefix/lib}, where @file{$prefix} corresponds to
|
||||||
|
the value given to configure using the @code{--prefix} option. But be
|
||||||
|
careful: this should only be done if it is clear the module does not
|
||||||
|
cause any harm. System administrators should be careful.
|
||||||
|
|
||||||
|
|
||||||
|
@node NSS Module Function Internals, , Adding another Service to NSS, Extending NSS
|
||||||
|
@subsection Internals of the NSS Module Functions
|
||||||
|
|
||||||
|
Until now we only provided the syntactic interface for the functions in
|
||||||
|
the NSS module. In fact there is not more much we can tell since the
|
||||||
|
implementation obviously is different for each function. But a few
|
||||||
|
general rules must be followed by all functions.
|
||||||
|
|
||||||
|
In fact there are four kinds of different functions which may appear in
|
||||||
|
the interface. All derive from the traditional ones for system databases.
|
||||||
|
@var{db} in the following table is normally an abbreviation for the
|
||||||
|
database (e.g., it is @code{pw} for the password database).
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item int _nss_@var{database}_set@var{db}ent (void)
|
||||||
|
This function prepares the service for following operations. For a
|
||||||
|
simple file based lookup this means files could be opened, for other
|
||||||
|
services this function simply is a noop.
|
||||||
|
|
||||||
|
One special case for this function is that it takes an additional
|
||||||
|
argument for some @var{database}s (i.e., the interface is
|
||||||
|
@code{int set@var{db}ent (int)}). @ref{Host Names}, which describes the
|
||||||
|
@code{sethostent} function.
|
||||||
|
|
||||||
|
The return value should be @var{NSS_STATUS_SUCCESS} or according to the
|
||||||
|
table above in case of an error (@pxref{NSS Modules Interface}).
|
||||||
|
|
||||||
|
@item int _nss_@var{database}_end@var{db}ent (void)
|
||||||
|
This function simply closes all files which are still open or removes
|
||||||
|
buffer caches. If there are no files or buffers to remove this is again
|
||||||
|
a simple noop.
|
||||||
|
|
||||||
|
There normally is no return value different to @var{NSS_STATUS_SUCCESS}.
|
||||||
|
|
||||||
|
@item int _nss_@var{database}_get@var{db}ent_r (@var{STRUCTURE} *result, char *buffer, int buflen)
|
||||||
|
Since this function will be called several times in a row to retrieve
|
||||||
|
one entry after the other it must keep some kind of state. But this
|
||||||
|
also means the functions are not really reentrant. They are reentrant
|
||||||
|
only in that simultaneous calls to this function will not try to
|
||||||
|
write the retrieved data in the same place (as it would be the case for
|
||||||
|
the non-reentrant functions); instead, it writes to the structure
|
||||||
|
pointed to by the @var{result} parameter. But the calls share a common
|
||||||
|
state and in the case of a file access this means they return neighboring
|
||||||
|
entries in the file.
|
||||||
|
|
||||||
|
The buffer of length @var{buflen} pointed to by @var{buffer} can be used
|
||||||
|
for storing some additional data for the result. It is @emph{not}
|
||||||
|
guaranteed that the same buffer will be passed for the next call of this
|
||||||
|
function. Therefore one must not misuse this buffer to save some state
|
||||||
|
information from one call to another.
|
||||||
|
|
||||||
|
As explained above this function could also have an additional last
|
||||||
|
argument. This depends on the database used; it happens only for
|
||||||
|
@code{host} and @code{network}.
|
||||||
|
|
||||||
|
The function shall return @code{NSS_STATUS_SUCCESS} as long as their are
|
||||||
|
more entries. When the last entry was read it should return
|
||||||
|
@code{NSS_STATUS_NOTFOUND}. When the buffer given as an argument is too
|
||||||
|
small for the data to be returned @code{NSS_STATUS_TRYAGAIN} should be
|
||||||
|
returned. When the service was not formerly initialized by a call to
|
||||||
|
@code{_nss_@var{DATABASE}_set@var{db}ent} all return value allowed for
|
||||||
|
this function can also be returned here.
|
||||||
|
|
||||||
|
@item int _nss_@var{DATABASE}_get@var{db}by@var{XX}_r (@var{PARAMS}, @var{STRUCTURE} *result, char *buffer, int buflen)
|
||||||
|
This function shall return the entry from the database which is
|
||||||
|
addressed by the @var{PARAMS}. The type and number of these arguments
|
||||||
|
vary. It must be individually determined by looking to the user-level
|
||||||
|
interface functions. All arguments given to the non-reentrant version
|
||||||
|
are here described by @var{PARAMS}.
|
||||||
|
|
||||||
|
The result must be stored in the structure pointed to by @var{result}.
|
||||||
|
If there is additional data to return (say strings, where the
|
||||||
|
@var{result} structure only contains pointers) the function must use the
|
||||||
|
@var{buffer} or length @var{buflen}. There must not be any references
|
||||||
|
to non-constant global data.
|
||||||
|
|
||||||
|
The implementation of this function should honour the @var{stayopen}
|
||||||
|
flag set by the @code{set@var{DB}ent} function whenever this makes sense.
|
||||||
|
|
||||||
|
Again, this function takes an additional last argument for the
|
||||||
|
@code{host} and @code{network} database.
|
||||||
|
|
||||||
|
The return value should as always follow the rules given above
|
||||||
|
(@pxref{NSS Modules Interface}).
|
||||||
|
|
||||||
|
@end table
|
16
manual/nsswitch.texi
Normal file
16
manual/nsswitch.texi
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# /etc/nsswitch.conf
|
||||||
|
#
|
||||||
|
# Name Service Switch configuration file.
|
||||||
|
#
|
||||||
|
|
||||||
|
passwd: db files nis
|
||||||
|
shadow: files
|
||||||
|
group: db files nis
|
||||||
|
|
||||||
|
hosts: files nisplus nis dns
|
||||||
|
networks: nisplus [NOTFOUND=return] files
|
||||||
|
|
||||||
|
ethers: nisplus [NOTFOUND=return] db files
|
||||||
|
protocols: nisplus [NOTFOUND=return] db files
|
||||||
|
rpc: nisplus [NOTFOUND=return] db files
|
||||||
|
services: nisplus [NOTFOUND=return] db files
|
@ -293,6 +293,21 @@ for the new string, @code{strdup} returns a null pointer. Otherwise it
|
|||||||
returns a pointer to the new string.
|
returns a pointer to the new string.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
@comment string.h
|
||||||
|
@comment GNU
|
||||||
|
@deftypefun {char *} strndup (const char *@var{s}, size_t @var{size})
|
||||||
|
This function is similar to @code{strdup} but always copies at most
|
||||||
|
@var{size} characters into the newly allocated string.
|
||||||
|
|
||||||
|
If the length of @var{s} is more than @var{size}, then @code{strndup}
|
||||||
|
copies just the first @var{size} characters and adds a closing null
|
||||||
|
terminator. Otherwise all characters are copied and the string is
|
||||||
|
terminated.
|
||||||
|
|
||||||
|
This function is different to @code{strncpy} in that it always
|
||||||
|
terminates the destination string.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
@comment string.h
|
@comment string.h
|
||||||
@comment Unknown origin
|
@comment Unknown origin
|
||||||
@deftypefun {char *} stpcpy (char *@var{to}, const char *@var{from})
|
@deftypefun {char *} stpcpy (char *@var{to}, const char *@var{from})
|
||||||
@ -314,6 +329,68 @@ comes from MS-DOG.
|
|||||||
Its behavior is undefined if the strings overlap.
|
Its behavior is undefined if the strings overlap.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
@comment string.h
|
||||||
|
@comment GNU
|
||||||
|
@deftypefun {char *} stpncpy (char *@var{to}, const char *@var{from}, size_t @var{size})
|
||||||
|
This function is similar to @code{stpcpy} but copies always exactly
|
||||||
|
@var{size} characters into @var{to}.
|
||||||
|
|
||||||
|
If the length of @var{from} is more then @var{size}, then @code{stpncpy}
|
||||||
|
copies just the first @var{size} characters and returns a pointer to the
|
||||||
|
character directly following the one which was copied last. Note that in
|
||||||
|
this case there is no null terminator written into @var{to}.
|
||||||
|
|
||||||
|
If the length of @var{from} is less than @var{size}, then @code{stpncpy}
|
||||||
|
copies all of @var{from}, followed by enough null characters to add up
|
||||||
|
to @var{size} characters in all. This behaviour is rarely useful, but it
|
||||||
|
is implemented to be useful in contexts where this behaviour of the
|
||||||
|
@code{strncpy} is used. @code{stpncpy} returns a pointer to the
|
||||||
|
@emph{first} written null character.
|
||||||
|
|
||||||
|
This function is not part of ANSI or POSIX but was found useful while
|
||||||
|
developing GNU C Library itself.
|
||||||
|
|
||||||
|
Its behaviour is undefined if the strings overlap.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@comment string.h
|
||||||
|
@comment GNU
|
||||||
|
@deftypefun {char *} strdupa (const char *@var{s})
|
||||||
|
This function is similar to @code{strdup} but allocates the new string
|
||||||
|
using @code{alloca} instead of @code{malloc}
|
||||||
|
@pxref{Variable Size Automatic}. This means of course the returned
|
||||||
|
string has the same limitations as any block of memory allocated using
|
||||||
|
@code{alloca}.
|
||||||
|
|
||||||
|
For obvious reasons @code{strdupa} is implemented only as a macro. I.e.,
|
||||||
|
you cannot get the address of this function. Despite this limitations
|
||||||
|
it is a useful function. The following code shows a situation where
|
||||||
|
using @code{malloc} would be a lot more expensive.
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
@include strdupa.c.texi
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
Please note that calling @code{strtok} using @var{path} directly is
|
||||||
|
illegal.
|
||||||
|
|
||||||
|
This function is only available if GNU CC is used.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@comment string.h
|
||||||
|
@comment GNU
|
||||||
|
@deftypefun {char *} strndupa (const char *@var{s}, size_t @var{size})
|
||||||
|
This function is similar to @code{strndup} but like @code{strdupa} it
|
||||||
|
allocates the new string using @code{alloca}
|
||||||
|
@pxref{Variable Size Automatic}. The same advantages and limitations
|
||||||
|
of @code{strdupa} are valid for @code{strndupa}, too.
|
||||||
|
|
||||||
|
This function is implemented only as a macro which means one cannot
|
||||||
|
get the address of it.
|
||||||
|
|
||||||
|
@code{strndupa} is only available if GNU CC is used.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
@comment string.h
|
@comment string.h
|
||||||
@comment ANSI
|
@comment ANSI
|
||||||
@deftypefun {char *} strcat (char *@var{to}, const char *@var{from})
|
@deftypefun {char *} strcat (char *@var{to}, const char *@var{from})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@node Users and Groups, System Information, Job Control, Top
|
@node Users and Groups, System Information, Name Service Switch, Top
|
||||||
@chapter Users and Groups
|
@chapter Users and Groups
|
||||||
|
|
||||||
Every user who can log in on the system is identified by a unique number
|
Every user who can log in on the system is identified by a unique number
|
||||||
@ -87,7 +87,7 @@ for purposes of access control. These IDs are also called the
|
|||||||
@dfn{effective user ID} and @dfn{effective group ID} of the process.
|
@dfn{effective user ID} and @dfn{effective group ID} of the process.
|
||||||
|
|
||||||
Your login shell starts out with a persona which consists of your user
|
Your login shell starts out with a persona which consists of your user
|
||||||
ID and your default group ID.
|
ID and your default group ID.
|
||||||
@c !!! also supplementary group IDs.
|
@c !!! also supplementary group IDs.
|
||||||
In normal circumstances, all your other processes inherit these values.
|
In normal circumstances, all your other processes inherit these values.
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ The return values and error conditions for @code{setregid} are the same
|
|||||||
as those for @code{setreuid}.
|
as those for @code{setreuid}.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
The GNU system also lets privileged processes change their supplementary
|
The GNU system also lets privileged processes change their supplementary
|
||||||
group IDs. To use @code{setgroups} or @code{initgroups}, your programs
|
group IDs. To use @code{setgroups} or @code{initgroups}, your programs
|
||||||
should include the header file @file{grp.h}.
|
should include the header file @file{grp.h}.
|
||||||
@pindex grp.h
|
@pindex grp.h
|
||||||
@ -417,14 +417,14 @@ user_user_id = getuid ();
|
|||||||
game_user_id = geteuid ();
|
game_user_id = geteuid ();
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
Then it can turn off game file access with
|
Then it can turn off game file access with
|
||||||
|
|
||||||
@smallexample
|
@smallexample
|
||||||
setuid (user_user_id);
|
setuid (user_user_id);
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
and turn it on with
|
and turn it on with
|
||||||
|
|
||||||
@smallexample
|
@smallexample
|
||||||
setuid (game_user_id);
|
setuid (game_user_id);
|
||||||
@ -478,7 +478,7 @@ file will be installed with the set-user-ID bit set and owned by the
|
|||||||
same user as the @file{scores} file. Typically, a system
|
same user as the @file{scores} file. Typically, a system
|
||||||
administrator will set up an account like @code{games} for this purpose.
|
administrator will set up an account like @code{games} for this purpose.
|
||||||
|
|
||||||
The executable file is given mode @code{4755}, so that doing an
|
The executable file is given mode @code{4755}, so that doing an
|
||||||
@samp{ls -l} on it produces output like:
|
@samp{ls -l} on it produces output like:
|
||||||
|
|
||||||
@smallexample
|
@smallexample
|
||||||
@ -608,7 +608,7 @@ record_score (int score)
|
|||||||
@node Tips for Setuid
|
@node Tips for Setuid
|
||||||
@section Tips for Writing Setuid Programs
|
@section Tips for Writing Setuid Programs
|
||||||
|
|
||||||
It is easy for setuid programs to give the user access that isn't
|
It is easy for setuid programs to give the user access that isn't
|
||||||
intended---in fact, if you want to avoid this, you need to be careful.
|
intended---in fact, if you want to avoid this, you need to be careful.
|
||||||
Here are some guidelines for preventing unintended access and
|
Here are some guidelines for preventing unintended access and
|
||||||
minimizing its consequences when it does occur:
|
minimizing its consequences when it does occur:
|
||||||
@ -731,7 +731,7 @@ are declared in the header file @file{pwd.h}.
|
|||||||
@comment pwd.h
|
@comment pwd.h
|
||||||
@comment POSIX.1
|
@comment POSIX.1
|
||||||
@deftp {Data Type} {struct passwd}
|
@deftp {Data Type} {struct passwd}
|
||||||
The @code{passwd} data structure is used to hold information about
|
The @code{passwd} data structure is used to hold information about
|
||||||
entries in the system user data base. It has at least the following members:
|
entries in the system user data base. It has at least the following members:
|
||||||
|
|
||||||
@table @code
|
@table @code
|
||||||
@ -887,7 +887,7 @@ database are declared in the header file @file{grp.h}.
|
|||||||
|
|
||||||
@comment grp.h
|
@comment grp.h
|
||||||
@comment POSIX.1
|
@comment POSIX.1
|
||||||
@deftp {Data Type} {struct group}
|
@deftp {Data Type} {struct group}
|
||||||
The @code{group} structure is used to hold information about an entry in
|
The @code{group} structure is used to hold information about an entry in
|
||||||
the system group database. It has at least the following members:
|
the system group database. It has at least the following members:
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ nss_lookup_function (service_user *ni, const char *fct_name)
|
|||||||
{
|
{
|
||||||
struct link_map *scope[2] = { map, NULL };
|
struct link_map *scope[2] = { map, NULL };
|
||||||
loadbase = _dl_lookup_symbol (name, &ref,
|
loadbase = _dl_lookup_symbol (name, &ref,
|
||||||
scope, map->l_name, 0, 0);
|
scope, map->l_name, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the function name. */
|
/* Construct the function name. */
|
||||||
|
1384
po/SYS_libc.pot
1384
po/SYS_libc.pot
File diff suppressed because it is too large
Load Diff
@ -13,3 +13,4 @@ msgstr ""
|
|||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=CHARSET\n"
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
"Content-Transfer-Encoding: ENCODING\n"
|
"Content-Transfer-Encoding: ENCODING\n"
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ struct spwd *
|
|||||||
__sgetspent_r (const char *string, struct spwd *result, char *buffer,
|
__sgetspent_r (const char *string, struct spwd *result, char *buffer,
|
||||||
int buflen)
|
int buflen)
|
||||||
{
|
{
|
||||||
return parse_line (strncpy (string, buffer, buflen), result, NULL, 0)
|
return parse_line (strncpy (buffer, string, buflen), result, NULL, 0)
|
||||||
? result : NULL;
|
? result : NULL;
|
||||||
}
|
}
|
||||||
weak_alias (__sgetspent_r, sgetspent_r)
|
weak_alias (__sgetspent_r, sgetspent_r)
|
||||||
|
@ -378,7 +378,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
|
|||||||
in the format described in <locale.h>. */
|
in the format described in <locale.h>. */
|
||||||
const char *grouping;
|
const char *grouping;
|
||||||
|
|
||||||
assert (sizeof (wchar_t) <= sizeof (wint_t));
|
assert (sizeof (wchar_t) == sizeof (wint_t));
|
||||||
|
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
|
@ -31,8 +31,6 @@ __strdup (const char *s)
|
|||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy (new, s, len);
|
return (char *) memcpy (new, s, len);
|
||||||
|
|
||||||
return (char *) new;
|
|
||||||
}
|
}
|
||||||
weak_alias (__strdup, strdup)
|
weak_alias (__strdup, strdup)
|
||||||
|
@ -341,8 +341,8 @@ elf_machine_rela (struct link_map *map,
|
|||||||
{
|
{
|
||||||
Elf64_Addr loadbase, sym_value;
|
Elf64_Addr loadbase, sym_value;
|
||||||
|
|
||||||
loadbase = RESOLVE (&sym, (Elf64_Addr)reloc_addr,
|
loadbase = RESOLVE (&sym,
|
||||||
r_info == R_ALPHA_JMP_SLOT);
|
r_info == R_ALPHA_JMP_SLOT ? DL_LOOKUP_NOPLT : 0);
|
||||||
sym_value = sym ? loadbase + sym->st_value : 0;
|
sym_value = sym ? loadbase + sym->st_value : 0;
|
||||||
|
|
||||||
if (r_info == R_ALPHA_GLOB_DAT)
|
if (r_info == R_ALPHA_GLOB_DAT)
|
||||||
|
@ -193,15 +193,15 @@ elf_machine_rel (struct link_map *map,
|
|||||||
switch (ELF32_R_TYPE (reloc->r_info))
|
switch (ELF32_R_TYPE (reloc->r_info))
|
||||||
{
|
{
|
||||||
case R_386_COPY:
|
case R_386_COPY:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, DL_LOOKUP_NOEXEC);
|
||||||
memcpy (reloc_addr, (void *) (loadbase + sym->st_value), sym->st_size);
|
memcpy (reloc_addr, (void *) (loadbase + sym->st_value), sym->st_size);
|
||||||
break;
|
break;
|
||||||
case R_386_GLOB_DAT:
|
case R_386_GLOB_DAT:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
||||||
break;
|
break;
|
||||||
case R_386_JMP_SLOT:
|
case R_386_JMP_SLOT:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 1);
|
loadbase = RESOLVE (&sym, DL_LOOKUP_NOPLT);
|
||||||
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
||||||
break;
|
break;
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
@ -222,7 +222,7 @@ elf_machine_rel (struct link_map *map,
|
|||||||
built-in definitions used while loading those libraries. */
|
built-in definitions used while loading those libraries. */
|
||||||
undo = map->l_addr + sym->st_value;
|
undo = map->l_addr + sym->st_value;
|
||||||
#endif
|
#endif
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
|
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ elf_machine_rel (struct link_map *map,
|
|||||||
*reloc_addr += map->l_addr;
|
*reloc_addr += map->l_addr;
|
||||||
break;
|
break;
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr += ((sym ? (loadbase + sym->st_value) : 0) -
|
*reloc_addr += ((sym ? (loadbase + sym->st_value) : 0) -
|
||||||
(Elf32_Addr) reloc_addr);
|
(Elf32_Addr) reloc_addr);
|
||||||
break;
|
break;
|
||||||
|
@ -205,29 +205,29 @@ elf_machine_rela (struct link_map *map,
|
|||||||
switch (ELF32_R_TYPE (reloc->r_info))
|
switch (ELF32_R_TYPE (reloc->r_info))
|
||||||
{
|
{
|
||||||
case R_68K_COPY:
|
case R_68K_COPY:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, DL_LOOKUP_NOEXEC);
|
||||||
memcpy (reloc_addr, (void *) (loadbase + sym->st_value), sym->st_size);
|
memcpy (reloc_addr, (void *) (loadbase + sym->st_value), sym->st_size);
|
||||||
break;
|
break;
|
||||||
case R_68K_GLOB_DAT:
|
case R_68K_GLOB_DAT:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
||||||
break;
|
break;
|
||||||
case R_68K_JMP_SLOT:
|
case R_68K_JMP_SLOT:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 1);
|
loadbase = RESOLVE (&sym, DL_LOOKUP_NOPLT);
|
||||||
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
||||||
break;
|
break;
|
||||||
case R_68K_8:
|
case R_68K_8:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*(char *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
*(char *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
||||||
+ reloc->r_addend);
|
+ reloc->r_addend);
|
||||||
break;
|
break;
|
||||||
case R_68K_16:
|
case R_68K_16:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*(short *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
*(short *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
||||||
+ reloc->r_addend);
|
+ reloc->r_addend);
|
||||||
break;
|
break;
|
||||||
case R_68K_32:
|
case R_68K_32:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
*reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
||||||
+ reloc->r_addend);
|
+ reloc->r_addend);
|
||||||
break;
|
break;
|
||||||
@ -235,17 +235,17 @@ elf_machine_rela (struct link_map *map,
|
|||||||
*reloc_addr = map->l_addr + reloc->r_addend;
|
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||||
break;
|
break;
|
||||||
case R_68K_PC8:
|
case R_68K_PC8:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*(char *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
*(char *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
||||||
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||||
break;
|
break;
|
||||||
case R_68K_PC16:
|
case R_68K_PC16:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*(short *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
*(short *) reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
||||||
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||||
break;
|
break;
|
||||||
case R_68K_PC32:
|
case R_68K_PC32:
|
||||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
*reloc_addr = ((sym ? (loadbase + sym->st_value) : 0)
|
||||||
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||||
break;
|
break;
|
||||||
|
@ -453,7 +453,7 @@ elf_machine_rel (struct link_map *map,
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
undo = 0;
|
undo = 0;
|
||||||
loadbase = RESOLVE (&sym, (ElfW(Addr)) reloc_addr, 0);
|
loadbase = RESOLVE (&sym, 0);
|
||||||
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
|
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -71,6 +71,7 @@ ENTRY(__clone)
|
|||||||
thread_start:
|
thread_start:
|
||||||
subl %ebp,%ebp /* terminate the stack frame */
|
subl %ebp,%ebp /* terminate the stack frame */
|
||||||
call *%ebx
|
call *%ebx
|
||||||
|
pushl %eax
|
||||||
#ifdef PIC
|
#ifdef PIC
|
||||||
call _exit@PLT
|
call _exit@PLT
|
||||||
#else
|
#else
|
||||||
|
75
sysdeps/unix/sysv/linux/m68k/clone.S
Normal file
75
sysdeps/unix/sysv/linux/m68k/clone.S
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||||
|
Contributed by Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
|
||||||
|
|
||||||
|
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., 675 Mass Ave,
|
||||||
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/* clone is even more special than fork as it mucks with stacks
|
||||||
|
and invokes a function in the right context after its all over. */
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <errnos.h>
|
||||||
|
|
||||||
|
/* int clone (int (*fn) (), void *child_stack, int flags, int nargs, ...) */
|
||||||
|
|
||||||
|
.text
|
||||||
|
ENTRY (__clone)
|
||||||
|
/* Sanity check arguments. */
|
||||||
|
movel #-EINVAL, %d0
|
||||||
|
movel 4(%sp), %a0 /* no NULL function pointers */
|
||||||
|
tstl %a0
|
||||||
|
jeq syscall_error
|
||||||
|
movel 8(%sp), %a1 /* no NULL stack pointers */
|
||||||
|
tstl %a1
|
||||||
|
jeq syscall_error
|
||||||
|
movel 16(%sp), %d1 /* no negative argument counts */
|
||||||
|
jmi syscall_error
|
||||||
|
|
||||||
|
/* Allocate space on the new stack and copy args over */
|
||||||
|
movel %d1, %d0
|
||||||
|
negl %d0
|
||||||
|
lea (%a1,%d0.l*4), %a1
|
||||||
|
jeq 2f
|
||||||
|
1: movel 16(%sp,%d1.l*4), -4(%a1,%d1.l*4)
|
||||||
|
subql #1, %d1
|
||||||
|
jne 1b
|
||||||
|
2:
|
||||||
|
|
||||||
|
/* Do the system call */
|
||||||
|
exg %d2, %a1 /* save %d2 and get stack pointer */
|
||||||
|
movel 12(%sp), %d1 /* get flags */
|
||||||
|
movel #SYS_ify (clone), %d0
|
||||||
|
trap #0
|
||||||
|
exg %d2, %a1 /* restore %d2 */
|
||||||
|
|
||||||
|
tstl %d0
|
||||||
|
jmi syscall_error
|
||||||
|
jeq thread_start
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
SYSCALL_ERROR_HANDLER
|
||||||
|
|
||||||
|
thread_start:
|
||||||
|
subl %fp, %fp /* terminate the stack frame */
|
||||||
|
jsr (%a0)
|
||||||
|
movel %d0, -(%sp)
|
||||||
|
#ifdef PIC
|
||||||
|
bsrl _exit@PLTPC
|
||||||
|
#else
|
||||||
|
jbsr _exit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
weak_alias (__clone, clone)
|
Loading…
Reference in New Issue
Block a user