X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/17d94f1ba4333a0d53558af02583dbf80e9157ff..512cdb9f2ba6dde0c24bfed13d095ea37e38a6ec:/src/sysdep.c diff --git a/src/sysdep.c b/src/sysdep.c index 4b0f54ebe6..a2bda96192 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1,5 +1,5 @@ /* 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. @@ -19,6 +19,14 @@ along with GNU Emacs. If not, see . */ #include +/* 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 #include "sysstdio.h" #ifdef HAVE_PWD_H @@ -102,6 +110,9 @@ along with GNU Emacs. If not, see . */ #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 #endif #include "syssignal.h" @@ -121,9 +132,8 @@ static const int baud_convert[] = 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. */ @@ -1399,29 +1409,19 @@ setup_pty (int fd) } #endif /* HAVE_PTYS */ -#ifdef HAVE_SOCKETS -#include -#include -#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 @@ -1439,110 +1439,15 @@ init_system_name (void) 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); } sigset_t empty_mask; @@ -2450,7 +2355,7 @@ emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte, { 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 (); @@ -3598,25 +3503,125 @@ system_process_attributes (Lisp_Object pid) #ifdef __STDC_ISO_10646__ # include +# include -# if defined HAVE_USELOCALE || defined HAVE_SETLOCALE +# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE # include # 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 + +# 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) +{ + 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) +str_collate (Lisp_Object s1, Lisp_Object s2, + Lisp_Object locale, Lisp_Object ignore_case) { - ptrdiff_t res, len, i, i_byte; + int res, err; + ptrdiff_t 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; -# endif USE_SAFE_ALLOCA; @@ -3633,57 +3638,68 @@ str_collate (Lisp_Object s1, Lisp_Object s2) 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)); - errno = 0; - res = wcscoll (p1, p2); - if (errno) - error ("Wrong argument: %s", strerror (errno)); + 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 int -str_collate (Lisp_Object s1, Lisp_Object s2) +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 */