* manual/Makefile (glibc-targets): Variable and targets removed.
Sat Jul 13 23:50:17 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* manual/Makefile (lib): New phony target. Depend on stamp files.
($(objpfx)stamp%-$(subdir)): New rule to create them when necessary.
1996-07-13 Paul Eggert <eggert@twinsun.com>
* time/strftime.c (strftime): Use space padding for %e, %k, %l,
to match Emacs format-time-string specification.
(DO_NUMBER_SPACEPAD): Renamed from DO_NUMBER_NOPAD.
Sat Jul 13 20:17:38 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* elf/dl-deps.c (_dl_map_object_deps): Take new args PRELOADS and
NPRELOADS, vector of `struct link_map *'s; add them to the searchlist
between MAP and its deps.
* elf/link.h: Fix decl.
* elf/rtld.c (dl_main): If not secure, parse LD_PRELOAD for
colon-separated list of names, map those and pass vector of ptrs as
PRELOADS list to _dl_map_object_deps.
* elf/dl-runtime.c (_dl_object_relocation_scope): Pass new args to
_dl_map_object_deps with empty preload list.
* elf/dl-open.c (_dl_open): Likewise.
* sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_open_zero_fill): Function
removed.
(__mmap): Pass MACH_PORT_NULL for memobj port when (flags & MAP_ANON).
* sysdeps/generic/dl-sysdep.c (_dl_sysdep_open_zero_fill):
Conditionalize defn on [! MAP_ANON].
* elf/dl-minimal.c (malloc): Conditionalize use of _dl_zerofd
on [! MAP_ANON].
* elf/rtld.c (dl_main): Likewise.
* elf/dl-load.c (_dl_zerofd): Conditionalize defn on [! MAP_ANON].
(_dl_map_object_from_fd): Conditionalize initialization of _dl_zerofd.
* elf/dl-fini.c (_dl_fini): Skip finalizer for executable itself.
Sat Jul 13 02:47:53 1996 David Mosberger-Tang <davidm@azstarnet.com>
* stdlib/random.c (__random): Declare as int32_t to be in sync
with declaration.
* socket/Makefile (headers): Add socketbits.h.
* misc/mntent.c (endmntent): Allow for NULL stream. SunOS does
it that way.
* grp/initgroups.c (initgroups): Add groups that user is a member
of, not the ones he is _not_ a member of.
* nss/nsswitch.c (known_compare): Make known_compare() a static
instead of a local function. The latter are difficult to debug
and slow to execute on certain platforms.
* sysdeps/posix/ttyname_r.c (ttyname_r): Use sizeof (dev) - 1 in
place of sizeof (dev). The size of a literal string includes the
NUL byte.
* sysdeps/unix/getlogin.c (getlogin): Initialize ut_fd with -1.
Thu Jul 11 16:59:10 1996 David Mosberger-Tang <davidm@azstarnet.com>
* misc/mntent.c (addmntent): Seek to end of file before writing
entry. Return 1 on error, not -1.
Tue Jul 9 19:08:05 1996 David Mosberger-Tang <davidm@azstarnet.com>
* sysdeps/unix/sysv/linux/syscalls.list: Mark bdflush as EXTRA
syscall.
Fri Jul 5 18:44:55 1996 David Mosberger-Tang <davidm@azstarnet.com>
* sysdeps/unix/sysv/linux/alpha/ioperm.c (port_to_cpu_addr): Size
shift amount for Jensen must be 5 not 4.
Sat Jul 13 20:04:28 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* socket/sys/socket.h (struct osockaddr): New type.
Sat Jul 13 03:50:53 1996 Ulrich Drepper <drepper@cygnus.com>
* misc/Makefile (routines): Add qefgcvt and qefgcvt_r.
* misc/efgcvt.c, misc/efgcvt_r.c: Change code so that the `double'
and `long double' versions can be generated.
* misc/qefgcvt.c, misc/qefgcvt_r.c: New files. Define macros
so that included efgcvt{,_r}.c file generate `long double'
versions.
* stdlib/stdlib.h: Add prototypes for q[efg]cvt() and q[ef]cvt_r()
functions.
* manual/startup.texi: Document new getsubopt function.
* manual/examples/subopt.c: New example program for documenting
getsubopt function.
Fri Jul 12 23:58:37 1996 Ulrich Drepper <drepper@cygnus.com>
* stdlib/Makefile (routines): Add getsubopt.
* stdlib/stdlib.h: Add prototype for getsubopt.
* stdlib/getsubopt.c: New file. Implement getsubopt function
to handle suboption parsing.
+Sun Jul 14 01:51:39 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * manual/Makefile (glibc-targets): Variable and targets removed.
+
+Sat Jul 13 23:50:17 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * manual/Makefile (lib): New phony target. Depend on stamp files.
+ ($(objpfx)stamp%-$(subdir)): New rule to create them when necessary.
+
+1996-07-13 Paul Eggert <eggert@twinsun.com>
+
+ * time/strftime.c (strftime): Use space padding for %e, %k, %l,
+ to match Emacs format-time-string specification.
+ (DO_NUMBER_SPACEPAD): Renamed from DO_NUMBER_NOPAD.
+
+Sat Jul 13 20:17:38 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * elf/dl-deps.c (_dl_map_object_deps): Take new args PRELOADS and
+ NPRELOADS, vector of `struct link_map *'s; add them to the searchlist
+ between MAP and its deps.
+ * elf/link.h: Fix decl.
+ * elf/rtld.c (dl_main): If not secure, parse LD_PRELOAD for
+ colon-separated list of names, map those and pass vector of ptrs as
+ PRELOADS list to _dl_map_object_deps.
+ * elf/dl-runtime.c (_dl_object_relocation_scope): Pass new args to
+ _dl_map_object_deps with empty preload list.
+ * elf/dl-open.c (_dl_open): Likewise.
+
+ * sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_open_zero_fill): Function
+ removed.
+ (__mmap): Pass MACH_PORT_NULL for memobj port when (flags & MAP_ANON).
+ * sysdeps/generic/dl-sysdep.c (_dl_sysdep_open_zero_fill):
+ Conditionalize defn on [! MAP_ANON].
+ * elf/dl-minimal.c (malloc): Conditionalize use of _dl_zerofd
+ on [! MAP_ANON].
+ * elf/rtld.c (dl_main): Likewise.
+ * elf/dl-load.c (_dl_zerofd): Conditionalize defn on [! MAP_ANON].
+ (_dl_map_object_from_fd): Conditionalize initialization of _dl_zerofd.
+
+ * elf/dl-fini.c (_dl_fini): Skip finalizer for executable itself.
+
+Sat Jul 13 02:47:53 1996 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * stdlib/random.c (__random): Declare as int32_t to be in sync
+ with declaration.
+
+ * socket/Makefile (headers): Add socketbits.h.
+
+ * misc/mntent.c (endmntent): Allow for NULL stream. SunOS does
+ it that way.
+
+ * grp/initgroups.c (initgroups): Add groups that user is a member
+ of, not the ones he is _not_ a member of.
+
+ * nss/nsswitch.c (known_compare): Make known_compare() a static
+ instead of a local function. The latter are difficult to debug
+ and slow to execute on certain platforms.
+
+ * sysdeps/posix/ttyname_r.c (ttyname_r): Use sizeof (dev) - 1 in
+ place of sizeof (dev). The size of a literal string includes the
+ NUL byte.
+
+ * sysdeps/unix/getlogin.c (getlogin): Initialize ut_fd with -1.
+
+Thu Jul 11 16:59:10 1996 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * misc/mntent.c (addmntent): Seek to end of file before writing
+ entry. Return 1 on error, not -1.
+
+Tue Jul 9 19:08:05 1996 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * sysdeps/unix/sysv/linux/syscalls.list: Mark bdflush as EXTRA
+ syscall.
+
+Fri Jul 5 18:44:55 1996 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * sysdeps/unix/sysv/linux/alpha/ioperm.c (port_to_cpu_addr): Size
+ shift amount for Jensen must be 5 not 4.
+
+Sat Jul 13 20:04:28 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * socket/sys/socket.h (struct osockaddr): New type.
+
+Sat Jul 13 03:50:53 1996 Ulrich Drepper <drepper@cygnus.com>
+
+ * misc/Makefile (routines): Add qefgcvt and qefgcvt_r.
+ * misc/efgcvt.c, misc/efgcvt_r.c: Change code so that the `double'
+ and `long double' versions can be generated.
+ * misc/qefgcvt.c, misc/qefgcvt_r.c: New files. Define macros
+ so that included efgcvt{,_r}.c file generate `long double'
+ versions.
+ * stdlib/stdlib.h: Add prototypes for q[efg]cvt() and q[ef]cvt_r()
+ functions.
+
+ * manual/startup.texi: Document new getsubopt function.
+ * manual/examples/subopt.c: New example program for documenting
+ getsubopt function.
+
+Fri Jul 12 23:58:37 1996 Ulrich Drepper <drepper@cygnus.com>
+
+ * stdlib/Makefile (routines): Add getsubopt.
+ * stdlib/stdlib.h: Add prototype for getsubopt.
+ * stdlib/getsubopt.c: New file. Implement getsubopt function
+ to handle suboption parsing.
+
Thu Jul 11 20:09:55 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* inet/getnetent_r.c: Define NEED_H_ERRNO.
* string/string.h: Don't define memccpy as macro for [__OPTIMIZE__].
-Thu Jun 27 23:43:22 1996 Richard Henderson <rth@tamu.edu>
-
- * sysdeps/alpha/dl-machine.h (elf_machine_rela): The Alpha's
- address-of operation and plt format conspire to require all
- dynamic relocs to be resolved to actual symbols not plt entries.
-
Thu Jun 27 02:49:28 1996 Ulrich Drepper <drepper@cygnus.com>
* catgets/gencat.c: Add casts to avoid signed<->unsigned warnings.
#include <stdlib.h>
void
-_dl_map_object_deps (struct link_map *map)
+_dl_map_object_deps (struct link_map *map,
+ struct link_map **preloads, unsigned int npreloads)
{
struct list
{
struct link_map *map;
struct list *next;
};
- struct list head, *tailp, *scanp;
+ struct list head[1 + npreloads], *tailp, *scanp;
unsigned int nlist;
/* Start the search list with one element: MAP itself. */
- head.map = map;
- head.next = NULL;
- nlist = 1;
+ head[0].map = map;
+
+ /* Add the preloaded items after MAP but before any of its dependencies. */
+ for (nlist = 0; nlist < npreloads; ++nlist)
+ {
+ head[nlist].next = &head[nlist + 1];
+ head[nlist + 1].map = preloads[nlist];
+ }
+
+ /* Terminate the list. */
+ head[nlist++].next = NULL;
/* We use `l_reserved' as a mark bit to detect objects we have already
put in the search list and avoid adding duplicate elements later in
dependencies and appending them to the list as we step through it.
This produces a flat, ordered list that represents a breadth-first
search of the dependency tree. */
- for (scanp = tailp = &head; scanp; scanp = scanp->next)
+ for (scanp = tailp = head; scanp; scanp = scanp->next)
{
struct link_map *l = scanp->map;
map->l_nsearchlist = nlist;
nlist = 0;
- for (scanp = &head; scanp; scanp = scanp->next)
+ for (scanp = head; scanp; scanp = scanp->next)
{
map->l_searchlist[nlist++] = scanp->map;
struct link_map *l;
for (l = _dl_loaded; l; l = l->l_next)
- if (l->l_init_called && l->l_info[DT_FINI])
+ if (l->l_init_called)
{
- (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
+ if (l->l_info[DT_FINI] &&
+ !(l->l_name[0] == '\0' && l->l_type == lt_executable))
+ (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
/* Make sure nothing happens if we are called twice. */
l->l_init_called = 0;
}
#define STRING(x) #x
+#ifdef MAP_ANON
+/* The fd is not examined when using MAP_ANON. */
+#define ANONFD -1
+#else
int _dl_zerofd = -1;
+#define ANONFD _dl_zerofd
+#endif
+
size_t _dl_pagesize;
if (header->e_phentsize != sizeof (ElfW(Phdr)))
LOSE ("ELF file's phentsize not the expected size");
+#ifndef MAP_ANON
+#define MAP_ANON 0
if (_dl_zerofd == -1)
{
_dl_zerofd = _dl_sysdep_open_zero_fill ();
_dl_signal_error (errno, NULL, "cannot open zero fill device");
}
}
+#endif
/* Enter the new object in the list of loaded objects. */
l = _dl_new_object (realname, name, l_type);
caddr_t mapat;
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
- _dl_zerofd, 0);
+ ANONFD, 0);
if (mapat == (caddr_t) -1)
lose (errno, "cannot map zero-fill pages");
}
void * weak_function
malloc (size_t n)
{
+#ifdef MAP_ANON
+#define _dl_zerofd (-1)
+#else
extern int _dl_zerofd;
- if (_dl_pagesize == 0)
- _dl_pagesize = __getpagesize ();
-
if (_dl_zerofd == -1)
_dl_zerofd = _dl_sysdep_open_zero_fill ();
+#define MAP_ANON 0
+#endif
+
+ if (_dl_pagesize == 0)
+ _dl_pagesize = __getpagesize ();
if (alloc_end == 0)
{
return new;
/* Load that object's dependencies. */
- _dl_map_object_deps (new);
+ _dl_map_object_deps (new, NULL, 0);
/* Relocate the objects loaded. We do this in reverse order so that copy
if (! l->l_searchlist)
/* We must construct the searchlist for this object. */
- _dl_map_object_deps (l);
+ _dl_map_object_deps (l, NULL, 0);
/* The primary scope is this object itself and its
dependencies. */
extern struct link_map *_dl_map_object (struct link_map *loader,
const char *name, int type);
-/* Call _dl_map_object on the dependencies of MAP, and
- set up MAP->l_searchlist. */
-extern void _dl_map_object_deps (struct link_map *map);
+/* Call _dl_map_object on the dependencies of MAP, and set up
+ MAP->l_searchlist. PRELOADS points to a vector of NPRELOADS previously
+ loaded objects that will be inserted into MAP->l_searchlist after MAP
+ but before its dependencies. */
+extern void _dl_map_object_deps (struct link_map *map,
+ struct link_map **preloads,
+ unsigned int npreloads);
/* Cache the locations of MAP's hash table. */
extern void _dl_setup_hash (struct link_map *map);
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/mman.h> /* Check if MAP_ANON is defined. */
#include "../stdio-common/_itoa.h"
struct link_map *l;
int lazy;
int list_only = 0;
+ struct link_map **preloads;
+ unsigned int npreloads;
if (*user_entry == (ElfW(Addr)) &_start)
{
l->l_next = &_dl_rtld_map;
_dl_rtld_map.l_prev = l;
- /* Load all the libraries specified by DT_NEEDED entries. */
- _dl_map_object_deps (l);
+ preloads = NULL;
+ npreloads = 0;
+ if (! _dl_secure)
+ {
+ const char *preloadlist = getenv ("LD_PRELOAD");
+ if (preloadlist)
+ {
+ /* The LD_PRELOAD environment variable gives a colon-separated
+ list of libraries that are loaded before the executable's
+ dependencies and prepended to the global scope list. */
+ char *list = strdupa (preloadlist);
+ char *p;
+ while ((p = strsep (&list, ":")) != NULL)
+ {
+ (void) _dl_map_object (NULL, p, lt_library);
+ ++npreloads;
+ }
+
+ if (npreloads != 0)
+ {
+ /* Set up PRELOADS with a vector of the preloaded libraries. */
+ struct link_map *l;
+ unsigned int i;
+ preloads = __alloca (npreloads * sizeof preloads[0]);
+ l = _dl_rtld_map.l_next; /* End of the chain before preloads. */
+ i = 0;
+ do
+ {
+ preloads[i++] = l;
+ l = l->l_next;
+ } while (l);
+ assert (i == npreloads);
+ }
+ }
+ }
+
+ /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
+ specified some libraries to load, these are inserted before the actual
+ dependencies in the executable's searchlist for symbol resolution. */
+ _dl_map_object_deps (l, preloads, npreloads);
+#ifndef MAP_ANON
/* We are done mapping things, so close the zero-fill descriptor. */
__close (_dl_zerofd);
_dl_zerofd = -1;
+#endif
/* Remove _dl_rtld_map from the chain. */
_dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;
register char **m;
for (m = g->gr_mem; *m != NULL; ++m)
- if (!strcmp (*m, user))
- break;
-
- if (*m == NULL)
- {
- /* Matched the user. Insert this group. */
- if (n == ngroups && limit <= 0)
- {
- /* Need a bigger buffer. */
- groups = memcpy (__alloca (ngroups * 2 * sizeof *groups),
- groups, ngroups * sizeof *groups);
- ngroups *= 2;
- }
-
- groups[n++] = g->gr_gid;
-
- if (n == limit)
- /* Can't take any more groups; stop searching. */
+ if (strcmp (*m, user) == 0)
+ {
+ /* Matches user. Insert this group. */
+ if (n == ngroups && limit <= 0)
+ {
+ /* Need a bigger buffer. */
+ groups = memcpy (__alloca (ngroups * 2 * sizeof *groups),
+ groups, ngroups * sizeof *groups);
+ ngroups *= 2;
+ }
+
+ groups[n++] = g->gr_gid;
+
+ if (n == limit)
+ /* Can't take any more groups; stop searching. */
+ goto done;
+
break;
- }
+ }
}
-
+done:
endgrent ();
return setgroups (n, groups);
uuencode $< < $< > $@.new
mv -f $@.new $@
-# The parent makefile sometimes invokes us with targets `subdir_REAL-TARGET'.
-subdir_%: % ;
-# For targets we don't define, do nothing.
-subdir_%: ;
-
.PHONY: mostlyclean distclean realclean clean
mostlyclean:
-rm -f libc.dvi libc.info*
TAGS: $(minimal-dist)
$(ETAGS) -o $@ $^
\f
-# These are targets that each glibc subdirectory is expected to understand.
-# ../Rules defines them for code subdirectories; for us, they are no-ops.
-glibc-targets := subdir_lib objects objs others tests subdir_lint.out \
- subdir_echo-headers subdir_echo-distinfo stubs
-.PHONY: $(glibc-targets)
-$(glibc-targets):
+# The parent makefile sometimes invokes us with targets `subdir_REAL-TARGET'.
+subdir_%: % ;
+# For targets we don't define, do nothing.
+subdir_%: ;
+# Create stamp files if they don't exist, so the parent makefile's rules for
+# updating the library archives are happy with us, and never think we have
+# changed the library.
+.PHONY: lib stubs
+lib: $(foreach o,$(object-suffixes),$(objpfx)stamp$o-$(subdir))
stubs: $(common-objpfx)stub-manual
-$(common-objpfx)stub-manual ../po/manual.pot:
+$(objpfx)stamp%-$(subdir) $(common-objpfx)stub-manual ../po/manual.pot:
cp /dev/null $@
# The top-level glibc Makefile expects subdir_install to update the stubs file.
subdir_install: stubs
-
\f
# Get rid of these variables if they came from the parent.
routines =
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int do_all;
+const char *type;
+int read_size;
+int write_size;
+int read_only;
+
+enum
+{
+ RO_OPTION = 0,
+ RW_OPTION,
+ READ_SIZE_OPTION,
+ WRITE_SIZE_OPTION
+};
+
+const char *mount_opts[] =
+{
+ [RO_OPTION] = "ro",
+ [RW_OPTION] = "rw",
+ [READ_SIZE_OPTION] = "rsize",
+ [WRITE_SIZE_OPTION] = "wsize"
+};
+
+int
+main (int argc, char *argv[])
+{
+ char *subopts, *value;
+ int opt;
+
+ while ((opt = getopt (argc, argv, "at:o:")) != EOF)
+ switch (opt)
+ {
+ case 'a':
+ do_all = 1;
+ break;
+ case 't':
+ type = optarg;
+ break;
+ case 'o':
+ subopts = optarg;
+ while (*subopts != '\0')
+ switch (getsubopt (&subopts, mount_opts, &value))
+ {
+ case RO_OPTION:
+ read_only = 1;
+ break;
+ case RW_OPTION:
+ read_only = 0;
+ break;
+ case READ_SIZE_OPTION:
+ if (value == NULL)
+ abort ();
+ read_size = atoi (value);
+ break;
+ case WRITE_SIZE_OPTION:
+ if (value == NULL)
+ abort ();
+ write_size = atoi (value);
+ break;
+ default:
+ /* Unknown suboption. */
+ printf ("Unknown suboption `%s'\n", value);
+ break;
+ }
+ break;
+ default:
+ abort ();
+ }
+
+ /* Do the real work. */
+
+ return 0;
+}
@code{main} to take two arguments, and use the value of @code{environ}.
@menu
-* Argument Syntax:: By convention, options start with a hyphen.
-* Parsing Options:: The @code{getopt} function.
-* Example of Getopt:: An example of parsing options with @code{getopt}.
-* Long Options:: GNU suggests utilities accept long-named options.
+* Argument Syntax:: By convention, options start with a hyphen.
+* Parsing Options:: The @code{getopt} function.
+* Example of Getopt:: An example of parsing options with @code{getopt}.
+* Long Options:: GNU suggests utilities accept long-named options.
Here is how to do that.
-* Long Option Example:: An example of using @code{getopt_long}.
+* Long Option Example:: An example of using @code{getopt_long}.
+* Suboptions:: Some programs need more detailed options.
+* Suboptions Example:: This shows how it could be done for @code{mount}.
@end menu
@node Argument Syntax
@include longopt.c.texi
@end smallexample
+@node Suboptions
+@subsection Parsing of Suboptions
+
+Having a single level of options is sometimes not enough. There might
+be too many options which have to be available or a set of options is
+closely related.
+
+For this case some programs use suboptions. One of the most prominent
+programs is certainly @code{mount}(8). The @code{-o} option take one
+argument which itself is a comma separated list of options. To ease the
+programming of code like this the function @code{getsubopt} is
+available.
+
+@comment stdlib.h
+@deftypefun int getsubopt (char **@var{optionp}, const char* const *@var{tokens}, char **@var{valuep})
+
+The @var{optionp} parameter must be a pointer to a variable containing
+the address of the string to process. When the function returns the
+reference is updated to point to the next suboption or to the
+terminating @samp{\0} character if there is no more suboption available.
+
+The @var{tokens} parameter references an array of strings containing the
+known suboptions. All strings must be @samp{\0} terminated and to mark
+the end a null pointer must be stored. When @code{getsubopt} finds a
+possible legal suboption it compares it with all strings available in
+the @var{tokens} array and returns the index in the string as the
+indicator.
+
+In case the suboption has an associated value introduced by a @samp{=}
+character, a pointer to the value is returned in @var{valuep}. The
+string is @samp{\0} terminated. If no argument is available
+@var{valuep} is set to the null pointer. By doing this the caller can
+check whether a necessary value is given or whether no unexpected value
+is present.
+
+In case the next suboption in the string is not mentioned in the
+@var{tokens} array the starting address of the suboption including a
+possible value is returned in @var{valuep} and the return value of the
+function is @samp{-1}.
+@end deftypefun
+
+@node Suboptions Example
+@subsection Parsing of Suboptions Example
+
+The code which might appear in the @code{mount}(8) program is a perfect
+example of the use of @code{getsubopt}:
+
+@smallexample
+@include subopt.c.texi
+@end smallexample
+
+
@node Environment Variables
@section Environment Variables
@menu
-* Environment Access:: How to get and set the values of
+* Environment Access:: How to get and set the values of
environment variables.
-* Standard Environment:: These environment variables have
+* Standard Environment:: These environment variables have
standard interpretations.
@end menu
insremque getttyent getusershell getpass ttyslot \
syslog syscall daemon \
mmap munmap mprotect msync madvise \
- efgcvt efgcvt_r \
+ efgcvt efgcvt_r qefgcvt qefgcvt_r \
hsearch hsearch_r tsearch lsearch \
err error
aux := init-misc
#include <stdlib.h>
#include <float.h>
+#ifndef FLOAT_TYPE
+#define FLOAT_TYPE double
+#define FUNC_PREFIX
+#define FLOAT_FMT_FLAG
#define MAXDIG (DBL_DIG + DBL_MAX_10_EXP)
+#endif
+
+#define APPEND(a, b) APPEND2 (a, b)
+#define APPEND2(a, b) a##b
+
char *
-fcvt (value, ndigit, decpt, sign)
- double value;
+APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign)
+ FLOAT_TYPE value;
int ndigit, *decpt, *sign;
{
static char buf[MAXDIG];
}
char *
-ecvt (value, ndigit, decpt, sign)
- double value;
+APPEND (FUNC_PREFIX, ecvt) (value, ndigit, decpt, sign)
+ FLOAT_TYPE value;
int ndigit, *decpt, *sign;
{
static char buf[MAXDIG];
}
char *
-gcvt (value, ndigit, buf)
- double value;
+APPEND (FUNC_PREFIX, gcvt) (value, ndigit, buf)
+ FLOAT_TYPE value;
int ndigit;
char *buf;
{
- sprintf (buf, "%.*g", ndigit, value);
+ sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", ndigit, value);
return buf;
}
/* [efg]cvt -- compatibility functions for floating point formatting,
- reentrent versions.
+ reentrant versions.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
#include <math.h>
#include <stdlib.h>
+#ifndef FLOAT_TYPE
+#define FLOAT_TYPE double
+#define FUNC_PREFIX
+#define FLOAT_FMT_FLAG
+#define FLOAT_NAME_EXT
+#endif
+
+#define APPEND(a, b) APPEND2 (a, b)
+#define APPEND2(a, b) a##b
+
+#define FLOOR APPEND(floor, FLOAT_NAME_EXT)
+#define FABS APPEND(fabs, FLOAT_NAME_EXT)
+#define LOG10 APPEND(log10, FLOAT_NAME_EXT)
+
+
int
-fcvt_r (value, ndigit, decpt, sign, buf, len)
- double value;
+APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len)
+ FLOAT_TYPE value;
int ndigit, *decpt, *sign;
char *buf;
size_t len;
if (*sign)
value = - value;
- n = snprintf (buf, len, "%.*f", ndigit, value);
+ n = snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", ndigit, value);
if (n < 0)
return -1;
return 0;
}
-weak_extern (floor) weak_extern (log10) weak_extern (fabs)
+#define weak_extern2(name) weak_extern (name)
+weak_extern2 (FLOOR) weak_extern2 (LOG10) weak_extern2 (FABS)
int
-ecvt_r (value, ndigit, decpt, sign, buf, len)
- double value;
+APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, buf, len)
+ FLOAT_TYPE value;
int ndigit, *decpt, *sign;
char *buf;
size_t len;
{
- double (*log10_function) (double) = &log10;
+ FLOAT_TYPE (*log10_function) (FLOAT_TYPE) = &LOG10;
if (log10_function)
{
/* Use the reasonable code if -lm is included. */
- ndigit -= (int) floor (log10 (fabs (value)));
+ ndigit -= (int) FLOOR (LOG10 (FABS (value)));
if (ndigit < 0)
ndigit = 0;
}
else
{
/* Slow code that doesn't require -lm functions. */
- double d;
+ FLOAT_TYPE d;
for (d = value < 0.0 ? - value : value;
ndigit > 0 && d >= 10.0;
d *= 0.1)
--ndigit;
}
- return fcvt_r (value, ndigit, decpt, sign, buf, len);
+ return APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len);
}
int
endmntent (FILE *stream)
{
- if (fclose (stream) != 0)
- return 0;
- return 1;
+ if (stream) /* SunOS 4.x allows for NULL stream */
+ fclose (stream);
+ return 1; /* SunOS 4.x says to always return 1 */
}
int
addmntent (FILE *stream, const struct mntent *mnt)
{
+ if (fseek (stream, 0, SEEK_END))
+ return 1;
+
return (fprintf (stream, "%s %s %s %s %d %d\n",
mnt->mnt_fsname,
mnt->mnt_dir,
mnt->mnt_opts,
mnt->mnt_freq,
mnt->mnt_passno)
- < 0 ? -1 : 0);
+ < 0 ? 1 : 0);
}
/* Search MNT->mnt_opts for an option matching OPT.
--- /dev/null
+/* q[efg]cvt -- compatibility functions for floating point formatting,
+ long double version.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define FLOAT_TYPE long double
+#define FUNC_PREFIX q
+#define FLOAT_FMT_FLAG "L"
+#define MAXDIG (LDBL_DIG + LDBL_MAX_10_EXP)
+
+#include "efgcvt.c"
--- /dev/null
+/* [efg]cvt -- compatibility functions for floating point formatting,
+ reentrant, long double versions.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define FLOAT_TYPE long double
+#define FUNC_PREFIX q
+#define FLOAT_FMT_FLAG "L"
+#define FLOAT_NAME_EXT l
+
+#include "efgcvt_r.c"
}
+/* Comparison function for searching NI->known tree. */
+static int
+known_compare (const void *p1, const void *p2)
+{
+ return p1 == p2 ? 0 : strcmp (*(const char *const *) p1,
+ *(const char *const *) p2);
+}
+
+
static void *
nss_lookup_function (service_user *ni, const char *fct_name)
{
- /* Comparison function for searching NI->known tree. */
- int known_compare (const void *p1, const void *p2)
- {
- return p1 == p2 ? 0 : strcmp (*(const char *const *) p1,
- *(const char *const *) p2);
- }
void **found, *result;
/* We now modify global data. Protect it. */
#
subdir := socket
-headers := sys/socket.h sys/un.h sockaddrcom.h
+headers := sys/socket.h sys/un.h sockaddrcom.h socketbits.h
routines := accept bind connect getpeername getsockname getsockopt \
listen recv recvfrom recvmsg send sendmsg sendto \
`struct msghdr', and `struct linger' types. */
#include <socketbits.h>
+#ifdef __USE_BSD
+/* This is the 4.3 BSD `struct sockaddr' format, which is used as wire
+ format in the grotty old 4.3 `talk' protocol. */
+struct osockaddr
+ {
+ unsigned short int sa_family;
+ unsigned char sa_data[14];
+ };
+#endif
/* This is the type we use for generic socket address arguments.
strtof strtod strtold \
system canonicalize \
a64l l64a \
- rpmatch strfmon
+ rpmatch strfmon getsubopt
distribute := exit.h grouping.h
tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
--- /dev/null
+/* getsubopt -- parse comma separate list into words
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Parse comma separated suboption from *OPTIONP and match against
+ strings in TOKENS. If found return index and set *VALUEP to
+ optional value introduced by an equal sign. If the suboption is
+ not part of TOKENS return in *VALUEP beginning of unknown
+ suboption. On exit *OPTIONP is set to the beginning of the next
+ otken or at the terminating NUL character. */
+int
+getsubopt (optionp, tokens, valuep)
+ char **optionp;
+ const char *const *tokens;
+ char **valuep;
+{
+ char *endp, *vstart;
+ int cnt;
+
+ if (**optionp == '\0')
+ return -1;
+
+ /* Find end of next token. */
+ endp = strchr (*optionp, ',');
+ if (endp == NULL)
+ endp = strchr (*optionp, '\0');
+
+ /* Find start of value. */
+ vstart = memchr (*optionp, '=', endp - *optionp);
+ if (vstart == NULL)
+ vstart = endp;
+
+ /* Try to match the characters between *OPTIONP and VSTART against
+ one of the TOKENS. */
+ for (cnt = 0; tokens[cnt] != NULL; ++cnt)
+ if (memcmp (*optionp, tokens[cnt], vstart - *optionp) == 0
+ && tokens[cnt][vstart - *optionp] == '\0')
+ {
+ /* We found the current option in TOKENS. */
+ *valuep = vstart != endp ? vstart : NULL;
+
+ if (*endp != '\0')
+ *endp++ = '\0';
+ *optionp = endp;
+
+ return cnt;
+ }
+
+ /* The current suboption does not match any option. */
+ *valuep = *optionp;
+
+ if (*endp != '\0')
+ *endp++ = '\0';
+ *optionp = endp;
+
+ return -1;
+}
rear pointers can't wrap on the same call by not testing the rear
pointer if the front one has wrapped. Returns a 31-bit random number. */
-int
+int32_t
__random ()
{
int32_t retval;
be written to BUF. */
char *gcvt __P ((double __value, int __ndigit, char *__buf));
+/* Long double versions of above functions. */
+char *qecvt __P ((__long_double_t __value, int __ndigit, int *__decpt,
+ int *sign));
+char *qfcvt __P ((__long_double_t __value, int __ndigit, int *__decpt,
+ int *sign));
+char *qgcvt __P ((__long_double_t __value, int __ndigit, char *__buf));
+
+
+#ifdef __USE_REENTRANT
/* Reentrant version of the functions above which provide their own
buffers. */
int ecvt_r __P ((double __value, int __ndigit, int *__decpt, int *sign,
char *__buf, size_t __len));
int fcvt_r __P ((double __value, int __ndigit, int *__decpt, int *sign,
char *__buf, size_t __len));
+
+int qecvt_r __P ((__long_double_t __value, int __ndigit, int *__decpt,
+ int *sign, char *__buf, size_t __len));
+int qfcvt_r __P ((__long_double_t __value, int __ndigit, int *__decpt,
+ int *sign, char *__buf, size_t __len));
+#endif
#endif
#endif
+#ifdef __USE_MISC
+/* Parse comma separated suboption from *OPTIONP and match against
+ strings in TOKENS. If found return index and set *VALUEP to
+ optional value introduced by an equal sign. If the suboption is
+ not part of TOKENS return in *VALUEP beginning of unknown
+ suboption. On exit *OPTIONP is set to the beginning of the next
+ otken or at the terminating NUL character. */
+extern int getsubopt __P ((char **__optionp, __const char *__const *__tokens,
+ char **__valuep));
+#endif
+
+
__END_DECLS
#endif /* stdlib.h */
--- /dev/null
+#include <socket/sys/socket.h>
{
}
+#ifndef MAP_ANON
+/* This is only needed if the system doesn't support MAP_ANON. */
+
int
_dl_sysdep_open_zero_fill (void)
{
return __open ("/dev/zero", O_RDONLY);
}
+#endif
void
_dl_sysdep_fatal (const char *msg, ...)
__mach_port_deallocate (__mach_task_self (), __mach_task_self_);
}
\f
-int
-_dl_sysdep_open_zero_fill (void)
-{
- /* The minimal mmap below uses the fd as a memory object port.
- The real mmap used for dlopen ignores the fd for MAP_ANON. */
- return (int) MACH_PORT_NULL;
-}
-
-
void
_dl_sysdep_fatal (const char *msg, ...)
{
err = __vm_map (__mach_task_self (),
&mapaddr, (vm_size_t) len, 0 /*ELF_MACHINE_USER_ADDRESS_MASK*/,
!(flags & MAP_FIXED),
- (mach_port_t) fd, (vm_offset_t) offset,
+ (flags & MAP_ANON) ? MACH_PORT_NULL : (mach_port_t) fd,
+ (vm_offset_t) offset,
flags & (MAP_COPY|MAP_PRIVATE),
vmprot, VM_PROT_ALL,
(flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
/* Test for the absolute minimal size. This makes life easier inside
the loop. */
- if (buflen < (int) (sizeof (dev) + 2))
+ if (buflen < (int) (sizeof (dev) + 1))
{
errno = EINVAL;
return -1;
return -1;
/* Prepare the result buffer. */
- memcpy (buf, dev, sizeof (dev));
- buf[sizeof (dev)] = '/';
- buflen -= sizeof (dev) + 1;
+ memcpy (buf, dev, sizeof (dev) - 1);
+ buf[sizeof (dev) - 1] = '/';
+ buflen -= sizeof (dev);
while ((d = readdir (dirstream)) != NULL)
if (d->d_fileno == myino)
{
char *cp;
- cp = __stpncpy (&buf[sizeof (dev) + 1], d->d_name,
+ cp = __stpncpy (&buf[sizeof (dev)], d->d_name,
MIN ((int) (_D_EXACT_NAMLEN (d) + 1), buflen));
cp[0] = '\0';
char tty_pathname[2 + 2 * NAME_MAX];
char *real_tty_path = tty_pathname;
char *result = NULL;
- static struct utmp_data utmp_data;
+ static struct utmp_data utmp_data = { ut_fd: -1 };
struct utmp *ut, line;
{
err = errno;
(void) close (d);
- if (errno != 0)
+ if (err != 0)
{
errno = err;
return NULL;
port_to_cpu_addr (unsigned long port, int iosys, int size)
{
if (iosys == IOSYS_JENSEN)
- {
- return (port << 7) + ((size - 1) << 4) + io.base;
- }
+ return (port << 7) + ((size - 1) << 5) + io.base;
else
- {
- return (port << 5) + ((size - 1) << 3) + io.base;
- }
+ return (port << 5) + ((size - 1) << 3) + io.base;
}
}
else
{
- char name[256];
FILE * fp;
fp = fopen (PATH_CPUINFO, "r");
if (!fp)
return -1;
- while ((n = fscanf (fp, "%256[^:]: %256[^\n]\n", name, systype)) != EOF)
+ while ((n = fscanf (fp, "system type : %256[^\n]\n", systype))
+ != EOF)
{
- if (n == 2 && strncmp (name, "system type", 11) == 0) {
+ if (n == 1)
break;
- }
+ else
+ fgets (systype, 256, fp);
}
fclose(fp);
# File name Caller Syscall name # args Strong name Weak names
adjtimex adjtime adjtimex 1 __adjtimex
-bdflush - bdflush 2 bdflush
+bdflush EXTRA bdflush 2 bdflush
create_module EXTRA create_module 3 create_module
delete_module EXTRA delete_module 3 delete_module
fdatasync - fdatasync 1 fdatasync
#define DO_NUMBER(digits, value) \
maxdigits = digits; number_value = value; goto do_number
-#define DO_NUMBER_NOPAD(digits, value) \
- maxdigits = digits; number_value = value; goto do_number_nopad
+#define DO_NUMBER_SPACEPAD(digits, value) \
+ maxdigits = digits; number_value = value; goto do_number_spacepad
case 'C':
DO_NUMBER (2, (1900 + tp->tm_year) / 100);
DO_NUMBER (2, tp->tm_mday);
case 'e': /* GNU extension: %d, but blank-padded. */
- DO_NUMBER_NOPAD (2, tp->tm_mday);
+ DO_NUMBER_SPACEPAD (2, tp->tm_mday);
/* All numeric formats set MAXDIGITS and NUMBER_VALUE and then
jump to one of these two labels. */
- do_number_nopad:
- /* Force `-' flag. */
- pad = pad_none;
+ do_number_spacepad:
+ /* Force `_' flag. */
+ pad = pad_space;
do_number:
{
DO_NUMBER (2, hour12);
case 'k': /* GNU extension. */
- DO_NUMBER_NOPAD (2, tp->tm_hour);
+ DO_NUMBER_SPACEPAD (2, tp->tm_hour);
case 'l': /* GNU extension. */
- DO_NUMBER_NOPAD (2, hour12);
+ DO_NUMBER_SPACEPAD (2, hour12);
case 'j':
DO_NUMBER (3, 1 + tp->tm_yday);