This source file includes following definitions.
- maybe_disable_address_randomization
- emacs_exec_file
- force_open
- init_standard_fds
- get_current_dir_name_or_unreachable
- emacs_get_current_dir_name
- discard_tty_input
- stuff_char
- init_baud_rate
- get_child_status
- wait_for_termination
- child_status_changed
- child_setup_tty
- sys_suspend
- sys_subshell
- save_signal_handlers
- restore_signal_handlers
- init_sigio
- reset_sigio
- request_sigio
- unrequest_sigio
- block_child_signal
- unblock_child_signal
- block_interrupt_signal
- restore_signal_mask
- init_foreground_group
- block_tty_out_signal
- unblock_tty_out_signal
- tcsetpgrp_without_stopping
- narrow_foreground_group
- widen_foreground_group
- emacs_get_tty
- emacs_set_tty
- init_all_sys_modes
- init_sys_modes
- tabs_safe_p
- suppress_echo_on_tty
- get_tty_size
- set_window_size
- reset_all_sys_modes
- reset_sys_modes
- setup_pty
- init_system_name
- emacs_sigaction_flags
- emacs_sigaction_init
- deliver_process_signal
- deliver_thread_signal
- handle_fatal_signal
- deliver_fatal_signal
- deliver_fatal_thread_signal
- handle_arith_signal
- handle_sigbus
- init_sigbus
- stack_overflow
- handle_sigsegv
- init_sigsegv
- init_sigsegv
- deliver_arith_signal
- handle_danger_signal
- deliver_danger_signal
- maybe_fatal_sig
- init_signals
- set_random_seed
- set_random_seed
- set_random_seed
- seed_random
- init_random
- get_random
- get_random_ulong
- snprintf
- emacs_backtrace
- emacs_abort
- emacs_fstatat
- sys_openat
- sys_fstat
- sys_faccessat
- emacs_openat
- emacs_open
- emacs_open_noquit
- emacs_fopen
- emacs_pipe
- posix_close
- emacs_close
- emacs_fdopen
- emacs_fclose
- emacs_unlink
- emacs_symlink
- emacs_rmdir
- emacs_mkdir
- emacs_renameat_noreplace
- emacs_rename
- emacs_fchmodat
- emacs_intr_read
- emacs_read
- emacs_read_quit
- emacs_full_write
- emacs_write
- emacs_write_sig
- emacs_write_quit
- emacs_perror
- renameat_noreplace
- safe_strsignal
- errstream
- errputc
- errwrite
- close_output_streams
- serial_open
- cfmakeraw
- cfsetspeed
- convert_speed
- serial_configure
- list_system_processes
- list_system_processes
- list_system_processes
- make_lisp_s_us
- make_lisp_timeval
- time_from_jiffies
- put_jiffies
- get_up_time
- procfs_ttyname
- procfs_get_total_memory
- system_process_attributes
- system_process_attributes
- system_process_attributes
- system_process_attributes
- system_process_attributes
- system_process_attributes
- DEFUN
- newlocale
- freelocale
- emacs_setlocale
- wcscoll_l
- towlower_l
- str_collate
- str_collate
- syms_of_sysdep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <execinfo.h>
23 #include "sysstdio.h"
24 #ifdef HAVE_PWD_H
25 #include <pwd.h>
26 #include <grp.h>
27 #endif
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <sys/random.h>
31 #include <unistd.h>
32
33 #include <c-ctype.h>
34 #include <close-stream.h>
35 #include <pathmax.h>
36 #include <utimens.h>
37
38 #include "lisp.h"
39 #include "sheap.h"
40 #include "sysselect.h"
41 #include "blockinput.h"
42
43 #ifdef HAVE_LINUX_FS_H
44 # include <linux/fs.h>
45 # include <sys/syscall.h>
46 #endif
47
48 #ifdef CYGWIN
49 # include <cygwin/fs.h>
50 #endif
51
52 #if defined DARWIN_OS || defined __FreeBSD__ || defined __OpenBSD__
53 # include <sys/sysctl.h>
54 #endif
55
56 #if defined __OpenBSD__
57 # include <sys/proc.h>
58 #endif
59
60 #ifdef DARWIN_OS
61 # include <libproc.h>
62 #endif
63
64 #ifdef __FreeBSD__
65
66
67 # define frame freebsd_frame
68 # include <sys/user.h>
69 # undef frame
70
71 # include <math.h>
72 #endif
73
74 #ifdef HAVE_SOCKETS
75 #include <sys/socket.h>
76 #include <netdb.h>
77 #endif
78
79 #ifdef WINDOWSNT
80 #define read sys_read
81 #define write sys_write
82 #ifndef STDERR_FILENO
83 #define STDERR_FILENO fileno(GetStdHandle(STD_ERROR_HANDLE))
84 #endif
85 #include "w32.h"
86 #endif
87
88 #include <sys/types.h>
89 #include <sys/stat.h>
90 #include <errno.h>
91
92
93 #ifdef HAVE_SYS_SYSTEMINFO_H
94 #include <sys/systeminfo.h>
95 #endif
96
97 #ifdef MSDOS
98 #include "msdos.h"
99 #endif
100
101 #include <sys/param.h>
102 #include <sys/file.h>
103 #include <fcntl.h>
104
105 #include "syssignal.h"
106 #include "systime.h"
107 #include "systty.h"
108 #include "syswait.h"
109
110 #ifdef HAVE_SYS_RESOURCE_H
111 # include <sys/resource.h>
112 #endif
113
114 #ifdef HAVE_SYS_UTSNAME_H
115 # include <sys/utsname.h>
116 # include <memory.h>
117 #endif
118
119 #include "keyboard.h"
120 #include "frame.h"
121 #include "termhooks.h"
122 #include "termchar.h"
123 #include "termopts.h"
124 #include "process.h"
125 #include "cm.h"
126
127 #ifdef WINDOWSNT
128 # include <direct.h>
129
130 # define _P_WAIT 0
131 int _cdecl _spawnlp (int, const char *, const char *, ...);
132
133
134 # include <sys/socket.h>
135 #endif
136
137 #ifdef HAVE_ANDROID
138 #include "android.h"
139 #endif
140
141 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
142 #include "sfntfont.h"
143 #endif
144
145
146 extern void tputs (const char *, int, int (*)(int));
147
148 static const int baud_convert[] =
149 {
150 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
151 1800, 2400, 4800, 9600, 19200, 38400
152 };
153
154 #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
155 # include <sys/personality.h>
156
157
158 static int exec_personality;
159
160
161
162 int
163 maybe_disable_address_randomization (int argc, char **argv)
164 {
165
166 static char const aslr_disabled_option[] = "--__aslr-disabled";
167
168 if (argc < 2 || strcmp (argv[1], aslr_disabled_option) != 0)
169 {
170
171
172
173 bool disable_aslr = will_dump_p ();
174 # ifdef __PPC64__
175 disable_aslr = true;
176 # endif
177 exec_personality = disable_aslr ? personality (0xffffffff) : -1;
178 if (exec_personality & ADDR_NO_RANDOMIZE)
179 exec_personality = -1;
180 if (exec_personality != -1
181 && personality (exec_personality | ADDR_NO_RANDOMIZE) != -1)
182 {
183 char **newargv = malloc ((argc + 2) * sizeof *newargv);
184 if (newargv)
185 {
186
187 newargv[0] = argv[0];
188 newargv[1] = (char *) aslr_disabled_option;
189 memcpy (&newargv[2], &argv[1], argc * sizeof *newargv);
190 execvp (newargv[0], newargv);
191 }
192
193
194 perror (argv[0]);
195 free (newargv);
196 }
197 }
198 else
199 {
200
201 argc--;
202 memmove (&argv[1], &argv[2], argc * sizeof *argv);
203 }
204
205 return argc;
206 }
207 #endif
208
209 #ifndef WINDOWSNT
210
211
212
213
214 int
215 emacs_exec_file (char const *file, char *const *argv, char *const *envp)
216 {
217 #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
218 if (exec_personality != -1)
219 personality (exec_personality);
220 #endif
221
222 execve (file, argv, envp);
223 return errno;
224 }
225
226 #endif
227
228
229 static void
230 force_open (int fd, int flags)
231 {
232 if (dup2 (fd, fd) < 0 && errno == EBADF)
233 {
234 int n = open (NULL_DEVICE, flags);
235 if (n < 0 || (fd != n && (dup2 (n, fd) < 0 || emacs_close (n) != 0)))
236 {
237 emacs_perror (NULL_DEVICE);
238 exit (EXIT_FAILURE);
239 }
240 }
241 }
242
243
244
245 static FILE *buferr;
246
247
248
249 void
250 init_standard_fds (void)
251 {
252
253
254
255
256 force_open (STDIN_FILENO, O_WRONLY);
257 force_open (STDOUT_FILENO, O_RDONLY);
258 force_open (STDERR_FILENO, O_RDONLY);
259
260
261
262 #ifdef _PC_PIPE_BUF
263 buferr = emacs_fdopen (STDERR_FILENO, "w");
264 if (buferr)
265 setvbuf (buferr, NULL, _IOLBF, 0);
266 #endif
267 }
268
269
270
271
272
273
274 static char *
275 get_current_dir_name_or_unreachable (void)
276 {
277
278
279
280 char *pwd;
281
282
283
284 ptrdiff_t dirsize_max = min (PTRDIFF_MAX, SIZE_MAX) - 1;
285
286
287
288 ptrdiff_t bufsize_max = dirsize_max;
289 #ifdef PATH_MAX
290 bufsize_max = min (bufsize_max, PATH_MAX);
291 #endif
292
293 # if HAVE_GET_CURRENT_DIR_NAME && !BROKEN_GET_CURRENT_DIR_NAME
294 # ifdef HYBRID_MALLOC
295 bool use_libc = will_dump_with_unexec_p ();
296 # else
297 bool use_libc = true;
298 # endif
299 if (use_libc)
300 {
301
302
303 pwd = get_current_dir_name ();
304 if (pwd)
305 {
306 if (strnlen (pwd, dirsize_max) < dirsize_max)
307 return pwd;
308 free (pwd);
309 errno = ERANGE;
310 }
311 return NULL;
312 }
313 # endif
314
315 size_t pwdlen;
316 struct stat dotstat, pwdstat;
317 pwd = getenv ("PWD");
318
319
320
321
322 if (pwd
323 && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max
324 && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0])
325 && emacs_fstatat (AT_FDCWD, pwd, &pwdstat, 0) == 0
326 && emacs_fstatat (AT_FDCWD, ".", &dotstat, 0) == 0
327 && dotstat.st_ino == pwdstat.st_ino
328 && dotstat.st_dev == pwdstat.st_dev)
329 return strdup (pwd);
330 else
331 {
332 ptrdiff_t buf_size = min (bufsize_max, 1024);
333 for (;;)
334 {
335 char *buf = malloc (buf_size);
336 if (!buf)
337 return NULL;
338 if (getcwd (buf, buf_size) == buf)
339 return buf;
340 free (buf);
341 if (errno != ERANGE || buf_size == bufsize_max)
342 return NULL;
343 buf_size = buf_size <= bufsize_max / 2 ? 2 * buf_size : bufsize_max;
344 }
345 }
346 }
347
348
349
350
351
352 char *
353 emacs_get_current_dir_name (void)
354 {
355 char *dir = get_current_dir_name_or_unreachable ();
356 if (dir && *dir == '(')
357 {
358 free (dir);
359 errno = ENOENT;
360 return NULL;
361 }
362 return dir;
363 }
364
365
366
367
368 void
369 discard_tty_input (void)
370 {
371 #ifndef WINDOWSNT
372 struct emacs_tty buf;
373
374 if (noninteractive)
375 return;
376
377 #ifdef MSDOS
378 while (dos_keyread () != -1)
379 ;
380 #else
381 {
382 struct tty_display_info *tty;
383 for (tty = tty_list; tty; tty = tty->next)
384 {
385 if (tty->input)
386 {
387 emacs_get_tty (fileno (tty->input), &buf);
388 emacs_set_tty (fileno (tty->input), &buf, 0);
389 }
390 }
391 }
392 #endif
393 #endif
394 }
395
396
397 #ifdef SIGTSTP
398
399
400
401
402
403
404 void
405 stuff_char (char c)
406 {
407 if (! (FRAMEP (selected_frame)
408 && FRAME_LIVE_P (XFRAME (selected_frame))
409 && FRAME_TERMCAP_P (XFRAME (selected_frame))))
410 return;
411
412
413 #ifdef TIOCSTI
414 ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
415 #else
416 error ("Cannot stuff terminal input characters in this version of Unix");
417 #endif
418 }
419
420 #endif
421
422 void
423 init_baud_rate (int fd)
424 {
425 int emacs_ospeed;
426
427 if (noninteractive)
428 emacs_ospeed = 0;
429 else
430 {
431 #ifdef DOS_NT
432 emacs_ospeed = 15;
433 #else
434 struct termios sg;
435
436 sg.c_cflag = B9600;
437 tcgetattr (fd, &sg);
438 emacs_ospeed = cfgetospeed (&sg);
439 #endif
440 }
441
442 baud_rate = (emacs_ospeed < ARRAYELTS (baud_convert)
443 ? baud_convert[emacs_ospeed] : 9600);
444 if (baud_rate == 0)
445 baud_rate = 1200;
446 }
447
448
449
450 #ifndef MSDOS
451
452
453
454
455
456
457
458
459
460
461 static pid_t
462 get_child_status (pid_t child, int *status, int options, bool interruptible)
463 {
464 pid_t pid;
465
466
467
468
469
470
471 eassert (child > 0);
472
473 while (true)
474 {
475
476
477 if (interruptible)
478 maybe_quit ();
479
480 pid = waitpid (child, status, options);
481 if (0 <= pid)
482 break;
483 if (errno != EINTR)
484 {
485
486
487
488
489 return pid;
490 }
491 }
492
493
494
495 if (pid && status && input_available_clear_time)
496 *input_available_clear_time = make_timespec (0, 0);
497
498 return pid;
499 }
500
501
502
503
504
505
506
507
508 bool
509 wait_for_termination (pid_t child, int *status, bool interruptible)
510 {
511 return 0 <= get_child_status (child, status, 0, interruptible);
512 }
513
514
515
516
517
518
519
520
521
522
523 pid_t
524 child_status_changed (pid_t child, int *status, int options)
525 {
526 return get_child_status (child, status, WNOHANG | options, 0);
527 }
528
529
530
531
532
533
534
535 void
536 child_setup_tty (int out)
537 {
538 #ifndef WINDOWSNT
539 struct emacs_tty s;
540
541 emacs_get_tty (out, &s);
542 s.main.c_oflag |= OPOST;
543 s.main.c_oflag &= ~ONLCR;
544 #ifdef NLDLY
545
546
547 #ifdef FFDLY
548 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
549
550 #else
551 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
552
553 #endif
554 #endif
555 s.main.c_lflag &= ~ECHO;
556 s.main.c_lflag |= ISIG;
557 #ifdef IUCLC
558 s.main.c_iflag &= ~IUCLC;
559 #endif
560 #ifdef ISTRIP
561 s.main.c_iflag &= ~ISTRIP;
562 #endif
563 #ifdef OLCUC
564 s.main.c_oflag &= ~OLCUC;
565 #endif
566 s.main.c_oflag &= ~TAB3;
567 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8;
568 s.main.c_cc[VERASE] = CDISABLE;
569 s.main.c_cc[VKILL] = CDISABLE;
570
571 #ifdef HPUX
572 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600;
573 #endif
574
575 #ifdef SIGNALS_VIA_CHARACTERS
576
577
578 if (s.main.c_cc[VQUIT] == CDISABLE)
579 s.main.c_cc[VQUIT] = '\\'&037;
580 if (s.main.c_cc[VINTR] == CDISABLE)
581 s.main.c_cc[VINTR] = 'C'&037;
582 #endif
583
584 #ifdef AIX
585
586
587 s.main.c_iflag &= ~IGNBRK;
588 s.main.c_iflag &= ~BRKINT;
589
590
591
592 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600;
593 #endif
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612 s.main.c_lflag |= ICANON;
613 s.main.c_cc[VEOF] = 'D'&037;
614 #if 0
615 s.main.c_cc[VMIN] = 1;
616 s.main.c_cc[VTIME] = 0;
617 #endif
618
619 emacs_set_tty (out, &s, 0);
620 #endif
621 }
622 #endif
623
624
625
626 struct save_signal
627 {
628 int code;
629 struct sigaction action;
630 };
631
632 static void save_signal_handlers (struct save_signal *);
633 static void restore_signal_handlers (struct save_signal *);
634
635
636
637 void
638 sys_suspend (void)
639 {
640 #ifndef DOS_NT
641 kill (0, SIGTSTP);
642 #else
643
644
645
646 sys_subshell ();
647
648 #endif
649 }
650
651
652
653 void
654 sys_subshell (void)
655 {
656 #ifdef DOS_NT
657 #ifdef MSDOS
658 int st;
659 char oldwd[MAXPATHLEN+1];
660 #else
661 char oldwd[MAX_UTF8_PATH];
662 #endif
663 #else
664 int status;
665 #endif
666 pid_t pid;
667 struct save_signal saved_handlers[5];
668 char *str = SSDATA (get_current_directory (true));
669
670 #ifdef DOS_NT
671 pid = 0;
672 #else
673 {
674 char *volatile str_volatile = str;
675 pid = VFORK ();
676 str = str_volatile;
677 }
678 #endif
679
680 if (pid < 0)
681 error ("Can't spawn subshell");
682
683 saved_handlers[0].code = SIGINT;
684 saved_handlers[1].code = SIGQUIT;
685 saved_handlers[2].code = SIGTERM;
686 #ifdef USABLE_SIGIO
687 saved_handlers[3].code = SIGIO;
688 saved_handlers[4].code = 0;
689 #elif defined (USABLE_SIGPOLL)
690 saved_handlers[3].code = SIGPOLL;
691 saved_handlers[4].code = 0;
692 #else
693 saved_handlers[3].code = 0;
694 #endif
695
696 #ifdef DOS_NT
697 save_signal_handlers (saved_handlers);
698 #endif
699
700 if (pid == 0)
701 {
702 const char *sh = 0;
703
704 #ifdef DOS_NT
705 getcwd (oldwd, sizeof oldwd);
706 if (sh == 0)
707 sh = egetenv ("SUSPEND");
708 #endif
709 if (sh == 0)
710 sh = egetenv ("SHELL");
711 if (sh == 0)
712 sh = "sh";
713
714
715 if (chdir (str) != 0)
716 {
717 #ifndef DOS_NT
718 emacs_perror (str);
719 _exit (EXIT_CANCELED);
720 #endif
721 }
722
723 #ifdef MSDOS
724 {
725 char *epwd = getenv ("PWD");
726 char old_pwd[MAXPATHLEN+1+4];
727
728
729 if (epwd)
730 {
731 strcpy (old_pwd, epwd);
732 setenv ("PWD", str, 1);
733 }
734 st = system (sh);
735 chdir (oldwd);
736 if (epwd)
737 putenv (old_pwd);
738 }
739 #else
740 #ifdef WINDOWSNT
741
742 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
743 chdir (oldwd);
744 if (pid == -1)
745 write (1, "Can't execute subshell", 22);
746 #else
747 execlp (sh, sh, (char *) 0);
748 emacs_perror (sh);
749 _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
750 #endif
751 #endif
752 }
753
754
755 #ifndef MSDOS
756 save_signal_handlers (saved_handlers);
757 #endif
758
759 #ifndef DOS_NT
760 wait_for_termination (pid, &status, 0);
761 #endif
762 restore_signal_handlers (saved_handlers);
763 }
764
765 static void
766 save_signal_handlers (struct save_signal *saved_handlers)
767 {
768 while (saved_handlers->code)
769 {
770 struct sigaction action;
771 emacs_sigaction_init (&action, SIG_IGN);
772 sigaction (saved_handlers->code, &action, &saved_handlers->action);
773 saved_handlers++;
774 }
775 }
776
777 static void
778 restore_signal_handlers (struct save_signal *saved_handlers)
779 {
780 while (saved_handlers->code)
781 {
782 sigaction (saved_handlers->code, &saved_handlers->action, 0);
783 saved_handlers++;
784 }
785 }
786
787 #ifdef USABLE_SIGIO
788 static int old_fcntl_flags[FD_SETSIZE];
789 #endif
790
791 void
792 init_sigio (int fd)
793 {
794 #ifdef USABLE_SIGIO
795 old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
796 fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
797 interrupts_deferred = 0;
798 #endif
799 }
800
801 #ifndef HAVE_ANDROID
802 #ifndef DOS_NT
803 #ifdef F_SETOWN
804 static void
805 reset_sigio (int fd)
806 {
807 #ifdef USABLE_SIGIO
808 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
809 #endif
810 }
811 #endif
812 #endif
813 #endif
814
815 void
816 request_sigio (void)
817 {
818 #if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
819 sigset_t unblocked;
820
821 if (noninteractive)
822 return;
823
824 sigemptyset (&unblocked);
825 # ifdef SIGWINCH
826 sigaddset (&unblocked, SIGWINCH);
827 # endif
828 # ifdef USABLE_SIGIO
829 sigaddset (&unblocked, SIGIO);
830 # else
831 sigaddset (&unblocked, SIGPOLL);
832 # endif
833 pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
834
835 interrupts_deferred = 0;
836 #endif
837 }
838
839 void
840 unrequest_sigio (void)
841 {
842 #if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
843 sigset_t blocked;
844
845 if (noninteractive)
846 return;
847
848 sigemptyset (&blocked);
849 # ifdef SIGWINCH
850 sigaddset (&blocked, SIGWINCH);
851 # endif
852 # ifdef USABLE_SIGIO
853 sigaddset (&blocked, SIGIO);
854 # else
855 sigaddset (&blocked, SIGPOLL);
856 # endif
857 pthread_sigmask (SIG_BLOCK, &blocked, 0);
858 interrupts_deferred = 1;
859 #endif
860 }
861
862 #ifndef MSDOS
863
864
865 void
866 block_child_signal (sigset_t *oldset)
867 {
868 sigset_t blocked;
869 sigemptyset (&blocked);
870 sigaddset (&blocked, SIGCHLD);
871 sigaddset (&blocked, SIGINT);
872 pthread_sigmask (SIG_BLOCK, &blocked, oldset);
873 }
874
875
876
877 void
878 unblock_child_signal (sigset_t const *oldset)
879 {
880 pthread_sigmask (SIG_SETMASK, oldset, 0);
881 }
882
883 #endif
884
885
886 void
887 block_interrupt_signal (sigset_t *oldset)
888 {
889 sigset_t blocked;
890 sigemptyset (&blocked);
891 sigaddset (&blocked, SIGINT);
892 pthread_sigmask (SIG_BLOCK, &blocked, oldset);
893 }
894
895
896 void
897 restore_signal_mask (sigset_t const *oldset)
898 {
899 pthread_sigmask (SIG_SETMASK, oldset, 0);
900 }
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924 static pid_t inherited_pgroup;
925
926 void
927 init_foreground_group (void)
928 {
929 pid_t pgrp = getpgrp ();
930 inherited_pgroup = getpid () == pgrp ? 0 : pgrp;
931 }
932
933
934
935 void
936 block_tty_out_signal (sigset_t *oldset)
937 {
938 #ifdef SIGTTOU
939 sigset_t blocked;
940 sigemptyset (&blocked);
941 sigaddset (&blocked, SIGTTOU);
942 pthread_sigmask (SIG_BLOCK, &blocked, oldset);
943 #endif
944 }
945
946 void
947 unblock_tty_out_signal (sigset_t const *oldset)
948 {
949 #ifdef SIGTTOU
950 pthread_sigmask (SIG_SETMASK, oldset, 0);
951 #endif
952 }
953
954
955
956
957
958
959
960
961 static void
962 tcsetpgrp_without_stopping (int fd, pid_t pgid)
963 {
964 #ifdef SIGTTOU
965 sigset_t oldset;
966 block_input ();
967 block_tty_out_signal (&oldset);
968 tcsetpgrp (fd, pgid);
969 unblock_tty_out_signal (&oldset);
970 unblock_input ();
971 #endif
972 }
973
974
975
976
977
978 static void
979 narrow_foreground_group (int fd)
980 {
981 if (inherited_pgroup && setpgid (0, 0) == 0)
982 tcsetpgrp_without_stopping (fd, getpid ());
983 }
984
985 #ifndef HAVE_ANDROID
986
987
988 static void
989 widen_foreground_group (int fd)
990 {
991 if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0)
992 tcsetpgrp_without_stopping (fd, inherited_pgroup);
993 }
994
995 #endif
996
997
998
999
1000
1001
1002
1003 int
1004 emacs_get_tty (int fd, struct emacs_tty *settings)
1005 {
1006
1007 memset (&settings->main, 0, sizeof (settings->main));
1008 #ifdef DOS_NT
1009 #ifdef WINDOWSNT
1010 HANDLE h = (HANDLE)_get_osfhandle (fd);
1011 DWORD console_mode;
1012
1013 if (h && h != INVALID_HANDLE_VALUE && GetConsoleMode (h, &console_mode))
1014 {
1015 settings->main = console_mode;
1016 return 0;
1017 }
1018 #endif
1019 return -1;
1020 #else
1021
1022 return tcgetattr (fd, &settings->main);
1023 #endif
1024 }
1025
1026
1027
1028
1029
1030
1031 int
1032 emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp)
1033 {
1034
1035 #ifdef DOS_NT
1036 #ifdef WINDOWSNT
1037 HANDLE h = (HANDLE)_get_osfhandle (fd);
1038
1039 if (h && h != INVALID_HANDLE_VALUE)
1040 {
1041 DWORD new_mode;
1042
1043
1044 if (flushp)
1045 FlushConsoleInputBuffer (h);
1046 new_mode = settings->main;
1047 SetConsoleMode (h, new_mode);
1048 }
1049 #endif
1050 #else
1051 int i;
1052
1053
1054
1055
1056
1057
1058
1059
1060 for (i = 0 ; i < 10 ; i++)
1061 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
1062 {
1063 if (errno == EINTR)
1064 continue;
1065 else
1066 return -1;
1067 }
1068 else
1069 {
1070 struct termios new;
1071
1072 memset (&new, 0, sizeof (new));
1073
1074 tcgetattr (fd, &new);
1075
1076
1077
1078
1079 if ( new.c_iflag == settings->main.c_iflag
1080 && new.c_oflag == settings->main.c_oflag
1081 && new.c_cflag == settings->main.c_cflag
1082 && new.c_lflag == settings->main.c_lflag
1083 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
1084 break;
1085 else
1086 continue;
1087 }
1088 #endif
1089
1090
1091 return 0;
1092 }
1093
1094
1095
1096 #ifdef F_SETOWN
1097 static int old_fcntl_owner[FD_SETSIZE];
1098 #endif
1099
1100
1101
1102
1103 void
1104 init_all_sys_modes (void)
1105 {
1106 struct tty_display_info *tty;
1107 for (tty = tty_list; tty; tty = tty->next)
1108 init_sys_modes (tty);
1109 }
1110
1111
1112
1113 void
1114 init_sys_modes (struct tty_display_info *tty_out)
1115 {
1116 struct emacs_tty tty;
1117 #ifndef DOS_NT
1118 Lisp_Object terminal;
1119 #endif
1120
1121 Vtty_erase_char = Qnil;
1122
1123 if (noninteractive)
1124 return;
1125
1126 if (!tty_out->output)
1127 return;
1128
1129 narrow_foreground_group (fileno (tty_out->input));
1130
1131 if (! tty_out->old_tty)
1132 tty_out->old_tty = xmalloc (sizeof *tty_out->old_tty);
1133
1134 emacs_get_tty (fileno (tty_out->input), tty_out->old_tty);
1135
1136 tty = *tty_out->old_tty;
1137
1138 #if !defined (DOS_NT)
1139 XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
1140
1141 tty.main.c_iflag |= (IGNBRK);
1142 tty.main.c_iflag &= ~ICRNL;
1143 #ifdef INLCR
1144
1145 tty.main.c_iflag &= ~INLCR;
1146 #endif
1147 #ifdef ISTRIP
1148 tty.main.c_iflag &= ~ISTRIP;
1149 #endif
1150 tty.main.c_lflag &= ~ECHO;
1151 tty.main.c_lflag &= ~ICANON;
1152 #ifdef IEXTEN
1153 tty.main.c_lflag &= ~IEXTEN;
1154 #endif
1155 tty.main.c_lflag |= ISIG;
1156 if (tty_out->flow_control)
1157 {
1158 tty.main.c_iflag |= IXON;
1159 #ifdef IXANY
1160 tty.main.c_iflag &= ~IXANY;
1161 #endif
1162 }
1163 else
1164 tty.main.c_iflag &= ~IXON;
1165 tty.main.c_oflag &= ~ONLCR;
1166
1167 tty.main.c_oflag &= ~TAB3;
1168 #ifdef CS8
1169 if (tty_out->meta_key)
1170 {
1171 tty.main.c_cflag |= CS8;
1172 tty.main.c_cflag &= ~PARENB;
1173 }
1174 #endif
1175
1176 XSETTERMINAL(terminal, tty_out->terminal);
1177 if (!NILP (Fcontrolling_tty_p (terminal)))
1178 {
1179 tty.main.c_cc[VINTR] = quit_char;
1180
1181
1182
1183 tty.main.c_cc[VQUIT] = quit_char;
1184 }
1185 else
1186 {
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202 tty.main.c_cc[VINTR] = CDISABLE;
1203 tty.main.c_cc[VQUIT] = CDISABLE;
1204 }
1205 tty.main.c_cc[VMIN] = 1;
1206 tty.main.c_cc[VTIME] = 0;
1207 #ifdef VSWTCH
1208 tty.main.c_cc[VSWTCH] = CDISABLE;
1209
1210 #endif
1211
1212 #ifdef VSUSP
1213 tty.main.c_cc[VSUSP] = CDISABLE;
1214 #endif
1215 #ifdef V_DSUSP
1216 tty.main.c_cc[V_DSUSP] = CDISABLE;
1217 #endif
1218 #ifdef VDSUSP
1219 tty.main.c_cc[VDSUSP] = CDISABLE;
1220 #endif
1221 #ifdef VLNEXT
1222 tty.main.c_cc[VLNEXT] = CDISABLE;
1223 #endif
1224 #ifdef VREPRINT
1225 tty.main.c_cc[VREPRINT] = CDISABLE;
1226 #endif
1227 #ifdef VWERASE
1228 tty.main.c_cc[VWERASE] = CDISABLE;
1229 #endif
1230 #ifdef VDISCARD
1231 tty.main.c_cc[VDISCARD] = CDISABLE;
1232 #endif
1233
1234 if (tty_out->flow_control)
1235 {
1236 #ifdef VSTART
1237 tty.main.c_cc[VSTART] = '\021';
1238 #endif
1239 #ifdef VSTOP
1240 tty.main.c_cc[VSTOP] = '\023';
1241 #endif
1242 }
1243 else
1244 {
1245 #ifdef VSTART
1246 tty.main.c_cc[VSTART] = CDISABLE;
1247 #endif
1248 #ifdef VSTOP
1249 tty.main.c_cc[VSTOP] = CDISABLE;
1250 #endif
1251 }
1252
1253 #ifdef AIX
1254 tty.main.c_cc[VSTRT] = CDISABLE;
1255 tty.main.c_cc[VSTOP] = CDISABLE;
1256 tty.main.c_cc[VSUSP] = CDISABLE;
1257 tty.main.c_cc[VDSUSP] = CDISABLE;
1258 if (tty_out->flow_control)
1259 {
1260 #ifdef VSTART
1261 tty.main.c_cc[VSTART] = '\021';
1262 #endif
1263 #ifdef VSTOP
1264 tty.main.c_cc[VSTOP] = '\023';
1265 #endif
1266 }
1267
1268
1269
1270
1271 tty.main.c_iflag &= ~IGNBRK;
1272 tty.main.c_iflag &= ~BRKINT;
1273 #endif
1274 #endif
1275
1276 #ifdef MSDOS
1277 if (!tty_out->term_initted)
1278 internal_terminal_init ();
1279 dos_ttraw (tty_out);
1280 #endif
1281
1282 emacs_set_tty (fileno (tty_out->input), &tty, 0);
1283
1284
1285
1286
1287 #ifndef HAIKU
1288
1289 #ifdef TCXONC
1290 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
1291 #endif
1292 #endif
1293 #ifdef TIOCSTART
1294 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
1295 #endif
1296
1297 #if !defined (DOS_NT)
1298 #ifdef TCOON
1299 if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
1300 #endif
1301 #endif
1302
1303 #ifdef F_GETOWN
1304 if (interrupt_input)
1305 {
1306 old_fcntl_owner[fileno (tty_out->input)] =
1307 fcntl (fileno (tty_out->input), F_GETOWN, 0);
1308 fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
1309 init_sigio (fileno (tty_out->input));
1310 #ifdef HAVE_GPM
1311 if (gpm_tty == tty_out)
1312 {
1313
1314 fcntl (gpm_fd, F_SETOWN, getpid ());
1315 fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
1316 init_sigio (gpm_fd);
1317 }
1318 #endif
1319 }
1320 #endif
1321
1322 const size_t buffer_size = (tty_out->output_buffer_size
1323 ? tty_out->output_buffer_size
1324 : BUFSIZ);
1325 setvbuf (tty_out->output, NULL, _IOFBF, buffer_size);
1326
1327 if (tty_out->terminal->set_terminal_modes_hook)
1328 tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
1329
1330 if (!tty_out->term_initted)
1331 {
1332 Lisp_Object tail, frame;
1333 FOR_EACH_FRAME (tail, frame)
1334 {
1335
1336 if (FRAME_TERMCAP_P (XFRAME (frame))
1337 && FRAME_TTY (XFRAME (frame)) == tty_out)
1338 init_frame_faces (XFRAME (frame));
1339 }
1340 }
1341
1342 if (tty_out->term_initted && no_redraw_on_reenter)
1343 {
1344
1345
1346 }
1347 else
1348 {
1349 Lisp_Object tail, frame;
1350 frame_garbaged = 1;
1351 FOR_EACH_FRAME (tail, frame)
1352 {
1353 if ((FRAME_TERMCAP_P (XFRAME (frame))
1354 || FRAME_MSDOS_P (XFRAME (frame)))
1355 && FRAME_TTY (XFRAME (frame)) == tty_out)
1356 FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1357 }
1358 }
1359
1360 tty_out->term_initted = 1;
1361 }
1362
1363
1364
1365
1366 bool
1367 tabs_safe_p (int fd)
1368 {
1369 struct emacs_tty etty;
1370
1371 emacs_get_tty (fd, &etty);
1372 #ifndef DOS_NT
1373 #ifdef TABDLY
1374 return ((etty.main.c_oflag & TABDLY) != TAB3);
1375 #else
1376 return 1;
1377 #endif
1378 #else
1379 return 0;
1380 #endif
1381 }
1382
1383
1384
1385 void
1386 suppress_echo_on_tty (int fd)
1387 {
1388 struct emacs_tty etty;
1389
1390 emacs_get_tty (fd, &etty);
1391 #ifdef DOS_NT
1392
1393 etty.main = 0;
1394 #else
1395 etty.main.c_lflag &= ~ICANON;
1396 etty.main.c_lflag &= ~ECHO;
1397 #endif
1398 emacs_set_tty (fd, &etty, 0);
1399 }
1400
1401
1402
1403
1404
1405 void
1406 get_tty_size (int fd, int *widthp, int *heightp)
1407 {
1408 #if defined TIOCGWINSZ
1409
1410
1411 struct winsize size;
1412
1413 if (ioctl (fd, TIOCGWINSZ, &size) == -1)
1414 *widthp = *heightp = 0;
1415 else
1416 {
1417 *widthp = size.ws_col;
1418 *heightp = size.ws_row;
1419 }
1420
1421 #elif defined TIOCGSIZE
1422
1423
1424 struct ttysize size;
1425
1426 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1427 *widthp = *heightp = 0;
1428 else
1429 {
1430 *widthp = size.ts_cols;
1431 *heightp = size.ts_lines;
1432 }
1433
1434 #elif defined WINDOWSNT
1435
1436 CONSOLE_SCREEN_BUFFER_INFO info;
1437 if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info))
1438 {
1439 *widthp = info.srWindow.Right - info.srWindow.Left + 1;
1440 *heightp = info.srWindow.Bottom - info.srWindow.Top + 1;
1441 }
1442 else
1443 *widthp = *heightp = 0;
1444
1445 #elif defined MSDOS
1446
1447 *widthp = ScreenCols ();
1448 *heightp = ScreenRows ();
1449
1450 #else
1451
1452 *widthp = 0;
1453 *heightp = 0;
1454
1455 #endif
1456 }
1457
1458
1459
1460
1461
1462 int
1463 set_window_size (int fd, int height, int width)
1464 {
1465 #ifdef TIOCSWINSZ
1466
1467
1468 struct winsize size;
1469 memset (&size, 0, sizeof (size));
1470 size.ws_row = height;
1471 size.ws_col = width;
1472
1473 return ioctl (fd, TIOCSWINSZ, &size);
1474
1475 #else
1476 #ifdef TIOCSSIZE
1477
1478
1479 struct ttysize size;
1480 memset (&size, 0, sizeof (size));
1481 size.ts_lines = height;
1482 size.ts_cols = width;
1483
1484 return ioctl (fd, TIOCGSIZE, &size);
1485 #else
1486 return -1;
1487 #endif
1488 #endif
1489 }
1490
1491
1492
1493
1494
1495 void
1496 reset_all_sys_modes (void)
1497 {
1498 struct tty_display_info *tty;
1499 for (tty = tty_list; tty; tty = tty->next)
1500 reset_sys_modes (tty);
1501 }
1502
1503
1504
1505
1506 void
1507 reset_sys_modes (struct tty_display_info *tty_out)
1508 {
1509 if (noninteractive)
1510 {
1511 fflush (stdout);
1512 return;
1513 }
1514
1515 #ifndef HAVE_ANDROID
1516 if (!tty_out->term_initted)
1517 return;
1518
1519 if (!tty_out->output)
1520 return;
1521
1522
1523
1524 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1525
1526
1527 if (tty_out->TS_clr_line)
1528 {
1529 emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
1530 }
1531 else
1532 {
1533 tty_turn_off_insert (tty_out);
1534
1535 for (int i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++)
1536 putc (' ', tty_out->output);
1537 }
1538
1539 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1540 fflush (tty_out->output);
1541
1542 if (tty_out->terminal->reset_terminal_modes_hook)
1543 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
1544
1545
1546 while (tcdrain (fileno (tty_out->output)) != 0 && errno == EINTR)
1547 continue;
1548
1549 #ifndef DOS_NT
1550 # ifdef F_SETOWN
1551 if (interrupt_input)
1552 {
1553 reset_sigio (fileno (tty_out->input));
1554 fcntl (fileno (tty_out->input), F_SETOWN,
1555 old_fcntl_owner[fileno (tty_out->input)]);
1556 }
1557 # endif
1558 fcntl (fileno (tty_out->input), F_SETFL,
1559 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NONBLOCK);
1560 #endif
1561
1562 if (tty_out->old_tty)
1563 while (emacs_set_tty (fileno (tty_out->input),
1564 tty_out->old_tty, 0) < 0 && errno == EINTR)
1565 ;
1566
1567 #ifdef MSDOS
1568 dos_ttcooked ();
1569 #endif
1570
1571 widen_foreground_group (fileno (tty_out->input));
1572 #endif
1573 }
1574
1575 #ifdef HAVE_PTYS
1576
1577
1578
1579 void
1580 setup_pty (int fd)
1581 {
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605 #ifdef FIONBIO
1606 #if defined (UNIX98_PTYS)
1607 {
1608 int on = 1;
1609 ioctl (fd, FIONBIO, &on);
1610 }
1611 #endif
1612 #endif
1613 }
1614 #endif
1615
1616 void
1617 init_system_name (void)
1618 {
1619 if (!build_details)
1620 {
1621
1622 Vsystem_name = Qnil;
1623 return;
1624 }
1625 char *hostname_alloc = NULL;
1626 char *hostname;
1627 #ifndef HAVE_GETHOSTNAME
1628 struct utsname uts;
1629 uname (&uts);
1630 hostname = uts.nodename;
1631 #else
1632 char hostname_buf[256];
1633 ptrdiff_t hostname_size = sizeof hostname_buf;
1634 hostname = hostname_buf;
1635
1636
1637
1638
1639
1640 for (;;)
1641 {
1642 gethostname (hostname, hostname_size - 1);
1643 hostname[hostname_size - 1] = '\0';
1644
1645
1646 if (strlen (hostname) < hostname_size - 1)
1647 break;
1648
1649 hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1,
1650 min (PTRDIFF_MAX, SIZE_MAX), 1);
1651 }
1652 #endif
1653 char *p;
1654 for (p = hostname; *p; p++)
1655 if (*p == ' ' || *p == '\t')
1656 *p = '-';
1657 if (! (STRINGP (Vsystem_name) && SBYTES (Vsystem_name) == p - hostname
1658 && strcmp (SSDATA (Vsystem_name), hostname) == 0))
1659 Vsystem_name = build_string (hostname);
1660 xfree (hostname_alloc);
1661 }
1662
1663 sigset_t empty_mask;
1664
1665 static struct sigaction process_fatal_action;
1666
1667 static int
1668 emacs_sigaction_flags (void)
1669 {
1670 #ifdef SA_RESTART
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680 if (noninteractive)
1681 return SA_RESTART;
1682 #endif
1683 return 0;
1684 }
1685
1686
1687
1688 void
1689 emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
1690 {
1691 sigemptyset (&action->sa_mask);
1692
1693
1694
1695 sigaddset (&action->sa_mask, SIGALRM);
1696 #ifdef SIGCHLD
1697 sigaddset (&action->sa_mask, SIGCHLD);
1698 #endif
1699 #ifdef SIGDANGER
1700 sigaddset (&action->sa_mask, SIGDANGER);
1701 #endif
1702 #ifdef PROFILER_CPU_SUPPORT
1703 sigaddset (&action->sa_mask, SIGPROF);
1704 #endif
1705 #ifdef SIGWINCH
1706 sigaddset (&action->sa_mask, SIGWINCH);
1707 #endif
1708 if (! noninteractive)
1709 {
1710 sigaddset (&action->sa_mask, SIGINT);
1711 sigaddset (&action->sa_mask, SIGQUIT);
1712 #ifdef USABLE_SIGIO
1713 sigaddset (&action->sa_mask, SIGIO);
1714 #elif defined (USABLE_SIGPOLL)
1715 sigaddset (&action->sa_mask, SIGPOLL);
1716 #endif
1717 }
1718
1719 action->sa_handler = handler;
1720 action->sa_flags = emacs_sigaction_flags ();
1721 }
1722
1723 #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1724 static pthread_t main_thread_id;
1725 #endif
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739 void
1740 deliver_process_signal (int sig, signal_handler_t handler)
1741 {
1742
1743
1744 int old_errno = errno;
1745
1746 bool on_main_thread = true;
1747 #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1748 if (! pthread_equal (pthread_self (), main_thread_id))
1749 {
1750 sigset_t blocked;
1751 sigemptyset (&blocked);
1752 sigaddset (&blocked, sig);
1753 pthread_sigmask (SIG_BLOCK, &blocked, 0);
1754 pthread_kill (main_thread_id, sig);
1755 on_main_thread = false;
1756 }
1757 #endif
1758 if (on_main_thread)
1759 handler (sig);
1760
1761 errno = old_errno;
1762 }
1763
1764
1765
1766
1767 enum { BACKTRACE_LIMIT_MAX = 500 };
1768 static void *thread_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
1769 static int thread_backtrace_npointers;
1770
1771
1772
1773
1774 static void
1775 deliver_thread_signal (int sig, signal_handler_t handler)
1776 {
1777 int old_errno = errno;
1778
1779 #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1780 if (! pthread_equal (pthread_self (), main_thread_id))
1781 {
1782 thread_backtrace_npointers
1783 = backtrace (thread_backtrace_buffer, BACKTRACE_LIMIT_MAX);
1784 sigaction (sig, &process_fatal_action, 0);
1785 pthread_kill (main_thread_id, sig);
1786
1787
1788 while (1)
1789 sigsuspend (&empty_mask);
1790 }
1791 #endif
1792
1793 handler (sig);
1794 errno = old_errno;
1795 }
1796
1797
1798 static void
1799 handle_fatal_signal (int sig)
1800 {
1801 terminate_due_to_signal (sig, 40);
1802 }
1803
1804 static void
1805 deliver_fatal_signal (int sig)
1806 {
1807 deliver_process_signal (sig, handle_fatal_signal);
1808 }
1809
1810 static void
1811 deliver_fatal_thread_signal (int sig)
1812 {
1813 deliver_thread_signal (sig, handle_fatal_signal);
1814 }
1815
1816 static AVOID
1817 handle_arith_signal (int sig)
1818 {
1819 pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
1820 xsignal0 (Qarith_error);
1821 }
1822
1823 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP
1824
1825 static void
1826 handle_sigbus (int sig, siginfo_t *siginfo, void *arg)
1827 {
1828
1829
1830
1831 if (sfntfont_detect_sigbus (siginfo->si_addr))
1832 return;
1833
1834 handle_fatal_signal (sig);
1835 }
1836
1837
1838
1839
1840 static int
1841 init_sigbus (void)
1842 {
1843 struct sigaction sa;
1844
1845 sigfillset (&sa.sa_mask);
1846 sa.sa_sigaction = handle_sigbus;
1847 sa.sa_flags = SA_SIGINFO;
1848
1849 if (sigaction (SIGBUS, &sa, NULL))
1850 return 1;
1851
1852 return 0;
1853 }
1854
1855 #endif
1856
1857
1858
1859
1860 #if defined HAVE_STACK_OVERFLOW_HANDLING && !defined WINDOWSNT \
1861 && (!defined HAVE_ANDROID || defined ANDROID_STUBIFY)
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871 static max_align_t sigsegv_stack[(64 * 1024
1872 + sizeof (max_align_t) - 1)
1873 / sizeof (max_align_t)];
1874
1875
1876
1877
1878 static bool
1879 stack_overflow (siginfo_t *siginfo)
1880 {
1881 if (!attempt_stack_overflow_recovery)
1882 return false;
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897 if (!siginfo)
1898 return false;
1899
1900
1901 char *addr = siginfo->si_addr;
1902 if (!addr)
1903 return false;
1904
1905
1906
1907 char const *bot = stack_bottom;
1908 char const *top = current_thread->stack_top;
1909
1910
1911
1912
1913
1914
1915
1916
1917 enum { LG_STACK_HEURISTIC = 8 };
1918
1919 if (bot < top)
1920 return 0 <= addr - top && addr - top < (top - bot) >> LG_STACK_HEURISTIC;
1921 else
1922 return 0 <= top - addr && top - addr < (bot - top) >> LG_STACK_HEURISTIC;
1923 }
1924
1925
1926
1927
1928 static void
1929 handle_sigsegv (int sig, siginfo_t *siginfo, void *arg)
1930 {
1931
1932
1933 bool fatal = gc_in_progress;
1934
1935 #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
1936 if (!fatal && !pthread_equal (pthread_self (), main_thread_id))
1937 fatal = true;
1938 #endif
1939
1940 if (!fatal && stack_overflow (siginfo))
1941 siglongjmp (return_to_command_loop, 1);
1942
1943
1944 deliver_fatal_thread_signal (sig);
1945 }
1946
1947
1948
1949
1950 static bool
1951 init_sigsegv (void)
1952 {
1953 struct sigaction sa;
1954 stack_t ss;
1955
1956 ss.ss_sp = sigsegv_stack;
1957 ss.ss_size = sizeof (sigsegv_stack);
1958 ss.ss_flags = 0;
1959 if (sigaltstack (&ss, NULL) < 0)
1960 return 0;
1961
1962 sigfillset (&sa.sa_mask);
1963 sa.sa_sigaction = handle_sigsegv;
1964 sa.sa_flags = SA_SIGINFO | SA_ONSTACK | emacs_sigaction_flags ();
1965 if (sigaction (SIGSEGV, &sa, NULL) < 0)
1966 return 0;
1967
1968 return 1;
1969 }
1970
1971 #else
1972
1973 #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
1974
1975 static bool
1976 init_sigsegv (void)
1977 {
1978 return 0;
1979 }
1980
1981 #endif
1982
1983 #endif
1984
1985 static void
1986 deliver_arith_signal (int sig)
1987 {
1988 deliver_thread_signal (sig, handle_arith_signal);
1989 }
1990
1991 #ifdef SIGDANGER
1992
1993
1994 static void
1995 handle_danger_signal (int sig)
1996 {
1997 malloc_warning ("Operating system warns that virtual memory is running low.\n");
1998
1999
2000 force_auto_save_soon ();
2001 }
2002
2003 static void
2004 deliver_danger_signal (int sig)
2005 {
2006 deliver_process_signal (sig, handle_danger_signal);
2007 }
2008 #endif
2009
2010
2011
2012 static void
2013 maybe_fatal_sig (int sig)
2014 {
2015 bool catch_sig = !noninteractive;
2016 if (!catch_sig)
2017 {
2018 struct sigaction old_action;
2019 sigaction (sig, 0, &old_action);
2020 catch_sig = old_action.sa_handler != SIG_IGN;
2021 }
2022 if (catch_sig)
2023 sigaction (sig, &process_fatal_action, 0);
2024 }
2025
2026 void
2027 init_signals (void)
2028 {
2029 struct sigaction thread_fatal_action;
2030 struct sigaction action;
2031
2032 sigemptyset (&empty_mask);
2033
2034 #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
2035 main_thread_id = pthread_self ();
2036 #endif
2037
2038
2039
2040
2041 if (will_dump_p ())
2042 return;
2043
2044 sigfillset (&process_fatal_action.sa_mask);
2045 process_fatal_action.sa_handler = deliver_fatal_signal;
2046 process_fatal_action.sa_flags = emacs_sigaction_flags ();
2047
2048 sigfillset (&thread_fatal_action.sa_mask);
2049 thread_fatal_action.sa_handler = deliver_fatal_thread_signal;
2050 thread_fatal_action.sa_flags = process_fatal_action.sa_flags;
2051
2052
2053
2054
2055
2056
2057 maybe_fatal_sig (SIGHUP);
2058 maybe_fatal_sig (SIGINT);
2059 maybe_fatal_sig (SIGTERM);
2060
2061
2062
2063
2064 if (! noninteractive)
2065 signal (SIGPIPE, SIG_IGN);
2066
2067 sigaction (SIGQUIT, &process_fatal_action, 0);
2068 #ifndef __vax__
2069 sigaction (SIGILL, &thread_fatal_action, 0);
2070 #endif
2071 sigaction (SIGTRAP, &thread_fatal_action, 0);
2072
2073
2074
2075
2076
2077 if (IEEE_FLOATING_POINT)
2078 sigaction (SIGFPE, &thread_fatal_action, 0);
2079 else
2080 {
2081 emacs_sigaction_init (&action, deliver_arith_signal);
2082 sigaction (SIGFPE, &action, 0);
2083 #ifdef __vax__
2084
2085
2086 sigaction (SIGILL, &action, 0);
2087 #endif
2088 }
2089
2090
2091
2092 #if !defined HAVE_ANDROID
2093 #ifdef SIGUSR1
2094 add_user_signal (SIGUSR1, "sigusr1");
2095 #endif
2096 #ifdef SIGUSR2
2097 add_user_signal (SIGUSR2, "sigusr2");
2098 #endif
2099 #endif
2100
2101 sigaction (SIGABRT, &thread_fatal_action, 0);
2102 #ifdef SIGPRE
2103 sigaction (SIGPRE, &thread_fatal_action, 0);
2104 #endif
2105 #ifdef SIGORE
2106 sigaction (SIGORE, &thread_fatal_action, 0);
2107 #endif
2108 #ifdef SIGUME
2109 sigaction (SIGUME, &thread_fatal_action, 0);
2110 #endif
2111 #ifdef SIGDLK
2112 sigaction (SIGDLK, &process_fatal_action, 0);
2113 #endif
2114 #ifdef SIGCPULIM
2115 sigaction (SIGCPULIM, &process_fatal_action, 0);
2116 #endif
2117 #ifdef SIGIOT
2118 sigaction (SIGIOT, &thread_fatal_action, 0);
2119 #endif
2120 #ifdef SIGEMT
2121 sigaction (SIGEMT, &thread_fatal_action, 0);
2122 #endif
2123 #ifdef SIGBUS
2124 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP
2125 if (init_sigbus ())
2126 #endif
2127 sigaction (SIGBUS, &thread_fatal_action, 0);
2128 #endif
2129 #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
2130 if (!init_sigsegv ())
2131 sigaction (SIGSEGV, &thread_fatal_action, 0);
2132 #endif
2133 #ifdef SIGSYS
2134 sigaction (SIGSYS, &thread_fatal_action, 0);
2135 #endif
2136 sigaction (SIGTERM, &process_fatal_action, 0);
2137 #ifdef SIGPROF
2138 signal (SIGPROF, SIG_IGN);
2139 #endif
2140 #ifdef SIGVTALRM
2141 sigaction (SIGVTALRM, &process_fatal_action, 0);
2142 #endif
2143 #ifdef SIGXCPU
2144 sigaction (SIGXCPU, &process_fatal_action, 0);
2145 #endif
2146 #ifdef SIGXFSZ
2147 sigaction (SIGXFSZ, &process_fatal_action, 0);
2148 #endif
2149
2150 #ifdef SIGDANGER
2151
2152 emacs_sigaction_init (&action, deliver_danger_signal);
2153 sigaction (SIGDANGER, &action, 0);
2154 #endif
2155
2156
2157 #ifdef SIGGRANT
2158 sigaction (SIGGRANT, &process_fatal_action, 0);
2159 #endif
2160 #ifdef SIGMIGRATE
2161 sigaction (SIGMIGRATE, &process_fatal_action, 0);
2162 #endif
2163 #ifdef SIGMSG
2164 sigaction (SIGMSG, &process_fatal_action, 0);
2165 #endif
2166 #ifdef SIGRETRACT
2167 sigaction (SIGRETRACT, &process_fatal_action, 0);
2168 #endif
2169 #ifdef SIGSAK
2170 sigaction (SIGSAK, &process_fatal_action, 0);
2171 #endif
2172 #ifdef SIGSOUND
2173 sigaction (SIGSOUND, &process_fatal_action, 0);
2174 #endif
2175 #ifdef SIGTALRM
2176 sigaction (SIGTALRM, &thread_fatal_action, 0);
2177 #endif
2178 }
2179
2180 #ifndef HAVE_RANDOM
2181 #ifdef random
2182 #define HAVE_RANDOM
2183 #endif
2184 #endif
2185
2186
2187
2188
2189
2190
2191 #ifndef RAND_BITS
2192 # ifdef HAVE_RANDOM
2193 # define RAND_BITS 31
2194 # else
2195 # ifdef HAVE_LRAND48
2196 # define RAND_BITS 31
2197 # define random lrand48
2198 # else
2199 # define RAND_BITS 15
2200 # if RAND_MAX == 32767
2201 # define random rand
2202 # else
2203 # if RAND_MAX == 2147483647
2204 # define random() (rand () >> 16)
2205 # else
2206 # ifdef USG
2207 # define random rand
2208 # else
2209 # define random() (rand () >> 16)
2210 # endif
2211 # endif
2212 # endif
2213 # endif
2214 # endif
2215 #endif
2216
2217 #ifdef HAVE_RANDOM
2218 typedef unsigned int random_seed;
2219 static void set_random_seed (random_seed arg) { srandom (arg); }
2220 #elif defined HAVE_LRAND48
2221 typedef long int random_seed;
2222 static void set_random_seed (random_seed arg) { srand48 (arg); }
2223 #else
2224 typedef unsigned int random_seed;
2225 static void set_random_seed (random_seed arg) { srand (arg); }
2226 #endif
2227
2228 void
2229 seed_random (void *seed, ptrdiff_t seed_size)
2230 {
2231 random_seed arg = 0;
2232 unsigned char *argp = (unsigned char *) &arg;
2233 unsigned char *seedp = seed;
2234 for (ptrdiff_t i = 0; i < seed_size; i++)
2235 argp[i % sizeof arg] ^= seedp[i];
2236 set_random_seed (arg);
2237 }
2238
2239 void
2240 init_random (void)
2241 {
2242 random_seed v;
2243 bool success = false;
2244
2245
2246
2247 #ifdef WINDOWSNT
2248
2249 success = w32_init_random (&v, sizeof v) == 0;
2250 #else
2251 verify (sizeof v <= 256);
2252 success = getrandom (&v, sizeof v, 0) == sizeof v;
2253 #endif
2254
2255
2256
2257 if (!success)
2258 {
2259 struct timespec t = current_timespec ();
2260 v = getpid () ^ t.tv_sec ^ t.tv_nsec;
2261 }
2262
2263 set_random_seed (v);
2264 }
2265
2266
2267
2268
2269
2270
2271 EMACS_INT
2272 get_random (void)
2273 {
2274 EMACS_UINT val = 0;
2275 int i;
2276 for (i = 0; i < (FIXNUM_BITS + RAND_BITS - 1) / RAND_BITS; i++)
2277 val = (random () ^ (val << RAND_BITS)
2278 ^ (val >> (EMACS_INT_WIDTH - RAND_BITS)));
2279 val ^= val >> (EMACS_INT_WIDTH - FIXNUM_BITS);
2280 return val & INTMASK;
2281 }
2282
2283
2284 unsigned long int
2285 get_random_ulong (void)
2286 {
2287 unsigned long int r = 0;
2288 for (int i = 0; i < (ULONG_WIDTH + RAND_BITS - 1) / RAND_BITS; i++)
2289 r = random () ^ (r << RAND_BITS) ^ (r >> (ULONG_WIDTH - RAND_BITS));
2290 return r;
2291 }
2292
2293 #ifndef HAVE_SNPRINTF
2294
2295 int
2296 snprintf (char *buf, size_t bufsize, char const *format, ...)
2297 {
2298 ptrdiff_t size = min (bufsize, PTRDIFF_MAX);
2299 ptrdiff_t nbytes = size - 1;
2300 va_list ap;
2301
2302 if (size)
2303 {
2304 va_start (ap, format);
2305 nbytes = doprnt (buf, size, format, 0, ap);
2306 va_end (ap);
2307 }
2308
2309 if (nbytes == size - 1)
2310 {
2311
2312
2313 char stackbuf[4000];
2314 char *b = stackbuf;
2315 ptrdiff_t bsize = sizeof stackbuf;
2316 va_start (ap, format);
2317 nbytes = evxprintf (&b, &bsize, stackbuf, -1, format, ap);
2318 va_end (ap);
2319 if (b != stackbuf)
2320 xfree (b);
2321 }
2322
2323 if (INT_MAX < nbytes)
2324 {
2325 #ifdef EOVERFLOW
2326 errno = EOVERFLOW;
2327 #else
2328 errno = EDOM;
2329 #endif
2330 return -1;
2331 }
2332 return nbytes;
2333 }
2334 #endif
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350 void
2351 emacs_backtrace (int backtrace_limit)
2352 {
2353 void *main_backtrace_buffer[BACKTRACE_LIMIT_MAX + 1];
2354 int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX);
2355 void *buffer;
2356 int npointers;
2357
2358 if (thread_backtrace_npointers)
2359 {
2360 buffer = thread_backtrace_buffer;
2361 npointers = thread_backtrace_npointers;
2362 }
2363 else
2364 {
2365 buffer = main_backtrace_buffer;
2366
2367
2368 if (bounded_limit < 0)
2369 {
2370 backtrace (buffer, 1);
2371 return;
2372 }
2373
2374 npointers = backtrace (buffer, bounded_limit + 1);
2375 }
2376
2377 if (npointers)
2378 {
2379 emacs_write (STDERR_FILENO, "Backtrace:\n", 11);
2380 backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
2381 if (bounded_limit < npointers)
2382 emacs_write (STDERR_FILENO, "...\n", 4);
2383 }
2384 }
2385
2386 #if !defined HAVE_NTGUI && !(defined HAVE_ANDROID \
2387 && !defined ANDROID_STUBIFY)
2388 void
2389 emacs_abort (void)
2390 {
2391 terminate_due_to_signal (SIGABRT, 40);
2392 }
2393 #endif
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405 int
2406 emacs_fstatat (int dirfd, char const *filename, void *st, int flags)
2407 {
2408 int r;
2409 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2410 while ((r = fstatat (dirfd, filename, st, flags)) != 0
2411 && errno == EINTR)
2412 maybe_quit ();
2413 #else
2414 while ((r = android_fstatat (dirfd, filename, st, flags)) != 0
2415 && errno == EINTR)
2416 maybe_quit ();
2417 #endif
2418 return r;
2419 }
2420
2421 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2422
2423 static int
2424 sys_openat (int dirfd, char const *file, int oflags, int mode)
2425 {
2426 #ifdef O_PATH
2427 return openat (dirfd, file, oflags, mode);
2428 #else
2429
2430
2431
2432 eassert (dirfd == AT_FDCWD);
2433 return open (file, oflags, mode);
2434 #endif
2435 }
2436
2437 #endif
2438
2439 int
2440 sys_fstat (int fd, struct stat *statb)
2441 {
2442 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2443 return fstat (fd, statb);
2444 #else
2445 return android_fstat (fd, statb);
2446 #endif
2447 }
2448
2449 int
2450 sys_faccessat (int fd, const char *pathname, int mode, int flags)
2451 {
2452 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2453 return faccessat (fd, pathname, mode, flags);
2454 #else
2455 return android_faccessat (fd, pathname, mode, flags);
2456 #endif
2457 }
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2468
2469 int
2470 emacs_openat (int dirfd, char const *file, int oflags, int mode)
2471 {
2472 int fd;
2473 if (! (oflags & O_TEXT))
2474 oflags |= O_BINARY;
2475 oflags |= O_CLOEXEC;
2476 while ((fd = sys_openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR)
2477 maybe_quit ();
2478 return fd;
2479 }
2480
2481 #endif
2482
2483 int
2484 emacs_open (char const *file, int oflags, int mode)
2485 {
2486 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2487 int fd;
2488 #endif
2489
2490 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2491 return emacs_openat (AT_FDCWD, file, oflags, mode);
2492 #else
2493 while ((fd = android_open (file, oflags, mode)) < 0 && errno == EINTR)
2494 maybe_quit ();
2495
2496 return fd;
2497 #endif
2498 }
2499
2500
2501
2502 int
2503 emacs_open_noquit (char const *file, int oflags, int mode)
2504 {
2505 int fd;
2506 if (! (oflags & O_TEXT))
2507 oflags |= O_BINARY;
2508 oflags |= O_CLOEXEC;
2509 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2510 do
2511 fd = open (file, oflags, mode);
2512 while (fd < 0 && errno == EINTR);
2513 #else
2514 do
2515 fd = android_open (file, oflags, mode);
2516 while (fd < 0 && errno == EINTR);
2517 #endif
2518 return fd;
2519 }
2520
2521
2522
2523
2524 FILE *
2525 emacs_fopen (char const *file, char const *mode)
2526 {
2527 int fd, omode, oflags;
2528 int bflag = 0;
2529 char const *m = mode;
2530
2531 switch (*m++)
2532 {
2533 case 'r': omode = O_RDONLY; oflags = 0; break;
2534 case 'w': omode = O_WRONLY; oflags = O_CREAT | O_TRUNC; break;
2535 case 'a': omode = O_WRONLY; oflags = O_CREAT | O_APPEND; break;
2536 default: emacs_abort ();
2537 }
2538
2539 while (*m)
2540 switch (*m++)
2541 {
2542 case '+': omode = O_RDWR; break;
2543 case 't': bflag = O_TEXT; break;
2544 default: break;
2545 }
2546
2547 fd = emacs_open (file, omode | oflags | bflag, 0666);
2548 return fd < 0 ? 0 : emacs_fdopen (fd, mode);
2549 }
2550
2551
2552
2553 int
2554 emacs_pipe (int fd[2])
2555 {
2556 #ifdef MSDOS
2557 return pipe (fd);
2558 #else
2559 return pipe2 (fd, O_BINARY | O_CLOEXEC);
2560 #endif
2561 }
2562
2563
2564
2565
2566
2567 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2568
2569 #ifndef POSIX_CLOSE_RESTART
2570 # define POSIX_CLOSE_RESTART 1
2571 static int
2572 posix_close (int fd, int flag)
2573 {
2574
2575 eassert (flag == POSIX_CLOSE_RESTART);
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591 return close (fd) == 0 || errno == EINTR ? 0 : -1;
2592 }
2593 #endif
2594
2595 #endif
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606 int
2607 emacs_close (int fd)
2608 {
2609 int r;
2610
2611 while (1)
2612 {
2613 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2614 r = posix_close (fd, POSIX_CLOSE_RESTART);
2615 #else
2616 r = android_close (fd) == 0 || errno == EINTR ? 0 : -1;
2617 #define POSIX_CLOSE_RESTART 1
2618 #endif
2619
2620 if (r == 0)
2621 return r;
2622 if (!POSIX_CLOSE_RESTART || errno != EINTR)
2623 {
2624 eassert (errno != EBADF || fd < 0);
2625 return errno == EINPROGRESS ? 0 : r;
2626 }
2627 }
2628 }
2629
2630
2631
2632
2633 FILE *
2634 emacs_fdopen (int fd, const char *mode)
2635 {
2636 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2637 return fdopen (fd, mode);
2638 #else
2639 return android_fdopen (fd, mode);
2640 #endif
2641 }
2642
2643
2644
2645
2646
2647 int
2648 emacs_fclose (FILE *stream)
2649 {
2650 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2651 return fclose (stream);
2652 #else
2653 return android_fclose (stream);
2654 #endif
2655 }
2656
2657
2658
2659
2660
2661 int
2662 emacs_unlink (const char *name)
2663 {
2664 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2665 return unlink (name);
2666 #else
2667 return android_unlink (name);
2668 #endif
2669 }
2670
2671 int
2672 emacs_symlink (const char *target, const char *linkname)
2673 {
2674 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2675 return symlink (target, linkname);
2676 #else
2677 return android_symlink (target, linkname);
2678 #endif
2679 }
2680
2681 int
2682 emacs_rmdir (const char *dirname)
2683 {
2684 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2685 return rmdir (dirname);
2686 #else
2687 return android_rmdir (dirname);
2688 #endif
2689 }
2690
2691 int
2692 emacs_mkdir (const char *dirname, mode_t mode)
2693 {
2694 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2695 return mkdir (dirname, mode);
2696 #else
2697 return android_mkdir (dirname, mode);
2698 #endif
2699 }
2700
2701 int
2702 emacs_renameat_noreplace (int srcfd, const char *src,
2703 int dstfd, const char *dst)
2704 {
2705 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2706 return renameat_noreplace (srcfd, src, dstfd, dst);
2707 #else
2708 return android_renameat_noreplace (srcfd, src, dstfd, dst);
2709 #endif
2710 }
2711
2712 int
2713 emacs_rename (const char *src, const char *dst)
2714 {
2715 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2716 return rename (src, dst);
2717 #else
2718 return android_rename (src, dst);
2719 #endif
2720 }
2721
2722 int
2723 emacs_fchmodat (int fd, const char *path, mode_t mode, int flags)
2724 {
2725 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2726 return fchmodat (fd, path, mode, flags);
2727 #else
2728 return android_fchmodat (fd, path, mode, flags);
2729 #endif
2730 }
2731
2732
2733
2734
2735
2736
2737
2738
2739 #ifndef MAX_RW_COUNT
2740 #define MAX_RW_COUNT (INT_MAX >> 18 << 18)
2741 #endif
2742
2743
2744 #ifndef SSIZE_MAX
2745 # define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
2746 #endif
2747 verify (MAX_RW_COUNT <= PTRDIFF_MAX);
2748 verify (MAX_RW_COUNT <= SIZE_MAX);
2749 verify (MAX_RW_COUNT <= SSIZE_MAX);
2750
2751 #ifdef WINDOWSNT
2752
2753
2754
2755 verify (MAX_RW_COUNT <= INT_MAX);
2756 verify (MAX_RW_COUNT <= UINT_MAX);
2757 #endif
2758
2759
2760
2761
2762
2763
2764 static ptrdiff_t
2765 emacs_intr_read (int fd, void *buf, ptrdiff_t nbyte, bool interruptible)
2766 {
2767
2768 eassert (nbyte <= MAX_RW_COUNT);
2769
2770 ssize_t result;
2771
2772 do
2773 {
2774 if (interruptible)
2775 maybe_quit ();
2776 result = read (fd, buf, nbyte);
2777 }
2778 while (result < 0 && errno == EINTR);
2779
2780 return result;
2781 }
2782
2783
2784
2785
2786
2787 ptrdiff_t
2788 emacs_read (int fd, void *buf, ptrdiff_t nbyte)
2789 {
2790 return emacs_intr_read (fd, buf, nbyte, false);
2791 }
2792
2793
2794 ptrdiff_t
2795 emacs_read_quit (int fd, void *buf, ptrdiff_t nbyte)
2796 {
2797 return emacs_intr_read (fd, buf, nbyte, true);
2798 }
2799
2800
2801
2802
2803
2804
2805
2806 static ptrdiff_t
2807 emacs_full_write (int fd, char const *buf, ptrdiff_t nbyte,
2808 int interruptible)
2809 {
2810 ptrdiff_t bytes_written = 0;
2811
2812 while (nbyte > 0)
2813 {
2814 ssize_t n = write (fd, buf, min (nbyte, MAX_RW_COUNT));
2815
2816 if (n < 0)
2817 {
2818 if (errno != EINTR)
2819 break;
2820
2821 if (interruptible)
2822 {
2823 if (0 < interruptible)
2824 maybe_quit ();
2825 if (pending_signals)
2826 process_pending_signals ();
2827 }
2828 }
2829 else
2830 {
2831 buf += n;
2832 nbyte -= n;
2833 bytes_written += n;
2834 }
2835 }
2836
2837 return bytes_written;
2838 }
2839
2840
2841
2842
2843
2844 ptrdiff_t
2845 emacs_write (int fd, void const *buf, ptrdiff_t nbyte)
2846 {
2847 return emacs_full_write (fd, buf, nbyte, 0);
2848 }
2849
2850
2851 ptrdiff_t
2852 emacs_write_sig (int fd, void const *buf, ptrdiff_t nbyte)
2853 {
2854 return emacs_full_write (fd, buf, nbyte, -1);
2855 }
2856
2857
2858 ptrdiff_t
2859 emacs_write_quit (int fd, void const *buf, ptrdiff_t nbyte)
2860 {
2861 return emacs_full_write (fd, buf, nbyte, 1);
2862 }
2863
2864
2865
2866
2867 void
2868 emacs_perror (char const *message)
2869 {
2870 int err = errno;
2871 char const *error_string = emacs_strerror (err);
2872 char const *command = (initial_argv && initial_argv[0]
2873 ? initial_argv[0] : "emacs");
2874
2875
2876 char buf[min (PIPE_BUF, MAX_ALLOCA)];
2877 int nbytes = snprintf (buf, sizeof buf, "%s: %s: %s\n",
2878 command, message, error_string);
2879 if (0 <= nbytes && nbytes < sizeof buf)
2880 emacs_write (STDERR_FILENO, buf, nbytes);
2881 else
2882 {
2883 emacs_write (STDERR_FILENO, command, strlen (command));
2884 emacs_write (STDERR_FILENO, ": ", 2);
2885 emacs_write (STDERR_FILENO, message, strlen (message));
2886 emacs_write (STDERR_FILENO, ": ", 2);
2887 emacs_write (STDERR_FILENO, error_string, strlen (error_string));
2888 emacs_write (STDERR_FILENO, "\n", 1);
2889 }
2890 errno = err;
2891 }
2892
2893
2894
2895
2896
2897 int
2898 renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst)
2899 {
2900 #if HAVE_RENAMEAT2 && defined RENAME_NOREPLACE
2901 return renameat2 (srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2902 #elif defined SYS_renameat2 && defined RENAME_NOREPLACE
2903
2904 return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2905 #elif defined RENAME_EXCL
2906 return renameatx_np (srcfd, src, dstfd, dst, RENAME_EXCL);
2907 #else
2908 # ifdef WINDOWSNT
2909 if (srcfd == AT_FDCWD && dstfd == AT_FDCWD)
2910 return sys_rename_replace (src, dst, 0);
2911 # endif
2912 errno = ENOSYS;
2913 return -1;
2914 #endif
2915 }
2916
2917
2918
2919 char const *
2920 safe_strsignal (int code)
2921 {
2922 char const *signame = sigdescr_np (code);
2923
2924 if (! signame)
2925 signame = "Unknown signal";
2926
2927 return signame;
2928 }
2929
2930
2931
2932
2933 static FILE *
2934 errstream (void)
2935 {
2936 FILE *err = buferr;
2937 if (!err)
2938 return stderr;
2939 fflush_unlocked (stderr);
2940 return err;
2941 }
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952 void
2953 errputc (int c)
2954 {
2955 fputc_unlocked (c, errstream ());
2956
2957 #ifdef WINDOWSNT
2958
2959
2960 if (c == '\n')
2961 fflush_unlocked (stderr);
2962 #endif
2963 }
2964
2965 void
2966 errwrite (void const *buf, ptrdiff_t nbuf)
2967 {
2968 fwrite_unlocked (buf, 1, nbuf, errstream ());
2969 }
2970
2971
2972
2973 void
2974 close_output_streams (void)
2975 {
2976
2977
2978
2979 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2980 fflush (stderr);
2981 fflush (stdout);
2982 return;
2983 #endif
2984
2985 if (close_stream (stdout) != 0)
2986 {
2987 emacs_perror ("Write error to standard output");
2988 _exit (EXIT_FAILURE);
2989 }
2990
2991
2992
2993 bool err = buferr && (fflush (buferr) != 0 || ferror (buferr));
2994 if (err | (ADDRESS_SANITIZER
2995 ? fflush (stderr) != 0 || ferror (stderr)
2996 : close_stream (stderr) != 0))
2997 _exit (EXIT_FAILURE);
2998 }
2999
3000 #ifndef DOS_NT
3001
3002 int
3003 serial_open (Lisp_Object port)
3004 {
3005 int fd = emacs_open (SSDATA (port), O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
3006 if (fd < 0)
3007 report_file_error ("Opening serial port", port);
3008 #ifdef TIOCEXCL
3009 ioctl (fd, TIOCEXCL, (char *) 0);
3010 #endif
3011
3012 return fd;
3013 }
3014
3015 #if !defined (HAVE_CFMAKERAW)
3016
3017
3018 static void
3019 cfmakeraw (struct termios *termios_p)
3020 {
3021 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
3022 termios_p->c_oflag &= ~OPOST;
3023 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
3024 termios_p->c_cflag &= ~(CSIZE|PARENB);
3025 termios_p->c_cflag |= CS8;
3026 }
3027 #endif
3028
3029 #if !defined (HAVE_CFSETSPEED)
3030
3031 static int
3032 cfsetspeed (struct termios *termios_p, speed_t vitesse)
3033 {
3034 return (cfsetispeed (termios_p, vitesse)
3035 + cfsetospeed (termios_p, vitesse));
3036 }
3037 #endif
3038
3039
3040
3041 struct speed_struct
3042 {
3043 speed_t value;
3044 speed_t internal;
3045 };
3046
3047 static const struct speed_struct speeds[] =
3048 {
3049 #ifdef B0
3050 { 0, B0 },
3051 #endif
3052 #ifdef B50
3053 { 50, B50 },
3054 #endif
3055 #ifdef B75
3056 { 75, B75 },
3057 #endif
3058 #ifdef B110
3059 { 110, B110 },
3060 #endif
3061 #ifdef B134
3062 { 134, B134 },
3063 #endif
3064 #ifdef B150
3065 { 150, B150 },
3066 #endif
3067 #ifndef HAVE_TINY_SPEED_T
3068 #ifdef B200
3069 { 200, B200 },
3070 #endif
3071 #ifdef B300
3072 { 300, B300 },
3073 #endif
3074 #ifdef B600
3075 { 600, B600 },
3076 #endif
3077 #ifdef B1200
3078 { 1200, B1200 },
3079 #endif
3080 #ifdef B1200
3081 { 1200, B1200 },
3082 #endif
3083 #ifdef B1800
3084 { 1800, B1800 },
3085 #endif
3086 #ifdef B2400
3087 { 2400, B2400 },
3088 #endif
3089 #ifdef B4800
3090 { 4800, B4800 },
3091 #endif
3092 #ifdef B9600
3093 { 9600, B9600 },
3094 #endif
3095 #ifdef B19200
3096 { 19200, B19200 },
3097 #endif
3098 #ifdef B38400
3099 { 38400, B38400 },
3100 #endif
3101 #ifdef B57600
3102 { 57600, B57600 },
3103 #endif
3104 #ifdef B76800
3105 { 76800, B76800 },
3106 #endif
3107 #ifdef B115200
3108 { 115200, B115200 },
3109 #endif
3110 #ifdef B153600
3111 { 153600, B153600 },
3112 #endif
3113 #ifdef B230400
3114 { 230400, B230400 },
3115 #endif
3116 #ifdef B307200
3117 { 307200, B307200 },
3118 #endif
3119 #ifdef B460800
3120 { 460800, B460800 },
3121 #endif
3122 #ifdef B500000
3123 { 500000, B500000 },
3124 #endif
3125 #ifdef B576000
3126 { 576000, B576000 },
3127 #endif
3128 #ifdef B921600
3129 { 921600, B921600 },
3130 #endif
3131 #ifdef B1000000
3132 { 1000000, B1000000 },
3133 #endif
3134 #ifdef B1152000
3135 { 1152000, B1152000 },
3136 #endif
3137 #ifdef B1500000
3138 { 1500000, B1500000 },
3139 #endif
3140 #ifdef B2000000
3141 { 2000000, B2000000 },
3142 #endif
3143 #ifdef B2500000
3144 { 2500000, B2500000 },
3145 #endif
3146 #ifdef B3000000
3147 { 3000000, B3000000 },
3148 #endif
3149 #ifdef B3500000
3150 { 3500000, B3500000 },
3151 #endif
3152 #ifdef B4000000
3153 { 4000000, B4000000 },
3154 #endif
3155 #endif
3156 };
3157
3158
3159
3160 static speed_t
3161 convert_speed (speed_t speed)
3162 {
3163 for (size_t i = 0; i < sizeof speeds / sizeof speeds[0]; i++)
3164 {
3165 if (speed == speeds[i].internal)
3166 return speed;
3167 else if (speed == speeds[i].value)
3168 return speeds[i].internal;
3169 }
3170 return speed;
3171 }
3172
3173
3174 void
3175 serial_configure (struct Lisp_Process *p,
3176 Lisp_Object contact)
3177 {
3178 Lisp_Object childp2 = Qnil;
3179 Lisp_Object tem = Qnil;
3180 struct termios attr;
3181 int err;
3182 char summary[4] = "???";
3183
3184 childp2 = Fcopy_sequence (p->childp);
3185
3186
3187 err = tcgetattr (p->outfd, &attr);
3188 if (err != 0)
3189 report_file_error ("Failed tcgetattr", Qnil);
3190 cfmakeraw (&attr);
3191 #if defined (CLOCAL)
3192 attr.c_cflag |= CLOCAL;
3193 #endif
3194 #if defined (CREAD)
3195 attr.c_cflag |= CREAD;
3196 #endif
3197
3198
3199 if (!NILP (plist_member (contact, QCspeed)))
3200 tem = plist_get (contact, QCspeed);
3201 else
3202 tem = plist_get (p->childp, QCspeed);
3203 CHECK_FIXNUM (tem);
3204 err = cfsetspeed (&attr, convert_speed (XFIXNUM (tem)));
3205 if (err != 0)
3206 report_file_error ("Failed cfsetspeed", tem);
3207 childp2 = plist_put (childp2, QCspeed, tem);
3208
3209
3210 if (!NILP (plist_member (contact, QCbytesize)))
3211 tem = plist_get (contact, QCbytesize);
3212 else
3213 tem = plist_get (p->childp, QCbytesize);
3214 if (NILP (tem))
3215 tem = make_fixnum (8);
3216 CHECK_FIXNUM (tem);
3217 if (XFIXNUM (tem) != 7 && XFIXNUM (tem) != 8)
3218 error (":bytesize must be nil (8), 7, or 8");
3219 summary[0] = XFIXNUM (tem) + '0';
3220 #if defined (CSIZE) && defined (CS7) && defined (CS8)
3221 attr.c_cflag &= ~CSIZE;
3222 attr.c_cflag |= ((XFIXNUM (tem) == 7) ? CS7 : CS8);
3223 #else
3224
3225 if (XFIXNUM (tem) != 8)
3226 error ("Bytesize cannot be changed");
3227 #endif
3228 childp2 = plist_put (childp2, QCbytesize, tem);
3229
3230
3231 if (!NILP (plist_member (contact, QCparity)))
3232 tem = plist_get (contact, QCparity);
3233 else
3234 tem = plist_get (p->childp, QCparity);
3235 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
3236 error (":parity must be nil (no parity), `even', or `odd'");
3237 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
3238 attr.c_cflag &= ~(PARENB | PARODD);
3239 attr.c_iflag &= ~(IGNPAR | INPCK);
3240 if (NILP (tem))
3241 {
3242 summary[1] = 'N';
3243 }
3244 else if (EQ (tem, Qeven))
3245 {
3246 summary[1] = 'E';
3247 attr.c_cflag |= PARENB;
3248 attr.c_iflag |= (IGNPAR | INPCK);
3249 }
3250 else if (EQ (tem, Qodd))
3251 {
3252 summary[1] = 'O';
3253 attr.c_cflag |= (PARENB | PARODD);
3254 attr.c_iflag |= (IGNPAR | INPCK);
3255 }
3256 #else
3257
3258 if (!NILP (tem))
3259 error ("Parity cannot be configured");
3260 #endif
3261 childp2 = plist_put (childp2, QCparity, tem);
3262
3263
3264 if (!NILP (plist_member (contact, QCstopbits)))
3265 tem = plist_get (contact, QCstopbits);
3266 else
3267 tem = plist_get (p->childp, QCstopbits);
3268 if (NILP (tem))
3269 tem = make_fixnum (1);
3270 CHECK_FIXNUM (tem);
3271 if (XFIXNUM (tem) != 1 && XFIXNUM (tem) != 2)
3272 error (":stopbits must be nil (1 stopbit), 1, or 2");
3273 summary[2] = XFIXNUM (tem) + '0';
3274 #if defined (CSTOPB)
3275 attr.c_cflag &= ~CSTOPB;
3276 if (XFIXNUM (tem) == 2)
3277 attr.c_cflag |= CSTOPB;
3278 #else
3279
3280 if (XFIXNUM (tem) != 1)
3281 error ("Stopbits cannot be configured");
3282 #endif
3283 childp2 = plist_put (childp2, QCstopbits, tem);
3284
3285
3286 if (!NILP (plist_member (contact, QCflowcontrol)))
3287 tem = plist_get (contact, QCflowcontrol);
3288 else
3289 tem = plist_get (p->childp, QCflowcontrol);
3290 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
3291 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
3292 #if defined (CRTSCTS)
3293 attr.c_cflag &= ~CRTSCTS;
3294 #endif
3295 #if defined (CNEW_RTSCTS)
3296 attr.c_cflag &= ~CNEW_RTSCTS;
3297 #endif
3298 #if defined (IXON) && defined (IXOFF)
3299 attr.c_iflag &= ~(IXON | IXOFF);
3300 #endif
3301 if (NILP (tem))
3302 {
3303
3304 }
3305 else if (EQ (tem, Qhw))
3306 {
3307 #if defined (CRTSCTS)
3308 attr.c_cflag |= CRTSCTS;
3309 #elif defined (CNEW_RTSCTS)
3310 attr.c_cflag |= CNEW_RTSCTS;
3311 #else
3312 error ("Hardware flowcontrol (RTS/CTS) not supported");
3313 #endif
3314 }
3315 else if (EQ (tem, Qsw))
3316 {
3317 #if defined (IXON) && defined (IXOFF)
3318 attr.c_iflag |= (IXON | IXOFF);
3319 #else
3320 error ("Software flowcontrol (XON/XOFF) not supported");
3321 #endif
3322 }
3323 childp2 = plist_put (childp2, QCflowcontrol, tem);
3324
3325
3326 err = tcsetattr (p->outfd, TCSANOW, &attr);
3327 if (err != 0)
3328 report_file_error ("Failed tcsetattr", Qnil);
3329
3330 childp2 = plist_put (childp2, QCsummary, build_string (summary));
3331 pset_childp (p, childp2);
3332 }
3333 #endif
3334
3335
3336
3337 #ifdef HAVE_PROCFS
3338
3339
3340
3341 Lisp_Object
3342 list_system_processes (void)
3343 {
3344 Lisp_Object procdir, match, proclist, next;
3345 Lisp_Object tail;
3346
3347
3348
3349
3350 procdir = build_string ("/proc");
3351 match = build_string ("[0-9]+");
3352 proclist = directory_files_internal (procdir, Qnil, match, Qt,
3353 false, Qnil, Qnil);
3354
3355
3356
3357 for (tail = proclist; CONSP (tail); tail = next)
3358 {
3359 next = XCDR (tail);
3360 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
3361 }
3362
3363
3364
3365 proclist = Fnreverse (proclist);
3366 return proclist;
3367 }
3368
3369 #elif defined DARWIN_OS || defined __FreeBSD__ || defined __OpenBSD__
3370
3371 Lisp_Object
3372 list_system_processes (void)
3373 {
3374 #ifdef DARWIN_OS
3375 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
3376 #elif defined __OpenBSD__
3377 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0,
3378 sizeof (struct kinfo_proc), 4096};
3379 #else
3380 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
3381 #endif
3382 size_t len;
3383 size_t mibsize = sizeof mib / sizeof mib[0];
3384 struct kinfo_proc *procs;
3385 size_t i;
3386
3387 Lisp_Object proclist = Qnil;
3388
3389 if (sysctl (mib, mibsize, NULL, &len, NULL, 0) != 0 || len == 0)
3390 return proclist;
3391
3392 procs = xmalloc (len);
3393 if (sysctl (mib, mibsize, procs, &len, NULL, 0) != 0 || len == 0)
3394 {
3395 xfree (procs);
3396 return proclist;
3397 }
3398
3399 len /= sizeof procs[0];
3400 for (i = 0; i < len; i++)
3401 {
3402 #ifdef DARWIN_OS
3403 proclist = Fcons (INT_TO_INTEGER (procs[i].kp_proc.p_pid), proclist);
3404 #elif defined __OpenBSD__
3405 proclist = Fcons (INT_TO_INTEGER (procs[i].p_pid), proclist);
3406 #else
3407 proclist = Fcons (INT_TO_INTEGER (procs[i].ki_pid), proclist);
3408 #endif
3409 }
3410
3411 xfree (procs);
3412
3413 return proclist;
3414 }
3415
3416
3417
3418
3419 #elif !defined (WINDOWSNT) && !defined (MSDOS) && !defined (HAIKU)
3420
3421 Lisp_Object
3422 list_system_processes (void)
3423 {
3424 return Qnil;
3425 }
3426
3427 #endif
3428
3429 #if (HAVE_GETRUSAGE \
3430 || defined __FreeBSD__ || defined DARWIN_OS || defined __OpenBSD__)
3431
3432 static Lisp_Object
3433 make_lisp_s_us (time_t s, long us)
3434 {
3435 Lisp_Object sec = make_int (s);
3436 Lisp_Object usec = make_fixnum (us);
3437 Lisp_Object hz = make_fixnum (1000000);
3438 Lisp_Object ticks = CALLN (Fplus, CALLN (Ftimes, sec, hz), usec);
3439 return Ftime_convert (Fcons (ticks, hz), Qnil);
3440 }
3441
3442 #endif
3443
3444 #if defined __FreeBSD__ || defined DARWIN_OS
3445
3446 static Lisp_Object
3447 make_lisp_timeval (struct timeval t)
3448 {
3449 return make_lisp_s_us (t.tv_sec, t.tv_usec);
3450 }
3451
3452 #endif
3453
3454 #if defined (GNU_LINUX) || defined (CYGWIN)
3455
3456 static Lisp_Object
3457 time_from_jiffies (unsigned long long ticks, Lisp_Object hz, Lisp_Object form)
3458 {
3459 return Ftime_convert (Fcons (make_uint (ticks), hz), form);
3460 }
3461
3462 static Lisp_Object
3463 put_jiffies (Lisp_Object attrs, Lisp_Object propname,
3464 unsigned long long ticks, Lisp_Object hz)
3465 {
3466 return Fcons (Fcons (propname, time_from_jiffies (ticks, hz, Qnil)), attrs);
3467 }
3468
3469 static Lisp_Object
3470 get_up_time (void)
3471 {
3472 FILE *fup;
3473 Lisp_Object up = Qnil;
3474
3475 block_input ();
3476 fup = emacs_fopen ("/proc/uptime", "r");
3477
3478 if (fup)
3479 {
3480 unsigned long long upsec;
3481 EMACS_UINT upfrac;
3482 int upfrac_start, upfrac_end;
3483
3484 if (fscanf (fup, "%llu.%n%"pI"u%n",
3485 &upsec, &upfrac_start, &upfrac, &upfrac_end)
3486 == 2)
3487 {
3488 EMACS_INT hz = 1;
3489 for (int i = upfrac_start; i < upfrac_end; i++)
3490 hz *= 10;
3491 Lisp_Object sec = make_uint (upsec);
3492 Lisp_Object subsec = Fcons (make_fixnum (upfrac), make_fixnum (hz));
3493 up = Ftime_add (sec, subsec);
3494 }
3495 fclose (fup);
3496 }
3497 unblock_input ();
3498
3499 return up;
3500 }
3501
3502 # ifdef GNU_LINUX
3503 #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
3504 #define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
3505
3506 static Lisp_Object
3507 procfs_ttyname (int rdev)
3508 {
3509 FILE *fdev;
3510 char name[PATH_MAX];
3511
3512 block_input ();
3513 fdev = emacs_fopen ("/proc/tty/drivers", "r");
3514 name[0] = 0;
3515
3516 if (fdev)
3517 {
3518 unsigned major;
3519 unsigned long minor_beg, minor_end;
3520 char minor[25];
3521 char *endp;
3522
3523 for (; !feof (fdev) && !ferror (fdev); name[0] = 0)
3524 {
3525 if (fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) >= 3
3526 && major == MAJOR (rdev))
3527 {
3528 minor_beg = strtoul (minor, &endp, 0);
3529 if (*endp == '\0')
3530 minor_end = minor_beg;
3531 else if (*endp == '-')
3532 minor_end = strtoul (endp + 1, &endp, 0);
3533 else
3534 continue;
3535
3536 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
3537 {
3538 sprintf (name + strlen (name), "%u", MINOR (rdev));
3539 break;
3540 }
3541 }
3542 }
3543 fclose (fdev);
3544 }
3545 unblock_input ();
3546 return build_string (name);
3547 }
3548 # endif
3549
3550 static uintmax_t
3551 procfs_get_total_memory (void)
3552 {
3553 FILE *fmem;
3554 uintmax_t retval = 2 * 1024 * 1024;
3555 int c;
3556
3557 block_input ();
3558 fmem = emacs_fopen ("/proc/meminfo", "r");
3559
3560 if (fmem)
3561 {
3562 uintmax_t entry_value;
3563 bool done;
3564
3565 do
3566 switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value))
3567 {
3568 case 1:
3569 retval = entry_value;
3570 done = 1;
3571 break;
3572
3573 case 0:
3574 while ((c = getc (fmem)) != EOF && c != '\n')
3575 continue;
3576 done = c == EOF;
3577 break;
3578
3579 default:
3580 done = 1;
3581 break;
3582 }
3583 while (!done);
3584
3585 fclose (fmem);
3586 }
3587 unblock_input ();
3588 return retval;
3589 }
3590
3591 Lisp_Object
3592 system_process_attributes (Lisp_Object pid)
3593 {
3594 char procfn[PATH_MAX], fn[PATH_MAX];
3595 struct stat st;
3596 struct passwd *pw;
3597 struct group *gr;
3598 long clocks_per_sec;
3599 char *procfn_end;
3600 char procbuf[1025], *p, *q UNINIT;
3601 int fd;
3602 ssize_t nread;
3603 static char const default_cmd[] = "???";
3604 const char *cmd = default_cmd;
3605 int cmdsize = sizeof default_cmd - 1;
3606 char *cmdline = NULL;
3607 ptrdiff_t cmdline_size;
3608 char c;
3609 intmax_t proc_id;
3610 int ppid, pgrp, sess, tty, tpgid, thcount;
3611 uid_t uid;
3612 gid_t gid;
3613 unsigned long long u_time, s_time, cutime, cstime, start;
3614 long priority, niceness, rss;
3615 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
3616 double pcpu, pmem;
3617 Lisp_Object attrs = Qnil;
3618 Lisp_Object decoded_cmd;
3619
3620 CHECK_NUMBER (pid);
3621 CONS_TO_INTEGER (pid, pid_t, proc_id);
3622 sprintf (procfn, "/proc/%"PRIdMAX, proc_id);
3623 if (stat (procfn, &st) < 0)
3624 return attrs;
3625
3626
3627 uid = st.st_uid;
3628 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (uid)), attrs);
3629 block_input ();
3630 pw = getpwuid (uid);
3631 unblock_input ();
3632 if (pw)
3633 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3634
3635 gid = st.st_gid;
3636 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (gid)), attrs);
3637 block_input ();
3638 gr = getgrgid (gid);
3639 unblock_input ();
3640 if (gr)
3641 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3642
3643 specpdl_ref count = SPECPDL_INDEX ();
3644 strcpy (fn, procfn);
3645 procfn_end = fn + strlen (fn);
3646 strcpy (procfn_end, "/stat");
3647 fd = emacs_open (fn, O_RDONLY, 0);
3648 if (fd < 0)
3649 nread = 0;
3650 else
3651 {
3652 record_unwind_protect_int (close_file_unwind, fd);
3653 nread = emacs_read_quit (fd, procbuf, sizeof procbuf - 1);
3654 }
3655 if (0 < nread)
3656 {
3657 procbuf[nread] = '\0';
3658 p = procbuf;
3659
3660 p = strchr (p, '(');
3661 if (p != NULL)
3662 {
3663 q = strrchr (p + 1, ')');
3664
3665 if (q != NULL)
3666 {
3667 cmd = p + 1;
3668 cmdsize = q - cmd;
3669 }
3670 }
3671 else
3672 q = NULL;
3673
3674 AUTO_STRING_WITH_LEN (cmd_str, cmd, cmdsize);
3675 decoded_cmd = code_convert_string_norecord (cmd_str,
3676 Vlocale_coding_system, 0);
3677 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3678
3679
3680
3681 if (q
3682 && (sscanf (q + 2, ("%c %d %d %d %d %d %*u %lu %lu %lu %lu "
3683 "%llu %llu %llu %llu %ld %ld %d %*d %llu %lu %ld"),
3684 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
3685 &minflt, &cminflt, &majflt, &cmajflt,
3686 &u_time, &s_time, &cutime, &cstime,
3687 &priority, &niceness, &thcount, &start, &vsize, &rss)
3688 == 20))
3689 {
3690 char state_str[2];
3691 state_str[0] = c;
3692 state_str[1] = '\0';
3693 attrs = Fcons (Fcons (Qstate, build_string (state_str)), attrs);
3694 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (ppid)), attrs);
3695 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pgrp)), attrs);
3696 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (sess)), attrs);
3697 # ifdef GNU_LINUX
3698 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
3699 # endif
3700 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (tpgid)), attrs);
3701 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (minflt)), attrs);
3702 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (majflt)), attrs);
3703 attrs = Fcons (Fcons (Qcminflt, INT_TO_INTEGER (cminflt)), attrs);
3704 attrs = Fcons (Fcons (Qcmajflt, INT_TO_INTEGER (cmajflt)), attrs);
3705
3706 clocks_per_sec = sysconf (_SC_CLK_TCK);
3707 if (0 < clocks_per_sec)
3708 {
3709 Lisp_Object hz = make_int (clocks_per_sec);
3710 attrs = put_jiffies (attrs, Qutime, u_time, hz);
3711 attrs = put_jiffies (attrs, Qstime, s_time, hz);
3712 attrs = put_jiffies (attrs, Qtime, s_time + u_time, hz);
3713 attrs = put_jiffies (attrs, Qcutime, cutime, hz);
3714 attrs = put_jiffies (attrs, Qcstime, cstime, hz);
3715 attrs = put_jiffies (attrs, Qctime, cstime + cutime, hz);
3716
3717 Lisp_Object uptime = get_up_time ();
3718 if (!NILP (uptime))
3719 {
3720 Lisp_Object now = Ftime_convert (Qnil, hz);
3721 Lisp_Object boot = Ftime_subtract (now, uptime);
3722 Lisp_Object tstart = time_from_jiffies (start, hz, hz);
3723 Lisp_Object lstart =
3724 Ftime_convert (Ftime_add (boot, tstart), Qnil);
3725 attrs = Fcons (Fcons (Qstart, lstart), attrs);
3726 Lisp_Object etime =
3727 Ftime_convert (Ftime_subtract (uptime, tstart), Qnil);
3728 attrs = Fcons (Fcons (Qetime, etime), attrs);
3729 pcpu = (100.0 * (s_time + u_time)
3730 / (clocks_per_sec * float_time (etime)));
3731 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
3732 }
3733 }
3734
3735 attrs = Fcons (Fcons (Qpri, make_fixnum (priority)), attrs);
3736 attrs = Fcons (Fcons (Qnice, make_fixnum (niceness)), attrs);
3737 attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (thcount)), attrs);
3738 attrs = Fcons (Fcons (Qvsize, INT_TO_INTEGER (vsize / 1024)), attrs);
3739 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (4 * rss)), attrs);
3740 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
3741 if (pmem > 100)
3742 pmem = 100;
3743 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
3744 }
3745 }
3746 unbind_to (count, Qnil);
3747
3748 # ifdef CYGWIN
3749
3750 strcpy (procfn_end, "/ctty");
3751 fd = emacs_open (fn, O_RDONLY, 0);
3752 if (fd < 0)
3753 nread = 0;
3754 else
3755 {
3756 record_unwind_protect_int (close_file_unwind, fd);
3757 nread = emacs_read_quit (fd, procbuf, sizeof procbuf);
3758 }
3759
3760 if (0 < nread && procbuf[nread - 1] == '\n')
3761 procbuf[nread - 1] = '\0';
3762 else
3763 procbuf[0] = '\0';
3764 attrs = Fcons (Fcons (Qttname, build_string (procbuf)), attrs);
3765 unbind_to (count, Qnil);
3766 # endif
3767
3768
3769 strcpy (procfn_end, "/cmdline");
3770 fd = emacs_open (fn, O_RDONLY, 0);
3771 if (fd >= 0)
3772 {
3773 ptrdiff_t readsize, nread_incr;
3774 record_unwind_protect_int (close_file_unwind, fd);
3775 record_unwind_protect_nothing ();
3776 nread = cmdline_size = 0;
3777
3778 do
3779 {
3780 cmdline = xpalloc (cmdline, &cmdline_size, 2, STRING_BYTES_BOUND, 1);
3781 set_unwind_protect_ptr (specpdl_ref_add (count, 1), xfree, cmdline);
3782
3783
3784 readsize = (cmdline_size >> 1) - nread;
3785
3786 nread_incr = emacs_read_quit (fd, cmdline + nread, readsize);
3787 nread += max (0, nread_incr);
3788 }
3789 while (nread_incr == readsize);
3790
3791 if (nread)
3792 {
3793
3794 for (p = cmdline + nread; cmdline < p && !p[-1]; p--)
3795 continue;
3796
3797
3798 q = cmdline + cmdline_size;
3799 while (cmdline < p)
3800 {
3801 char c = *--p;
3802 *--q = c ? c : ' ';
3803 if (c_isspace (c) || c == '\\')
3804 *--q = '\\';
3805 }
3806
3807 nread = cmdline + cmdline_size - q;
3808 }
3809
3810 if (!nread)
3811 {
3812 nread = cmdsize + 2;
3813 cmdline_size = nread + 1;
3814 q = cmdline = xrealloc (cmdline, cmdline_size);
3815 set_unwind_protect_ptr (specpdl_ref_add (count, 1), xfree, cmdline);
3816 sprintf (cmdline, "[%.*s]", cmdsize, cmd);
3817 }
3818
3819 AUTO_STRING_WITH_LEN (cmd_str, q, nread);
3820 decoded_cmd = code_convert_string_norecord (cmd_str,
3821 Vlocale_coding_system, 0);
3822 unbind_to (count, Qnil);
3823 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3824 }
3825
3826 return attrs;
3827 }
3828
3829 #elif defined (SOLARIS2) && defined (HAVE_PROCFS)
3830
3831
3832
3833 #if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
3834 #define PROCFS_FILE_OFFSET_BITS_HACK 1
3835 #undef _FILE_OFFSET_BITS
3836 #else
3837 #define PROCFS_FILE_OFFSET_BITS_HACK 0
3838 #endif
3839
3840 #include <procfs.h>
3841
3842 #if PROCFS_FILE_OFFSET_BITS_HACK == 1
3843 #define _FILE_OFFSET_BITS 64
3844 #ifdef _FILE_OFFSET_BITS
3845 #endif
3846 #endif
3847
3848 Lisp_Object
3849 system_process_attributes (Lisp_Object pid)
3850 {
3851 char procfn[PATH_MAX], fn[PATH_MAX];
3852 struct stat st;
3853 struct passwd *pw;
3854 struct group *gr;
3855 char *procfn_end;
3856 struct psinfo pinfo;
3857 int fd;
3858 ssize_t nread;
3859 intmax_t proc_id;
3860 uid_t uid;
3861 gid_t gid;
3862 Lisp_Object attrs = Qnil;
3863 Lisp_Object decoded_cmd;
3864
3865 CHECK_NUMBER (pid);
3866 CONS_TO_INTEGER (pid, pid_t, proc_id);
3867 sprintf (procfn, "/proc/%"PRIdMAX, proc_id);
3868 if (stat (procfn, &st) < 0)
3869 return attrs;
3870
3871
3872 uid = st.st_uid;
3873 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (uid)), attrs);
3874 block_input ();
3875 pw = getpwuid (uid);
3876 unblock_input ();
3877 if (pw)
3878 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3879
3880 gid = st.st_gid;
3881 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (gid)), attrs);
3882 block_input ();
3883 gr = getgrgid (gid);
3884 unblock_input ();
3885 if (gr)
3886 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3887
3888 specpdl_ref count = SPECPDL_INDEX ();
3889 strcpy (fn, procfn);
3890 procfn_end = fn + strlen (fn);
3891 strcpy (procfn_end, "/psinfo");
3892 fd = emacs_open (fn, O_RDONLY, 0);
3893 if (fd < 0)
3894 nread = 0;
3895 else
3896 {
3897 record_unwind_protect_int (close_file_unwind, fd);
3898 nread = emacs_read_quit (fd, &pinfo, sizeof pinfo);
3899 }
3900
3901 if (nread == sizeof pinfo)
3902 {
3903 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (pinfo.pr_ppid)), attrs);
3904 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pinfo.pr_pgid)), attrs);
3905 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (pinfo.pr_sid)), attrs);
3906
3907 {
3908 char state_str[2];
3909 state_str[0] = pinfo.pr_lwp.pr_sname;
3910 state_str[1] = '\0';
3911 attrs = Fcons (Fcons (Qstate, build_string (state_str)), attrs);
3912 }
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931 attrs = Fcons (Fcons (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
3932 attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), attrs);
3933 attrs = Fcons (Fcons (Qpri, make_fixnum (pinfo.pr_lwp.pr_pri)), attrs);
3934 attrs = Fcons (Fcons (Qnice, make_fixnum (pinfo.pr_lwp.pr_nice)), attrs);
3935 attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (pinfo.pr_nlwp)), attrs);
3936
3937 attrs = Fcons (Fcons (Qstart, make_lisp_time (pinfo.pr_start)), attrs);
3938 attrs = Fcons (Fcons (Qvsize, INT_TO_INTEGER (pinfo.pr_size)), attrs);
3939 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (pinfo.pr_rssize)), attrs);
3940
3941
3942
3943 attrs = Fcons (Fcons (Qpcpu,
3944 make_float (100.0 / 0x8000 * pinfo.pr_pctcpu)),
3945 attrs);
3946 attrs = Fcons (Fcons (Qpmem,
3947 make_float (100.0 / 0x8000 * pinfo.pr_pctmem)),
3948 attrs);
3949
3950 AUTO_STRING (fname, pinfo.pr_fname);
3951 decoded_cmd = code_convert_string_norecord (fname,
3952 Vlocale_coding_system, 0);
3953 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3954 AUTO_STRING (psargs, pinfo.pr_psargs);
3955 decoded_cmd = code_convert_string_norecord (psargs,
3956 Vlocale_coding_system, 0);
3957 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3958 }
3959 return unbind_to (count, attrs);
3960 }
3961
3962 #elif defined __FreeBSD__
3963
3964 Lisp_Object
3965 system_process_attributes (Lisp_Object pid)
3966 {
3967 int proc_id;
3968 int pagesize = getpagesize ();
3969 unsigned long npages;
3970 int fscale;
3971 struct passwd *pw;
3972 struct group *gr;
3973 char *ttyname;
3974 size_t len;
3975 char args[MAXPATHLEN];
3976
3977 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
3978 struct kinfo_proc proc;
3979 size_t proclen = sizeof proc;
3980
3981 Lisp_Object attrs = Qnil;
3982 Lisp_Object decoded_comm;
3983
3984 CHECK_NUMBER (pid);
3985 CONS_TO_INTEGER (pid, int, proc_id);
3986 mib[3] = proc_id;
3987
3988 if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0 || proclen == 0)
3989 return attrs;
3990
3991 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (proc.ki_uid)), attrs);
3992
3993 block_input ();
3994 pw = getpwuid (proc.ki_uid);
3995 unblock_input ();
3996 if (pw)
3997 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3998
3999 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (proc.ki_svgid)), attrs);
4000
4001 block_input ();
4002 gr = getgrgid (proc.ki_svgid);
4003 unblock_input ();
4004 if (gr)
4005 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
4006
4007 AUTO_STRING (comm, proc.ki_comm);
4008 decoded_comm = code_convert_string_norecord (comm, Vlocale_coding_system, 0);
4009
4010 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
4011 {
4012 char state[2] = {'\0', '\0'};
4013 switch (proc.ki_stat)
4014 {
4015 case SRUN:
4016 state[0] = 'R';
4017 break;
4018
4019 case SSLEEP:
4020 state[0] = 'S';
4021 break;
4022
4023 case SLOCK:
4024 state[0] = 'D';
4025 break;
4026
4027 case SZOMB:
4028 state[0] = 'Z';
4029 break;
4030
4031 case SSTOP:
4032 state[0] = 'T';
4033 break;
4034 }
4035 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
4036 }
4037
4038 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (proc.ki_ppid)), attrs);
4039 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (proc.ki_pgid)), attrs);
4040 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (proc.ki_sid)), attrs);
4041
4042 block_input ();
4043 ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
4044 unblock_input ();
4045 if (ttyname)
4046 attrs = Fcons (Fcons (Qttname, build_string (ttyname)), attrs);
4047
4048 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.ki_tpgid)), attrs);
4049 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (proc.ki_rusage.ru_minflt)),
4050 attrs);
4051 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (proc.ki_rusage.ru_majflt)),
4052 attrs);
4053 attrs = Fcons (Fcons (Qcminflt, make_fixnum (proc.ki_rusage_ch.ru_minflt)), attrs);
4054 attrs = Fcons (Fcons (Qcmajflt, make_fixnum (proc.ki_rusage_ch.ru_majflt)), attrs);
4055
4056 Lisp_Object utime = make_lisp_timeval (proc.ki_rusage.ru_utime);
4057 attrs = Fcons (Fcons (Qutime, utime), attrs);
4058 Lisp_Object stime = make_lisp_timeval (proc.ki_rusage.ru_stime);
4059 attrs = Fcons (Fcons (Qstime, stime), attrs);
4060 attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
4061
4062 Lisp_Object cutime = make_lisp_timeval (proc.ki_rusage_ch.ru_utime);
4063 attrs = Fcons (Fcons (Qcutime, cutime), attrs);
4064 Lisp_Object cstime = make_lisp_timeval (proc.ki_rusage_ch.ru_stime);
4065 attrs = Fcons (Fcons (Qcstime, cstime), attrs);
4066 attrs = Fcons (Fcons (Qctime, Ftime_add (cutime, cstime)), attrs);
4067
4068 attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (proc.ki_numthreads)), attrs);
4069 attrs = Fcons (Fcons (Qpri, make_fixnum (proc.ki_pri.pri_native)), attrs);
4070 attrs = Fcons (Fcons (Qnice, make_fixnum (proc.ki_nice)), attrs);
4071 Lisp_Object start = make_lisp_timeval (proc.ki_start);
4072 attrs = Fcons (Fcons (Qstart, start), attrs);
4073 attrs = Fcons (Fcons (Qvsize, make_fixnum (proc.ki_size >> 10)), attrs);
4074 attrs = Fcons (Fcons (Qrss, make_fixnum (proc.ki_rssize * pagesize >> 10)),
4075 attrs);
4076
4077 Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
4078 Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
4079 attrs = Fcons (Fcons (Qetime, etime), attrs);
4080
4081 len = sizeof fscale;
4082 if (sysctlbyname ("kern.fscale", &fscale, &len, NULL, 0) == 0)
4083 {
4084 double pcpu;
4085 fixpt_t ccpu;
4086 len = sizeof ccpu;
4087 if (sysctlbyname ("kern.ccpu", &ccpu, &len, NULL, 0) == 0)
4088 {
4089 pcpu = (100.0 * proc.ki_pctcpu / fscale
4090 / (1 - exp (proc.ki_swtime * log ((double) ccpu / fscale))));
4091 attrs = Fcons (Fcons (Qpcpu, INT_TO_INTEGER (pcpu)), attrs);
4092 }
4093 }
4094
4095 len = sizeof npages;
4096 if (sysctlbyname ("hw.availpages", &npages, &len, NULL, 0) == 0)
4097 {
4098 double pmem = (proc.ki_flag & P_INMEM
4099 ? 100.0 * proc.ki_rssize / npages
4100 : 0);
4101 attrs = Fcons (Fcons (Qpmem, INT_TO_INTEGER (pmem)), attrs);
4102 }
4103
4104 mib[2] = KERN_PROC_ARGS;
4105 len = MAXPATHLEN;
4106 if (sysctl (mib, 4, args, &len, NULL, 0) == 0 && len != 0)
4107 {
4108 int i;
4109 for (i = 0; i < len; i++)
4110 {
4111 if (! args[i] && i < len - 1)
4112 args[i] = ' ';
4113 }
4114
4115 AUTO_STRING (comm, args);
4116 decoded_comm = code_convert_string_norecord (comm,
4117 Vlocale_coding_system, 0);
4118
4119 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
4120 }
4121
4122 return attrs;
4123 }
4124
4125 #elif defined __OpenBSD__
4126
4127 Lisp_Object
4128 system_process_attributes (Lisp_Object pid)
4129 {
4130 int proc_id, fscale, i;
4131 int pagesize = getpagesize ();
4132 int mib[6];
4133 size_t len;
4134 double pct;
4135 char *ttyname, args[ARG_MAX];
4136 struct kinfo_proc proc;
4137 struct passwd *pw;
4138 struct group *gr;
4139 struct uvmexp uvmexp;
4140
4141 Lisp_Object attrs = Qnil;
4142 Lisp_Object decoded_comm;
4143
4144 CHECK_NUMBER (pid);
4145 CONS_TO_INTEGER (pid, int, proc_id);
4146
4147 len = sizeof proc;
4148 mib[0] = CTL_KERN;
4149 mib[1] = KERN_PROC;
4150 mib[2] = KERN_PROC_PID;
4151 mib[3] = proc_id;
4152 mib[4] = len;
4153 mib[5] = 1;
4154 if (sysctl (mib, 6, &proc, &len, NULL, 0) != 0)
4155 return attrs;
4156
4157 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (proc.p_uid)), attrs);
4158
4159 block_input ();
4160 pw = getpwuid (proc.p_uid);
4161 unblock_input ();
4162 if (pw)
4163 attrs = Fcons (Fcons (Quser, build_string(pw->pw_name)), attrs);
4164
4165 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER(proc.p_svgid)), attrs);
4166
4167 block_input ();
4168 gr = getgrgid (proc.p_svgid);
4169 unblock_input ();
4170 if (gr)
4171 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
4172
4173 AUTO_STRING (comm, proc.p_comm);
4174 decoded_comm = code_convert_string_norecord (comm, Vlocale_coding_system, 0);
4175 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
4176
4177 {
4178 char state[2] = {'\0', '\0'};
4179 switch (proc.p_stat) {
4180 case SIDL:
4181 state[0] = 'I';
4182 break;
4183 case SRUN:
4184 state[0] = 'R';
4185 break;
4186 case SSLEEP:
4187 state[0] = 'S';
4188 break;
4189 case SSTOP:
4190 state[0] = 'T';
4191 break;
4192 case SZOMB:
4193 state[0] = 'Z';
4194 break;
4195 case SDEAD:
4196 state[0] = 'D';
4197 break;
4198 }
4199 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
4200 }
4201
4202 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (proc.p_ppid)), attrs);
4203 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (proc.p_gid)), attrs);
4204 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (proc.p_sid)), attrs);
4205
4206 block_input ();
4207 ttyname = proc.p_tdev == NODEV ? NULL : devname (proc.p_tdev, S_IFCHR);
4208 unblock_input ();
4209 if (ttyname)
4210 attrs = Fcons (Fcons (Qttname, build_string (ttyname)), attrs);
4211
4212 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.p_tpgid)), attrs);
4213 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (proc.p_uru_minflt)),
4214 attrs);
4215 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (proc.p_uru_majflt)),
4216 attrs);
4217
4218
4219
4220 Lisp_Object utime = make_lisp_s_us (proc.p_uutime_sec, proc.p_uutime_usec);
4221 attrs = Fcons (Fcons (Qutime, utime), attrs);
4222 Lisp_Object stime = make_lisp_s_us (proc.p_ustime_sec, proc.p_ustime_usec);
4223 attrs = Fcons (Fcons (Qstime, stime), attrs);
4224 attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
4225
4226 attrs = Fcons (Fcons (Qcutime, make_lisp_s_us (proc.p_uctime_sec,
4227 proc.p_uctime_usec)),
4228 attrs);
4229
4230
4231
4232 attrs = Fcons (Fcons (Qpri, make_fixnum (proc.p_priority)), attrs);
4233 attrs = Fcons (Fcons (Qnice, make_fixnum (proc.p_nice)), attrs);
4234
4235
4236
4237 attrs = Fcons (Fcons (Qstart, make_lisp_s_us (proc.p_ustart_sec,
4238 proc.p_ustart_usec)),
4239 attrs);
4240
4241 len = (proc.p_vm_tsize + proc.p_vm_dsize + proc.p_vm_ssize) * pagesize >> 10;
4242 attrs = Fcons (Fcons (Qvsize, make_fixnum (len)), attrs);
4243
4244 attrs = Fcons (Fcons (Qrss, make_fixnum (proc.p_vm_rssize * pagesize >> 10)),
4245 attrs);
4246
4247 Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
4248 Lisp_Object start = make_lisp_s_us (proc.p_ustart_sec,
4249 proc.p_ustart_usec);
4250 Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
4251 attrs = Fcons (Fcons (Qetime, etime), attrs);
4252
4253 len = sizeof (fscale);
4254 mib[0] = CTL_KERN;
4255 mib[1] = KERN_FSCALE;
4256 if (sysctl (mib, 2, &fscale, &len, NULL, 0) != -1)
4257 {
4258 pct = (double)proc.p_pctcpu / fscale * 100.0;
4259 attrs = Fcons (Fcons (Qpcpu, make_float (pct)), attrs);
4260 }
4261
4262 len = sizeof (uvmexp);
4263 mib[0] = CTL_VM;
4264 mib[1] = VM_UVMEXP;
4265 if (sysctl (mib, 2, &uvmexp, &len, NULL, 0) != -1)
4266 {
4267 pct = (100.0 * (double)proc.p_vm_rssize / uvmexp.npages);
4268 attrs = Fcons (Fcons (Qpmem, make_float (pct)), attrs);
4269 }
4270
4271 len = sizeof args;
4272 mib[0] = CTL_KERN;
4273 mib[1] = KERN_PROC_ARGS;
4274 mib[2] = proc_id;
4275 mib[3] = KERN_PROC_ARGV;
4276 if (sysctl (mib, 4, &args, &len, NULL, 0) == 0 && len != 0)
4277 {
4278 char **argv = (char**)args;
4279
4280
4281
4282
4283
4284 for (i = 0; argv[i] != NULL; ++i)
4285 {
4286 if (argv[i+1] != NULL)
4287 {
4288 len = strlen (argv[i]);
4289 argv[i][len] = ' ';
4290 }
4291 }
4292
4293 AUTO_STRING (comm, *argv);
4294 decoded_comm = code_convert_string_norecord (comm,
4295 Vlocale_coding_system, 0);
4296 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
4297 }
4298
4299 return attrs;
4300 }
4301
4302 #elif defined DARWIN_OS
4303
4304 #define HAVE_RUSAGE_INFO_CURRENT (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
4305 #define HAVE_PROC_PIDINFO (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
4306
4307 Lisp_Object
4308 system_process_attributes (Lisp_Object pid)
4309 {
4310 int proc_id, i;
4311 struct passwd *pw;
4312 struct group *gr;
4313 char *ttyname;
4314 struct timeval starttime;
4315 dev_t tdev;
4316 uid_t uid;
4317 gid_t gid;
4318
4319 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
4320 struct kinfo_proc proc;
4321 size_t len = sizeof proc;
4322
4323 Lisp_Object attrs = Qnil;
4324 Lisp_Object decoded_comm;
4325
4326 CHECK_NUMBER (pid);
4327 CONS_TO_INTEGER (pid, int, proc_id);
4328 mib[3] = proc_id;
4329
4330 if (sysctl (mib, 4, &proc, &len, NULL, 0) != 0 || len == 0)
4331 return attrs;
4332
4333 uid = proc.kp_eproc.e_ucred.cr_uid;
4334 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (uid)), attrs);
4335
4336 block_input ();
4337 pw = getpwuid (uid);
4338 unblock_input ();
4339 if (pw)
4340 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
4341
4342 gid = proc.kp_eproc.e_pcred.p_svgid;
4343 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (gid)), attrs);
4344
4345 block_input ();
4346 gr = getgrgid (gid);
4347 unblock_input ();
4348 if (gr)
4349 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
4350
4351 char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
4352 char *comm;
4353
4354 if (proc_pidpath (proc_id, pathbuf, sizeof(pathbuf)) > 0)
4355 {
4356 if ((comm = strrchr (pathbuf, '/')))
4357 comm++;
4358 else
4359 comm = pathbuf;
4360 }
4361 else
4362 comm = proc.kp_proc.p_comm;
4363
4364 decoded_comm = (code_convert_string_norecord
4365 (build_unibyte_string (comm),
4366 Vlocale_coding_system, 0));
4367 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
4368
4369 {
4370 char state[2] = {'\0', '\0'};
4371 switch (proc.kp_proc.p_stat)
4372 {
4373 case SRUN:
4374 state[0] = 'R';
4375 break;
4376
4377 case SSLEEP:
4378 state[0] = 'S';
4379 break;
4380
4381 case SZOMB:
4382 state[0] = 'Z';
4383 break;
4384
4385 case SSTOP:
4386 state[0] = 'T';
4387 break;
4388
4389 case SIDL:
4390 state[0] = 'I';
4391 break;
4392 }
4393 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
4394 }
4395
4396 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (proc.kp_eproc.e_ppid)), attrs);
4397 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (proc.kp_eproc.e_pgid)), attrs);
4398
4399 tdev = proc.kp_eproc.e_tdev;
4400 block_input ();
4401 ttyname = tdev == NODEV ? NULL : devname (tdev, S_IFCHR);
4402 unblock_input ();
4403 if (ttyname)
4404 attrs = Fcons (Fcons (Qttname, build_string (ttyname)), attrs);
4405
4406 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.kp_eproc.e_tpgid)),
4407 attrs);
4408
4409 #if HAVE_RUSAGE_INFO_CURRENT
4410 rusage_info_current ri;
4411 if (proc_pid_rusage(proc_id, RUSAGE_INFO_CURRENT, (rusage_info_t *) &ri) == 0)
4412 {
4413 struct timespec utime = make_timespec (ri.ri_user_time / TIMESPEC_HZ,
4414 ri.ri_user_time % TIMESPEC_HZ);
4415 struct timespec stime = make_timespec (ri.ri_system_time / TIMESPEC_HZ,
4416 ri.ri_system_time % TIMESPEC_HZ);
4417 attrs = Fcons (Fcons (Qutime, make_lisp_time (utime)), attrs);
4418 attrs = Fcons (Fcons (Qstime, make_lisp_time (stime)), attrs);
4419 attrs = Fcons (Fcons (Qtime, make_lisp_time (timespec_add (utime, stime))), attrs);
4420
4421 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (ri.ri_pageins)), attrs);
4422 }
4423 #else
4424 struct rusage *rusage = proc.kp_proc.p_ru;
4425 if (rusage)
4426 {
4427 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (rusage->ru_minflt)),
4428 attrs);
4429 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (rusage->ru_majflt)),
4430 attrs);
4431
4432 Lisp_Object utime = make_lisp_timeval (rusage->ru_utime);
4433 Lisp_Object stime = make_lisp_timeval (rusage->ru_stime);
4434 attrs = Fcons (Fcons (Qutime, utime), attrs);
4435 attrs = Fcons (Fcons (Qstime, stime), attrs);
4436 attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
4437 }
4438 #endif
4439
4440 starttime = proc.kp_proc.p_starttime;
4441 attrs = Fcons (Fcons (Qnice, make_fixnum (proc.kp_proc.p_nice)), attrs);
4442 Lisp_Object start = make_lisp_timeval (starttime);
4443 attrs = Fcons (Fcons (Qstart, start), attrs);
4444
4445 Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
4446 Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
4447 attrs = Fcons (Fcons (Qetime, etime), attrs);
4448
4449 #if HAVE_PROC_PIDINFO
4450 struct proc_taskinfo taskinfo;
4451 if (proc_pidinfo (proc_id, PROC_PIDTASKINFO, 0, &taskinfo, sizeof (taskinfo)) > 0)
4452 {
4453 attrs = Fcons (Fcons (Qvsize, make_fixnum (taskinfo.pti_virtual_size / 1024)), attrs);
4454 attrs = Fcons (Fcons (Qrss, make_fixnum (taskinfo.pti_resident_size / 1024)), attrs);
4455 attrs = Fcons (Fcons (Qthcount, make_fixnum (taskinfo.pti_threadnum)), attrs);
4456 }
4457 #endif
4458
4459 #ifdef KERN_PROCARGS2
4460 char args[ARG_MAX];
4461 mib[1] = KERN_PROCARGS2;
4462 mib[2] = proc_id;
4463 len = sizeof args;
4464
4465 if (sysctl (mib, 3, &args, &len, NULL, 0) == 0 && len != 0)
4466 {
4467 char *start, *end;
4468
4469 int argc = *(int*)args;
4470 start = args + sizeof (int);
4471
4472 start += strlen (start) + 1;
4473 while ((start - args < len) && ! *start) start++;
4474
4475
4476 for (i = 0, end = start; i < argc && (end - args) < len; i++)
4477 {
4478 end += strlen (end) + 1;
4479 }
4480
4481 len = end - start;
4482 for (int i = 0; i < len; i++)
4483 {
4484 if (! start[i] && i < len - 1)
4485 start[i] = ' ';
4486 }
4487
4488 AUTO_STRING (comm, start);
4489 decoded_comm = code_convert_string_norecord (comm,
4490 Vlocale_coding_system, 0);
4491 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
4492 }
4493 #endif
4494
4495 return attrs;
4496 }
4497
4498
4499
4500
4501 #elif !defined (WINDOWSNT) && !defined (MSDOS) && !defined (HAIKU)
4502
4503 Lisp_Object
4504 system_process_attributes (Lisp_Object pid)
4505 {
4506 return Qnil;
4507 }
4508
4509 #endif
4510
4511 DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
4512 0, 0, 0,
4513 doc:
4514
4515
4516
4517 )
4518 (void)
4519 {
4520 #ifdef HAVE_GETRUSAGE
4521 struct rusage usage;
4522 time_t secs;
4523 int usecs;
4524
4525 if (getrusage (RUSAGE_SELF, &usage) < 0)
4526
4527 xsignal0 (Qerror);
4528
4529
4530 secs = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
4531 usecs = usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
4532 if (usecs >= 1000000)
4533 {
4534 usecs -= 1000000;
4535 secs++;
4536 }
4537 return make_lisp_s_us (secs, usecs);
4538 #else
4539 #ifdef WINDOWSNT
4540 return w32_get_internal_run_time ();
4541 #else
4542 return Fcurrent_time ();
4543 #endif
4544 #endif
4545 }
4546
4547
4548
4549 #ifdef __STDC_ISO_10646__
4550 # include <wchar.h>
4551 # include <wctype.h>
4552
4553 # if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE
4554 # include <locale.h>
4555 # endif
4556 # ifndef LC_COLLATE
4557 # define LC_COLLATE 0
4558 # endif
4559 # ifndef LC_COLLATE_MASK
4560 # define LC_COLLATE_MASK 0
4561 # endif
4562 # ifndef LC_CTYPE
4563 # define LC_CTYPE 0
4564 # endif
4565 # ifndef LC_CTYPE_MASK
4566 # define LC_CTYPE_MASK 0
4567 # endif
4568
4569 # ifndef HAVE_NEWLOCALE
4570 # undef freelocale
4571 # undef locale_t
4572 # undef newlocale
4573 # undef wcscoll_l
4574 # undef towlower_l
4575 # define freelocale emacs_freelocale
4576 # define locale_t emacs_locale_t
4577 # define newlocale emacs_newlocale
4578 # define wcscoll_l emacs_wcscoll_l
4579 # define towlower_l emacs_towlower_l
4580
4581 typedef char const *locale_t;
4582
4583 static locale_t
4584 newlocale (int category_mask, char const *locale, locale_t loc)
4585 {
4586 return locale;
4587 }
4588
4589 static void
4590 freelocale (locale_t loc)
4591 {
4592 }
4593
4594 static char *
4595 emacs_setlocale (int category, char const *locale)
4596 {
4597 # ifdef HAVE_SETLOCALE
4598 errno = 0;
4599 char *loc = setlocale (category, locale);
4600 if (loc || errno)
4601 return loc;
4602 errno = EINVAL;
4603 # else
4604 errno = ENOTSUP;
4605 # endif
4606 return 0;
4607 }
4608
4609 static int
4610 wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc)
4611 {
4612 int result = 0;
4613 char *oldloc = emacs_setlocale (LC_COLLATE, NULL);
4614 int err;
4615
4616 if (! oldloc)
4617 err = errno;
4618 else
4619 {
4620 USE_SAFE_ALLOCA;
4621 char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
4622 strcpy (oldcopy, oldloc);
4623 if (! emacs_setlocale (LC_COLLATE, loc))
4624 err = errno;
4625 else
4626 {
4627 errno = 0;
4628 result = wcscoll (a, b);
4629 err = errno;
4630 if (! emacs_setlocale (LC_COLLATE, oldcopy))
4631 err = errno;
4632 }
4633 SAFE_FREE ();
4634 }
4635
4636 errno = err;
4637 return result;
4638 }
4639
4640 static wint_t
4641 towlower_l (wint_t wc, locale_t loc)
4642 {
4643 wint_t result = wc;
4644 char *oldloc = emacs_setlocale (LC_CTYPE, NULL);
4645
4646 if (oldloc)
4647 {
4648 USE_SAFE_ALLOCA;
4649 char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
4650 strcpy (oldcopy, oldloc);
4651 if (emacs_setlocale (LC_CTYPE, loc))
4652 {
4653 result = towlower (wc);
4654 emacs_setlocale (LC_COLLATE, oldcopy);
4655 }
4656 SAFE_FREE ();
4657 }
4658
4659 return result;
4660 }
4661 # endif
4662
4663 int
4664 str_collate (Lisp_Object s1, Lisp_Object s2,
4665 Lisp_Object locale, Lisp_Object ignore_case)
4666 {
4667 int res, err;
4668 ptrdiff_t len, i, i_byte;
4669 wchar_t *p1, *p2;
4670
4671 USE_SAFE_ALLOCA;
4672
4673
4674 len = SCHARS (s1); i = i_byte = 0;
4675 SAFE_NALLOCA (p1, 1, len + 1);
4676 while (i < len)
4677 {
4678 wchar_t *p = &p1[i];
4679 *p = fetch_string_char_advance (s1, &i, &i_byte);
4680 }
4681 p1[len] = 0;
4682
4683 len = SCHARS (s2); i = i_byte = 0;
4684 SAFE_NALLOCA (p2, 1, len + 1);
4685 while (i < len)
4686 {
4687 wchar_t *p = &p2[i];
4688 *p = fetch_string_char_advance (s2, &i, &i_byte);
4689 }
4690 p2[len] = 0;
4691
4692 if (STRINGP (locale))
4693 {
4694 locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK,
4695 SSDATA (locale), 0);
4696 if (!loc)
4697 error ("Invalid locale %s: %s", SSDATA (locale), emacs_strerror (errno));
4698
4699 if (! NILP (ignore_case))
4700 for (int i = 1; i < 3; i++)
4701 {
4702 wchar_t *p = (i == 1) ? p1 : p2;
4703 for (; *p; p++)
4704 *p = towlower_l (*p, loc);
4705 }
4706
4707 errno = 0;
4708 res = wcscoll_l (p1, p2, loc);
4709 err = errno;
4710 freelocale (loc);
4711 }
4712 else
4713 {
4714 if (! NILP (ignore_case))
4715 for (int i = 1; i < 3; i++)
4716 {
4717 wchar_t *p = (i == 1) ? p1 : p2;
4718 for (; *p; p++)
4719 *p = towlower (*p);
4720 }
4721
4722 errno = 0;
4723 res = wcscoll (p1, p2);
4724 err = errno;
4725 }
4726 # ifndef HAVE_NEWLOCALE
4727 if (err)
4728 error ("Invalid locale or string for collation: %s", emacs_strerror (err));
4729 # else
4730 if (err)
4731 error ("Invalid string for collation: %s", emacs_strerror (err));
4732 # endif
4733
4734 SAFE_FREE ();
4735 return res;
4736 }
4737 #endif
4738
4739 #ifdef WINDOWSNT
4740 int
4741 str_collate (Lisp_Object s1, Lisp_Object s2,
4742 Lisp_Object locale, Lisp_Object ignore_case)
4743 {
4744
4745 char *loc = STRINGP (locale) ? SSDATA (locale) : NULL;
4746 int res, err = errno;
4747
4748 errno = 0;
4749 res = w32_compare_strings (SSDATA (s1), SSDATA (s2), loc, !NILP (ignore_case));
4750 if (errno)
4751 error ("Invalid string for collation: %s", strerror (errno));
4752
4753 errno = err;
4754 return res;
4755 }
4756 #endif
4757
4758 void
4759 syms_of_sysdep (void)
4760 {
4761 defsubr (&Sget_internal_run_time);
4762 }