@comment syslog.h
@comment BSD
-@deftypefun void openlog (char *@var{ident}, int @var{option},
- int @var{facility})
+@deftypefun void openlog (const char *@var{ident}, int @var{option}, int @var{facility})
@code{openlog} opens or reopens a connection to Syslog in preparation
for submitting messages.
to identify the source of the message, and people conventionally set it
to the name of the program that will submit the messages.
+If @var{ident} is NULL, or if @code{openlog} is not called, the default
+identification string used in Syslog messages will be the program name,
+taken from argv[0].
+
+Please note that the string pointer @var{ident} will be retained
+internally by the Syslog routines. You must not free the memory that
+@var{ident} points to. It is also dangerous to pass a reference to an
+automatic variable since leaving the scope would mean ending the
+lifetime of the variable. If you want to change the @var{ident} string,
+you must call @code{openlog} again; overwriting the string pointed to by
+@var{ident} is not thread-safe.
+
+You can cause the Syslog routines to drop the reference to @var{ident} and
+go back to the default string (the program name taken from argv[0]), by
+calling @code{closelog}: @xref{closelog}.
+
+In particular, if you are writing code for a shared library that might get
+loaded and then unloaded (e.g. a PAM module), and you use @code{openlog},
+you must call @code{closelog} before any point where your library might
+get unloaded, as in this example:
+
+@smallexample
+#include <syslog.h>
+
+void
+shared_library_function (void)
+@{
+ openlog ("mylibrary", option, priority);
+
+ syslog (LOG_INFO, "shared library has been invoked");
+
+ closelog ();
+@}
+@end smallexample
+
+Without the call to @code{closelog}, future invocations of @code{syslog}
+by the program using the shared library may crash, if the library gets
+unloaded and the memory containing the string @code{"mylibrary"} becomes
+unmapped. This is a limitation of the BSD syslog interface.
+
@code{openlog} may or may not open the @file{/dev/log} socket, depending
on @var{option}. If it does, it tries to open it and connect it as a
stream socket. If that doesn't work, it tries to open it and connect it
@deftypefun void closelog (void)
@code{closelog} closes the current Syslog connection, if there is one.
-This include closing the @file{dev/log} socket, if it is open.
-
-There is very little reason to use this function. It does not flush any
-buffers; you can reopen a Syslog connection without closing it first;
-The connection gets closed automatically on exec or exit.
-@code{closelog} has primarily aesthetic value.
+This includes closing the @file{dev/log} socket, if it is open.
+@code{closelog} also sets the identification string for Syslog messages
+back to the default, if @code{openlog} was called with a non-NULL argument
+to @var{ident}. The default identification string is the program name
+taken from argv[0].
+
+If you are writing shared library code that uses @code{openlog} to
+generate custom syslog output, you should use @code{closelog} to drop the
+GNU C library's internal reference to the @var{ident} pointer when you are
+done. Please read the section on @code{openlog} for more information:
+@xref{openlog}.
+
+@code{closelog} does not flush any buffers. You do not have to call
+@code{closelog} before re-opening a Syslog connection with @code{initlog}.
+Syslog connections are automatically closed on exec or exit.
@end deftypefun
/* An alternative to qsort, with an identical interface.
This file is part of the GNU C Library.
- Copyright (C) 1992, 1995-1997, 1999, 2000, 2001 Free Software Foundation, Inc.
- Written by Mike Haertel, September 1988.
+ Copyright (C) 1992, 1995-1997, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Original Implementation by Mike Haertel, September 1988.
+ Towers of Hanoi Mergesort by Roger Sayle, January 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
02111-1307 USA. */
#include <alloca.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <memcopy.h>
#include <errno.h>
+
+/* Check whether pointer P is aligned for access by type T. */
+#define TYPE_ALIGNED(P,T) (((char *) (P) - (char *) 0) % __alignof__ (T) == 0)
+
+
+static int hanoi_sort (char *b, size_t n, size_t s,
+ __compar_fn_t cmp, char *t);
+static int hanoi_sort_int (int *b, size_t n,
+ __compar_fn_t cmp, int *t);
+#if INT_MAX != LONG_MAX
+static int hanoi_sort_long (long int *b, size_t n,
+ __compar_fn_t cmp, long int *t);
+#endif
static void msort_with_tmp (void *b, size_t n, size_t s,
- __compar_fn_t cmp, char *t);
+ __compar_fn_t cmp, void *t);
-static void
-msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp,
- char *t)
+
+/* This routine implements "Towers of Hanoi Mergesort". The algorithm
+ sorts the n elements of size s pointed to by array b using comparison
+ function cmp. The argument t points to a suitable temporary buffer.
+ If the return value is zero, the sorted array is returned in b, and
+ for non-zero return values the sorted array is returned in t. */
+static int
+hanoi_sort (char *b, size_t n, size_t s, __compar_fn_t cmp, char *t)
{
- char *tmp;
- char *b1, *b2;
size_t n1, n2;
+ char *b1,*b2;
+ char *t1,*t2;
+ char *s1,*s2;
+ size_t size;
+ int result;
+ char *ptr;
if (n <= 1)
- return;
+ return 0;
- n1 = n / 2;
+ if (n == 2)
+ {
+ b2 = b + s;
+ if ((*cmp) (b, b2) <= 0)
+ return 0;
+ memcpy (__mempcpy (t, b2, s), b, s);
+ return 1;
+ }
+
+ n1 = n/2;
n2 = n - n1;
+ /* n1 < n2! */
+
+ size = n1 * s;
b1 = b;
- b2 = (char *) b + (n1 * s);
-
- msort_with_tmp (b1, n1, s, cmp, t);
- msort_with_tmp (b2, n2, s, cmp, t);
-
- tmp = t;
-
- if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0)
- /* We are operating on aligned words. Use direct word stores. */
- while (n1 > 0 && n2 > 0)
- {
- if ((*cmp) (b1, b2) <= 0)
- {
- --n1;
- *((op_t *) tmp)++ = *((op_t *) b1)++;
- }
- else
- {
- --n2;
- *((op_t *) tmp)++ = *((op_t *) b2)++;
- }
- }
+ b2 = b + size;
+
+ t1 = t;
+ t2 = t + size;
+
+ /* Recursively call hanoi_sort to sort the two halves of the array.
+ Depending upon the return values, determine the values s1 and s2
+ the locations of the two sorted subarrays, ptr, the location to
+ contain the sorted array and result, the return value for this
+ function. Note that "ptr = result? t : b". */
+ if (hanoi_sort (b1, n1, s, cmp, t1))
+ {
+ if (hanoi_sort (b2, n2, s, cmp, t2))
+ {
+ result = 0;
+ ptr = b;
+ s1 = t1;
+ s2 = t2;
+ }
+ else
+ {
+ result = 0;
+ ptr = b;
+ s1 = t1;
+ s2 = b2;
+ }
+ }
else
- while (n1 > 0 && n2 > 0)
- {
- if ((*cmp) (b1, b2) <= 0)
- {
- tmp = (char *) __mempcpy (tmp, b1, s);
- b1 += s;
- --n1;
- }
- else
- {
- tmp = (char *) __mempcpy (tmp, b2, s);
- b2 += s;
- --n2;
- }
- }
- if (n1 > 0)
- memcpy (tmp, b1, n1 * s);
- memcpy (b, t, (n - n2) * s);
+ {
+ if (hanoi_sort (b2, n2, s, cmp, t2))
+ {
+ result = 1;
+ ptr = t;
+ s1 = b1;
+ s2 = t2;
+ }
+ else
+ {
+ result = 1;
+ ptr = t;
+ s1 = b1;
+ s2 = b2;
+ }
+ }
+
+ /* Merge the two sorted arrays s1 and s2 of n1 and n2 elements
+ respectively, placing the result in ptr. On entry, n1 > 0
+ && n2 > 0, and with each iteration either n1 or n2 is decreased
+ until either reaches zero, and the loop terminates via return. */
+ for (;;)
+ {
+ if ((*cmp) (s1, s2) <= 0)
+ {
+ ptr = (char *) __mempcpy (ptr, s1, s);
+ s1 += s;
+ --n1;
+ if (n1 == 0)
+ {
+ if (ptr != s2)
+ memcpy (ptr, s2, n2 * s);
+ return result;
+ }
+ }
+ else
+ {
+ ptr = (char *) __mempcpy (ptr, s2, s);
+ s2 += s;
+ --n2;
+ if (n2 == 0)
+ {
+ memcpy (ptr, s1, n1 * s);
+ return result;
+ }
+ }
+ }
+}
+
+
+/* This routine is a variant of hanoi_sort that is optimized for the
+ case where items to be sorted are the size of ints, and both b and
+ t are suitably aligned. The parameter s in not needed as it is
+ known to be sizeof(int). */
+static int
+hanoi_sort_int (int *b, size_t n, __compar_fn_t cmp, int *t)
+{
+ size_t n1, n2;
+ int *b1,*b2;
+ int *t1,*t2;
+ int *s1,*s2;
+ int result;
+ int *ptr;
+
+ if (n <= 1)
+ return 0;
+
+ if (n == 2)
+ {
+ if ((*cmp) (b, b + 1) <= 0)
+ return 0;
+ t[0] = b[1];
+ t[1] = b[0];
+ return 1;
+ }
+
+ n1 = n/2;
+ n2 = n - n1;
+ /* n1 < n2! */
+
+ b1 = b;
+ b2 = b + n1;
+
+ t1 = t;
+ t2 = t + n1;
+
+ /* Recursively call hanoi_sort_int to sort the two halves. */
+ if (hanoi_sort_int (b1, n1, cmp, t1))
+ {
+ if (hanoi_sort_int (b2, n2, cmp, t2))
+ {
+ result = 0;
+ ptr = b;
+ s1 = t1;
+ s2 = t2;
+ }
+ else
+ {
+ result = 0;
+ ptr = b;
+ s1 = t1;
+ s2 = b2;
+ }
+ }
+ else
+ {
+ if (hanoi_sort_int (b2, n2, cmp, t2))
+ {
+ result = 1;
+ ptr = t;
+ s1 = b1;
+ s2 = t2;
+ }
+ else
+ {
+ result = 1;
+ ptr = t;
+ s1 = b1;
+ s2 = b2;
+ }
+ }
+
+ /* Merge n1 elements from s1 and n2 elements from s2 into ptr. */
+ for (;;)
+ {
+ if ((*cmp) (s1, s2) <= 0)
+ {
+ *ptr++ = *s1++;
+ --n1;
+ if (n1 == 0)
+ {
+ if (ptr != s2)
+ memcpy (ptr, s2, n2 * sizeof (int));
+ return result;
+ }
+ }
+ else
+ {
+ *ptr++ = *s2++;
+ --n2;
+ if (n2 == 0)
+ {
+ memcpy (ptr, s1, n1 * sizeof (int));
+ return result;
+ }
+ }
+ }
+}
+
+
+#if INT_MAX != LONG_MAX
+/* This routine is a variant of hanoi_sort that is optimized for the
+ case where items to be sorted are the size of longs, and both b and
+ t are suitably aligned. The parameter s in not needed as it is
+ known to be sizeof(long). In case sizeof(int)== sizeof(long) we
+ do not need this code since it would be the same as hanoi_sort_int. */
+static int
+hanoi_sort_long (long int *b, size_t n, __compar_fn_t cmp, long int *t)
+{
+ size_t n1, n2;
+ long int *b1,*b2;
+ long int *t1,*t2;
+ long int *s1,*s2;
+ int result;
+ long int *ptr;
+
+ if (n <= 1)
+ return 0;
+
+ if (n == 2)
+ {
+ if ((*cmp) (b, b + 1) <= 0)
+ return 0;
+ t[0] = b[1];
+ t[1] = b[0];
+ return 1;
+ }
+
+ n1 = n/2;
+ n2 = n - n1;
+ /* n1 < n2! */
+
+ b1 = b;
+ b2 = b + n1;
+
+ t1 = t;
+ t2 = t + n1;
+
+ /* Recursively call hanoi_sort_long to sort the two halves. */
+ if (hanoi_sort_long (b1, n1, cmp, t1))
+ {
+ if (hanoi_sort_long (b2, n2, cmp, t2))
+ {
+ result = 0;
+ ptr = b;
+ s1 = t1;
+ s2 = t2;
+ }
+ else
+ {
+ result = 0;
+ ptr = b;
+ s1 = t1;
+ s2 = b2;
+ }
+ }
+ else
+ {
+ if (hanoi_sort_long (b2, n2, cmp, t2))
+ {
+ result = 1;
+ ptr = t;
+ s1 = b1;
+ s2 = t2;
+ }
+ else
+ {
+ result = 1;
+ ptr = t;
+ s1 = b1;
+ s2 = b2;
+ }
+ }
+
+ /* Merge n1 elements from s1 and n2 elements from s2 into ptr. */
+ for (;;)
+ {
+ if ((*cmp) (s1, s2) <= 0)
+ {
+ *ptr++ = *s1++;
+ --n1;
+ if (n1 == 0)
+ {
+ if (ptr != s2)
+ memcpy (ptr, s2, n2 * sizeof (long));
+ return result;
+ }
+ }
+ else
+ {
+ *ptr++ = *s2++;
+ --n2;
+ if (n2 == 0)
+ {
+ memcpy (ptr, s1, n1 * sizeof (long));
+ return result;
+ }
+ }
+ }
+}
+#endif
+
+
+/* This routine preserves the original interface to msort_with_tmp and
+ determines which variant of hanoi_sort to call, based upon item size
+ and alignment. */
+
+static void
+msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp, void *t)
+{
+ const size_t size = n * s;
+
+ if (s == sizeof (int) && TYPE_ALIGNED (b, int))
+ {
+ if (hanoi_sort_int (b, n, cmp, t))
+ memcpy (b, t, size);
+ }
+#if INT_MAX != LONG_MAX
+ else if (s == sizeof (long int) && TYPE_ALIGNED (b, long int))
+ {
+ if (hanoi_sort_long (b, n, cmp, t))
+ memcpy (b, t, size);
+ }
+#endif
+ else
+ {
+ /* Call the generic implementation. */
+ if (hanoi_sort (b, n, s, cmp, t))
+ memcpy (b, t, size);
+ }
}
void
if (size < 1024)
{
void *buf = __alloca (size);
-
+
/* The temporary array is small, so put it on the stack. */
msort_with_tmp (b, n, s, cmp, buf);
}
measured in bytes. */
/* If the memory requirements are too high don't allocate memory. */
- if (size / pagesize > phys_pages)
+ if ((long int) (size / pagesize) > phys_pages)
_quicksort (b, n, s, cmp);
else
{