diff options
48 files changed, 1830 insertions, 316 deletions
diff --git a/ChangeLog b/ChangeLog index e08445df95..f3b284705f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,120 @@ +1999-12-17 Ulrich Drepper <drepper@cygnus.com> + + * string/bits/string2.h (__strtok_r_1c): Help gcc optimizing string + access. + + * locale/programs/ld-collate.c: Implement handling of absolute + ellipsis. Parsing of file and constructing the internal data + structures should now be complete. + (collate_finish): Start adding support to generate the data + structures which are written out to the file. + + * intl/dcgettext.c: Rewrite to handle caching of previous results here + instead of in the dcgettext macro. + * intl/libintl.h (dcgettext): Don't define for systems using this + glibc or systems with tsearch. + + * sysdeps/generic/mathdef.h: Protect definitions for math.h + against double inclusion. + * sysdeps/alpha/fpu/bits/mathdef.h: Likewise. + * sysdeps/i386/fpu/bits/mathdef.h: Likewise. + * sysdeps/m68k/fpu/bits/mathdef.h: Likewise. + * sysdeps/powerpc/fpu/bits/mathdef.h: Likewise. + + * sysdeps/i386/fpu/libm-test-ulps: Add more deltas (are mobile PIIs + that different?). + +1999-12-17 Andreas Jaeger <aj@suse.de> + + * rt/aio.h (struct aiocb64): Add member __next_prio to sync the + struct with aiocb. + + * rt/Makefile (tests): Added tst-aio64. + Added dependency rules for tst-aio64. + + * rt/tst-aio64.c: New file, copied from tst-aio.c and changed for + 64bit tests. + +1999-12-15 Thorsten Kukuk <kukuk@suse.de> + + * sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c: Removed. + * sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c: Removed. + * sysdeps/unix/sysv/linux/bits/resource.h: Change RLIM_INFINITY back to + old value (signed long). + * sysdeps/unix/sysv/linux/i386/bits/resource.h: New, with unsigned + long RLIM_INFINITY. + * sysdeps/unix/sysv/linux/getrlimit.c: Moved from here to ... + * sysdeps/unix/sysv/linux/i386/getrlimit.c: ... here. + * sysdeps/unix/sysv/linux/getrlimit64.c: Moved from here to ... + * sysdeps/unix/sysv/linux/i386/getrlimit64.c: ... here. + * sysdeps/unix/sysv/linux/oldgetrlimit64.c: Moved from here to ... + * sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c: ... here. + * sysdeps/unix/sysv/linux/oldsetrlimit64.c: Moved from here to ... + * sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c: ... here. + * sysdeps/unix/sysv/linux/setrlimit.c: Moved from here to ... + * sysdeps/unix/sysv/linux/i386/setrlimit.c: ... here. + * sysdeps/unix/sysv/linux/setrlimit64.c: Moved from here to ... + * sysdeps/unix/sysv/linux/i386/setrlimit64.c: ... here. + * sysdeps/unix/sysv/linux/sparc/bits/resource.h: New. + * sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c: Removed. + * sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c: Removed. + +1999-12-17 Andreas Jaeger <aj@suse.de> + + * elf/ldconfig.c: Add new option -l to manualy link shared + libraries. + (options): Added option. + (parse_opt): Set option. + (main): Handle option. + (manual_link): New function. + +1999-12-17 Thorsten Kukuk <kukuk@suse.de> + + * string/bits/string2.h: Fix patch from 1999-12-07. + +1999-12-16 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/generic/strsep.c: If delim string has only one character + don't run over end of string. + + * locale/programs/ld-collate.c (insert_weights): Also update next + pointer of last cursor element. + (insert_value): Return nonzero value if nothing got inserted. + (handle_ellipsis): Don't do anything if to-value cannot be inserted. + +1999-12-10 Jakub Jelinek <jakub@redhat.com> + + * stdlib/longlong.h (__sparc_v9__): Use %rDIGIT instead of %DIGIT + where appropriate. + +1999-12-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c (__sigaction): + Copy sa_flags into kernel sigaction structure. + +1999-12-14 Andreas Jaeger <aj@suse.de> + + * string/tester.c (test_strsep): More tests for access beyond + the final NUL. The first two tests come from PR libc/1486 by + martinea@iro.umontreal.ca. + +1999-12-14 Thorsten Kukuk <kukuk@suse.de> + + * nis/ypclnt.c: Correct handling of cached client handles. + (__xdr_ypresp_all): Call callback function for errors, too, + like Solaris does. + * nis/nss_compat/compat-grp.c: Make sure errno is always set correct. + * nis/nss_compat/compat-initgroups.c: Likewise. + * nis/nss_compat/compat-spwd.c: Likewise. + * nis/nss_nis/nis-alias.c: Likewise. + * nis/nss_nis/nis-ethers.c: Likewise. + * nis/nss_nis/nis-grp.c: Likewise. + * nis/nss_nis/nis-hosts.c: Likewise. + * nis/nss_nis/nis-netgrp.c: Likewise. + * nis/nss_nis/nis-publickey.c: Likewise. + * nis/nss_nis/nis-service.c: Likewise. Also use services.byservicename + Map if available, optimize query if name/port and protocol is known. + 1999-12-12 Ulrich Drepper <drepper@cygnus.com> * locale/programs/ld-collate.c (collate_read): Make symbolic diff --git a/bits/mathdef.h b/bits/mathdef.h index d306e54366..0c30b01f52 100644 --- a/bits/mathdef.h +++ b/bits/mathdef.h @@ -20,7 +20,9 @@ # error "Never use <bits/mathdef.h> directly; include <math.h> instead" #endif -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + /* Normally, there is no long double type and the `float' and `double' expressions are evaluated as `double'. */ typedef double float_t; /* `float' expressions are evaluated as diff --git a/elf/ldconfig.c b/elf/ldconfig.c index 6c2bcb2d4f..98a4817202 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -97,6 +97,9 @@ static int opt_only_cline = 0; /* Path to root for chroot. */ static char *opt_chroot; +/* Manually link given shared libraries. */ +static int opt_manual_link = 0; + /* Cache file to use. */ static const char *cache_file; @@ -119,6 +122,7 @@ static const struct argp_option options[] = { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0}, { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0}, { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0}, + { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0}, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -148,6 +152,9 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'f': config_file = arg; break; + case 'l': + opt_manual_link = 1; + break; case 'N': opt_build_cache = 0; break; @@ -323,6 +330,75 @@ create_links (const char *path, const char *libname, const char *soname) fputs ("\n", stdout); } +/* Manually link the given library. */ +static void +manual_link (char *library) +{ + char *path; + char *libname; + char *soname; + struct stat stat_buf; + int flag; + + /* Prepare arguments for create_links call. Split library name in + directory and filename first. Since path is allocated, we've got + to be careful to free at the end. */ + path = xstrdup (library); + libname = strrchr (path, '/'); + + if (libname) + { + /* Successfully split names. Check if path is just "/" to avoid + an empty path. */ + if (libname == path) + { + libname = library + 1; + path = xrealloc (path, 2); + strcpy (path, "/"); + } + else + { + *libname = '\0'; + ++libname; + } + } + else + { + /* There's no path, construct one. */ + libname = library; + path = xrealloc (path, 2); + strcpy (path, "."); + } + + /* Do some sanity checks first. */ + if (lstat (library, &stat_buf)) + { + error (0, errno, _("Can't lstat %s"), library); + free (path); + return; + } + /* We don't want links here! */ + else if (!S_ISREG (stat_buf.st_mode)) + { + error (0, 0, _("Ignored file %s since it is not a regular file."), + library); + free (path); + return; + } + libname = basename (library); + if (process_file (library, libname, &flag, &soname, 0)) + { + error (0, 0, _("No link created since soname could not be found for %s"), + library); + free (path); + return; + } + create_links (path, libname, soname); + free (soname); + free (path); +} + + /* Read a whole directory and search for libraries. The purpose is two-fold: - search for libraries which will be added to the cache @@ -595,8 +671,9 @@ main (int argc, char **argv) /* Parse and process arguments. */ argp_parse (&argp, argc, argv, 0, &remaining, NULL); - /* Remaining arguments are additional libraries. */ - if (remaining != argc) + /* Remaining arguments are additional libraries if opt_manual_link + is not set. */ + if (remaining != argc && !opt_manual_link) { int i; for (i = remaining; i < argc; ++i) @@ -626,6 +703,18 @@ main (int argc, char **argv) exit (0); } + if (opt_manual_link) + { + /* Link all given libraries manually. */ + int i; + + for (i = remaining; i < argc; ++i) + manual_link (argv [i]); + + exit (0); + } + + if (opt_build_cache) init_cache (); diff --git a/intl/dcgettext.c b/intl/dcgettext.c index d482da39b8..8e51970495 100644 --- a/intl/dcgettext.c +++ b/intl/dcgettext.c @@ -121,6 +121,9 @@ char *getcwd (); # ifndef HAVE_STPCPY static char *stpcpy PARAMS ((char *dest, const char *src)); # endif +# ifndef HAVE_MEMPCPY +static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); +# endif #endif /* Amount to increase buffer size by in each try. */ @@ -130,7 +133,7 @@ static char *stpcpy PARAMS ((char *dest, const char *src)); /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define PATH_MAX but might cause redefinition warnings when sys/param.h is later included (as on MORE/BSD 4.3). */ -#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__)) +#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) # include <limits.h> #endif @@ -138,16 +141,16 @@ static char *stpcpy PARAMS ((char *dest, const char *src)); # define _POSIX_PATH_MAX 255 #endif -#if !defined(PATH_MAX) && defined(_PC_PATH_MAX) +#if !defined PATH_MAX && defined _PC_PATH_MAX # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) #endif /* Don't include sys/param.h if it already has been. */ -#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN) +#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN # include <sys/param.h> #endif -#if !defined(PATH_MAX) && defined(MAXPATHLEN) +#if !defined PATH_MAX && defined MAXPATHLEN # define PATH_MAX MAXPATHLEN #endif @@ -165,6 +168,68 @@ static char *stpcpy PARAMS ((char *dest, const char *src)); # define HAVE_LOCALE_NULL #endif +/* We want to allocate a string at the end of the struct. gcc makes + this easy. */ +#ifdef __GNUC__ +# define ZERO 0 +#else +# define ZERO 1 +#endif + +/* This is the type used for the search tree where known translations + are stored. */ +struct known_translation_t +{ + /* Domain in which to search. */ + char *domain; + + /* The category. */ + int category; + + /* State of the catalog counter at the point the string was found. */ + int counter; + + /* And finally the translation. */ + const char *translation; + + /* Pointer to the string in question. */ + char msgid[ZERO]; +}; + +/* Root of the search tree with known translations. We can use this + only if the system provides the `tsearch' function family. */ +#if defined HAVE_TSEARCH || defined _LIBC +# include <search.h> + +static void *root; + +# ifdef _LIBC +# define tsearch __tsearch +# endif + +/* Function to compare two entries in the table of known translations. */ +static int +transcmp (const void *p1, const void *p2) +{ + struct known_translation_t *s1 = (struct known_translation_t *) p1; + struct known_translation_t *s2 = (struct known_translation_t *) p2; + int result; + + result = strcmp (s1->msgid, s2->msgid); + if (result == 0) + { + result = strcmp (s1->msgid, s2->msgid); + if (result == 0) + /* We compare the category last (though this is the cheapest + operation) since it is hopefully always the same (namely + LC_MESSAGES). */ + result = s1->category - s2->category; + } + + return result; +} +#endif + /* Name of the default domain used for gettext(3) prior any call to textdomain(3). The default value for this is "messages". */ const char _nl_default_default_domain[] = "messages"; @@ -268,12 +333,34 @@ DCGETTEXT (domainname, msgid, category) char *dirname, *xdomainname; char *single_locale; char *retval; - int saved_errno = errno; + int saved_errno; +#if defined HAVE_TSEARCH || defined _LIBC + struct known_translation_t *search; + struct known_translation_t **foundp; + size_t msgid_len = strlen (msgid) + 1; +#endif + size_t domainname_len; /* If no real MSGID is given return NULL. */ if (msgid == NULL) return NULL; +#if defined HAVE_TSEARCH || defined _LIBC + /* Try to find the translation among those which we found at some time. */ + search = (struct known_translation_t *) alloca (sizeof (*search) + + msgid_len); + memcpy (search->msgid, msgid, msgid_len); + search->domain = (char *) domainname; + search->category = category; + + foundp = (struct known_translation_t **) tfind (search, &root, transcmp); + if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) + return (char *) (*foundp)->translation; +#endif + + /* Preserve the `errno' value. */ + saved_errno = errno; + /* See whether this is a SUID binary or not. */ DETERMINE_SECURE; @@ -340,12 +427,13 @@ DCGETTEXT (domainname, msgid, category) categoryname = category_to_name (category); categoryvalue = guess_category_value (category, categoryname); + domainname_len = strlen (domainname); xdomainname = (char *) alloca (strlen (categoryname) - + strlen (domainname) + 5); + + domainname_len + 5); ADD_BLOCK (block_list, xdomainname); - stpcpy (stpcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), - domainname), + stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), + domainname, domainname_len), ".mo"); /* Creating working area. */ @@ -422,6 +510,38 @@ DCGETTEXT (domainname, msgid, category) { FREE_BLOCKS (block_list); __set_errno (saved_errno); +#if defined HAVE_TSEARCH || defined _LIBC + if (foundp == NULL) + { + /* Create a new entry and add it to the search tree. */ + struct known_translation_t *newp; + + newp = (struct known_translation_t *) + malloc (sizeof (*newp) + msgid_len + + domainname_len + 1 - ZERO); + if (newp != NULL) + { + newp->domain = mempcpy (newp->msgid, msgid, msgid_len); + memcpy (newp->domain, domainname, domainname_len + 1); + newp->category = category; + newp->counter = _nl_msg_cat_cntr; + newp->translation = retval; + + /* Insert the entry in the search tree. */ + foundp = (struct known_translation_t **) + tsearch (newp, &root, transcmp); + if (&newp != foundp) + /* The insert failed. */ + free (newp); + } + } + else + { + /* We can update the existing entry. */ + (*foundp)->counter = _nl_msg_cat_cntr; + (*foundp)->translation = retval; + } +#endif return retval; } } @@ -571,12 +691,13 @@ _nl_find_msg (domain_file, msgid) return NULL; if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len - && strcmp (msgid, - domain->data + W (domain->must_swap, - domain->orig_tab[nstr - 1].offset)) - == 0) - return (char *) domain->data - + W (domain->must_swap, domain->trans_tab[nstr - 1].offset); + && (strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr - 1].offset)) + == 0)) + return ((char *) domain->data + + W (domain->must_swap, + domain->trans_tab[nstr - 1].offset)); } /* NOTREACHED */ } @@ -590,9 +711,9 @@ _nl_find_msg (domain_file, msgid) int cmp_val; act = (bottom + top) / 2; - cmp_val = strcmp (msgid, domain->data - + W (domain->must_swap, - domain->orig_tab[act].offset)); + cmp_val = strcmp (msgid, (domain->data + + W (domain->must_swap, + domain->orig_tab[act].offset))); if (cmp_val < 0) top = act; else if (cmp_val > 0) @@ -602,9 +723,9 @@ _nl_find_msg (domain_file, msgid) } /* If an translation is found return this. */ - return bottom >= top ? NULL : (char *) domain->data - + W (domain->must_swap, - domain->trans_tab[act].offset); + return bottom >= top ? NULL : ((char *) domain->data + + W (domain->must_swap, + domain->trans_tab[act].offset)); } @@ -728,6 +849,17 @@ stpcpy (dest, src) } #endif +#if !_LIBC && !HAVE_MEMPCPY +static void * +mempcpy (dest, src, n) + void *dest; + const void *src; + size_t n; +{ + return (void *) ((char *) memcpy (dst, src, n) + n); +} +#endif + #ifdef _LIBC /* If we want to free all resources we have to do some work at @@ -748,6 +880,9 @@ free_mem (void) if (_nl_current_default_domain != _nl_default_default_domain) /* Yes, again a pointer comparison. */ free ((char *) _nl_current_default_domain); + + /* Remove the search tree with the know translations. */ + __tdestroy (root, free); } text_set_element (__libc_subfreeres, free_mem); diff --git a/intl/libintl.h b/intl/libintl.h index aec7ea4b27..0c987e7d73 100644 --- a/intl/libintl.h +++ b/intl/libintl.h @@ -82,7 +82,7 @@ extern char *bindtextdomain (__const char *__domainname, # define dgettext(domainname, msgid) \ dcgettext (domainname, msgid, LC_MESSAGES) -# if __GNUC_PREREQ (2,7) +# if __GLIBC__ >= 2 && __GNUC_PREREQ (2,7) /* Variable defined in loadmsgcat.c which gets incremented every time a new catalog is loaded. */ extern int _nl_msg_cat_cntr; diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 7d161b8254..9bdf83e951 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,11 @@ +1999-12-18 Ulrich Drepper <drepper@cygnus.com> + + * manager.c (pthread_allocate_stack): Correct computation of + new_thread_bottom. Correct handling of stack size and when the + rlimit method to guard for stack growth is used. + * pthread.c (pthread_initialize): Stack limit must be STACK_SIZE + minus one pagesize (not two). + 1999-12-03 Andreas Jaeger <aj@suse.de> * Versions: Add __res_state with version GLIBC_2.2. diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c index 307ce63721..0cbb426c9d 100644 --- a/linuxthreads/manager.c +++ b/linuxthreads/manager.c @@ -289,9 +289,12 @@ static int pthread_allocate_stack(const pthread_attr_t *attr, } else { + stacksize = STACK_SIZE - pagesize; + if (attr != NULL) + stacksize = MIN (stacksize, roundup(attr->__stacksize, pagesize)); /* Allocate space for stack and thread descriptor at default address */ new_thread = default_new_thread; - new_thread_bottom = (char *) new_thread - STACK_SIZE; + new_thread_bottom = (char *) (new_thread + 1) - stacksize; if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE), INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, @@ -300,14 +303,10 @@ static int pthread_allocate_stack(const pthread_attr_t *attr, return -1; /* We manage to get a stack. Now see whether we need a guard and allocate it if necessary. Notice that the default - attributes (stack_size = STACK_SIZE - pagesize and - guardsize = pagesize) do not need a guard page, since - the RLIMIT_STACK soft limit prevents stacks from - running into one another. */ - if (attr == NULL || - attr->__guardsize == 0 || - (attr->__guardsize == pagesize && - attr->__stacksize == STACK_SIZE - pagesize)) + attributes (stack_size = STACK_SIZE - pagesize) do not need + a guard page, since the RLIMIT_STACK soft limit prevents stacks + from running into one another. */ + if (stacksize == STACK_SIZE - pagesize) { /* We don't need a guard page. */ guardaddr = NULL; @@ -316,10 +315,7 @@ static int pthread_allocate_stack(const pthread_attr_t *attr, else { /* Put a bad page at the bottom of the stack */ - stacksize = roundup(attr->__stacksize, pagesize); - if (stacksize >= STACK_SIZE - pagesize) - stacksize = STACK_SIZE - pagesize; - guardaddr = (void *)new_thread - stacksize; + guardaddr = (void *)new_thread_bottom - stacksize; guardsize = attr->__guardsize; if (mmap ((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0) == MAP_FAILED) diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c index 41d09a833c..a9083635b6 100644 --- a/linuxthreads/pthread.c +++ b/linuxthreads/pthread.c @@ -300,10 +300,9 @@ static void pthread_initialize(void) __pthread_initial_thread_bos = (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); /* Play with the stack size limit to make sure that no stack ever grows - beyond STACK_SIZE minus two pages (one page for the thread descriptor - immediately beyond, and one page to act as a guard page). */ + beyond STACK_SIZE minus one page (to act as a guard page). */ getrlimit(RLIMIT_STACK, &limit); - max_stack = STACK_SIZE - 2 * __getpagesize(); + max_stack = STACK_SIZE - __getpagesize(); if (limit.rlim_cur > max_stack) { limit.rlim_cur = max_stack; setrlimit(RLIMIT_STACK, &limit); diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c index 42fd601064..87005e86ab 100644 --- a/locale/programs/ld-collate.c +++ b/locale/programs/ld-collate.c @@ -73,7 +73,8 @@ struct element_t const char *mbs; const uint32_t *wcs; - int order; + int mborder; + int wcorder; struct element_list_t *weights; @@ -87,6 +88,9 @@ struct element_t /* Predecessor and successor in the order list. */ struct element_t *last; struct element_t *next; + + /* Next element in multibyte output list. */ + struct element_t *mbnext; }; /* Special element value. */ @@ -151,6 +155,10 @@ struct locale_collate_t that the definitions from more than one input file contains information. Therefore we keep all relevant input in a list. */ struct locale_collate_t *next; + + /* Arrays with heads of the list for each of the leading bytes in + the multibyte sequences. */ + struct element_t *mbheads[256]; }; @@ -176,7 +184,7 @@ make_seclist_elem (struct locale_collate_t *collate, const char *string, static struct element_t * -new_element (struct locale_collate_t *collate, const char *mbs, +new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen, const uint32_t *wcs, const char *name, size_t namelen) { struct element_t *newp; @@ -185,7 +193,10 @@ new_element (struct locale_collate_t *collate, const char *mbs, sizeof (*newp)); newp->name = name == NULL ? NULL : obstack_copy (&collate->mempool, name, namelen); - newp->mbs = mbs; + if (mbs != NULL) + newp->mbs = obstack_copy0 (&collate->mempool, mbs, mbslen); + else + newp->mbs = NULL; if (wcs != NULL) { size_t nwcs = wcslen ((wchar_t *) wcs) + 1; @@ -196,7 +207,8 @@ new_element (struct locale_collate_t *collate, const char *mbs, } else newp->wcs = NULL; - newp->order = 0; + newp->mborder = 0; + newp->wcorder = 0; /* Will be allocated later. */ newp->weights = NULL; @@ -209,6 +221,8 @@ new_element (struct locale_collate_t *collate, const char *mbs, newp->last = NULL; newp->next = NULL; + newp->mbnext = NULL; + return newp; } @@ -457,14 +471,15 @@ find_element (struct linereader *ldfile, struct locale_collate_t *collate, result = sym->order; if (result == NULL) - result = sym->order = new_element (collate, NULL, NULL, NULL, 0); + result = sym->order = new_element (collate, NULL, 0, NULL, + NULL, 0); } else if (find_entry (&collate->elem_table, str, len, (void **) &result) != 0) { /* It's also no collation element. So it is an character element defined later. */ - result = new_element (collate, NULL, NULL, str, len); + result = new_element (collate, NULL, 0, NULL, str, len); if (result != NULL) /* Insert it into the sequence table. */ insert_entry (&collate->seq_table, str, len, result); @@ -499,6 +514,8 @@ insert_weights (struct linereader *ldfile, struct element_t *elem, elem->line = ldfile->lineno; elem->last = collate->cursor; elem->next = collate->cursor ? collate->cursor->next : NULL; + if (collate->cursor != NULL) + collate->cursor->next = elem; elem->weights = (struct element_list_t *) obstack_alloc (&collate->mempool, nrules * sizeof (struct element_list_t)); memset (elem->weights, '\0', nrules * sizeof (struct element_list_t)); @@ -683,7 +700,7 @@ insert_weights (struct linereader *ldfile, struct element_t *elem, } -static void +static int insert_value (struct linereader *ldfile, struct token *arg, struct charmap_t *charmap, struct repertoire_t *repertoire, struct locale_collate_t *collate) @@ -721,14 +738,14 @@ insert_value (struct linereader *ldfile, struct token *arg, elem = sym->order; if (elem == NULL) - elem = sym->order = new_element (collate, NULL, NULL, NULL, 0); + elem = sym->order = new_element (collate, NULL, 0, NULL, NULL, 0); } else if (find_entry (&collate->elem_table, arg->val.str.startmb, arg->val.str.lenmb, (void **) &elem) != 0) { /* It's also no collation element. Therefore ignore it. */ lr_ignore_rest (ldfile, 0); - return; + return 1; } } else @@ -741,6 +758,7 @@ insert_value (struct linereader *ldfile, struct token *arg, /* We have to allocate an entry. */ elem = new_element (collate, seq != NULL ? seq->bytes : NULL, + seq != NULL ? seq->nbytes : 0, wcs, arg->val.str.startmb, arg->val.str.lenmb); /* And add it to the table. */ @@ -755,14 +773,16 @@ insert_value (struct linereader *ldfile, struct token *arg, if (elem->next != NULL || (collate->cursor != NULL && elem->next == collate->cursor)) { - lr_error (ldfile, _("order for `%.*s' already defined at %s:%Z"), + lr_error (ldfile, _("order for `%.*s' already defined at %s:%zu"), arg->val.str.lenmb, arg->val.str.startmb, elem->file, elem->line); lr_ignore_rest (ldfile, 0); - return; + return 1; } insert_weights (ldfile, elem, charmap, repertoire, collate, tok_none); + + return 0; } @@ -780,8 +800,11 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg, startp = collate->cursor; /* Process and add the end-entry. */ - if (arg != NULL) - insert_value (ldfile, arg, charmap, repertoire, collate); + if (arg != NULL + && insert_value (ldfile, arg, charmap, repertoire, collate)) + /* Something went wrong with inserting the to-value. This means + we cannot process the ellipsis. */ + return; /* Reset the cursor. */ collate->cursor = startp; @@ -805,7 +828,168 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg, if (ellipsis == tok_ellipsis3) { - /* XXX */ + /* One requirement we make here: the length of the byte + sequences for the first and end character must be the same. + This is mainly to prevent unwanted effects and this is often + not what is wanted. */ + size_t len = (startp->mbs != NULL ? strlen (startp->mbs) + : (endp->mbs != NULL ? strlen (endp->mbs) : 0)); + char mbcnt[len + 1]; + char mbend[len + 1]; + + /* Well, this should be caught somewhere else already. Just to + make sure. */ + assert (startp == NULL || startp->wcs == NULL || startp->wcs[1] == 0); + assert (endp == NULL || endp->wcs == NULL || endp->wcs[1] == 0); + + if (startp != NULL && endp != NULL + && startp->mbs != NULL && endp->mbs != NULL + && strlen (startp->mbs) != strlen (endp->mbs)) + { + lr_error (ldfile, _("\ +%s: byte sequences of first and last character must have the same length"), + "LC_COLLATE"); + return; + } + + /* Determine whether we have to generate multibyte sequences. */ + if ((startp == NULL || startp->mbs != NULL) + && (endp == NULL || endp->mbs != NULL)) + { + int cnt; + int ret; + + /* Prepare the beginning byte sequence. This is either from the + beginning byte sequence or it is all nulls if it was an + initial ellipsis. */ + if (startp == NULL || startp->mbs == NULL) + memset (mbcnt, '\0', len); + else + { + memcpy (mbcnt, startp->mbs, len); + + /* And increment it so that the value is the first one we will + try to insert. */ + for (cnt = len - 1; cnt >= 0; --cnt) + if (++mbcnt[cnt] != '\0') + break; + } + mbcnt[len] = '\0'; + + /* And the end sequence. */ + if (endp == NULL || endp->mbs == NULL) + memset (mbend, '\0', len); + else + memcpy (mbend, endp->mbs, len); + mbend[len] = '\0'; + + /* Test whether we have a correct range. */ + ret = memcmp (mbcnt, mbend, len); + if (ret >= 0) + { + if (ret > 0) + lr_error (ldfile, _("%s: byte sequence of first character of \ +sequence is not lower than that of the last character"), "LC_COLLATE"); + return; + } + + /* Generate the byte sequences data. */ + while (1) + { + struct charseq *seq; + + /* Quite a bit of work ahead. We have to find the character + definition for the byte sequence and then determine the + wide character belonging to it. */ + seq = charmap_find_symbol (charmap, mbcnt, len); + if (seq != NULL) + { + struct element_t *elem; + size_t namelen; + + if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE) + seq->ucs4 = repertoire_find_value (repertoire, seq->name, + strlen (seq->name)); + + /* I don't this this can ever happen. */ + assert (seq->name != NULL); + namelen = strlen (seq->name); + + /* Now we are ready to insert the new value in the + sequence. Find out whether the element is + already known. */ + if (find_entry (&collate->seq_table, seq->name, namelen, + (void **) &elem) != 0) + { + uint32_t wcs[2] = { seq->ucs4, 0 }; + + /* We have to allocate an entry. */ + elem = new_element (collate, mbcnt, len, wcs, seq->name, + namelen); + + /* And add it to the table. */ + if (insert_entry (&collate->seq_table, seq->name, + namelen, elem) != 0) + /* This cannot happen. */ + assert (! "Internal error"); + } + + /* Test whether this element is not already in the list. */ + if (elem->next != NULL || (collate->cursor != NULL + && elem->next == collate->cursor)) + { + lr_error (ldfile, _("\ +order for `%.*s' already defined at %s:%zu"), + namelen, seq->name, elem->file, elem->line); + goto increment; + } + + /* Enqueue the new element. */ + elem->last = collate->cursor; + elem->next = collate->cursor->next; + elem->last->next = elem; + if (elem->next != NULL) + elem->next->last = elem; + collate->cursor = elem; + + /* Add the weight value. We take them from the + `ellipsis_weights' member of `collate'. */ + elem->weights = (struct element_list_t *) + obstack_alloc (&collate->mempool, + nrules * sizeof (struct element_list_t)); + for (cnt = 0; cnt < nrules; ++cnt) + if (collate->ellipsis_weight.weights[cnt].cnt == 1 + && (collate->ellipsis_weight.weights[cnt].w[0] + == ELEMENT_ELLIPSIS2)) + { + elem->weights[cnt].w = (struct element_t **) + obstack_alloc (&collate->mempool, + sizeof (struct element_t *)); + elem->weights[cnt].w[0] = elem; + elem->weights[cnt].cnt = 1; + } + else + { + /* Simly use the weight from `ellipsis_weight'. */ + elem->weights[cnt].w = + collate->ellipsis_weight.weights[cnt].w; + elem->weights[cnt].cnt = + collate->ellipsis_weight.weights[cnt].cnt; + } + } + + /* Increment for the next round. */ + increment: + for (cnt = len - 1; cnt >= 0; --cnt) + if (++mbcnt[cnt] != '\0') + break; + + /* Find out whether this was all. */ + if (cnt < 0 || memcmp (mbcnt, mbend, len) >= 0) + /* Yep, that's all. */ + break; + } + } } else { @@ -883,7 +1067,7 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg, && elem->next == collate->cursor)) { lr_error (ldfile, _("\ -%s: order for `%.*s' already defined at %s:%Z"), +%s: order for `%.*s' already defined at %s:%zu"), "LC_COLLATE", lenfrom, buf, elem->file, elem->line); continue; @@ -923,6 +1107,7 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg, /* We have to allocate an entry. */ elem = new_element (collate, seq != NULL ? seq->bytes : NULL, + seq != NULL ? seq->nbytes : 0, wc == ILLEGAL_CHAR_VALUE ? NULL : wcs, buf, lenfrom); @@ -1023,6 +1208,67 @@ collate_startup (struct linereader *ldfile, struct localedef_t *locale, void collate_finish (struct localedef_t *locale, struct charmap_t *charmap) { + /* Now is the time when we can assign the individual collation + values for all the symbols. We have possibly different values + for the wide- and the multibyte-character symbols. This is done + since it might make a difference in the encoding if there is in + some cases no multibyte-character but there are wide-characters. + (The other way around it is not important since theencoded + collation value in the wide-character case is 32 bits wide and + therefore requires no encoding). + + The lowest collation value assigned is 2. Zero is reserved for + the NUL byte terminating the strings in the `strxfrm'/`wcsxfrm' + functions and 1 is used to separate the individual passes for the + different rules. + + We also have to construct is list with all the bytes/words which + can come first in a sequence, followed by all the elements which + also start with this byte/word. The order is reverse which has + among others the important effect that longer strings are located + first in the list. This is required for the output data since + the algorithm used in `strcoll' etc depends on this. + + The multibyte case is easy. We simply sort into an array with + 256 elements. */ + struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate; + int mbact = 2; + int wcact = 2; + struct element_t *runp = collate->start; + + while (runp != NULL) + { + if (runp->mbs != NULL) + { + struct element_t **eptr; + + /* Determine the order. */ + runp->mborder = mbact++; + + /* Find the point where to insert in the list. */ + eptr = &collate->mbheads[(unsigned int) runp->mbs[0]]; + while (*eptr != NULL) + { + /* Check which string is larger, the one we want to insert + or the current element of the list we are looking at. */ + assert (runp->mbs[0] == (*eptr)->mbs[0]); + if (strcmp (runp->mbs, (*eptr)->mbs) > 0) + break; + + eptr = &(*eptr)->mbnext; + } + + /* Set the pointers. */ + runp->mbnext = *eptr; + *eptr = runp; + } + + if (runp->wcs != NULL) + runp->wcorder = wcact++; + + /* Up to the next entry. */ + runp = runp->next; + } } @@ -1257,7 +1503,8 @@ collate_read (struct linereader *ldfile, struct localedef_t *result, if (insert_entry (&collate->elem_table, symbol, symbol_len, new_element (collate, - NULL, NULL, NULL, 0)) < 0) + NULL, 0, NULL, symbol, + symbol_len)) < 0) lr_error (ldfile, _("\ error while adding collating element")); } @@ -1519,9 +1766,12 @@ error while adding equivalent collating symbol")); goto err_label; /* Handle ellipsis at end of list. */ - if (was_ellipsis) - /* XXX */ - abort (); + if (was_ellipsis != tok_none) + { + handle_ellipsis (ldfile, NULL, was_ellipsis, charmap, repertoire, + collate); + was_ellipsis = tok_none; + } state = 2; lr_ignore_rest (ldfile, 1); @@ -1543,9 +1793,12 @@ error while adding equivalent collating symbol")); state = 2; /* Handle ellipsis at end of list. */ - if (was_ellipsis) - /* XXX */ - abort (); + if (was_ellipsis != tok_none) + { + handle_ellipsis (ldfile, arg, was_ellipsis, charmap, + repertoire, collate); + was_ellipsis = tok_none; + } } else if (state != 2 && state != 3) goto err_label; @@ -1610,9 +1863,12 @@ error while adding equivalent collating symbol")); state = 2; /* Handle ellipsis at end of list. */ - if (was_ellipsis) - /* XXX */ - abort (); + if (was_ellipsis != tok_none) + { + handle_ellipsis (ldfile, NULL, was_ellipsis, charmap, + repertoire, collate); + was_ellipsis = tok_none; + } } else if (state == 3) { @@ -1848,7 +2104,7 @@ error while adding equivalent collating symbol")); && collate->undefined.next == collate->cursor)) { lr_error (ldfile, - _("%s: order for `%.*s' already defined at %s:%Z"), + _("%s: order for `%.*s' already defined at %s:%zu"), "LC_COLLATE", 9, "UNDEFINED", collate->undefined.file, collate->undefined.line); lr_ignore_rest (ldfile, 0); @@ -1892,9 +2148,12 @@ error while adding equivalent collating symbol")); "LC_COLLATE"); /* Handle ellipsis at end of list. */ - if (was_ellipsis) - /* XXX */ - abort (); + if (was_ellipsis != tok_none) + { + handle_ellipsis (ldfile, NULL, was_ellipsis, charmap, + repertoire, collate); + was_ellipsis = tok_none; + } } else if (state == 3) error (0, 0, _("%s: missing `reorder-end' keyword"), diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c index ac56f6fbec..2de46088df 100644 --- a/nis/nss_compat/compat-grp.c +++ b/nis/nss_compat/compat-grp.c @@ -1,6 +1,6 @@ /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 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 @@ -730,7 +730,10 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp, enum nss_status status; if (name[0] == '-' || name[0] == '+') - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } __libc_lock_lock (lock); @@ -915,7 +918,10 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent, status = getgrgid_plusgroup (gid, result, buffer, buflen, errnop); if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else return status; } diff --git a/nis/nss_compat/compat-initgroups.c b/nis/nss_compat/compat-initgroups.c index 47b395ede6..d4c3422bd4 100644 --- a/nis/nss_compat/compat-initgroups.c +++ b/nis/nss_compat/compat-initgroups.c @@ -263,6 +263,7 @@ getgrent_next_nis (struct group *result, ent_t *ent, char *buffer, if (yp_get_default_domain (&domain) != YPERR_SUCCESS) { ent->nis = 0; + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; } @@ -445,7 +446,10 @@ getgrnam_plusgroup (const char *name, struct group *result, char *buffer, ++p; parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop); if (parse_res == -1) - return NSS_STATUS_TRYAGAIN; + { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } } if (parse_res) diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c index 1290346881..f254fadf5c 100644 --- a/nis/nss_compat/compat-spwd.c +++ b/nis/nss_compat/compat-spwd.c @@ -383,6 +383,7 @@ getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent, if (parse_res == -1) { ent->netgrdata.cursor = saved_cursor; + *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } @@ -1112,7 +1113,10 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, && result->sp_namp[1] != '@') { if (strcmp (&result->sp_namp[1], name) == 0) - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else continue; } @@ -1128,8 +1132,11 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, status = getspnam_plususer (name, result, buffer, buflen, errnop); if (status == NSS_STATUS_RETURN) - /* We couldn't parse the entry */ - return NSS_STATUS_NOTFOUND; + { + /* We couldn't parse the entry */ + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else return status; } @@ -1142,7 +1149,10 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, status = getspnam_plususer (name, result, buffer, buflen, errnop); if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } else return status; } @@ -1159,7 +1169,10 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd, enum nss_status status; if (name[0] == '-' || name[0] == '+') - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } if (ni == NULL) { diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c index 64d0bf8de5..e6e2386547 100644 --- a/nis/nss_nis/nis-alias.c +++ b/nis/nss_nis/nis-alias.c @@ -278,7 +278,10 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias, if (parse_res == -1) return NSS_STATUS_TRYAGAIN; else - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } } return NSS_STATUS_SUCCESS; diff --git a/nis/nss_nis/nis-ethers.c b/nis/nss_nis/nis-ethers.c index c95f766469..c1ea32adc5 100644 --- a/nis/nss_nis/nis-ethers.c +++ b/nis/nss_nis/nis-ethers.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 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 @@ -241,7 +241,10 @@ _nss_nis_gethostton_r (const char *name, struct ether *eth, if (parse_res == -1) return NSS_STATUS_TRYAGAIN; else - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } } return NSS_STATUS_SUCCESS; } diff --git a/nis/nss_nis/nis-grp.c b/nis/nss_nis/nis-grp.c index 6dca66e4df..62e6b475b7 100644 --- a/nis/nss_nis/nis-grp.c +++ b/nis/nss_nis/nis-grp.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 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 @@ -207,7 +207,7 @@ _nss_nis_getgrnam_r (const char *name, struct group *grp, return NSS_STATUS_TRYAGAIN; else { - *errnop = EAGAIN; + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; } } diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c index 0ddc930687..15aff251e5 100644 --- a/nis/nss_nis/nis-hosts.c +++ b/nis/nss_nis/nis-hosts.c @@ -321,6 +321,7 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, else { *h_errnop = HOST_NOT_FOUND; + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; } } @@ -392,7 +393,10 @@ _nss_nis_gethostbyaddr_r (char *addr, size_t addrlen, int af, *errnop = errno; } if (retval == NSS_STATUS_NOTFOUND) - *h_errnop = HOST_NOT_FOUND; + { + *h_errnop = HOST_NOT_FOUND; + *errnop = ENOENT; + } return retval; } diff --git a/nis/nss_nis/nis-netgrp.c b/nis/nss_nis/nis-netgrp.c index d170b56f50..0d3ed44d3f 100644 --- a/nis/nss_nis/nis-netgrp.c +++ b/nis/nss_nis/nis-netgrp.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 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 @@ -117,7 +117,10 @@ _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen, enum nss_status status; if (cursor == NULL) - return NSS_STATUS_NOTFOUND; + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } __libc_lock_lock (lock); diff --git a/nis/nss_nis/nis-publickey.c b/nis/nss_nis/nis-publickey.c index 73afd442a9..821accfbae 100644 --- a/nis/nss_nis/nis-publickey.c +++ b/nis/nss_nis/nis-publickey.c @@ -1,6 +1,6 @@ -/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 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 @@ -50,8 +50,11 @@ _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop) domain = strchr (netname, '@'); if (!domain) - return NSS_STATUS_UNAVAIL; - domain++; + { + *errnop = EINVAL; + return NSS_STATUS_UNAVAIL; + } + ++domain; retval = yperr2nss (yp_match (domain, "publickey.byname", netname, strlen (netname), &result, &len)); @@ -95,8 +98,11 @@ _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd, domain = strchr (netname, '@'); if (!domain) - return NSS_STATUS_UNAVAIL; - domain++; + { + *errnop = EINVAL; + return NSS_STATUS_UNAVAIL; + } + ++domain; retval = yperr2nss (yp_match (domain, "publickey.byname", netname, strlen (netname), &result, &len)); @@ -196,10 +202,13 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, domain = strchr (netname, '@'); if (!domain) - return NSS_STATUS_UNAVAIL; + { + *errnop = EINVAL; + return NSS_STATUS_UNAVAIL; + } /* Point past the '@' character */ - domain++; + ++domain; lookup = NULL; yperr = yp_match (domain, "netid.byname", netname, strlen (netname), &lookup, &len); @@ -209,11 +218,13 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, break; /* the successful case */ case YPERR_DOMAIN: case YPERR_KEY: + *errnop = ENOENT; return NSS_STATUS_NOTFOUND; case YPERR_MAP: default: return NSS_STATUS_UNAVAIL; } + if (lookup) { enum nss_status err; @@ -224,7 +235,9 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, return err; } else - return NSS_STATUS_NOTFOUND; - + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } return NSS_STATUS_SUCCESS; } diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c index 103b1e4115..cece55c283 100644 --- a/nis/nss_nis/nis-service.c +++ b/nis/nss_nis/nis-service.c @@ -172,7 +172,7 @@ internal_nis_getservent_r (struct servent *serv, char *buffer, return NSS_STATUS_NOTFOUND; } p = strncpy (buffer, data->next->val, buflen); - while (isspace (*p)) + while (isspace (*p)) ++p; parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop); @@ -215,6 +215,63 @@ _nss_nis_getservbyname_r (const char *name, char *protocol, return NSS_STATUS_UNAVAIL; } + /* If the protocol is given, we could try if our NIS server knows + about services.byservicename map. If yes, we only need one query */ + if (protocol != NULL) + { + char key[strlen (name) + strlen (protocol) + 2]; + char *cp, *domain, *result; + size_t keylen, len; + + /* If this fails, the other solution will also fail. */ + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* key is: "name/protocol" */ + cp = stpcpy (key, name); + *cp++ = '/'; + stpcpy (cp, protocol); + keylen = strlen (key); + status = yperr2nss (yp_match (domain, "services.byservicename", key, + keylen, &result, &len)); + + /* If we found the key, it's ok and parse the result. If not, + fall through and parse the complete table. */ + if (status == NSS_STATUS_SUCCESS) + { + struct parser_data *pdata = (void *) buffer; + int parse_res; + char *p; + + if ((size_t) (len + 1) > buflen) + { + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + parse_res = _nss_files_parse_servent (p, serv, pdata, + buflen, errnop); + if (parse_res < 0) + { + if (parse_res == -1) + return NSS_STATUS_TRYAGAIN; + else + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } + } + else + return NSS_STATUS_SUCCESS; + } + } + status = internal_nis_setservent (&data); if (status != NSS_STATUS_SUCCESS) return status; @@ -256,10 +313,57 @@ _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv, enum nss_status status; int found; - if (protocol == NULL) + /* If the protocol is given, we only need one query */ + if (protocol != NULL) { - *errnop = EINVAL; - return NSS_STATUS_UNAVAIL; + char key[100 + strlen (protocol) + 2]; + char *domain, *result; + size_t keylen, len; + + /* If this fails, the other solution will also fail. */ + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* key is: "port/protocol" */ + keylen = snprintf (key, sizeof (key), "%d/%s", port, protocol); + status = yperr2nss (yp_match (domain, "services.byname", key, + keylen, &result, &len)); + + /* If we found the key, it's ok and parse the result. If not, + fall through and parse the complete table. */ + if (status == NSS_STATUS_SUCCESS) + { + struct parser_data *pdata = (void *) buffer; + int parse_res; + char *p; + + if ((size_t) (len + 1) > buflen) + { + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + parse_res = _nss_files_parse_servent (p, serv, pdata, + buflen, errnop); + if (parse_res < 0) + { + if (parse_res == -1) + return NSS_STATUS_TRYAGAIN; + else + { + *errnop = ENOENT; + return NSS_STATUS_NOTFOUND; + } + } + else + return NSS_STATUS_SUCCESS; + } } status = internal_nis_setservent (&data); @@ -270,7 +374,8 @@ _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv, while (!found && ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &data)) == NSS_STATUS_SUCCESS)) - if (serv->s_port == port && strcmp (serv->s_proto, protocol) == 0) + if (serv->s_port == port && + (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)) found = 1; internal_nis_endservent (&data); diff --git a/nis/ypclnt.c b/nis/ypclnt.c index 1dc9ca3126..00d0f8b4c8 100644 --- a/nis/ypclnt.c +++ b/nis/ypclnt.c @@ -1,6 +1,6 @@ /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 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 @@ -42,7 +42,6 @@ struct dom_binding struct sockaddr_in dom_server_addr; int dom_socket; CLIENT *dom_client; - long int dom_vers; }; typedef struct dom_binding dom_binding; @@ -63,7 +62,6 @@ __yp_bind (const char *domain, dom_binding **ypdb) int clnt_sock; CLIENT *client; int is_new = 0; - int try; if (domain == NULL || domain[0] == '\0') return YPERR_BADARGS; @@ -83,137 +81,127 @@ __yp_bind (const char *domain, dom_binding **ypdb) { is_new = 1; ysd = (dom_binding *) calloc (1, sizeof *ysd); - ysd->dom_socket = -1; - ysd->dom_vers = -1; } - try = 0; - - do - { - ++try; - if (try > MAXTRIES) - { - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - #if USE_BINDINGDIR - if (ysd->dom_vers < 1 && try == 1) /* Try binding dir only first time */ + if (ysd->dom_client == NULL) + { + /* Try binding dir at first if we have no binding */ + char path[sizeof (BINDINGDIR) + strlen (domain) + 10]; + struct iovec vec[2]; + unsigned short port; + int fd; + + sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS); + fd = open (path, O_RDONLY); + if (fd >= 0) { - char path[sizeof (BINDINGDIR) - 1 + strlen (domain) + 10]; - struct iovec vec[2]; - unsigned short port; - int fd; - - sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS); - fd = open (path, O_RDONLY); - if (fd >= 0) + /* We have a binding file and could save a RPC call */ + vec[0].iov_base = &port; + vec[0].iov_len = sizeof (port); + vec[1].iov_base = &ypbr; + vec[1].iov_len = sizeof (ypbr); + + if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr)) { - /* We have a binding file and could save a RPC call */ - vec[0].iov_base = &port; - vec[0].iov_len = sizeof (port); - vec[1].iov_base = &ypbr; - vec[1].iov_len = sizeof (ypbr); - - if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr)) - { - ysd->dom_server_addr.sin_family = AF_INET; - memcpy (&ysd->dom_server_addr.sin_port, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, - sizeof (ysd->dom_server_addr.sin_port)); - memcpy (&ysd->dom_server_addr.sin_addr.s_addr, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, - sizeof (ysd->dom_server_addr.sin_addr.s_addr)); - ysd->dom_vers = YPVERS; - strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); - ysd->dom_domain[YPMAXDOMAIN] = '\0'; - } - close (fd); + ysd->dom_server_addr.sin_family = AF_INET; + memcpy (&ysd->dom_server_addr.sin_port, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, + sizeof (ysd->dom_server_addr.sin_port)); + memcpy (&ysd->dom_server_addr.sin_addr.s_addr, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, + sizeof (ysd->dom_server_addr.sin_addr.s_addr)); + strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); + ysd->dom_domain[YPMAXDOMAIN] = '\0'; + + ysd->dom_socket = RPC_ANYSOCK; + ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, + YPVERS, UDPTIMEOUT, + &ysd->dom_socket); + + if (ysd->dom_client != NULL) + /* If the program exits, close the socket */ + if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) + perror ("fcntl: F_SETFD"); } + close (fd); } + } #endif /* USE_BINDINGDIR */ - if (ysd->dom_vers == -1) + if (ysd->dom_client == NULL) + { + memset (&clnt_saddr, '\0', sizeof clnt_saddr); + clnt_saddr.sin_family = AF_INET; + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + clnt_sock = RPC_ANYSOCK; + client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, + &clnt_sock, 0, 0); + if (client == NULL) { - if (ysd->dom_client) - { - clnt_destroy (ysd->dom_client); - ysd->dom_client = NULL; - ysd->dom_socket = -1; - } - memset (&clnt_saddr, '\0', sizeof clnt_saddr); - clnt_saddr.sin_family = AF_INET; - clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - clnt_sock = RPC_ANYSOCK; - client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, - &clnt_sock, 0, 0); - if (client == NULL) - { - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - /* - ** Check the port number -- should be < IPPORT_RESERVED. - ** If not, it's possible someone has registered a bogus - ** ypbind with the portmapper and is trying to trick us. - */ - if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED) - { - clnt_destroy (client); - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - - if (clnt_call (client, YPBINDPROC_DOMAIN, - (xdrproc_t) xdr_domainname, (caddr_t) &domain, - (xdrproc_t) xdr_ypbind_resp, - (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS) - { - clnt_destroy (client); - if (is_new) - free (ysd); - return YPERR_YPBIND; - } - - clnt_destroy (client); - - if (ypbr.ypbind_status != YPBIND_SUCC_VAL) - { - fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"), - ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error)); - if (is_new) - free (ysd); - return YPERR_DOMAIN; - } - memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); - ysd->dom_server_addr.sin_family = AF_INET; - memcpy (&ysd->dom_server_addr.sin_port, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, - sizeof (ysd->dom_server_addr.sin_port)); - memcpy (&ysd->dom_server_addr.sin_addr.s_addr, - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, - sizeof (ysd->dom_server_addr.sin_addr.s_addr)); - ysd->dom_vers = YPVERS; - strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); - ysd->dom_domain[YPMAXDOMAIN] = '\0'; - } + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + /* Check the port number -- should be < IPPORT_RESERVED. + If not, it's possible someone has registered a bogus + ypbind with the portmapper and is trying to trick us. */ + if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED) + { + clnt_destroy (client); + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + + if (clnt_call (client, YPBINDPROC_DOMAIN, + (xdrproc_t) xdr_domainname, (caddr_t) &domain, + (xdrproc_t) xdr_ypbind_resp, + (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS) + { + clnt_destroy (client); + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + + clnt_destroy (client); + + if (ypbr.ypbind_status != YPBIND_SUCC_VAL) + { + fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"), + ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error)); + if (is_new) + free (ysd); + return YPERR_DOMAIN; + } + memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); + ysd->dom_server_addr.sin_family = AF_INET; + memcpy (&ysd->dom_server_addr.sin_port, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, + sizeof (ysd->dom_server_addr.sin_port)); + memcpy (&ysd->dom_server_addr.sin_addr.s_addr, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, + sizeof (ysd->dom_server_addr.sin_addr.s_addr)); + strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); + ysd->dom_domain[YPMAXDOMAIN] = '\0'; ysd->dom_socket = RPC_ANYSOCK; ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS, UDPTIMEOUT, &ysd->dom_socket); - if (ysd->dom_client == NULL) - ysd->dom_vers = -1; + if (ysd->dom_client != NULL) + /* If the program exits, close the socket */ + if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) + perror ("fcntl: F_SETFD"); } - while (ysd->dom_client == NULL); - /* If the program exists, close the socket */ - if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) - perror ("fcntl: F_SETFD"); + if (ysd->dom_client == NULL) + { + if (is_new) + free (ysd); + return YPERR_YPSERV; + } if (is_new && ypdb != NULL) { @@ -229,7 +217,60 @@ __yp_unbind (dom_binding *ydb) { clnt_destroy (ydb->dom_client); ydb->dom_client = NULL; - ydb->dom_socket = -1; +} + +int +yp_bind (const char *indomain) +{ + int status; + + __libc_lock_lock (ypbindlist_lock); + + status = __yp_bind (indomain, &__ypbindlist); + + __libc_lock_unlock (ypbindlist_lock); + + return status; +} + +static void +yp_unbind_locked (const char *indomain) +{ + dom_binding *ydbptr, *ydbptr2; + + ydbptr2 = NULL; + ydbptr = __ypbindlist; + + while (ydbptr != NULL) + { + if (strcmp (ydbptr->dom_domain, indomain) == 0) + { + dom_binding *work; + + work = ydbptr; + if (ydbptr2 == NULL) + __ypbindlist = __ypbindlist->dom_pnext; + else + ydbptr2 = ydbptr->dom_pnext; + __yp_unbind (work); + free (work); + break; + } + ydbptr2 = ydbptr; + ydbptr = ydbptr->dom_pnext; + } +} + +void +yp_unbind (const char *indomain) +{ + __libc_lock_lock (ypbindlist_lock); + + yp_unbind_locked (indomain); + + __libc_lock_unlock (ypbindlist_lock); + + return; } static int @@ -278,14 +319,26 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, if (result != RPC_SUCCESS) { - clnt_perror (ydb->dom_client, "do_ypcall: clnt_call"); - ydb->dom_vers = -1; - if (!use_ypbindlist) + /* Don't print the error message on the first try. It + could be that we use cached data which is now invalid. */ + if (try != 0) + clnt_perror (ydb->dom_client, "do_ypcall: clnt_call"); + + if (use_ypbindlist) + { + /* We use ypbindlist, and the old cached data is + invalid. unbind now and create a new binding */ + yp_unbind_locked (domain); + __libc_lock_unlock (ypbindlist_lock); + use_ypbindlist = FALSE; + } + else { __yp_unbind (ydb); free (ydb); - ydb = NULL; } + + ydb = NULL; status = YPERR_RPC; } else @@ -311,52 +364,6 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, return status; } -int -yp_bind (const char *indomain) -{ - int status; - - __libc_lock_lock (ypbindlist_lock); - - status = __yp_bind (indomain, &__ypbindlist); - - __libc_lock_unlock (ypbindlist_lock); - - return status; -} - -void -yp_unbind (const char *indomain) -{ - dom_binding *ydbptr, *ydbptr2; - - __libc_lock_lock (ypbindlist_lock); - - ydbptr2 = NULL; - ydbptr = __ypbindlist; - while (ydbptr != NULL) - { - if (strcmp (ydbptr->dom_domain, indomain) == 0) - { - dom_binding *work; - - work = ydbptr; - if (ydbptr2 == NULL) - __ypbindlist = __ypbindlist->dom_pnext; - else - ydbptr2 = ydbptr->dom_pnext; - __yp_unbind (work); - free (work); - break; - } - ydbptr2 = ydbptr; - ydbptr = ydbptr->dom_pnext; - } - - __libc_lock_unlock (ypbindlist_lock); - - return; -} __libc_lock_define_initialized (static, domainname_lock) @@ -374,7 +381,7 @@ yp_get_default_domain (char **outdomain) result = YPERR_NODOM; else if (strcmp (__ypdomainname, "(none)") == 0) { - /* If domainname is not set, some Systems will return "(none)" */ + /* If domainname is not set, some systems will return "(none)" */ __ypdomainname[0] = '\0'; result = YPERR_NODOM; } @@ -629,6 +636,10 @@ __xdr_ypresp_all (XDR *xdrs, u_long *objp) int keylen = resp.ypresp_all_u.val.key.keydat_len; int vallen = resp.ypresp_all_u.val.val.valdat_len; + /* We are not allowed to modify the key and val data. + But we are allowed to add data behind the buffer, + if we don't modify the length. So add an extra NUL + character to avoid trouble with broken code. */ *objp = YP_TRUE; memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen); key[keylen] = '\0'; @@ -640,14 +651,13 @@ __xdr_ypresp_all (XDR *xdrs, u_long *objp) return TRUE; } break; - case YP_NOMORE: - *objp = YP_NOMORE; - xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); - return TRUE; - break; default: *objp = resp.ypresp_all_u.val.stat; xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + /* Sun says we don't need to make this call, but must return + immediatly. Since Solaris makes this call, we will call + the callback function, too. */ + (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data); return TRUE; } } diff --git a/rt/Makefile b/rt/Makefile index b102cc834e..2044eb4bf6 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -35,7 +35,7 @@ include ../Makeconfig ifeq ($(have-thread-library),yes) -tests := tst-aio +tests := tst-aio tst-aio64 extra-libs := librt extra-libs-others := $(extra-libs) @@ -51,6 +51,8 @@ $(objpfx)librt.so: $(common-objpfx)libc.so $(shared-thread-library) ifeq (yes,$(build-shared)) $(objpfx)tst-aio: $(objpfx)librt.so $(shared-thread-library) +$(objpfx)tst-aio64: $(objpfx)librt.so $(shared-thread-library) else $(objpfx)tst-aio: $(objpfx)librt.a $(static-thread-library) -endif \ No newline at end of file +$(objpfx)tst-aio64: $(objpfx)librt.a $(static-thread-library) +endif diff --git a/rt/aio.h b/rt/aio.h index 0190ce9cd5..205d63afe7 100644 --- a/rt/aio.h +++ b/rt/aio.h @@ -57,7 +57,8 @@ struct aiocb char __unused[32]; }; -/* The same for the 64bit offsets. */ +/* The same for the 64bit offsets. Please note that the members aio_fildes + to __return_value have to be the same in aiocb and aiocb64. */ #ifdef __USE_LARGEFILE64 struct aiocb64 { @@ -69,6 +70,7 @@ struct aiocb64 struct sigevent aio_sigevent; /* Signal number and value. */ /* Internal members. */ + struct aiocb *__next_prio; int __abs_prio; int __policy; int __error_code; diff --git a/rt/tst-aio64.c b/rt/tst-aio64.c new file mode 100644 index 0000000000..60db0dd1aa --- /dev/null +++ b/rt/tst-aio64.c @@ -0,0 +1,196 @@ +/* Tests for 64bit AIO in librt. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + 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 _LARGEFILE_SOURCE 1 +#include <aio.h> +#include <errno.h> +#include <error.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + + +/* Prototype for our test function. */ +extern void do_prepare (int argc, char *argv[]); +extern int do_test (int argc, char *argv[]); + +/* We have a preparation function. */ +#define PREPARE do_prepare + +/* We might need a bit longer timeout. */ +#define TIMEOUT 20 /* sec */ + +/* This defines the `main' function and some more. */ +#include <test-skeleton.c> + + +/* These are for the temporary file we generate. */ +char *name; +int fd; + +void +do_prepare (int argc, char *argv[]) +{ + char name_len; + + name_len = strlen (test_dir); + name = malloc (name_len + sizeof ("/aioXXXXXX")); + mempcpy (mempcpy (name, test_dir, name_len), + "/aioXXXXXX", sizeof ("/aioXXXXXX")); + add_temp_file (name); + + /* Open our test file. */ + fd = mkstemp (name); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); +} + + +int +test_file (const void *buf, size_t size, int fd, const char *msg) +{ + struct stat st; + char tmp[size]; + + errno = 0; + if (fstat (fd, &st) < 0) + { + error (0, errno, "%s: failed stat", msg); + return 1; + } + + if (st.st_size != size) + { + error (0, errno, "%s: wrong size: %lu, should be %lu", + msg, (unsigned long int) st.st_size, (unsigned long int) size); + return 1; + } + + if (pread (fd, tmp, size, 0) != size) + { + error (0, errno, "%s: failed stat", msg); + return 1; + } + + if (memcmp (buf, tmp, size) != 0) + { + error (0, errno, "%s: failed comparison", msg); + return 1; + } + + printf ("%s test ok\n", msg); + + return 0; +} + + +void +do_wait (struct aiocb64 **cbp, size_t nent) +{ + int go_on; + do + { + size_t cnt; + + aio_suspend64 ((const struct aiocb64 *const *) cbp, nent, NULL); + go_on = 0; + for (cnt = 0; cnt < nent; ++cnt) + if (cbp[cnt] != NULL && aio_error64 (cbp[cnt]) == EINPROGRESS) + go_on = 1; + else + cbp[cnt] = NULL; + } + while (go_on); +} + + +int +do_test (int argc, char *argv[]) +{ + struct aiocb64 cbs[10]; + struct aiocb64 *cbp[10]; + char buf[1000]; + size_t cnt; + int result = 0; + + /* Preparation. */ + for (cnt = 0; cnt < 10; ++cnt) + { + cbs[cnt].aio_fildes = fd; + cbs[cnt].aio_reqprio = 0; + cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100); + cbs[cnt].aio_nbytes = 100; + cbs[cnt].aio_offset = cnt * 100; + cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; + + cbp[cnt] = &cbs[cnt]; + } + + /* First a simple test. */ + for (cnt = 10; cnt > 0; ) + aio_write64 (cbp[--cnt]); + /* Wait 'til the results are there. */ + do_wait (cbp, 10); + /* Test this. */ + result |= test_file (buf, sizeof (buf), fd, "aio_write"); + + /* Read now as we've written it. */ + memset (buf, '\0', sizeof (buf)); + /* Issue the commands. */ + for (cnt = 10; cnt > 0; ) + { + --cnt; + cbp[cnt] = &cbs[cnt]; + aio_read64 (cbp[cnt]); + } + /* Wait 'til the results are there. */ + do_wait (cbp, 10); + /* Test this. */ + for (cnt = 0; cnt < 1000; ++cnt) + if (buf[cnt] != '0' + (cnt / 100)) + { + result = 1; + error (0, 0, "comparison failed for aio_read test"); + break; + } + + if (cnt == 1000) + puts ("aio_read test ok"); + + /* Remove the test file contents. */ + if (ftruncate64 (fd, 0) < 0) + { + error (0, errno, "ftruncate failed\n"); + result = 1; + } + + /* Test lio_listio. */ + for (cnt = 0; cnt < 10; ++cnt) + { + cbs[cnt].aio_lio_opcode = LIO_WRITE; + cbp[cnt] = &cbs[cnt]; + } + /* Issue the command. */ + lio_listio64 (LIO_WAIT, cbp, 10, NULL); + /* ...and immediately test it since we started it in wait mode. */ + result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)"); + + return result; +} diff --git a/stdlib/longlong.h b/stdlib/longlong.h index f76f4799c7..a2e56c4c67 100644 --- a/stdlib/longlong.h +++ b/stdlib/longlong.h @@ -1185,8 +1185,8 @@ UDItype __umulsidi3 (USItype, USItype); #if (defined (__sparc_v9__) || (defined (__sparc__) && defined (__arch64__)) \ || defined (__sparcv9)) && W_TYPE_SIZE == 64 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %4,%5,%1 - add %2,%3,%0 + __asm__ ("addcc %r4,%5,%1 + add %r2,%3,%0 bcs,a,pn %%xcc, 1f add %0, 1, %0 1:" \ @@ -1199,8 +1199,8 @@ UDItype __umulsidi3 (USItype, USItype); __CLOBBER_CC) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subcc %4,%5,%1 - sub %2,%3,%0 + __asm__ ("subcc %r4,%5,%1 + sub %r2,%3,%0 bcs,a,pn %%xcc, 1f sub %0, 1, %0 1:" \ diff --git a/string/bits/string2.h b/string/bits/string2.h index 4d1baa2062..336aafef9a 100644 --- a/string/bits/string2.h +++ b/string/bits/string2.h @@ -118,7 +118,7 @@ __STRING2_COPY_TYPE (8); __uint8_t __c = (__uint8_t) (c); \ \ /* This `switch' statement will be removed at compile-time. */ \ - switch ((unsigned int) n) \ + switch ((unsigned int) (n)) \ { \ case 15: \ __u->__ui = __c * 0x01010101; \ @@ -1078,8 +1078,10 @@ __strtok_r_1c (char *__s, char __sep, char **__nextp) __extension__ \ ({ char __r0, __r1, __r2; \ (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \ - && (__r0 = ((__const char *) (reject))[0], __r0 != '\0') \ - ? ((__r1 = ((__const char *) (reject))[1], __r1 == '\0') \ + && (__r0 = ((__const char *) (reject))[0], \ + ((__const char *) (reject))[0] != '\0') \ + ? ((__r1 = ((__const char *) (reject))[1], \ + ((__const char *) (reject))[1] == '\0') \ ? __strsep_1c (s, __r0) \ : ((__r2 = ((__const char *) (reject))[2], __r2 == '\0') \ ? __strsep_2c (s, __r0, __r1) \ diff --git a/string/tester.c b/string/tester.c index 4fed10e4b4..d9043e046f 100644 --- a/string/tester.c +++ b/string/tester.c @@ -807,6 +807,7 @@ test_strtok_r (void) void test_strsep (void) { + char *ptr; it = "strsep"; cp = strcpy(one, "first, second, third"); equal(strsep(&cp, ", "), "first", 1); /* Basic test. */ @@ -901,6 +902,32 @@ test_strsep (void) equal(strsep(&cp, "xy,"), "", 71); check(strsep(&cp, "x,y") == NULL, 72); check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */ + + cp = strcpy(one, "ABC"); + one[4] = ':'; + equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */ + ptr = strsep(&cp, ":"); + equal(ptr, "", 75); + check(ptr == one + 3, 76); + check(cp == NULL, 77); + + cp = strcpy(one, "ABC"); + one[4] = ':'; + equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */ + ptr = strsep(&cp, ":."); + equal(ptr, "", 79); + check(ptr == one + 3, 80); + + cp = strcpy(one, "ABC"); /* No token in string. */ + equal(strsep(&cp, ","), "ABC", 81); + check(cp == NULL, 82); + + *one = '\0'; /* Empty string. */ + cp = one; + ptr = strsep(&cp, ","); + equal(ptr, "", 83); + check(ptr == one, 84); + check(cp == NULL, 85); } void diff --git a/sysdeps/alpha/fpu/bits/mathdef.h b/sysdeps/alpha/fpu/bits/mathdef.h index f5d5de8b12..30f93dda1c 100644 --- a/sysdeps/alpha/fpu/bits/mathdef.h +++ b/sysdeps/alpha/fpu/bits/mathdef.h @@ -23,7 +23,9 @@ /* FIXME! This file describes properties of the compiler, not the machine; it should not be part of libc! */ -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + # ifdef __GNUC__ # if __STDC__ == 1 diff --git a/sysdeps/generic/bits/mathdef.h b/sysdeps/generic/bits/mathdef.h index d306e54366..0c30b01f52 100644 --- a/sysdeps/generic/bits/mathdef.h +++ b/sysdeps/generic/bits/mathdef.h @@ -20,7 +20,9 @@ # error "Never use <bits/mathdef.h> directly; include <math.h> instead" #endif -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + /* Normally, there is no long double type and the `float' and `double' expressions are evaluated as `double'. */ typedef double float_t; /* `float' expressions are evaluated as diff --git a/sysdeps/generic/strsep.c b/sysdeps/generic/strsep.c index 7ca44f3c3a..004d8d8ac2 100644 --- a/sysdeps/generic/strsep.c +++ b/sysdeps/generic/strsep.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992, 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1992, 93, 96, 97, 98, 99 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 @@ -43,6 +43,8 @@ __strsep (char **stringp, const char *delim) { if (*begin == ch) end = begin; + else if (*begin == '\0') + end = NULL; else end = strchr (begin + 1, ch); } diff --git a/sysdeps/i386/fpu/bits/mathdef.h b/sysdeps/i386/fpu/bits/mathdef.h index ba5129895d..9436877a77 100644 --- a/sysdeps/i386/fpu/bits/mathdef.h +++ b/sysdeps/i386/fpu/bits/mathdef.h @@ -20,7 +20,9 @@ # error "Never use <bits/mathdef.h> directly; include <math.h> instead" #endif -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + /* The ix87 FPUs evaluate all values in the 80 bit floating-point format which is also available for the user as `long double'. Therefore we define: */ diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps index 443117da63..195bcca168 100644 --- a/sysdeps/i386/fpu/libm-test-ulps +++ b/sysdeps/i386/fpu/libm-test-ulps @@ -488,10 +488,14 @@ Test "Real part of: ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383 ildouble: 2 ldouble: 2 Test "Imaginary part of: ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383224937 i": +float: 1 +ifloat: 1 ildouble: 23 ldouble: 23 Test "Real part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i": Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i": +float: 1 +ifloat: 1 double: 0.5 idouble: 0.5 Test "Real part of: ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i": @@ -636,6 +640,9 @@ idouble: 1 Test "j0 (8.0) == 0.17165080713755390609": float: 1 ifloat: 1 +Test "j0 (10.0) == -0.24593576445134833520": +double: 2 +idouble: 2 # j1 Test "j1 (10.0) == 0.043472746168861436670": @@ -654,6 +661,8 @@ ifloat: 1 Test "jn (0, 10.0) == -0.24593576445134833520": float: 1 ifloat: 1 +double: 2 +idouble: 2 Test "jn (0, 2.0) == 0.22389077914123566805": float: 1 ifloat: 1 @@ -673,33 +682,46 @@ idouble: 1 Test "jn (1, 8.0) == 0.23463634685391462438": float: 1 ifloat: 1 +Test "jn (10, -1.0) == 0.26306151236874532070e-9": +float: 1 +ifloat: 1 Test "jn (10, 0.1) == 0.26905328954342155795e-19": double: 4 float: 2 idouble: 4 ifloat: 2 Test "jn (10, 0.7) == 0.75175911502153953928e-11": -double: 3 +double: 4 float: 1 -idouble: 3 +idouble: 4 ifloat: 1 -Test "jn (10, 2.0) == 0.25153862827167367096e-6": +Test "jn (10, 1.0) == 0.26306151236874532070e-9": float: 1 ifloat: 1 -double: 1 -idouble: 1 -Test "jn (10, 10.0) == 0.20748610663335885770": +Test "jn (10, 2.0) == 0.25153862827167367096e-6": float: 1 ifloat: 1 +double: 2 +idouble: 2 +Test "jn (10, 10.0) == 0.20748610663335885770": +float: 2 +ifloat: 2 +double: 4 +idouble: 4 Test "jn (3, 0.1) == 0.000020820315754756261429": double: 1 idouble: 1 Test "jn (3, 0.7) == 0.0069296548267508408077": double: 2 idouble: 2 +Test "jn (3, 2.0) == 0.12894324947440205110": +double: 1 +idouble: 1 Test "jn (3, 10.0) == 0.058379379305186812343": float: 1 ifloat: 1 +double: 3 +idouble: 3 # lgamma Test "lgamma (-0.5) == log(2*sqrt(pi))": @@ -847,6 +869,8 @@ float: 1 idouble: 1 ifloat: 1 Test "y0 (0.7) == -0.19066492933739506743": +float: 1 +ifloat: 1 double: 2 idouble: 2 Test "y0 (1.0) == 0.088256964215676957983": @@ -857,6 +881,8 @@ ifloat: 1 Test "y0 (1.5) == 0.38244892379775884396": float: 1 ifloat: 1 +double: 1 +idouble: 1 Test "y0 (2.0) == 0.51037567264974511960": double: 1 idouble: 1 @@ -891,9 +917,9 @@ idouble: 3 ifloat: 2 Test "y1 (2.0) == -0.10703243154093754689": double: 1 -float: 1 +float: 2 idouble: 1 -ifloat: 1 +ifloat: 2 Test "y1 (8.0) == -0.15806046173124749426": float: 2 ifloat: 2 @@ -905,6 +931,8 @@ float: 1 idouble: 1 ifloat: 1 Test "yn (0, 0.7) == -0.19066492933739506743": +float: 1 +ifloat: 1 double: 2 idouble: 2 Test "yn (0, 1.0) == 0.088256964215676957983": @@ -915,6 +943,8 @@ ifloat: 1 Test "yn (0, 1.5) == 0.38244892379775884396": float: 1 ifloat: 1 +double: 1 +idouble: 1 Test "yn (0, 2.0) == 0.51037567264974511960": double: 1 idouble: 1 @@ -947,9 +977,9 @@ idouble: 3 ifloat: 2 Test "yn (1, 2.0) == -0.10703243154093754689": double: 1 -float: 1 +float: 2 idouble: 1 -ifloat: 1 +ifloat: 2 Test "yn (1, 8.0) == -0.15806046173124749426": float: 2 ifloat: 2 @@ -974,8 +1004,8 @@ ifloat: 1 Test "yn (10, 2.0) == -129184.54220803928264": float: 1 ifloat: 1 -double: 1 -idouble: 1 +double: 2 +idouble: 2 Test "yn (3, 0.1) == -5099.3323786129048894": double: 1 float: 1 @@ -984,6 +1014,9 @@ ifloat: 1 Test "yn (3, 0.7) == -15.819479052819633505": double: 2 idouble: 2 +Test "yn (3, 2.0) == -1.1277837768404277861": +double: 1 +idouble: 1 Test "yn (3, 10.0) == -0.25136265718383732978": double: 1 float: 1 @@ -1263,6 +1296,8 @@ ildouble: 286 ldouble: 286 Function: Imaginary part of "ctanh": +float: 1 +ifloat: 1 double: 1 idouble: 1 ildouble: 3074 @@ -1313,8 +1348,8 @@ ldouble: 560 Function: "j0": float: 1 ifloat: 1 -double: 1 -idouble: 1 +double: 2 +idouble: 2 Function: "j1": double: 1 diff --git a/sysdeps/m68k/fpu/bits/mathdef.h b/sysdeps/m68k/fpu/bits/mathdef.h index 2f650ec8b5..c80dad3fe1 100644 --- a/sysdeps/m68k/fpu/bits/mathdef.h +++ b/sysdeps/m68k/fpu/bits/mathdef.h @@ -20,7 +20,9 @@ # error "Never use <bits/mathdef.h> directly; include <math.h> instead" #endif -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + /* The m68k FPUs evaluate all values in the 96 bit floating-point format which is also available for the user as `long double'. Therefore we define: */ diff --git a/sysdeps/powerpc/fpu/bits/mathdef.h b/sysdeps/powerpc/fpu/bits/mathdef.h index 71378c8458..577a596843 100644 --- a/sysdeps/powerpc/fpu/bits/mathdef.h +++ b/sysdeps/powerpc/fpu/bits/mathdef.h @@ -27,7 +27,9 @@ FIXME! This file does not deal with the -fshort-double option of gcc! */ -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + # ifdef __GNUC__ # if __STDC__ == 1 diff --git a/sysdeps/sparc/fpu/bits/mathdef.h b/sysdeps/sparc/fpu/bits/mathdef.h index c58167ce83..9477790654 100644 --- a/sysdeps/sparc/fpu/bits/mathdef.h +++ b/sysdeps/sparc/fpu/bits/mathdef.h @@ -25,7 +25,9 @@ /* FIXME! This file describes properties of the compiler, not the machine; it should not be part of libc! */ -#if defined __USE_ISOC99 && defined _MATH_H +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + # ifdef __GNUC__ # if __STDC__ == 1 diff --git a/sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c deleted file mode 100644 index 9feab0e6b8..0000000000 --- a/sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c +++ /dev/null @@ -1 +0,0 @@ -/* getrlimit64 is the same as getrlimit. */ diff --git a/sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c b/sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c deleted file mode 100644 index 8edcff0086..0000000000 --- a/sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c +++ /dev/null @@ -1 +0,0 @@ -/* setrlimit64 is the same as setrlimit. */ diff --git a/sysdeps/unix/sysv/linux/bits/resource.h b/sysdeps/unix/sysv/linux/bits/resource.h index fcff605892..6a3d86ce18 100644 --- a/sysdeps/unix/sysv/linux/bits/resource.h +++ b/sysdeps/unix/sysv/linux/bits/resource.h @@ -106,13 +106,13 @@ enum __rlimit_resource /* Value to indicate that there is no limit. */ #ifndef __USE_FILE_OFFSET64 -# define RLIM_INFINITY ((unsigned long int)(~0UL)) +# define RLIM_INFINITY ((long int)(~0UL >> 1)) #else -# define RLIM_INFINITY 0xffffffffffffffffuLL +# define RLIM_INFINITY 0x7fffffffffffffffLL #endif #ifdef __USE_LARGEFILE64 -# define RLIM64_INFINITY 0xffffffffffffffffuLL +# define RLIM64_INFINITY 0x7fffffffffffffffLL #endif /* We can represent all limits. */ diff --git a/sysdeps/unix/sysv/linux/i386/bits/resource.h b/sysdeps/unix/sysv/linux/i386/bits/resource.h new file mode 100644 index 0000000000..fcff605892 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/bits/resource.h @@ -0,0 +1,227 @@ +/* Bit values & structures for resource limits. Linux version. + Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use <bits/resource.h> directly; include <sys/resource.h> instead." +#endif + +#include <asm/resource.h> +#include <bits/types.h> + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + _RLIMIT_CPU = RLIMIT_CPU, +#undef RLIMIT_CPU + RLIMIT_CPU = _RLIMIT_CPU, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + _RLIMIT_FSIZE = RLIMIT_FSIZE, +#undef RLIMIT_FSIZE + RLIMIT_FSIZE = _RLIMIT_FSIZE, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + _RLIMIT_DATA = RLIMIT_DATA, +#undef RLIMIT_DATA + RLIMIT_DATA = _RLIMIT_DATA, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + _RLIMIT_STACK = RLIMIT_STACK, +#undef RLIMIT_STACK + RLIMIT_STACK = _RLIMIT_STACK, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + _RLIMIT_CORE = RLIMIT_CORE, +#undef RLIMIT_CORE + RLIMIT_CORE = _RLIMIT_CORE, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + _RLIMIT_RSS = RLIMIT_RSS, +#undef RLIMIT_RSS + RLIMIT_RSS = _RLIMIT_RSS, +#define RLIMIT_RSS RLIMIT_RSS + + /* Number of open files. */ + _RLIMIT_NOFILE = RLIMIT_NOFILE, +#undef RLIMIT_NOFILE + RLIMIT_NOFILE = _RLIMIT_NOFILE, + RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE RLIMIT_OFILE + + /* Address space limit (?) */ + _RLIMIT_AS = RLIMIT_AS, +#undef RLIMIT_AS + RLIMIT_AS = _RLIMIT_AS, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + _RLIMIT_NPROC = RLIMIT_NPROC, +#undef RLIMIT_NPROC + RLIMIT_NPROC = _RLIMIT_NPROC, +#define RLIMIT_NPROC RLIMIT_NPROC + + /* Locked-in-memory address space. */ + _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK, +#undef RLIMIT_MEMLOCK + RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK, +#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK + + RLIMIT_NLIMITS = RLIM_NLIMITS, +#undef RLIM_NLIMITS + RLIM_NLIMITS = RLIMIT_NLIMITS +#define RLIMIT_NLIMITS RLIMIT_NLIMITS +#define RLIM_NLIMITS RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((unsigned long int)(~0UL)) +#else +# define RLIM_INFINITY 0xffffffffffffffffuLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffuLL +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1, +#define RUSAGE_CHILDREN RUSAGE_CHILDREN + + /* Both. */ + RUSAGE_BOTH = -2 +#define RUSAGE_BOTH RUSAGE_BOTH +}; + +#define __need_timeval +#include <bits/time.h> /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/sysdeps/unix/sysv/linux/getrlimit.c b/sysdeps/unix/sysv/linux/i386/getrlimit.c index 14a879c5df..14a879c5df 100644 --- a/sysdeps/unix/sysv/linux/getrlimit.c +++ b/sysdeps/unix/sysv/linux/i386/getrlimit.c diff --git a/sysdeps/unix/sysv/linux/getrlimit64.c b/sysdeps/unix/sysv/linux/i386/getrlimit64.c index 602dd28d8a..602dd28d8a 100644 --- a/sysdeps/unix/sysv/linux/getrlimit64.c +++ b/sysdeps/unix/sysv/linux/i386/getrlimit64.c diff --git a/sysdeps/unix/sysv/linux/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c index 5fb0becfbe..5fb0becfbe 100644 --- a/sysdeps/unix/sysv/linux/oldgetrlimit64.c +++ b/sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c diff --git a/sysdeps/unix/sysv/linux/oldsetrlimit64.c b/sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c index c5448dcdce..c5448dcdce 100644 --- a/sysdeps/unix/sysv/linux/oldsetrlimit64.c +++ b/sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c diff --git a/sysdeps/unix/sysv/linux/setrlimit.c b/sysdeps/unix/sysv/linux/i386/setrlimit.c index 2123360fc9..2123360fc9 100644 --- a/sysdeps/unix/sysv/linux/setrlimit.c +++ b/sysdeps/unix/sysv/linux/i386/setrlimit.c diff --git a/sysdeps/unix/sysv/linux/setrlimit64.c b/sysdeps/unix/sysv/linux/i386/setrlimit64.c index 3e7e5cc0e0..3e7e5cc0e0 100644 --- a/sysdeps/unix/sysv/linux/setrlimit64.c +++ b/sysdeps/unix/sysv/linux/i386/setrlimit64.c diff --git a/sysdeps/unix/sysv/linux/sparc/bits/resource.h b/sysdeps/unix/sysv/linux/sparc/bits/resource.h new file mode 100644 index 0000000000..abfe433c59 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/bits/resource.h @@ -0,0 +1,243 @@ +/* Bit values & structures for resource limits. Linux version. + Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use <bits/resource.h> directly; include <sys/resource.h> instead." +#endif + +#include <asm/resource.h> +#include <bits/types.h> + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + _RLIMIT_CPU = RLIMIT_CPU, +#undef RLIMIT_CPU + RLIMIT_CPU = _RLIMIT_CPU, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + _RLIMIT_FSIZE = RLIMIT_FSIZE, +#undef RLIMIT_FSIZE + RLIMIT_FSIZE = _RLIMIT_FSIZE, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + _RLIMIT_DATA = RLIMIT_DATA, +#undef RLIMIT_DATA + RLIMIT_DATA = _RLIMIT_DATA, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + _RLIMIT_STACK = RLIMIT_STACK, +#undef RLIMIT_STACK + RLIMIT_STACK = _RLIMIT_STACK, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + _RLIMIT_CORE = RLIMIT_CORE, +#undef RLIMIT_CORE + RLIMIT_CORE = _RLIMIT_CORE, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + _RLIMIT_RSS = RLIMIT_RSS, +#undef RLIMIT_RSS + RLIMIT_RSS = _RLIMIT_RSS, +#define RLIMIT_RSS RLIMIT_RSS + + /* Number of open files. */ + _RLIMIT_NOFILE = RLIMIT_NOFILE, +#undef RLIMIT_NOFILE + RLIMIT_NOFILE = _RLIMIT_NOFILE, + RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE RLIMIT_OFILE + + /* Address space limit (?) */ + _RLIMIT_AS = RLIMIT_AS, +#undef RLIMIT_AS + RLIMIT_AS = _RLIMIT_AS, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + _RLIMIT_NPROC = RLIMIT_NPROC, +#undef RLIMIT_NPROC + RLIMIT_NPROC = _RLIMIT_NPROC, +#define RLIMIT_NPROC RLIMIT_NPROC + + /* Locked-in-memory address space. */ + _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK, +#undef RLIMIT_MEMLOCK + RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK, +#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK + + RLIMIT_NLIMITS = RLIM_NLIMITS, +#undef RLIM_NLIMITS + RLIM_NLIMITS = RLIMIT_NLIMITS +#define RLIMIT_NLIMITS RLIMIT_NLIMITS +#define RLIM_NLIMITS RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#if __WORDSIZE == 64 + +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((unsigned long int)(~0UL)) +#else +# define RLIM_INFINITY 0xffffffffffffffffuLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffuLL +#endif + +#else + +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +#else +# define RLIM_INFINITY 0x7fffffffffffffffLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffLL +#endif + +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1, +#define RUSAGE_CHILDREN RUSAGE_CHILDREN + + /* Both. */ + RUSAGE_BOTH = -2 +#define RUSAGE_BOTH RUSAGE_BOTH +}; + +#define __need_timeval +#include <bits/time.h> /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c deleted file mode 100644 index 9feab0e6b8..0000000000 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c +++ /dev/null @@ -1 +0,0 @@ -/* getrlimit64 is the same as getrlimit. */ diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c b/sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c deleted file mode 100644 index 8edcff0086..0000000000 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c +++ /dev/null @@ -1 +0,0 @@ -/* setrlimit64 is the same as setrlimit. */ diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c index cbfc248c8e..34d3c62e86 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c @@ -44,6 +44,7 @@ __sigaction (int sig, __const struct sigaction *act, struct sigaction *oact) { kact.k_sa_handler = act->sa_handler; memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); + kact.sa_flags = act->sa_flags; kact.sa_restorer = NULL; } |