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
|
||||
@rm -f $@.new
|
||||
$(XGETTEXT) --keyword=_ --keyword=N_ --add-comments=TRANS --sort-output -d - \
|
||||
$(XGETTEXTFLAGS-$(@F)) > $@.new $^
|
||||
$(XGETTEXT) --keyword=_ --keyword=N_ --add-comments=TRANS --sort-output \
|
||||
--omit-header -n -d - $(XGETTEXTFLAGS-$(@F)) > $@.new $^
|
||||
mv -f $@.new $@
|
||||
endef
|
||||
|
||||
@ -146,15 +146,12 @@ else
|
||||
endif
|
||||
|
||||
$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.
|
||||
XGETTEXTFLAGS-siglist.pot = -a --no-location
|
||||
XGETTEXTFLAGS-errlist.pot = -a --no-location
|
||||
|
||||
all-pot = $P/libc-top.pot $P/subdirs.pot \
|
||||
$P/siglist.pot $P/errlist.pot
|
||||
all-pot = $P/libc-top.pot $P/subdirs.pot $P/siglist.pot
|
||||
|
||||
ifndef subdir
|
||||
# Collect all the subdir messages, massaging the file names in comments
|
||||
@ -173,7 +170,7 @@ $P/SYS_libc.pot: $(all-pot)
|
||||
@rm -f $@.new
|
||||
sed -e 's/VERSION/$(version)/' -e "s/DATE/`date +'%Y-%m-%d %k:%M'`/" \
|
||||
po/header.pot > $@.new
|
||||
$(XGETTEXT) -d - -n -s --omit-header $^ >> $@.new
|
||||
$(XGETTEXT) -d - --omit-header -n -s $^ >> $@.new
|
||||
mv -f $@.new $@
|
||||
test ! -d CVS || cvs ci -m'Regenerated from source files' $@
|
||||
|
||||
|
@ -454,9 +454,10 @@ endef
|
||||
object-suffixes-left := $(object-suffixes)
|
||||
include $(o-iterator)
|
||||
define do-ar
|
||||
topdir=`cd $(..).; pwd`; \
|
||||
$(patsubst %,cd %;,$(objdir)) \
|
||||
$(AUTOLOCK) ${O%-lib}.lck $(AR) cru$(verbose) ${O%-lib} \
|
||||
$(patsubst $(objpfx)%,%,$^)
|
||||
$$topdir/autolock.sh ${O%-lib}.lck $(AR) cru$(verbose) ${O%-lib} \
|
||||
$(patsubst $(objpfx)%,%,$^)
|
||||
rm -f $@
|
||||
touch $@
|
||||
endef
|
||||
@ -474,7 +475,9 @@ define o-iterator-doit
|
||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)($(ar-symtab-name)): \
|
||||
$(common-objpfx)$(patsubst %,$(libtype$o),c)(\
|
||||
$(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)
|
||||
endef
|
||||
ifndef subdir
|
||||
|
@ -34,7 +34,6 @@ CC = @CC@
|
||||
BUILD_CC = @BUILD_CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
AR = @AR@
|
||||
AUTOLOCK = @AUTOLOCK@
|
||||
RANLIB = @RANLIB@
|
||||
AS = $(CC) -c
|
||||
|
||||
|
@ -308,8 +308,6 @@ fi
|
||||
AC_PROG_CPP
|
||||
AC_CHECK_TOOL(AR, ar)
|
||||
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
|
||||
echo '#include <stddef.h>
|
||||
|
@ -70,11 +70,25 @@ int _dl_zerofd = -1;
|
||||
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
|
||||
opened on FD. */
|
||||
|
||||
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 *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;
|
||||
free (l);
|
||||
}
|
||||
free (name);
|
||||
free (realname);
|
||||
_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.
|
||||
Just bump its reference count and return it. */
|
||||
__close (fd);
|
||||
free (name);
|
||||
free (realname);
|
||||
++l->l_opencount;
|
||||
return l;
|
||||
@ -524,11 +540,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type)
|
||||
fd = __open (cached, O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
size_t cl = strlen (cached) + 1;
|
||||
realname = malloc (cl);
|
||||
if (realname)
|
||||
memcpy (realname, cached, cl);
|
||||
else
|
||||
realname = local_strdup (cached);
|
||||
if (realname == NULL)
|
||||
{
|
||||
__close (fd);
|
||||
fd = -1;
|
||||
@ -548,11 +561,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type)
|
||||
fd = __open (name, O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
size_t len = strlen (name) + 1;
|
||||
realname = malloc (len);
|
||||
if (realname)
|
||||
memcpy (realname, name, len);
|
||||
else
|
||||
realname = local_strdup (name);
|
||||
if (realname == NULL)
|
||||
{
|
||||
__close (fd);
|
||||
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)
|
||||
_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
|
||||
UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero,
|
||||
then a PLT entry cannot satisfy the reference; some different binding
|
||||
must be found. */
|
||||
UNDEF_NAME. FLAGS is a set of flags. If DL_LOOKUP_NOEXEC is set,
|
||||
then don't search the executable for a definition; this used for
|
||||
copy relocs. If DL_LOOKUP_NOPLT is set, then a PLT entry cannot
|
||||
satisfy the reference; some different binding must be found. */
|
||||
|
||||
ElfW(Addr)
|
||||
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||
struct link_map *symbol_scope[],
|
||||
const char *reference_name,
|
||||
ElfW(Addr) reloc_addr,
|
||||
int noplt)
|
||||
int flags)
|
||||
{
|
||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||
struct
|
||||
@ -75,6 +75,10 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||
|
||||
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);
|
||||
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];
|
||||
|
||||
if (sym->st_value == 0 || /* No value. */
|
||||
/* Cannot resolve to the location being filled in. */
|
||||
reloc_addr == map->l_addr + sym->st_value ||
|
||||
(noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */
|
||||
((flags & DL_LOOKUP_NOPLT) != 0 /* Reject PLT entry. */
|
||||
&& sym->st_shndx == SHN_UNDEF))
|
||||
continue;
|
||||
|
||||
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);
|
||||
|
||||
/* 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, \
|
||||
l->l_name, reloc_addr, noplt))
|
||||
l->l_name, flags))
|
||||
|
||||
#include "dynamic-link.h"
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy);
|
||||
|
@ -122,9 +122,9 @@ fixup (
|
||||
|
||||
{
|
||||
/* 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, \
|
||||
l->l_name, reloc_addr, noplt))
|
||||
l->l_name, flags))
|
||||
#include "dynamic-link.h"
|
||||
|
||||
/* Perform the specified relocation. */
|
||||
|
@ -28,6 +28,6 @@ _dl_symbol_value (struct link_map *map, const char *name)
|
||||
ElfW(Addr) loadbase;
|
||||
const ElfW(Sym) *ref = 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;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ dlsym (void *handle, const char *name)
|
||||
scope = &(_dl_global_scope ?: _dl_default_scope)[2];
|
||||
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);
|
||||
|
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
|
||||
l_searchlist (i.e. the segment of the dependency tree starting at that
|
||||
object) is searched in turn. REFERENCE_NAME should name the object
|
||||
containing the reference; it is used in error messages. RELOC_ADDR is
|
||||
the address being fixed up and the chosen symbol cannot be one with this
|
||||
value. If NOPLT is nonzero, then the reference must not be resolved to
|
||||
a PLT entry. */
|
||||
containing the reference; it is used in error messages. FLAGS is a
|
||||
set of flags: */
|
||||
#define DL_LOOKUP_NOEXEC 1 /* Don't search the executable for a
|
||||
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,
|
||||
const ElfW(Sym) **sym,
|
||||
struct link_map *symbol_scope[],
|
||||
const char *reference_name,
|
||||
ElfW(Addr) reloc_addr,
|
||||
int noplt);
|
||||
int flags);
|
||||
|
||||
/* 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);
|
||||
|
@ -62,7 +62,7 @@ _dl_start (void *arg)
|
||||
/* This #define produces dynamic linking inline functions for
|
||||
bootstrap relocation instead of general-purpose relocation. */
|
||||
#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"
|
||||
|
||||
/* 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;
|
||||
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||
&_dl_default_scope[2],
|
||||
"argument", 0, 0);
|
||||
"argument", 0);
|
||||
char buf[20], *bp;
|
||||
buf[sizeof buf - 1] = '\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.
|
||||
* Processes:: How to create processes and run other programs.
|
||||
* 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.
|
||||
* System Information:: Getting information about the
|
||||
hardware and software configuration
|
||||
@ -806,6 +807,13 @@ Functions for Job Control
|
||||
* Process Group Functions:: Functions for manipulating process groups.
|
||||
* 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
|
||||
|
||||
* 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 process.texi
|
||||
@include job.texi
|
||||
@include nss.texi
|
||||
@include users.texi
|
||||
@include sysinfo.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.
|
||||
@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 Unknown origin
|
||||
@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.
|
||||
@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 ANSI
|
||||
@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
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
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}.
|
||||
@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
|
||||
should include the header file @file{grp.h}.
|
||||
@pindex grp.h
|
||||
@ -417,14 +417,14 @@ user_user_id = getuid ();
|
||||
game_user_id = geteuid ();
|
||||
@end smallexample
|
||||
|
||||
Then it can turn off game file access with
|
||||
Then it can turn off game file access with
|
||||
|
||||
@smallexample
|
||||
setuid (user_user_id);
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
and turn it on with
|
||||
and turn it on with
|
||||
|
||||
@smallexample
|
||||
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
|
||||
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:
|
||||
|
||||
@smallexample
|
||||
@ -608,7 +608,7 @@ record_score (int score)
|
||||
@node Tips for Setuid
|
||||
@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.
|
||||
Here are some guidelines for preventing unintended access and
|
||||
minimizing its consequences when it does occur:
|
||||
@ -731,7 +731,7 @@ are declared in the header file @file{pwd.h}.
|
||||
@comment pwd.h
|
||||
@comment POSIX.1
|
||||
@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:
|
||||
|
||||
@table @code
|
||||
@ -887,7 +887,7 @@ database are declared in the header file @file{grp.h}.
|
||||
|
||||
@comment grp.h
|
||||
@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 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 };
|
||||
loadbase = _dl_lookup_symbol (name, &ref,
|
||||
scope, map->l_name, 0, 0);
|
||||
scope, map->l_name, 0);
|
||||
}
|
||||
|
||||
/* 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"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: ENCODING\n"
|
||||
|
||||
|
@ -66,7 +66,7 @@ struct spwd *
|
||||
__sgetspent_r (const char *string, struct spwd *result, char *buffer,
|
||||
int buflen)
|
||||
{
|
||||
return parse_line (strncpy (string, buffer, buflen), result, NULL, 0)
|
||||
return parse_line (strncpy (buffer, string, buflen), result, NULL, 0)
|
||||
? result : NULL;
|
||||
}
|
||||
weak_alias (__sgetspent_r, sgetspent_r)
|
||||
|
@ -378,7 +378,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
|
||||
in the format described in <locale.h>. */
|
||||
const char *grouping;
|
||||
|
||||
assert (sizeof (wchar_t) <= sizeof (wint_t));
|
||||
assert (sizeof (wchar_t) == sizeof (wint_t));
|
||||
|
||||
if (group)
|
||||
{
|
||||
|
@ -31,8 +31,6 @@ __strdup (const char *s)
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (new, s, len);
|
||||
|
||||
return (char *) new;
|
||||
return (char *) memcpy (new, s, len);
|
||||
}
|
||||
weak_alias (__strdup, strdup)
|
||||
|
@ -341,8 +341,8 @@ elf_machine_rela (struct link_map *map,
|
||||
{
|
||||
Elf64_Addr loadbase, sym_value;
|
||||
|
||||
loadbase = RESOLVE (&sym, (Elf64_Addr)reloc_addr,
|
||||
r_info == R_ALPHA_JMP_SLOT);
|
||||
loadbase = RESOLVE (&sym,
|
||||
r_info == R_ALPHA_JMP_SLOT ? DL_LOOKUP_NOPLT : 0);
|
||||
sym_value = sym ? loadbase + sym->st_value : 0;
|
||||
|
||||
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))
|
||||
{
|
||||
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);
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
case R_386_32:
|
||||
@ -222,7 +222,7 @@ elf_machine_rel (struct link_map *map,
|
||||
built-in definitions used while loading those libraries. */
|
||||
undo = map->l_addr + sym->st_value;
|
||||
#endif
|
||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
||||
loadbase = RESOLVE (&sym, 0);
|
||||
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
|
||||
break;
|
||||
}
|
||||
@ -233,7 +233,7 @@ elf_machine_rel (struct link_map *map,
|
||||
*reloc_addr += map->l_addr;
|
||||
break;
|
||||
case R_386_PC32:
|
||||
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
|
||||
loadbase = RESOLVE (&sym, 0);
|
||||
*reloc_addr += ((sym ? (loadbase + sym->st_value) : 0) -
|
||||
(Elf32_Addr) reloc_addr);
|
||||
break;
|
||||
|
@ -205,29 +205,29 @@ elf_machine_rela (struct link_map *map,
|
||||
switch (ELF32_R_TYPE (reloc->r_info))
|
||||
{
|
||||
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);
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
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)
|
||||
+ reloc->r_addend);
|
||||
break;
|
||||
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)
|
||||
+ reloc->r_addend);
|
||||
break;
|
||||
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->r_addend);
|
||||
break;
|
||||
@ -235,17 +235,17 @@ elf_machine_rela (struct link_map *map,
|
||||
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||
break;
|
||||
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)
|
||||
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||
break;
|
||||
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)
|
||||
+ reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||
break;
|
||||
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->r_addend - (Elf32_Addr) reloc_addr);
|
||||
break;
|
||||
|
@ -453,7 +453,7 @@ elf_machine_rel (struct link_map *map,
|
||||
else
|
||||
#endif
|
||||
undo = 0;
|
||||
loadbase = RESOLVE (&sym, (ElfW(Addr)) reloc_addr, 0);
|
||||
loadbase = RESOLVE (&sym, 0);
|
||||
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
|
||||
}
|
||||
break;
|
||||
|
@ -71,6 +71,7 @@ ENTRY(__clone)
|
||||
thread_start:
|
||||
subl %ebp,%ebp /* terminate the stack frame */
|
||||
call *%ebx
|
||||
pushl %eax
|
||||
#ifdef PIC
|
||||
call _exit@PLT
|
||||
#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