/* Interfaces to system-dependent kernel and library entries.
- Copyright (C) 1985-1988, 1993-1995, 1999-2014 Free Software
+ Copyright (C) 1985-1988, 1993-1995, 1999-2015 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
+/* If HYBRID_GET_CURRENT_DIR_NAME is defined in conf_post.h, then we
+ need the following before including unistd.h, in order to pick up
+ the right prototype for gget_current_dir_name. */
+#ifdef HYBRID_GET_CURRENT_DIR_NAME
+#undef get_current_dir_name
+#define get_current_dir_name gget_current_dir_name
+#endif
+
#include <execinfo.h>
#include "sysstdio.h"
#ifdef HAVE_PWD_H
#define _P_WAIT 0
int _cdecl _spawnlp (int, const char *, const char *, ...);
int _cdecl _getpid (void);
+/* The following is needed for O_CLOEXEC, F_SETFD, FD_CLOEXEC, and
+ several prototypes of functions called below. */
+#include <sys/socket.h>
#endif
#include "syssignal.h"
1800, 2400, 4800, 9600, 19200, 38400
};
-
-#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
-
+#if !defined HAVE_GET_CURRENT_DIR_NAME || defined BROKEN_GET_CURRENT_DIR_NAME \
+ || (defined HYBRID_GET_CURRENT_DIR_NAME)
/* Return the current working directory. Returns NULL on errors.
Any other returned value must be freed with free. This is used
only when get_current_dir_name is not defined on the system. */
}
#endif /* HAVE_PTYS */
\f
-#ifdef HAVE_SOCKETS
-#include <sys/socket.h>
-#include <netdb.h>
-#endif /* HAVE_SOCKETS */
-
-#ifdef TRY_AGAIN
-#ifndef HAVE_H_ERRNO
-extern int h_errno;
-#endif
-#endif /* TRY_AGAIN */
-
void
init_system_name (void)
{
+ char *hostname_alloc = NULL;
+ char *hostname;
#ifndef HAVE_GETHOSTNAME
struct utsname uts;
uname (&uts);
- Vsystem_name = build_string (uts.nodename);
+ hostname = uts.nodename;
#else /* HAVE_GETHOSTNAME */
- char *hostname_alloc = NULL;
char hostname_buf[256];
ptrdiff_t hostname_size = sizeof hostname_buf;
- char *hostname = hostname_buf;
+ hostname = hostname_buf;
/* Try to get the host name; if the buffer is too short, try
again. Apparently, the only indication gethostname gives of
hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1,
min (PTRDIFF_MAX, SIZE_MAX), 1);
}
-#ifdef HAVE_SOCKETS
- /* Turn the hostname into the official, fully-qualified hostname.
- Don't do this if we're going to dump; this can confuse system
- libraries on some machines and make the dumped emacs core dump. */
-#ifndef CANNOT_DUMP
- if (initialized)
-#endif /* not CANNOT_DUMP */
- if (! strchr (hostname, '.'))
- {
- int count;
-#ifdef HAVE_GETADDRINFO
- struct addrinfo *res;
- struct addrinfo hints;
- int ret;
-
- memset (&hints, 0, sizeof (hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_CANONNAME;
-
- for (count = 0;; count++)
- {
- if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
- || ret != EAI_AGAIN)
- break;
-
- if (count >= 5)
- break;
- Fsleep_for (make_number (1), Qnil);
- }
-
- if (ret == 0)
- {
- struct addrinfo *it = res;
- while (it)
- {
- char *fqdn = it->ai_canonname;
- if (fqdn && strchr (fqdn, '.')
- && strcmp (fqdn, "localhost.localdomain") != 0)
- break;
- it = it->ai_next;
- }
- if (it)
- {
- ptrdiff_t len = strlen (it->ai_canonname);
- if (hostname_size <= len)
- {
- hostname_size = len + 1;
- hostname = hostname_alloc = xrealloc (hostname_alloc,
- hostname_size);
- }
- strcpy (hostname, it->ai_canonname);
- }
- freeaddrinfo (res);
- }
-#else /* !HAVE_GETADDRINFO */
- struct hostent *hp;
- for (count = 0;; count++)
- {
-
-#ifdef TRY_AGAIN
- h_errno = 0;
-#endif
- hp = gethostbyname (hostname);
-#ifdef TRY_AGAIN
- if (! (hp == 0 && h_errno == TRY_AGAIN))
-#endif
-
- break;
-
- if (count >= 5)
- break;
- Fsleep_for (make_number (1), Qnil);
- }
-
- if (hp)
- {
- char *fqdn = (char *) hp->h_name;
-
- if (!strchr (fqdn, '.'))
- {
- /* We still don't have a fully qualified domain name.
- Try to find one in the list of alternate names */
- char **alias = hp->h_aliases;
- while (*alias
- && (!strchr (*alias, '.')
- || !strcmp (*alias, "localhost.localdomain")))
- alias++;
- if (*alias)
- fqdn = *alias;
- }
- hostname = fqdn;
- }
-#endif /* !HAVE_GETADDRINFO */
- }
-#endif /* HAVE_SOCKETS */
- Vsystem_name = build_string (hostname);
- xfree (hostname_alloc);
#endif /* HAVE_GETHOSTNAME */
- {
- char *p;
- for (p = SSDATA (Vsystem_name); *p; p++)
- if (*p == ' ' || *p == '\t')
- *p = '-';
- }
+ char *p;
+ for (p = hostname; *p; p++)
+ if (*p == ' ' || *p == '\t')
+ *p = '-';
+ if (! (STRINGP (Vsystem_name) && SBYTES (Vsystem_name) == p - hostname
+ && strcmp (SSDATA (Vsystem_name), hostname) == 0))
+ Vsystem_name = build_string (hostname);
+ xfree (hostname_alloc);
}
\f
sigset_t empty_mask;
#ifdef HAVE_STACK_OVERFLOW_HANDLING
-/* True if stack grows down as expected on most OS/ABI variants. */
+/* -1 if stack grows down as expected on most OS/ABI variants, 1 otherwise. */
-static bool stack_grows_down;
+static int stack_direction;
/* Alternate stack used by SIGSEGV handler below. */
if (!getrlimit (RLIMIT_STACK, &rlim))
{
- enum { STACK_EXTRA = 16 * 1024 };
- char *fault_addr = (char *) siginfo->si_addr;
- unsigned long used = (stack_grows_down
- ? stack_bottom - fault_addr
- : fault_addr - stack_bottom);
-
- if (used + STACK_EXTRA > rlim.rlim_cur)
- /* Most likely this is it. */
+ enum { STACK_DANGER_ZONE = 16 * 1024 };
+ char *beg, *end, *addr;
+
+ beg = stack_bottom;
+ end = stack_bottom + stack_direction * rlim.rlim_cur;
+ if (beg > end)
+ addr = beg, beg = end, end = addr;
+ addr = (char *) siginfo->si_addr;
+ /* If we're somewhere on stack and too close to
+ one of its boundaries, most likely this is it. */
+ if (beg < addr && addr < end
+ && (addr - beg < STACK_DANGER_ZONE
+ || end - addr < STACK_DANGER_ZONE))
siglongjmp (return_to_command_loop, 1);
}
}
+
+ /* Otherwise we can't do anything with this. */
+ deliver_fatal_thread_signal (sig);
}
+/* Return true if we have successfully set up SIGSEGV handler on alternate
+ stack. Otherwise we just treat SIGSEGV among the rest of fatal signals. */
+
static bool
init_sigsegv (void)
{
struct sigaction sa;
stack_t ss;
- stack_grows_down = ((char *) &ss < stack_bottom);
+ stack_direction = ((char *) &ss < stack_bottom) ? -1 : 1;
ss.ss_sp = sigsegv_stack;
ss.ss_size = sizeof (sigsegv_stack);
{
if (errno == EINTR)
{
- /* I originally used `QUIT' but that might causes files to
+ /* I originally used `QUIT' but that might cause files to
be truncated if you hit C-g in the middle of it. --Stef */
if (process_signals && pending_signals)
process_pending_signals ();
#ifdef __STDC_ISO_10646__
# include <wchar.h>
+# include <wctype.h>
-# if defined HAVE_USELOCALE || defined HAVE_SETLOCALE
+# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE
# include <locale.h>
# endif
-# ifndef HAVE_SETLOCALE
-# define setlocale(category, locale) ((char *) 0)
+# ifndef LC_COLLATE
+# define LC_COLLATE 0
+# endif
+# ifndef LC_COLLATE_MASK
+# define LC_COLLATE_MASK 0
+# endif
+# ifndef LC_CTYPE
+# define LC_CTYPE 0
+# endif
+# ifndef LC_CTYPE_MASK
+# define LC_CTYPE_MASK 0
# endif
-ptrdiff_t
-str_collate (Lisp_Object s1, Lisp_Object s2)
+# ifndef HAVE_NEWLOCALE
+# undef freelocale
+# undef locale_t
+# undef newlocale
+# undef wcscoll_l
+# undef towlower_l
+# define freelocale emacs_freelocale
+# define locale_t emacs_locale_t
+# define newlocale emacs_newlocale
+# define wcscoll_l emacs_wcscoll_l
+# define towlower_l emacs_towlower_l
+
+typedef char const *locale_t;
+
+static locale_t
+newlocale (int category_mask, char const *locale, locale_t loc)
{
- ptrdiff_t res, len, i, i_byte;
- wchar_t *p1, *p2;
- Lisp_Object lc_collate;
-# ifdef HAVE_USELOCALE
- locale_t loc = 0, oldloc = 0;
-# else
- char *oldloc = NULL;
+ return locale;
+}
+
+static void
+freelocale (locale_t loc)
+{
+}
+
+static char *
+emacs_setlocale (int category, char const *locale)
+{
+# ifdef HAVE_SETLOCALE
+ errno = 0;
+ char *loc = setlocale (category, locale);
+ if (loc || errno)
+ return loc;
+ errno = EINVAL;
+# else
+ errno = ENOTSUP;
+# endif
+ return 0;
+}
+
+static int
+wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc)
+{
+ int result = 0;
+ char *oldloc = emacs_setlocale (LC_COLLATE, NULL);
+ int err;
+
+ if (! oldloc)
+ err = errno;
+ else
+ {
+ USE_SAFE_ALLOCA;
+ char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
+ strcpy (oldcopy, oldloc);
+ if (! emacs_setlocale (LC_COLLATE, loc))
+ err = errno;
+ else
+ {
+ errno = 0;
+ result = wcscoll (a, b);
+ err = errno;
+ if (! emacs_setlocale (LC_COLLATE, oldcopy))
+ err = errno;
+ }
+ SAFE_FREE ();
+ }
+
+ errno = err;
+ return result;
+}
+
+static wint_t
+towlower_l (wint_t wc, locale_t loc)
+{
+ wint_t result = wc;
+ char *oldloc = emacs_setlocale (LC_CTYPE, NULL);
+
+ if (oldloc)
+ {
+ USE_SAFE_ALLOCA;
+ char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
+ strcpy (oldcopy, oldloc);
+ if (emacs_setlocale (LC_CTYPE, loc))
+ {
+ result = towlower (wc);
+ emacs_setlocale (LC_COLLATE, oldcopy);
+ }
+ SAFE_FREE ();
+ }
+
+ return result;
+}
# endif
+int
+str_collate (Lisp_Object s1, Lisp_Object s2,
+ Lisp_Object locale, Lisp_Object ignore_case)
+{
+ int res, err;
+ ptrdiff_t len, i, i_byte;
+ wchar_t *p1, *p2;
+
USE_SAFE_ALLOCA;
/* Convert byte stream to code points. */
FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte);
*(p2+len) = 0;
- /* Create a new locale object, and set it. */
- lc_collate =
- Fgetenv_internal (build_string ("LC_COLLATE"), Vprocess_environment);
-
- if (STRINGP (lc_collate))
+ if (STRINGP (locale))
{
-#ifdef HAVE_USELOCALE
- loc = newlocale (LC_COLLATE_MASK, SSDATA (lc_collate), 0);
- if (loc)
- oldloc = uselocale (loc);
-#else
- oldloc = setlocale (LC_COLLATE, NULL);
- if (oldloc)
- {
- oldloc = xstrdup (oldloc);
- setlocale (LC_COLLATE, SSDATA (lc_collate));
- }
-#endif
- }
+ locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK,
+ SSDATA (locale), 0);
+ if (!loc)
+ error ("Invalid locale %s: %s", SSDATA (locale), strerror (errno));
- res = wcscoll (p1, p2);
+ if (! NILP (ignore_case))
+ for (int i = 1; i < 3; i++)
+ {
+ wchar_t *p = (i == 1) ? p1 : p2;
+ for (; *p; p++)
+ *p = towlower_l (*p, loc);
+ }
-#ifdef HAVE_USELOCALE
- /* Free the locale object, and reset. */
- if (loc)
- freelocale (loc);
- if (oldloc)
- uselocale (oldloc);
-#else
- /* Restore the original locale. */
- setlocale (LC_COLLATE, oldloc);
- xfree (oldloc);
-#endif
+ errno = 0;
+ res = wcscoll_l (p1, p2, loc);
+ err = errno;
+ freelocale (loc);
+ }
+ else
+ {
+ if (! NILP (ignore_case))
+ for (int i = 1; i < 3; i++)
+ {
+ wchar_t *p = (i == 1) ? p1 : p2;
+ for (; *p; p++)
+ *p = towlower (*p);
+ }
+
+ errno = 0;
+ res = wcscoll (p1, p2);
+ err = errno;
+ }
+# ifndef HAVE_NEWLOCALE
+ if (err)
+ error ("Invalid locale or string for collation: %s", strerror (err));
+# else
+ if (err)
+ error ("Invalid string for collation: %s", strerror (err));
+# endif
- /* Return result. */
SAFE_FREE ();
return res;
}
-#endif /* __STDC_ISO_10646__ */
+#endif /* __STDC_ISO_10646__ */
#ifdef WINDOWSNT
-ptrdiff_t
-str_collate (Lisp_Object s1, Lisp_Object s2)
+int
+str_collate (Lisp_Object s1, Lisp_Object s2,
+ Lisp_Object locale, Lisp_Object ignore_case)
{
- Lisp_Object lc_collate =
- Fgetenv_internal (build_string ("LC_COLLATE"), Vprocess_environment);
- char *loc = STRINGP (lc_collate) ? SSDATA (lc_collate) : NULL;
- return w32_compare_strings (SDATA (s1), SDATA (s2), loc);
+ char *loc = STRINGP (locale) ? SSDATA (locale) : NULL;
+ int res, err = errno;
+
+ errno = 0;
+ res = w32_compare_strings (SDATA (s1), SDATA (s2), loc, !NILP (ignore_case));
+ if (errno)
+ error ("Invalid string for collation: %s", strerror (errno));
+
+ errno = err;
+ return res;
}
#endif /* WINDOWSNT */