aboutsummaryrefslogtreecommitdiffstats
path: root/src/sysdep.c
diff options
context:
space:
mode:
authorKen Raeburn2015-11-01 01:42:21 -0400
committerKen Raeburn2015-11-01 01:42:21 -0400
commit39372e1a1032521be74575bb06f95a3898fbae30 (patch)
tree754bd242a23d2358ea116126fcb0a629947bd9ec /src/sysdep.c
parent6a3121904d76e3b2f63007341d48c5c1af55de80 (diff)
parente11aaee266da52937a3a031cb108fe13f68958c3 (diff)
downloademacs-39372e1a1032521be74575bb06f95a3898fbae30.tar.gz
emacs-39372e1a1032521be74575bb06f95a3898fbae30.zip
merge from trunk
Diffstat (limited to 'src/sysdep.c')
-rw-r--r--src/sysdep.c714
1 files changed, 505 insertions, 209 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 0533a5d3e02..ba6be57278e 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1,5 +1,5 @@
1/* Interfaces to system-dependent kernel and library entries. 1/* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985-1988, 1993-1995, 1999-2013 Free Software 2 Copyright (C) 1985-1988, 1993-1995, 1999-2015 Free Software
3 Foundation, Inc. 3 Foundation, Inc.
4 4
5This file is part of GNU Emacs. 5This file is part of GNU Emacs.
@@ -19,7 +19,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20#include <config.h> 20#include <config.h>
21 21
22#define SYSTIME_INLINE EXTERN_INLINE 22/* If HYBRID_GET_CURRENT_DIR_NAME is defined in conf_post.h, then we
23 need the following before including unistd.h, in order to pick up
24 the right prototype for gget_current_dir_name. */
25#ifdef HYBRID_GET_CURRENT_DIR_NAME
26#undef get_current_dir_name
27#define get_current_dir_name gget_current_dir_name
28#endif
23 29
24#include <execinfo.h> 30#include <execinfo.h>
25#include "sysstdio.h" 31#include "sysstdio.h"
@@ -59,7 +65,6 @@ extern int h_errno;
59# include <sys/user.h> 65# include <sys/user.h>
60# undef frame 66# undef frame
61 67
62# include <sys/resource.h>
63# include <math.h> 68# include <math.h>
64#endif 69#endif
65 70
@@ -99,13 +104,11 @@ extern int h_errno;
99 104
100#include "keyboard.h" 105#include "keyboard.h"
101#include "frame.h" 106#include "frame.h"
102#include "window.h"
103#include "termhooks.h" 107#include "termhooks.h"
104#include "termchar.h" 108#include "termchar.h"
105#include "termopts.h" 109#include "termopts.h"
106#include "dispextern.h"
107#include "process.h" 110#include "process.h"
108#include "cm.h" /* for reset_sys_modes */ 111#include "cm.h"
109 112
110#ifdef WINDOWSNT 113#ifdef WINDOWSNT
111#include <direct.h> 114#include <direct.h>
@@ -113,14 +116,14 @@ extern int h_errno;
113#define _P_WAIT 0 116#define _P_WAIT 0
114int _cdecl _spawnlp (int, const char *, const char *, ...); 117int _cdecl _spawnlp (int, const char *, const char *, ...);
115int _cdecl _getpid (void); 118int _cdecl _getpid (void);
119/* The following is needed for O_CLOEXEC, F_SETFD, FD_CLOEXEC, and
120 several prototypes of functions called below. */
121#include <sys/socket.h>
116#endif 122#endif
117 123
118#include "syssignal.h" 124#include "syssignal.h"
119#include "systime.h" 125#include "systime.h"
120 126
121static void emacs_get_tty (int, struct emacs_tty *);
122static int emacs_set_tty (int, struct emacs_tty *, bool);
123
124/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */ 127/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */
125#ifndef ULLONG_MAX 128#ifndef ULLONG_MAX
126#define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int) 129#define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int)
@@ -135,13 +138,12 @@ static const int baud_convert[] =
135 1800, 2400, 4800, 9600, 19200, 38400 138 1800, 2400, 4800, 9600, 19200, 38400
136 }; 139 };
137 140
138 141#if !defined HAVE_GET_CURRENT_DIR_NAME || defined BROKEN_GET_CURRENT_DIR_NAME \
139#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME) 142 || (defined HYBRID_GET_CURRENT_DIR_NAME)
140
141/* Return the current working directory. Returns NULL on errors. 143/* Return the current working directory. Returns NULL on errors.
142 Any other returned value must be freed with free. This is used 144 Any other returned value must be freed with free. This is used
143 only when get_current_dir_name is not defined on the system. */ 145 only when get_current_dir_name is not defined on the system. */
144char* 146char *
145get_current_dir_name (void) 147get_current_dir_name (void)
146{ 148{
147 char *buf; 149 char *buf;
@@ -235,7 +237,9 @@ discard_tty_input (void)
235void 237void
236stuff_char (char c) 238stuff_char (char c)
237{ 239{
238 if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) 240 if (! (FRAMEP (selected_frame)
241 && FRAME_LIVE_P (XFRAME (selected_frame))
242 && FRAME_TERMCAP_P (XFRAME (selected_frame))))
239 return; 243 return;
240 244
241/* Should perhaps error if in batch mode */ 245/* Should perhaps error if in batch mode */
@@ -268,7 +272,7 @@ init_baud_rate (int fd)
268#endif /* not DOS_NT */ 272#endif /* not DOS_NT */
269 } 273 }
270 274
271 baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0] 275 baud_rate = (emacs_ospeed < ARRAYELTS (baud_convert)
272 ? baud_convert[emacs_ospeed] : 9600); 276 ? baud_convert[emacs_ospeed] : 9600);
273 if (baud_rate == 0) 277 if (baud_rate == 0)
274 baud_rate = 1200; 278 baud_rate = 1200;
@@ -317,7 +321,7 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
317 /* If successful and status is requested, tell wait_reading_process_output 321 /* If successful and status is requested, tell wait_reading_process_output
318 that it needs to wake up and look around. */ 322 that it needs to wake up and look around. */
319 if (pid && status && input_available_clear_time) 323 if (pid && status && input_available_clear_time)
320 *input_available_clear_time = make_emacs_time (0, 0); 324 *input_available_clear_time = make_timespec (0, 0);
321 325
322 return pid; 326 return pid;
323} 327}
@@ -477,7 +481,11 @@ sys_subshell (void)
477{ 481{
478#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */ 482#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
479 int st; 483 int st;
484#ifdef MSDOS
480 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */ 485 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
486#else
487 char oldwd[MAX_UTF8_PATH];
488#endif
481#endif 489#endif
482 pid_t pid; 490 pid_t pid;
483 int status; 491 int status;
@@ -599,7 +607,7 @@ restore_signal_handlers (struct save_signal *saved_handlers)
599} 607}
600 608
601#ifdef USABLE_SIGIO 609#ifdef USABLE_SIGIO
602static int old_fcntl_flags[MAXDESC]; 610static int old_fcntl_flags[FD_SETSIZE];
603#endif 611#endif
604 612
605void 613void
@@ -612,6 +620,7 @@ init_sigio (int fd)
612#endif 620#endif
613} 621}
614 622
623#ifndef DOS_NT
615static void 624static void
616reset_sigio (int fd) 625reset_sigio (int fd)
617{ 626{
@@ -619,6 +628,7 @@ reset_sigio (int fd)
619 fcntl (fd, F_SETFL, old_fcntl_flags[fd]); 628 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
620#endif 629#endif
621} 630}
631#endif
622 632
623void 633void
624request_sigio (void) 634request_sigio (void)
@@ -658,15 +668,29 @@ unrequest_sigio (void)
658 interrupts_deferred = 1; 668 interrupts_deferred = 1;
659#endif 669#endif
660} 670}
671
672#ifndef MSDOS
673/* Block SIGCHLD. */
661 674
662void 675void
663ignore_sigio (void) 676block_child_signal (sigset_t *oldset)
664{ 677{
665#ifdef USABLE_SIGIO 678 sigset_t blocked;
666 signal (SIGIO, SIG_IGN); 679 sigemptyset (&blocked);
667#endif 680 sigaddset (&blocked, SIGCHLD);
681 sigaddset (&blocked, SIGINT);
682 pthread_sigmask (SIG_BLOCK, &blocked, oldset);
668} 683}
669 684
685/* Unblock SIGCHLD. */
686
687void
688unblock_child_signal (sigset_t const *oldset)
689{
690 pthread_sigmask (SIG_SETMASK, oldset, 0);
691}
692
693#endif /* !MSDOS */
670 694
671/* Saving and restoring the process group of Emacs's terminal. */ 695/* Saving and restoring the process group of Emacs's terminal. */
672 696
@@ -701,21 +725,21 @@ init_foreground_group (void)
701/* Block and unblock SIGTTOU. */ 725/* Block and unblock SIGTTOU. */
702 726
703void 727void
704block_tty_out_signal (void) 728block_tty_out_signal (sigset_t *oldset)
705{ 729{
706#ifdef SIGTTOU 730#ifdef SIGTTOU
707 sigset_t blocked; 731 sigset_t blocked;
708 sigemptyset (&blocked); 732 sigemptyset (&blocked);
709 sigaddset (&blocked, SIGTTOU); 733 sigaddset (&blocked, SIGTTOU);
710 pthread_sigmask (SIG_BLOCK, &blocked, 0); 734 pthread_sigmask (SIG_BLOCK, &blocked, oldset);
711#endif 735#endif
712} 736}
713 737
714void 738void
715unblock_tty_out_signal (void) 739unblock_tty_out_signal (sigset_t const *oldset)
716{ 740{
717#ifdef SIGTTOU 741#ifdef SIGTTOU
718 pthread_sigmask (SIG_SETMASK, &empty_mask, 0); 742 pthread_sigmask (SIG_SETMASK, oldset, 0);
719#endif 743#endif
720} 744}
721 745
@@ -730,10 +754,11 @@ static void
730tcsetpgrp_without_stopping (int fd, pid_t pgid) 754tcsetpgrp_without_stopping (int fd, pid_t pgid)
731{ 755{
732#ifdef SIGTTOU 756#ifdef SIGTTOU
757 sigset_t oldset;
733 block_input (); 758 block_input ();
734 block_tty_out_signal (); 759 block_tty_out_signal (&oldset);
735 tcsetpgrp (fd, pgid); 760 tcsetpgrp (fd, pgid);
736 unblock_tty_out_signal (); 761 unblock_tty_out_signal (&oldset);
737 unblock_input (); 762 unblock_input ();
738#endif 763#endif
739} 764}
@@ -760,15 +785,28 @@ widen_foreground_group (int fd)
760/* Getting and setting emacs_tty structures. */ 785/* Getting and setting emacs_tty structures. */
761 786
762/* Set *TC to the parameters associated with the terminal FD, 787/* Set *TC to the parameters associated with the terminal FD,
763 or clear it if the parameters are not available. */ 788 or clear it if the parameters are not available.
764static void 789 Return 0 on success, -1 on failure. */
790int
765emacs_get_tty (int fd, struct emacs_tty *settings) 791emacs_get_tty (int fd, struct emacs_tty *settings)
766{ 792{
767 /* Retrieve the primary parameters - baud rate, character size, etcetera. */ 793 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
768#ifndef DOS_NT
769 /* We have those nifty POSIX tcmumbleattr functions. */
770 memset (&settings->main, 0, sizeof (settings->main)); 794 memset (&settings->main, 0, sizeof (settings->main));
771 tcgetattr (fd, &settings->main); 795#ifdef DOS_NT
796#ifdef WINDOWSNT
797 HANDLE h = (HANDLE)_get_osfhandle (fd);
798 DWORD console_mode;
799
800 if (h && h != INVALID_HANDLE_VALUE && GetConsoleMode (h, &console_mode))
801 {
802 settings->main = console_mode;
803 return 0;
804 }
805#endif /* WINDOWSNT */
806 return -1;
807#else /* !DOS_NT */
808 /* We have those nifty POSIX tcmumbleattr functions. */
809 return tcgetattr (fd, &settings->main);
772#endif 810#endif
773} 811}
774 812
@@ -777,11 +815,26 @@ emacs_get_tty (int fd, struct emacs_tty *settings)
777 *SETTINGS. If FLUSHP, discard input. 815 *SETTINGS. If FLUSHP, discard input.
778 Return 0 if all went well, and -1 (setting errno) if anything failed. */ 816 Return 0 if all went well, and -1 (setting errno) if anything failed. */
779 817
780static int 818int
781emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp) 819emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp)
782{ 820{
783 /* Set the primary parameters - baud rate, character size, etcetera. */ 821 /* Set the primary parameters - baud rate, character size, etcetera. */
784#ifndef DOS_NT 822#ifdef DOS_NT
823#ifdef WINDOWSNT
824 HANDLE h = (HANDLE)_get_osfhandle (fd);
825
826 if (h && h != INVALID_HANDLE_VALUE)
827 {
828 DWORD new_mode;
829
830 /* Assume the handle is open for input. */
831 if (flushp)
832 FlushConsoleInputBuffer (h);
833 new_mode = settings->main;
834 SetConsoleMode (h, new_mode);
835 }
836#endif /* WINDOWSNT */
837#else /* !DOS_NT */
785 int i; 838 int i;
786 /* We have those nifty POSIX tcmumbleattr functions. 839 /* We have those nifty POSIX tcmumbleattr functions.
787 William J. Smith <wjs@wiis.wang.com> writes: 840 William J. Smith <wjs@wiis.wang.com> writes:
@@ -828,7 +881,7 @@ emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp)
828 881
829 882
830#ifdef F_SETOWN 883#ifdef F_SETOWN
831static int old_fcntl_owner[MAXDESC]; 884static int old_fcntl_owner[FD_SETSIZE];
832#endif /* F_SETOWN */ 885#endif /* F_SETOWN */
833 886
834/* This may also be defined in stdio, 887/* This may also be defined in stdio,
@@ -1122,6 +1175,24 @@ tabs_safe_p (int fd)
1122 return 0; 1175 return 0;
1123#endif /* DOS_NT */ 1176#endif /* DOS_NT */
1124} 1177}
1178
1179/* Discard echoing. */
1180
1181void
1182suppress_echo_on_tty (int fd)
1183{
1184 struct emacs_tty etty;
1185
1186 emacs_get_tty (fd, &etty);
1187#ifdef DOS_NT
1188 /* Set raw input mode. */
1189 etty.main = 0;
1190#else
1191 etty.main.c_lflag &= ~ICANON; /* Disable buffering */
1192 etty.main.c_lflag &= ~ECHO; /* Disable echoing */
1193#endif /* ! WINDOWSNT */
1194 emacs_set_tty (fd, &etty, 0);
1195}
1125 1196
1126/* Get terminal size from system. 1197/* Get terminal size from system.
1127 Store number of lines into *HEIGHTP and width into *WIDTHP. 1198 Store number of lines into *HEIGHTP and width into *WIDTHP.
@@ -1254,7 +1325,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
1254 int i; 1325 int i;
1255 tty_turn_off_insert (tty_out); 1326 tty_turn_off_insert (tty_out);
1256 1327
1257 for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++) 1328 for (i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++)
1258 { 1329 {
1259 fputc (' ', tty_out->output); 1330 fputc (' ', tty_out->output);
1260 } 1331 }
@@ -1339,15 +1410,16 @@ setup_pty (int fd)
1339void 1410void
1340init_system_name (void) 1411init_system_name (void)
1341{ 1412{
1413 char *hostname_alloc = NULL;
1414 char *hostname;
1342#ifndef HAVE_GETHOSTNAME 1415#ifndef HAVE_GETHOSTNAME
1343 struct utsname uts; 1416 struct utsname uts;
1344 uname (&uts); 1417 uname (&uts);
1345 Vsystem_name = build_string (uts.nodename); 1418 hostname = uts.nodename;
1346#else /* HAVE_GETHOSTNAME */ 1419#else /* HAVE_GETHOSTNAME */
1347 char *hostname_alloc = NULL;
1348 char hostname_buf[256]; 1420 char hostname_buf[256];
1349 ptrdiff_t hostname_size = sizeof hostname_buf; 1421 ptrdiff_t hostname_size = sizeof hostname_buf;
1350 char *hostname = hostname_buf; 1422 hostname = hostname_buf;
1351 1423
1352 /* Try to get the host name; if the buffer is too short, try 1424 /* Try to get the host name; if the buffer is too short, try
1353 again. Apparently, the only indication gethostname gives of 1425 again. Apparently, the only indication gethostname gives of
@@ -1365,110 +1437,15 @@ init_system_name (void)
1365 hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1, 1437 hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1,
1366 min (PTRDIFF_MAX, SIZE_MAX), 1); 1438 min (PTRDIFF_MAX, SIZE_MAX), 1);
1367 } 1439 }
1368#ifdef HAVE_SOCKETS
1369 /* Turn the hostname into the official, fully-qualified hostname.
1370 Don't do this if we're going to dump; this can confuse system
1371 libraries on some machines and make the dumped emacs core dump. */
1372#ifndef CANNOT_DUMP
1373 if (initialized)
1374#endif /* not CANNOT_DUMP */
1375 if (! strchr (hostname, '.'))
1376 {
1377 int count;
1378#ifdef HAVE_GETADDRINFO
1379 struct addrinfo *res;
1380 struct addrinfo hints;
1381 int ret;
1382
1383 memset (&hints, 0, sizeof (hints));
1384 hints.ai_socktype = SOCK_STREAM;
1385 hints.ai_flags = AI_CANONNAME;
1386
1387 for (count = 0;; count++)
1388 {
1389 if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
1390 || ret != EAI_AGAIN)
1391 break;
1392
1393 if (count >= 5)
1394 break;
1395 Fsleep_for (make_number (1), Qnil);
1396 }
1397
1398 if (ret == 0)
1399 {
1400 struct addrinfo *it = res;
1401 while (it)
1402 {
1403 char *fqdn = it->ai_canonname;
1404 if (fqdn && strchr (fqdn, '.')
1405 && strcmp (fqdn, "localhost.localdomain") != 0)
1406 break;
1407 it = it->ai_next;
1408 }
1409 if (it)
1410 {
1411 ptrdiff_t len = strlen (it->ai_canonname);
1412 if (hostname_size <= len)
1413 {
1414 hostname_size = len + 1;
1415 hostname = hostname_alloc = xrealloc (hostname_alloc,
1416 hostname_size);
1417 }
1418 strcpy (hostname, it->ai_canonname);
1419 }
1420 freeaddrinfo (res);
1421 }
1422#else /* !HAVE_GETADDRINFO */
1423 struct hostent *hp;
1424 for (count = 0;; count++)
1425 {
1426
1427#ifdef TRY_AGAIN
1428 h_errno = 0;
1429#endif
1430 hp = gethostbyname (hostname);
1431#ifdef TRY_AGAIN
1432 if (! (hp == 0 && h_errno == TRY_AGAIN))
1433#endif
1434
1435 break;
1436
1437 if (count >= 5)
1438 break;
1439 Fsleep_for (make_number (1), Qnil);
1440 }
1441
1442 if (hp)
1443 {
1444 char *fqdn = (char *) hp->h_name;
1445
1446 if (!strchr (fqdn, '.'))
1447 {
1448 /* We still don't have a fully qualified domain name.
1449 Try to find one in the list of alternate names */
1450 char **alias = hp->h_aliases;
1451 while (*alias
1452 && (!strchr (*alias, '.')
1453 || !strcmp (*alias, "localhost.localdomain")))
1454 alias++;
1455 if (*alias)
1456 fqdn = *alias;
1457 }
1458 hostname = fqdn;
1459 }
1460#endif /* !HAVE_GETADDRINFO */
1461 }
1462#endif /* HAVE_SOCKETS */
1463 Vsystem_name = build_string (hostname);
1464 xfree (hostname_alloc);
1465#endif /* HAVE_GETHOSTNAME */ 1440#endif /* HAVE_GETHOSTNAME */
1466 { 1441 char *p;
1467 char *p; 1442 for (p = hostname; *p; p++)
1468 for (p = SSDATA (Vsystem_name); *p; p++) 1443 if (*p == ' ' || *p == '\t')
1469 if (*p == ' ' || *p == '\t') 1444 *p = '-';
1470 *p = '-'; 1445 if (! (STRINGP (Vsystem_name) && SBYTES (Vsystem_name) == p - hostname
1471 } 1446 && strcmp (SSDATA (Vsystem_name), hostname) == 0))
1447 Vsystem_name = build_string (hostname);
1448 xfree (hostname_alloc);
1472} 1449}
1473 1450
1474sigset_t empty_mask; 1451sigset_t empty_mask;
@@ -1504,7 +1481,9 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
1504 /* When handling a signal, block nonfatal system signals that are caught 1481 /* When handling a signal, block nonfatal system signals that are caught
1505 by Emacs. This makes race conditions less likely. */ 1482 by Emacs. This makes race conditions less likely. */
1506 sigaddset (&action->sa_mask, SIGALRM); 1483 sigaddset (&action->sa_mask, SIGALRM);
1484#ifdef SIGCHLD
1507 sigaddset (&action->sa_mask, SIGCHLD); 1485 sigaddset (&action->sa_mask, SIGCHLD);
1486#endif
1508#ifdef SIGDANGER 1487#ifdef SIGDANGER
1509 sigaddset (&action->sa_mask, SIGDANGER); 1488 sigaddset (&action->sa_mask, SIGDANGER);
1510#endif 1489#endif
@@ -1523,9 +1502,6 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
1523#endif 1502#endif
1524 } 1503 }
1525 1504
1526 if (! IEEE_FLOATING_POINT)
1527 sigaddset (&action->sa_mask, SIGFPE);
1528
1529 action->sa_handler = handler; 1505 action->sa_handler = handler;
1530 action->sa_flags = emacs_sigaction_flags (); 1506 action->sa_flags = emacs_sigaction_flags ();
1531} 1507}
@@ -1645,6 +1621,112 @@ handle_arith_signal (int sig)
1645 xsignal0 (Qarith_error); 1621 xsignal0 (Qarith_error);
1646} 1622}
1647 1623
1624#if defined HAVE_STACK_OVERFLOW_HANDLING && !defined WINDOWSNT
1625
1626/* Alternate stack used by SIGSEGV handler below. */
1627
1628static unsigned char sigsegv_stack[SIGSTKSZ];
1629
1630
1631/* Return true if SIGINFO indicates a stack overflow. */
1632
1633static bool
1634stack_overflow (siginfo_t *siginfo)
1635{
1636 /* In theory, a more-accurate heuristic can be obtained by using
1637 GNU/Linux pthread_getattr_np along with POSIX pthread_attr_getstack
1638 and pthread_attr_getguardsize to find the location and size of the
1639 guard area. In practice, though, these functions are so hard to
1640 use reliably that they're not worth bothering with. E.g., see:
1641 https://sourceware.org/bugzilla/show_bug.cgi?id=16291
1642 Other operating systems also have problems, e.g., Solaris's
1643 stack_violation function is tailor-made for this problem, but it
1644 doesn't work on Solaris 11.2 x86-64 with a 32-bit executable.
1645
1646 GNU libsigsegv is overkill for Emacs; otherwise it might be a
1647 candidate here. */
1648
1649 if (!siginfo)
1650 return false;
1651
1652 /* The faulting address. */
1653 char *addr = siginfo->si_addr;
1654 if (!addr)
1655 return false;
1656
1657 /* The known top and bottom of the stack. The actual stack may
1658 extend a bit beyond these boundaries. */
1659 char *bot = stack_bottom;
1660 char *top = near_C_stack_top ();
1661
1662 /* Log base 2 of the stack heuristic ratio. This ratio is the size
1663 of the known stack divided by the size of the guard area past the
1664 end of the stack top. The heuristic is that a bad address is
1665 considered to be a stack overflow if it occurs within
1666 stacksize>>LG_STACK_HEURISTIC bytes above the top of the known
1667 stack. This heuristic is not exactly correct but it's good
1668 enough in practice. */
1669 enum { LG_STACK_HEURISTIC = 8 };
1670
1671 if (bot < top)
1672 return 0 <= addr - top && addr - top < (top - bot) >> LG_STACK_HEURISTIC;
1673 else
1674 return 0 <= top - addr && top - addr < (bot - top) >> LG_STACK_HEURISTIC;
1675}
1676
1677
1678/* Attempt to recover from SIGSEGV caused by C stack overflow. */
1679
1680static void
1681handle_sigsegv (int sig, siginfo_t *siginfo, void *arg)
1682{
1683 /* Hard GC error may lead to stack overflow caused by
1684 too nested calls to mark_object. No way to survive. */
1685 bool fatal = gc_in_progress;
1686
1687#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1688 if (!fatal && !pthread_equal (pthread_self (), main_thread))
1689 fatal = true;
1690#endif
1691
1692 if (!fatal && stack_overflow (siginfo))
1693 siglongjmp (return_to_command_loop, 1);
1694
1695 /* Otherwise we can't do anything with this. */
1696 deliver_fatal_thread_signal (sig);
1697}
1698
1699/* Return true if we have successfully set up SIGSEGV handler on alternate
1700 stack. Otherwise we just treat SIGSEGV among the rest of fatal signals. */
1701
1702static bool
1703init_sigsegv (void)
1704{
1705 struct sigaction sa;
1706 stack_t ss;
1707
1708 ss.ss_sp = sigsegv_stack;
1709 ss.ss_size = sizeof (sigsegv_stack);
1710 ss.ss_flags = 0;
1711 if (sigaltstack (&ss, NULL) < 0)
1712 return 0;
1713
1714 sigfillset (&sa.sa_mask);
1715 sa.sa_sigaction = handle_sigsegv;
1716 sa.sa_flags = SA_SIGINFO | SA_ONSTACK | emacs_sigaction_flags ();
1717 return sigaction (SIGSEGV, &sa, NULL) < 0 ? 0 : 1;
1718}
1719
1720#else /* not HAVE_STACK_OVERFLOW_HANDLING or WINDOWSNT */
1721
1722static bool
1723init_sigsegv (void)
1724{
1725 return 0;
1726}
1727
1728#endif /* HAVE_STACK_OVERFLOW_HANDLING && !WINDOWSNT */
1729
1648static void 1730static void
1649deliver_arith_signal (int sig) 1731deliver_arith_signal (int sig)
1650{ 1732{
@@ -1709,7 +1791,9 @@ init_signals (bool dumping)
1709# ifdef SIGBUS 1791# ifdef SIGBUS
1710 sys_siglist[SIGBUS] = "Bus error"; 1792 sys_siglist[SIGBUS] = "Bus error";
1711# endif 1793# endif
1794# ifdef SIGCHLD
1712 sys_siglist[SIGCHLD] = "Child status changed"; 1795 sys_siglist[SIGCHLD] = "Child status changed";
1796# endif
1713# ifdef SIGCONT 1797# ifdef SIGCONT
1714 sys_siglist[SIGCONT] = "Continued"; 1798 sys_siglist[SIGCONT] = "Continued";
1715# endif 1799# endif
@@ -1909,7 +1993,8 @@ init_signals (bool dumping)
1909#ifdef SIGBUS 1993#ifdef SIGBUS
1910 sigaction (SIGBUS, &thread_fatal_action, 0); 1994 sigaction (SIGBUS, &thread_fatal_action, 0);
1911#endif 1995#endif
1912 sigaction (SIGSEGV, &thread_fatal_action, 0); 1996 if (!init_sigsegv ())
1997 sigaction (SIGSEGV, &thread_fatal_action, 0);
1913#ifdef SIGSYS 1998#ifdef SIGSYS
1914 sigaction (SIGSYS, &thread_fatal_action, 0); 1999 sigaction (SIGSYS, &thread_fatal_action, 0);
1915#endif 2000#endif
@@ -2021,8 +2106,8 @@ seed_random (void *seed, ptrdiff_t seed_size)
2021void 2106void
2022init_random (void) 2107init_random (void)
2023{ 2108{
2024 EMACS_TIME t = current_emacs_time (); 2109 struct timespec t = current_timespec ();
2025 uintmax_t v = getpid () ^ EMACS_SECS (t) ^ EMACS_NSECS (t); 2110 uintmax_t v = getpid () ^ t.tv_sec ^ t.tv_nsec;
2026 seed_random (&v, sizeof v); 2111 seed_random (&v, sizeof v);
2027} 2112}
2028 2113
@@ -2089,7 +2174,17 @@ snprintf (char *buf, size_t bufsize, char const *format, ...)
2089/* If a backtrace is available, output the top lines of it to stderr. 2174/* If a backtrace is available, output the top lines of it to stderr.
2090 Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines. 2175 Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines.
2091 This function may be called from a signal handler, so it should 2176 This function may be called from a signal handler, so it should
2092 not invoke async-unsafe functions like malloc. */ 2177 not invoke async-unsafe functions like malloc.
2178
2179 If BACKTRACE_LIMIT is -1, initialize tables that 'backtrace' uses
2180 but do not output anything. This avoids some problems that can
2181 otherwise occur if the malloc arena is corrupted before 'backtrace'
2182 is called, since 'backtrace' may call malloc if the tables are not
2183 initialized.
2184
2185 If the static variable THREAD_BACKTRACE_NPOINTERS is nonzero, a
2186 fatal error has occurred in some other thread; generate a thread
2187 backtrace instead, ignoring BACKTRACE_LIMIT. */
2093void 2188void
2094emacs_backtrace (int backtrace_limit) 2189emacs_backtrace (int backtrace_limit)
2095{ 2190{
@@ -2106,6 +2201,14 @@ emacs_backtrace (int backtrace_limit)
2106 else 2201 else
2107 { 2202 {
2108 buffer = main_backtrace_buffer; 2203 buffer = main_backtrace_buffer;
2204
2205 /* Work around 'backtrace' bug; see Bug#19959 and glibc bug#18084. */
2206 if (bounded_limit < 0)
2207 {
2208 backtrace (buffer, 1);
2209 return;
2210 }
2211
2109 npointers = backtrace (buffer, bounded_limit + 1); 2212 npointers = backtrace (buffer, bounded_limit + 1);
2110 } 2213 }
2111 2214
@@ -2127,6 +2230,7 @@ emacs_abort (void)
2127#endif 2230#endif
2128 2231
2129/* Open FILE for Emacs use, using open flags OFLAG and mode MODE. 2232/* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
2233 Use binary I/O on systems that care about text vs binary I/O.
2130 Arrange for subprograms to not inherit the file descriptor. 2234 Arrange for subprograms to not inherit the file descriptor.
2131 Prefer a method that is multithread-safe, if available. 2235 Prefer a method that is multithread-safe, if available.
2132 Do not fail merely because the open was interrupted by a signal. 2236 Do not fail merely because the open was interrupted by a signal.
@@ -2136,6 +2240,8 @@ int
2136emacs_open (const char *file, int oflags, int mode) 2240emacs_open (const char *file, int oflags, int mode)
2137{ 2241{
2138 int fd; 2242 int fd;
2243 if (! (oflags & O_TEXT))
2244 oflags |= O_BINARY;
2139 oflags |= O_CLOEXEC; 2245 oflags |= O_CLOEXEC;
2140 while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) 2246 while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
2141 QUIT; 2247 QUIT;
@@ -2180,13 +2286,17 @@ emacs_fopen (char const *file, char const *mode)
2180int 2286int
2181emacs_pipe (int fd[2]) 2287emacs_pipe (int fd[2])
2182{ 2288{
2183 int result = pipe2 (fd, O_CLOEXEC); 2289#ifdef MSDOS
2290 return pipe (fd);
2291#else /* !MSDOS */
2292 int result = pipe2 (fd, O_BINARY | O_CLOEXEC);
2184 if (! O_CLOEXEC && result == 0) 2293 if (! O_CLOEXEC && result == 0)
2185 { 2294 {
2186 fcntl (fd[0], F_SETFD, FD_CLOEXEC); 2295 fcntl (fd[0], F_SETFD, FD_CLOEXEC);
2187 fcntl (fd[1], F_SETFD, FD_CLOEXEC); 2296 fcntl (fd[1], F_SETFD, FD_CLOEXEC);
2188 } 2297 }
2189 return result; 2298 return result;
2299#endif /* !MSDOS */
2190} 2300}
2191 2301
2192/* Approximate posix_close and POSIX_CLOSE_RESTART well enough for Emacs. 2302/* Approximate posix_close and POSIX_CLOSE_RESTART well enough for Emacs.
@@ -2259,9 +2369,9 @@ emacs_close (int fd)
2259 Return the number of bytes read, which might be less than NBYTE. 2369 Return the number of bytes read, which might be less than NBYTE.
2260 On error, set errno and return -1. */ 2370 On error, set errno and return -1. */
2261ptrdiff_t 2371ptrdiff_t
2262emacs_read (int fildes, char *buf, ptrdiff_t nbyte) 2372emacs_read (int fildes, void *buf, ptrdiff_t nbyte)
2263{ 2373{
2264 register ssize_t rtnval; 2374 ssize_t rtnval;
2265 2375
2266 /* There is no need to check against MAX_RW_COUNT, since no caller ever 2376 /* There is no need to check against MAX_RW_COUNT, since no caller ever
2267 passes a size that large to emacs_read. */ 2377 passes a size that large to emacs_read. */
@@ -2290,7 +2400,7 @@ emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte,
2290 { 2400 {
2291 if (errno == EINTR) 2401 if (errno == EINTR)
2292 { 2402 {
2293 /* I originally used `QUIT' but that might causes files to 2403 /* I originally used `QUIT' but that might cause files to
2294 be truncated if you hit C-g in the middle of it. --Stef */ 2404 be truncated if you hit C-g in the middle of it. --Stef */
2295 if (process_signals && pending_signals) 2405 if (process_signals && pending_signals)
2296 process_pending_signals (); 2406 process_pending_signals ();
@@ -2312,14 +2422,14 @@ emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte,
2312 interrupted or if a partial write occurs. Return the number of 2422 interrupted or if a partial write occurs. Return the number of
2313 bytes written, setting errno if this is less than NBYTE. */ 2423 bytes written, setting errno if this is less than NBYTE. */
2314ptrdiff_t 2424ptrdiff_t
2315emacs_write (int fildes, char const *buf, ptrdiff_t nbyte) 2425emacs_write (int fildes, void const *buf, ptrdiff_t nbyte)
2316{ 2426{
2317 return emacs_full_write (fildes, buf, nbyte, 0); 2427 return emacs_full_write (fildes, buf, nbyte, 0);
2318} 2428}
2319 2429
2320/* Like emacs_write, but also process pending signals if interrupted. */ 2430/* Like emacs_write, but also process pending signals if interrupted. */
2321ptrdiff_t 2431ptrdiff_t
2322emacs_write_sig (int fildes, char const *buf, ptrdiff_t nbyte) 2432emacs_write_sig (int fildes, void const *buf, ptrdiff_t nbyte)
2323{ 2433{
2324 return emacs_full_write (fildes, buf, nbyte, 1); 2434 return emacs_full_write (fildes, buf, nbyte, 1);
2325} 2435}
@@ -2357,7 +2467,7 @@ emacs_perror (char const *message)
2357 Use the least timeval not less than T. 2467 Use the least timeval not less than T.
2358 Return an extremal value if the result would overflow. */ 2468 Return an extremal value if the result would overflow. */
2359struct timeval 2469struct timeval
2360make_timeval (EMACS_TIME t) 2470make_timeval (struct timespec t)
2361{ 2471{
2362 struct timeval tv; 2472 struct timeval tv;
2363 tv.tv_sec = t.tv_sec; 2473 tv.tv_sec = t.tv_sec;
@@ -2384,7 +2494,7 @@ make_timeval (EMACS_TIME t)
2384 If FD is nonnegative, then FILE can be NULL. */ 2494 If FD is nonnegative, then FILE can be NULL. */
2385int 2495int
2386set_file_times (int fd, const char *filename, 2496set_file_times (int fd, const char *filename,
2387 EMACS_TIME atime, EMACS_TIME mtime) 2497 struct timespec atime, struct timespec mtime)
2388{ 2498{
2389 struct timespec timespec[2]; 2499 struct timespec timespec[2];
2390 timespec[0] = atime; 2500 timespec[0] = atime;
@@ -2618,10 +2728,8 @@ Lisp_Object
2618list_system_processes (void) 2728list_system_processes (void)
2619{ 2729{
2620 Lisp_Object procdir, match, proclist, next; 2730 Lisp_Object procdir, match, proclist, next;
2621 struct gcpro gcpro1, gcpro2; 2731 Lisp_Object tail;
2622 register Lisp_Object tail;
2623 2732
2624 GCPRO2 (procdir, match);
2625 /* For every process on the system, there's a directory in the 2733 /* For every process on the system, there's a directory in the
2626 "/proc" pseudo-directory whose name is the numeric ID of that 2734 "/proc" pseudo-directory whose name is the numeric ID of that
2627 process. */ 2735 process. */
@@ -2636,7 +2744,6 @@ list_system_processes (void)
2636 next = XCDR (tail); 2744 next = XCDR (tail);
2637 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil)); 2745 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
2638 } 2746 }
2639 UNGCPRO;
2640 2747
2641 /* directory_files_internal returns the files in reverse order; undo 2748 /* directory_files_internal returns the files in reverse order; undo
2642 that. */ 2749 that. */
@@ -2658,7 +2765,6 @@ list_system_processes (void)
2658 struct kinfo_proc *procs; 2765 struct kinfo_proc *procs;
2659 size_t i; 2766 size_t i;
2660 2767
2661 struct gcpro gcpro1;
2662 Lisp_Object proclist = Qnil; 2768 Lisp_Object proclist = Qnil;
2663 2769
2664 if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0) 2770 if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0)
@@ -2671,7 +2777,6 @@ list_system_processes (void)
2671 return proclist; 2777 return proclist;
2672 } 2778 }
2673 2779
2674 GCPRO1 (proclist);
2675 len /= sizeof (struct kinfo_proc); 2780 len /= sizeof (struct kinfo_proc);
2676 for (i = 0; i < len; i++) 2781 for (i = 0; i < len; i++)
2677 { 2782 {
@@ -2681,7 +2786,6 @@ list_system_processes (void)
2681 proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist); 2786 proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist);
2682#endif 2787#endif
2683 } 2788 }
2684 UNGCPRO;
2685 2789
2686 xfree (procs); 2790 xfree (procs);
2687 2791
@@ -2701,7 +2805,7 @@ list_system_processes (void)
2701#endif /* !defined (WINDOWSNT) */ 2805#endif /* !defined (WINDOWSNT) */
2702 2806
2703#if defined GNU_LINUX && defined HAVE_LONG_LONG_INT 2807#if defined GNU_LINUX && defined HAVE_LONG_LONG_INT
2704static EMACS_TIME 2808static struct timespec
2705time_from_jiffies (unsigned long long tval, long hz) 2809time_from_jiffies (unsigned long long tval, long hz)
2706{ 2810{
2707 unsigned long long s = tval / hz; 2811 unsigned long long s = tval / hz;
@@ -2710,34 +2814,34 @@ time_from_jiffies (unsigned long long tval, long hz)
2710 2814
2711 if (TYPE_MAXIMUM (time_t) < s) 2815 if (TYPE_MAXIMUM (time_t) < s)
2712 time_overflow (); 2816 time_overflow ();
2713 if (LONG_MAX - 1 <= ULLONG_MAX / EMACS_TIME_RESOLUTION 2817 if (LONG_MAX - 1 <= ULLONG_MAX / TIMESPEC_RESOLUTION
2714 || frac <= ULLONG_MAX / EMACS_TIME_RESOLUTION) 2818 || frac <= ULLONG_MAX / TIMESPEC_RESOLUTION)
2715 ns = frac * EMACS_TIME_RESOLUTION / hz; 2819 ns = frac * TIMESPEC_RESOLUTION / hz;
2716 else 2820 else
2717 { 2821 {
2718 /* This is reachable only in the unlikely case that HZ * HZ 2822 /* This is reachable only in the unlikely case that HZ * HZ
2719 exceeds ULLONG_MAX. It calculates an approximation that is 2823 exceeds ULLONG_MAX. It calculates an approximation that is
2720 guaranteed to be in range. */ 2824 guaranteed to be in range. */
2721 long hz_per_ns = (hz / EMACS_TIME_RESOLUTION 2825 long hz_per_ns = (hz / TIMESPEC_RESOLUTION
2722 + (hz % EMACS_TIME_RESOLUTION != 0)); 2826 + (hz % TIMESPEC_RESOLUTION != 0));
2723 ns = frac / hz_per_ns; 2827 ns = frac / hz_per_ns;
2724 } 2828 }
2725 2829
2726 return make_emacs_time (s, ns); 2830 return make_timespec (s, ns);
2727} 2831}
2728 2832
2729static Lisp_Object 2833static Lisp_Object
2730ltime_from_jiffies (unsigned long long tval, long hz) 2834ltime_from_jiffies (unsigned long long tval, long hz)
2731{ 2835{
2732 EMACS_TIME t = time_from_jiffies (tval, hz); 2836 struct timespec t = time_from_jiffies (tval, hz);
2733 return make_lisp_time (t); 2837 return make_lisp_time (t);
2734} 2838}
2735 2839
2736static EMACS_TIME 2840static struct timespec
2737get_up_time (void) 2841get_up_time (void)
2738{ 2842{
2739 FILE *fup; 2843 FILE *fup;
2740 EMACS_TIME up = make_emacs_time (0, 0); 2844 struct timespec up = make_timespec (0, 0);
2741 2845
2742 block_input (); 2846 block_input ();
2743 fup = emacs_fopen ("/proc/uptime", "r"); 2847 fup = emacs_fopen ("/proc/uptime", "r");
@@ -2755,18 +2859,18 @@ get_up_time (void)
2755 if (TYPE_MAXIMUM (time_t) < upsec) 2859 if (TYPE_MAXIMUM (time_t) < upsec)
2756 { 2860 {
2757 upsec = TYPE_MAXIMUM (time_t); 2861 upsec = TYPE_MAXIMUM (time_t);
2758 upfrac = EMACS_TIME_RESOLUTION - 1; 2862 upfrac = TIMESPEC_RESOLUTION - 1;
2759 } 2863 }
2760 else 2864 else
2761 { 2865 {
2762 int upfraclen = upfrac_end - upfrac_start; 2866 int upfraclen = upfrac_end - upfrac_start;
2763 for (; upfraclen < LOG10_EMACS_TIME_RESOLUTION; upfraclen++) 2867 for (; upfraclen < LOG10_TIMESPEC_RESOLUTION; upfraclen++)
2764 upfrac *= 10; 2868 upfrac *= 10;
2765 for (; LOG10_EMACS_TIME_RESOLUTION < upfraclen; upfraclen--) 2869 for (; LOG10_TIMESPEC_RESOLUTION < upfraclen; upfraclen--)
2766 upfrac /= 10; 2870 upfrac /= 10;
2767 upfrac = min (upfrac, EMACS_TIME_RESOLUTION - 1); 2871 upfrac = min (upfrac, TIMESPEC_RESOLUTION - 1);
2768 } 2872 }
2769 up = make_emacs_time (upsec, upfrac); 2873 up = make_timespec (upsec, upfrac);
2770 } 2874 }
2771 fclose (fup); 2875 fclose (fup);
2772 } 2876 }
@@ -2887,12 +2991,11 @@ system_process_attributes (Lisp_Object pid)
2887 unsigned long long u_time, s_time, cutime, cstime, start; 2991 unsigned long long u_time, s_time, cutime, cstime, start;
2888 long priority, niceness, rss; 2992 long priority, niceness, rss;
2889 unsigned long minflt, majflt, cminflt, cmajflt, vsize; 2993 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
2890 EMACS_TIME tnow, tstart, tboot, telapsed, us_time; 2994 struct timespec tnow, tstart, tboot, telapsed, us_time;
2891 double pcpu, pmem; 2995 double pcpu, pmem;
2892 Lisp_Object attrs = Qnil; 2996 Lisp_Object attrs = Qnil;
2893 Lisp_Object cmd_str, decoded_cmd; 2997 Lisp_Object cmd_str, decoded_cmd;
2894 ptrdiff_t count; 2998 ptrdiff_t count;
2895 struct gcpro gcpro1, gcpro2;
2896 2999
2897 CHECK_NUMBER_OR_FLOAT (pid); 3000 CHECK_NUMBER_OR_FLOAT (pid);
2898 CONS_TO_INTEGER (pid, pid_t, proc_id); 3001 CONS_TO_INTEGER (pid, pid_t, proc_id);
@@ -2900,8 +3003,6 @@ system_process_attributes (Lisp_Object pid)
2900 if (stat (procfn, &st) < 0) 3003 if (stat (procfn, &st) < 0)
2901 return attrs; 3004 return attrs;
2902 3005
2903 GCPRO2 (attrs, decoded_cmd);
2904
2905 /* euid egid */ 3006 /* euid egid */
2906 uid = st.st_uid; 3007 uid = st.st_uid;
2907 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); 3008 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
@@ -3008,20 +3109,19 @@ system_process_attributes (Lisp_Object pid)
3008 attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs); 3109 attrs = Fcons (Fcons (Qnice, make_number (niceness)), attrs);
3009 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount)), 3110 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount)),
3010 attrs); 3111 attrs);
3011 tnow = current_emacs_time (); 3112 tnow = current_timespec ();
3012 telapsed = get_up_time (); 3113 telapsed = get_up_time ();
3013 tboot = sub_emacs_time (tnow, telapsed); 3114 tboot = timespec_sub (tnow, telapsed);
3014 tstart = time_from_jiffies (start, clocks_per_sec); 3115 tstart = time_from_jiffies (start, clocks_per_sec);
3015 tstart = add_emacs_time (tboot, tstart); 3116 tstart = timespec_add (tboot, tstart);
3016 attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs); 3117 attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs);
3017 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize / 1024)), 3118 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize / 1024)),
3018 attrs); 3119 attrs);
3019 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4 * rss)), attrs); 3120 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4 * rss)), attrs);
3020 telapsed = sub_emacs_time (tnow, tstart); 3121 telapsed = timespec_sub (tnow, tstart);
3021 attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs); 3122 attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
3022 us_time = time_from_jiffies (u_time + s_time, clocks_per_sec); 3123 us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
3023 pcpu = (EMACS_TIME_TO_DOUBLE (us_time) 3124 pcpu = timespectod (us_time) / timespectod (telapsed);
3024 / EMACS_TIME_TO_DOUBLE (telapsed));
3025 if (pcpu > 1.0) 3125 if (pcpu > 1.0)
3026 pcpu = 1.0; 3126 pcpu = 1.0;
3027 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs); 3127 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
@@ -3091,7 +3191,6 @@ system_process_attributes (Lisp_Object pid)
3091 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); 3191 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3092 } 3192 }
3093 3193
3094 UNGCPRO;
3095 return attrs; 3194 return attrs;
3096} 3195}
3097 3196
@@ -3130,7 +3229,6 @@ system_process_attributes (Lisp_Object pid)
3130 gid_t gid; 3229 gid_t gid;
3131 Lisp_Object attrs = Qnil; 3230 Lisp_Object attrs = Qnil;
3132 Lisp_Object decoded_cmd; 3231 Lisp_Object decoded_cmd;
3133 struct gcpro gcpro1, gcpro2;
3134 ptrdiff_t count; 3232 ptrdiff_t count;
3135 3233
3136 CHECK_NUMBER_OR_FLOAT (pid); 3234 CHECK_NUMBER_OR_FLOAT (pid);
@@ -3139,8 +3237,6 @@ system_process_attributes (Lisp_Object pid)
3139 if (stat (procfn, &st) < 0) 3237 if (stat (procfn, &st) < 0)
3140 return attrs; 3238 return attrs;
3141 3239
3142 GCPRO2 (attrs, decoded_cmd);
3143
3144 /* euid egid */ 3240 /* euid egid */
3145 uid = st.st_uid; 3241 uid = st.st_uid;
3146 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs); 3242 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
@@ -3233,22 +3329,21 @@ system_process_attributes (Lisp_Object pid)
3233 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); 3329 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3234 } 3330 }
3235 unbind_to (count, Qnil); 3331 unbind_to (count, Qnil);
3236 UNGCPRO;
3237 return attrs; 3332 return attrs;
3238} 3333}
3239 3334
3240#elif defined __FreeBSD__ 3335#elif defined __FreeBSD__
3241 3336
3242static EMACS_TIME 3337static struct timespec
3243timeval_to_EMACS_TIME (struct timeval t) 3338timeval_to_timespec (struct timeval t)
3244{ 3339{
3245 return make_emacs_time (t.tv_sec, t.tv_usec * 1000); 3340 return make_timespec (t.tv_sec, t.tv_usec * 1000);
3246} 3341}
3247 3342
3248static Lisp_Object 3343static Lisp_Object
3249make_lisp_timeval (struct timeval t) 3344make_lisp_timeval (struct timeval t)
3250{ 3345{
3251 return make_lisp_time (timeval_to_EMACS_TIME (t)); 3346 return make_lisp_time (timeval_to_timespec (t));
3252} 3347}
3253 3348
3254Lisp_Object 3349Lisp_Object
@@ -3263,13 +3358,12 @@ system_process_attributes (Lisp_Object pid)
3263 char *ttyname; 3358 char *ttyname;
3264 size_t len; 3359 size_t len;
3265 char args[MAXPATHLEN]; 3360 char args[MAXPATHLEN];
3266 EMACS_TIME t, now; 3361 struct timespec t, now;
3267 3362
3268 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID}; 3363 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
3269 struct kinfo_proc proc; 3364 struct kinfo_proc proc;
3270 size_t proclen = sizeof proc; 3365 size_t proclen = sizeof proc;
3271 3366
3272 struct gcpro gcpro1, gcpro2;
3273 Lisp_Object attrs = Qnil; 3367 Lisp_Object attrs = Qnil;
3274 Lisp_Object decoded_comm; 3368 Lisp_Object decoded_comm;
3275 3369
@@ -3280,8 +3374,6 @@ system_process_attributes (Lisp_Object pid)
3280 if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0) 3374 if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0)
3281 return attrs; 3375 return attrs;
3282 3376
3283 GCPRO2 (attrs, decoded_comm);
3284
3285 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs); 3377 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
3286 3378
3287 block_input (); 3379 block_input ();
@@ -3350,8 +3442,8 @@ system_process_attributes (Lisp_Object pid)
3350 attrs); 3442 attrs);
3351 attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)), 3443 attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)),
3352 attrs); 3444 attrs);
3353 t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage.ru_utime), 3445 t = timespec_add (timeval_to_timespec (proc.ki_rusage.ru_utime),
3354 timeval_to_EMACS_TIME (proc.ki_rusage.ru_stime)); 3446 timeval_to_timespec (proc.ki_rusage.ru_stime));
3355 attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs); 3447 attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
3356 3448
3357 attrs = Fcons (Fcons (Qcutime, 3449 attrs = Fcons (Fcons (Qcutime,
@@ -3360,8 +3452,8 @@ system_process_attributes (Lisp_Object pid)
3360 attrs = Fcons (Fcons (Qcstime, 3452 attrs = Fcons (Fcons (Qcstime,
3361 make_lisp_timeval (proc.ki_rusage_ch.ru_utime)), 3453 make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
3362 attrs); 3454 attrs);
3363 t = add_emacs_time (timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_utime), 3455 t = timespec_add (timeval_to_timespec (proc.ki_rusage_ch.ru_utime),
3364 timeval_to_EMACS_TIME (proc.ki_rusage_ch.ru_stime)); 3456 timeval_to_timespec (proc.ki_rusage_ch.ru_stime));
3365 attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs); 3457 attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
3366 3458
3367 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)), 3459 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (proc.ki_numthreads)),
@@ -3373,8 +3465,8 @@ system_process_attributes (Lisp_Object pid)
3373 attrs = Fcons (Fcons (Qrss, make_number (proc.ki_rssize * pagesize >> 10)), 3465 attrs = Fcons (Fcons (Qrss, make_number (proc.ki_rssize * pagesize >> 10)),
3374 attrs); 3466 attrs);
3375 3467
3376 now = current_emacs_time (); 3468 now = current_timespec ();
3377 t = sub_emacs_time (now, timeval_to_EMACS_TIME (proc.ki_start)); 3469 t = timespec_sub (now, timeval_to_timespec (proc.ki_start));
3378 attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs); 3470 attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
3379 3471
3380 len = sizeof fscale; 3472 len = sizeof fscale;
@@ -3419,7 +3511,6 @@ system_process_attributes (Lisp_Object pid)
3419 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs); 3511 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
3420 } 3512 }
3421 3513
3422 UNGCPRO;
3423 return attrs; 3514 return attrs;
3424} 3515}
3425 3516
@@ -3434,3 +3525,208 @@ system_process_attributes (Lisp_Object pid)
3434} 3525}
3435 3526
3436#endif /* !defined (WINDOWSNT) */ 3527#endif /* !defined (WINDOWSNT) */
3528
3529/* Wide character string collation. */
3530
3531#ifdef __STDC_ISO_10646__
3532# include <wchar.h>
3533# include <wctype.h>
3534
3535# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE
3536# include <locale.h>
3537# endif
3538# ifndef LC_COLLATE
3539# define LC_COLLATE 0
3540# endif
3541# ifndef LC_COLLATE_MASK
3542# define LC_COLLATE_MASK 0
3543# endif
3544# ifndef LC_CTYPE
3545# define LC_CTYPE 0
3546# endif
3547# ifndef LC_CTYPE_MASK
3548# define LC_CTYPE_MASK 0
3549# endif
3550
3551# ifndef HAVE_NEWLOCALE
3552# undef freelocale
3553# undef locale_t
3554# undef newlocale
3555# undef wcscoll_l
3556# undef towlower_l
3557# define freelocale emacs_freelocale
3558# define locale_t emacs_locale_t
3559# define newlocale emacs_newlocale
3560# define wcscoll_l emacs_wcscoll_l
3561# define towlower_l emacs_towlower_l
3562
3563typedef char const *locale_t;
3564
3565static locale_t
3566newlocale (int category_mask, char const *locale, locale_t loc)
3567{
3568 return locale;
3569}
3570
3571static void
3572freelocale (locale_t loc)
3573{
3574}
3575
3576static char *
3577emacs_setlocale (int category, char const *locale)
3578{
3579# ifdef HAVE_SETLOCALE
3580 errno = 0;
3581 char *loc = setlocale (category, locale);
3582 if (loc || errno)
3583 return loc;
3584 errno = EINVAL;
3585# else
3586 errno = ENOTSUP;
3587# endif
3588 return 0;
3589}
3590
3591static int
3592wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc)
3593{
3594 int result = 0;
3595 char *oldloc = emacs_setlocale (LC_COLLATE, NULL);
3596 int err;
3597
3598 if (! oldloc)
3599 err = errno;
3600 else
3601 {
3602 USE_SAFE_ALLOCA;
3603 char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
3604 strcpy (oldcopy, oldloc);
3605 if (! emacs_setlocale (LC_COLLATE, loc))
3606 err = errno;
3607 else
3608 {
3609 errno = 0;
3610 result = wcscoll (a, b);
3611 err = errno;
3612 if (! emacs_setlocale (LC_COLLATE, oldcopy))
3613 err = errno;
3614 }
3615 SAFE_FREE ();
3616 }
3617
3618 errno = err;
3619 return result;
3620}
3621
3622static wint_t
3623towlower_l (wint_t wc, locale_t loc)
3624{
3625 wint_t result = wc;
3626 char *oldloc = emacs_setlocale (LC_CTYPE, NULL);
3627
3628 if (oldloc)
3629 {
3630 USE_SAFE_ALLOCA;
3631 char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
3632 strcpy (oldcopy, oldloc);
3633 if (emacs_setlocale (LC_CTYPE, loc))
3634 {
3635 result = towlower (wc);
3636 emacs_setlocale (LC_COLLATE, oldcopy);
3637 }
3638 SAFE_FREE ();
3639 }
3640
3641 return result;
3642}
3643# endif
3644
3645int
3646str_collate (Lisp_Object s1, Lisp_Object s2,
3647 Lisp_Object locale, Lisp_Object ignore_case)
3648{
3649 int res, err;
3650 ptrdiff_t len, i, i_byte;
3651 wchar_t *p1, *p2;
3652
3653 USE_SAFE_ALLOCA;
3654
3655 /* Convert byte stream to code points. */
3656 len = SCHARS (s1); i = i_byte = 0;
3657 SAFE_NALLOCA (p1, 1, len + 1);
3658 while (i < len)
3659 FETCH_STRING_CHAR_ADVANCE (*(p1+i-1), s1, i, i_byte);
3660 *(p1+len) = 0;
3661
3662 len = SCHARS (s2); i = i_byte = 0;
3663 SAFE_NALLOCA (p2, 1, len + 1);
3664 while (i < len)
3665 FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte);
3666 *(p2+len) = 0;
3667
3668 if (STRINGP (locale))
3669 {
3670 locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK,
3671 SSDATA (locale), 0);
3672 if (!loc)
3673 error ("Invalid locale %s: %s", SSDATA (locale), strerror (errno));
3674
3675 if (! NILP (ignore_case))
3676 for (int i = 1; i < 3; i++)
3677 {
3678 wchar_t *p = (i == 1) ? p1 : p2;
3679 for (; *p; p++)
3680 *p = towlower_l (*p, loc);
3681 }
3682
3683 errno = 0;
3684 res = wcscoll_l (p1, p2, loc);
3685 err = errno;
3686 freelocale (loc);
3687 }
3688 else
3689 {
3690 if (! NILP (ignore_case))
3691 for (int i = 1; i < 3; i++)
3692 {
3693 wchar_t *p = (i == 1) ? p1 : p2;
3694 for (; *p; p++)
3695 *p = towlower (*p);
3696 }
3697
3698 errno = 0;
3699 res = wcscoll (p1, p2);
3700 err = errno;
3701 }
3702# ifndef HAVE_NEWLOCALE
3703 if (err)
3704 error ("Invalid locale or string for collation: %s", strerror (err));
3705# else
3706 if (err)
3707 error ("Invalid string for collation: %s", strerror (err));
3708# endif
3709
3710 SAFE_FREE ();
3711 return res;
3712}
3713#endif /* __STDC_ISO_10646__ */
3714
3715#ifdef WINDOWSNT
3716int
3717str_collate (Lisp_Object s1, Lisp_Object s2,
3718 Lisp_Object locale, Lisp_Object ignore_case)
3719{
3720
3721 char *loc = STRINGP (locale) ? SSDATA (locale) : NULL;
3722 int res, err = errno;
3723
3724 errno = 0;
3725 res = w32_compare_strings (SDATA (s1), SDATA (s2), loc, !NILP (ignore_case));
3726 if (errno)
3727 error ("Invalid string for collation: %s", strerror (errno));
3728
3729 errno = err;
3730 return res;
3731}
3732#endif /* WINDOWSNT */