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 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2648 int
2649 emacs_fclose (FILE *stream)
2650 {
2651 return android_fclose (stream);
2652 }
2653 #endif
2654
2655
2656
2657
2658
2659 int
2660 emacs_unlink (const char *name)
2661 {
2662 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2663 return unlink (name);
2664 #else
2665 return android_unlink (name);
2666 #endif
2667 }
2668
2669 int
2670 emacs_symlink (const char *target, const char *linkname)
2671 {
2672 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2673 return symlink (target, linkname);
2674 #else
2675 return android_symlink (target, linkname);
2676 #endif
2677 }
2678
2679 int
2680 emacs_rmdir (const char *dirname)
2681 {
2682 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2683 return rmdir (dirname);
2684 #else
2685 return android_rmdir (dirname);
2686 #endif
2687 }
2688
2689 int
2690 emacs_mkdir (const char *dirname, mode_t mode)
2691 {
2692 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2693 return mkdir (dirname, mode);
2694 #else
2695 return android_mkdir (dirname, mode);
2696 #endif
2697 }
2698
2699 int
2700 emacs_renameat_noreplace (int srcfd, const char *src,
2701 int dstfd, const char *dst)
2702 {
2703 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2704 return renameat_noreplace (srcfd, src, dstfd, dst);
2705 #else
2706 return android_renameat_noreplace (srcfd, src, dstfd, dst);
2707 #endif
2708 }
2709
2710 int
2711 emacs_rename (const char *src, const char *dst)
2712 {
2713 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2714 return rename (src, dst);
2715 #else
2716 return android_rename (src, dst);
2717 #endif
2718 }
2719
2720 int
2721 emacs_fchmodat (int fd, const char *path, mode_t mode, int flags)
2722 {
2723 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
2724 return fchmodat (fd, path, mode, flags);
2725 #else
2726 return android_fchmodat (fd, path, mode, flags);
2727 #endif
2728 }
2729
2730
2731
2732
2733
2734
2735
2736
2737 #ifndef MAX_RW_COUNT
2738 #define MAX_RW_COUNT (INT_MAX >> 18 << 18)
2739 #endif
2740
2741
2742 #ifndef SSIZE_MAX
2743 # define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
2744 #endif
2745 verify (MAX_RW_COUNT <= PTRDIFF_MAX);
2746 verify (MAX_RW_COUNT <= SIZE_MAX);
2747 verify (MAX_RW_COUNT <= SSIZE_MAX);
2748
2749 #ifdef WINDOWSNT
2750
2751
2752
2753 verify (MAX_RW_COUNT <= INT_MAX);
2754 verify (MAX_RW_COUNT <= UINT_MAX);
2755 #endif
2756
2757
2758
2759
2760
2761
2762 static ptrdiff_t
2763 emacs_intr_read (int fd, void *buf, ptrdiff_t nbyte, bool interruptible)
2764 {
2765
2766 eassert (nbyte <= MAX_RW_COUNT);
2767
2768 ssize_t result;
2769
2770 do
2771 {
2772 if (interruptible)
2773 maybe_quit ();
2774 result = read (fd, buf, nbyte);
2775 }
2776 while (result < 0 && errno == EINTR);
2777
2778 return result;
2779 }
2780
2781
2782
2783
2784
2785 ptrdiff_t
2786 emacs_read (int fd, void *buf, ptrdiff_t nbyte)
2787 {
2788 return emacs_intr_read (fd, buf, nbyte, false);
2789 }
2790
2791
2792 ptrdiff_t
2793 emacs_read_quit (int fd, void *buf, ptrdiff_t nbyte)
2794 {
2795 return emacs_intr_read (fd, buf, nbyte, true);
2796 }
2797
2798
2799
2800
2801
2802
2803
2804 static ptrdiff_t
2805 emacs_full_write (int fd, char const *buf, ptrdiff_t nbyte,
2806 int interruptible)
2807 {
2808 ptrdiff_t bytes_written = 0;
2809
2810 while (nbyte > 0)
2811 {
2812 ssize_t n = write (fd, buf, min (nbyte, MAX_RW_COUNT));
2813
2814 if (n < 0)
2815 {
2816 if (errno != EINTR)
2817 break;
2818
2819 if (interruptible)
2820 {
2821 if (0 < interruptible)
2822 maybe_quit ();
2823 if (pending_signals)
2824 process_pending_signals ();
2825 }
2826 }
2827 else
2828 {
2829 buf += n;
2830 nbyte -= n;
2831 bytes_written += n;
2832 }
2833 }
2834
2835 return bytes_written;
2836 }
2837
2838
2839
2840
2841
2842 ptrdiff_t
2843 emacs_write (int fd, void const *buf, ptrdiff_t nbyte)
2844 {
2845 return emacs_full_write (fd, buf, nbyte, 0);
2846 }
2847
2848
2849 ptrdiff_t
2850 emacs_write_sig (int fd, void const *buf, ptrdiff_t nbyte)
2851 {
2852 return emacs_full_write (fd, buf, nbyte, -1);
2853 }
2854
2855
2856 ptrdiff_t
2857 emacs_write_quit (int fd, void const *buf, ptrdiff_t nbyte)
2858 {
2859 return emacs_full_write (fd, buf, nbyte, 1);
2860 }
2861
2862
2863
2864
2865 void
2866 emacs_perror (char const *message)
2867 {
2868 int err = errno;
2869 char const *error_string = emacs_strerror (err);
2870 char const *command = (initial_argv && initial_argv[0]
2871 ? initial_argv[0] : "emacs");
2872
2873
2874 char buf[min (PIPE_BUF, MAX_ALLOCA)];
2875 int nbytes = snprintf (buf, sizeof buf, "%s: %s: %s\n",
2876 command, message, error_string);
2877 if (0 <= nbytes && nbytes < sizeof buf)
2878 emacs_write (STDERR_FILENO, buf, nbytes);
2879 else
2880 {
2881 emacs_write (STDERR_FILENO, command, strlen (command));
2882 emacs_write (STDERR_FILENO, ": ", 2);
2883 emacs_write (STDERR_FILENO, message, strlen (message));
2884 emacs_write (STDERR_FILENO, ": ", 2);
2885 emacs_write (STDERR_FILENO, error_string, strlen (error_string));
2886 emacs_write (STDERR_FILENO, "\n", 1);
2887 }
2888 errno = err;
2889 }
2890
2891
2892
2893
2894
2895 int
2896 renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst)
2897 {
2898 #if HAVE_RENAMEAT2 && defined RENAME_NOREPLACE
2899 return renameat2 (srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2900 #elif defined SYS_renameat2 && defined RENAME_NOREPLACE
2901
2902 return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2903 #elif defined RENAME_EXCL
2904 return renameatx_np (srcfd, src, dstfd, dst, RENAME_EXCL);
2905 #else
2906 # ifdef WINDOWSNT
2907 if (srcfd == AT_FDCWD && dstfd == AT_FDCWD)
2908 return sys_rename_replace (src, dst, 0);
2909 # endif
2910 errno = ENOSYS;
2911 return -1;
2912 #endif
2913 }
2914
2915
2916
2917 char const *
2918 safe_strsignal (int code)
2919 {
2920 char const *signame = sigdescr_np (code);
2921
2922 if (! signame)
2923 signame = "Unknown signal";
2924
2925 return signame;
2926 }
2927
2928
2929
2930
2931 static FILE *
2932 errstream (void)
2933 {
2934 FILE *err = buferr;
2935 if (!err)
2936 return stderr;
2937 fflush_unlocked (stderr);
2938 return err;
2939 }
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950 void
2951 errputc (int c)
2952 {
2953 fputc_unlocked (c, errstream ());
2954
2955 #ifdef WINDOWSNT
2956
2957
2958 if (c == '\n')
2959 fflush_unlocked (stderr);
2960 #endif
2961 }
2962
2963 void
2964 errwrite (void const *buf, ptrdiff_t nbuf)
2965 {
2966 fwrite_unlocked (buf, 1, nbuf, errstream ());
2967 }
2968
2969
2970
2971 void
2972 close_output_streams (void)
2973 {
2974
2975
2976
2977
2978
2979
2980
2981 #ifdef __ANDROID__
2982 fflush (stderr);
2983 fflush (stdout);
2984 #else
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 #endif
2999 }
3000
3001 #ifndef DOS_NT
3002
3003 int
3004 serial_open (Lisp_Object port)
3005 {
3006 int fd = emacs_open (SSDATA (port), O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
3007 if (fd < 0)
3008 report_file_error ("Opening serial port", port);
3009 #ifdef TIOCEXCL
3010 ioctl (fd, TIOCEXCL, (char *) 0);
3011 #endif
3012
3013 return fd;
3014 }
3015
3016 #if !defined (HAVE_CFMAKERAW)
3017
3018
3019 static void
3020 cfmakeraw (struct termios *termios_p)
3021 {
3022 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
3023 termios_p->c_oflag &= ~OPOST;
3024 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
3025 termios_p->c_cflag &= ~(CSIZE|PARENB);
3026 termios_p->c_cflag |= CS8;
3027 }
3028 #endif
3029
3030 #if !defined (HAVE_CFSETSPEED)
3031
3032 static int
3033 cfsetspeed (struct termios *termios_p, speed_t vitesse)
3034 {
3035 return (cfsetispeed (termios_p, vitesse)
3036 + cfsetospeed (termios_p, vitesse));
3037 }
3038 #endif
3039
3040
3041
3042 struct speed_struct
3043 {
3044 speed_t value;
3045 speed_t internal;
3046 };
3047
3048 static const struct speed_struct speeds[] =
3049 {
3050 #ifdef B0
3051 { 0, B0 },
3052 #endif
3053 #ifdef B50
3054 { 50, B50 },
3055 #endif
3056 #ifdef B75
3057 { 75, B75 },
3058 #endif
3059 #ifdef B110
3060 { 110, B110 },
3061 #endif
3062 #ifdef B134
3063 { 134, B134 },
3064 #endif
3065 #ifdef B150
3066 { 150, B150 },
3067 #endif
3068 #ifndef HAVE_TINY_SPEED_T
3069 #ifdef B200
3070 { 200, B200 },
3071 #endif
3072 #ifdef B300
3073 { 300, B300 },
3074 #endif
3075 #ifdef B600
3076 { 600, B600 },
3077 #endif
3078 #ifdef B1200
3079 { 1200, B1200 },
3080 #endif
3081 #ifdef B1200
3082 { 1200, B1200 },
3083 #endif
3084 #ifdef B1800
3085 { 1800, B1800 },
3086 #endif
3087 #ifdef B2400
3088 { 2400, B2400 },
3089 #endif
3090 #ifdef B4800
3091 { 4800, B4800 },
3092 #endif
3093 #ifdef B9600
3094 { 9600, B9600 },
3095 #endif
3096 #ifdef B19200
3097 { 19200, B19200 },
3098 #endif
3099 #ifdef B38400
3100 { 38400, B38400 },
3101 #endif
3102 #ifdef B57600
3103 { 57600, B57600 },
3104 #endif
3105 #ifdef B76800
3106 { 76800, B76800 },
3107 #endif
3108 #ifdef B115200
3109 { 115200, B115200 },
3110 #endif
3111 #ifdef B153600
3112 { 153600, B153600 },
3113 #endif
3114 #ifdef B230400
3115 { 230400, B230400 },
3116 #endif
3117 #ifdef B307200
3118 { 307200, B307200 },
3119 #endif
3120 #ifdef B460800
3121 { 460800, B460800 },
3122 #endif
3123 #ifdef B500000
3124 { 500000, B500000 },
3125 #endif
3126 #ifdef B576000
3127 { 576000, B576000 },
3128 #endif
3129 #ifdef B921600
3130 { 921600, B921600 },
3131 #endif
3132 #ifdef B1000000
3133 { 1000000, B1000000 },
3134 #endif
3135 #ifdef B1152000
3136 { 1152000, B1152000 },
3137 #endif
3138 #ifdef B1500000
3139 { 1500000, B1500000 },
3140 #endif
3141 #ifdef B2000000
3142 { 2000000, B2000000 },
3143 #endif
3144 #ifdef B2500000
3145 { 2500000, B2500000 },
3146 #endif
3147 #ifdef B3000000
3148 { 3000000, B3000000 },
3149 #endif
3150 #ifdef B3500000
3151 { 3500000, B3500000 },
3152 #endif
3153 #ifdef B4000000
3154 { 4000000, B4000000 },
3155 #endif
3156 #endif
3157 };
3158
3159
3160
3161 static speed_t
3162 convert_speed (speed_t speed)
3163 {
3164 for (size_t i = 0; i < sizeof speeds / sizeof speeds[0]; i++)
3165 {
3166 if (speed == speeds[i].internal)
3167 return speed;
3168 else if (speed == speeds[i].value)
3169 return speeds[i].internal;
3170 }
3171 return speed;
3172 }
3173
3174
3175 void
3176 serial_configure (struct Lisp_Process *p,
3177 Lisp_Object contact)
3178 {
3179 Lisp_Object childp2 = Qnil;
3180 Lisp_Object tem = Qnil;
3181 struct termios attr;
3182 int err;
3183 char summary[4] = "???";
3184
3185 childp2 = Fcopy_sequence (p->childp);
3186
3187
3188 err = tcgetattr (p->outfd, &attr);
3189 if (err != 0)
3190 report_file_error ("Failed tcgetattr", Qnil);
3191 cfmakeraw (&attr);
3192 #if defined (CLOCAL)
3193 attr.c_cflag |= CLOCAL;
3194 #endif
3195 #if defined (CREAD)
3196 attr.c_cflag |= CREAD;
3197 #endif
3198
3199
3200 if (!NILP (plist_member (contact, QCspeed)))
3201 tem = plist_get (contact, QCspeed);
3202 else
3203 tem = plist_get (p->childp, QCspeed);
3204 CHECK_FIXNUM (tem);
3205 err = cfsetspeed (&attr, convert_speed (XFIXNUM (tem)));
3206 if (err != 0)
3207 report_file_error ("Failed cfsetspeed", tem);
3208 childp2 = plist_put (childp2, QCspeed, tem);
3209
3210
3211 if (!NILP (plist_member (contact, QCbytesize)))
3212 tem = plist_get (contact, QCbytesize);
3213 else
3214 tem = plist_get (p->childp, QCbytesize);
3215 if (NILP (tem))
3216 tem = make_fixnum (8);
3217 CHECK_FIXNUM (tem);
3218 if (XFIXNUM (tem) != 7 && XFIXNUM (tem) != 8)
3219 error (":bytesize must be nil (8), 7, or 8");
3220 summary[0] = XFIXNUM (tem) + '0';
3221 #if defined (CSIZE) && defined (CS7) && defined (CS8)
3222 attr.c_cflag &= ~CSIZE;
3223 attr.c_cflag |= ((XFIXNUM (tem) == 7) ? CS7 : CS8);
3224 #else
3225
3226 if (XFIXNUM (tem) != 8)
3227 error ("Bytesize cannot be changed");
3228 #endif
3229 childp2 = plist_put (childp2, QCbytesize, tem);
3230
3231
3232 if (!NILP (plist_member (contact, QCparity)))
3233 tem = plist_get (contact, QCparity);
3234 else
3235 tem = plist_get (p->childp, QCparity);
3236 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
3237 error (":parity must be nil (no parity), `even', or `odd'");
3238 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
3239 attr.c_cflag &= ~(PARENB | PARODD);
3240 attr.c_iflag &= ~(IGNPAR | INPCK);
3241 if (NILP (tem))
3242 {
3243 summary[1] = 'N';
3244 }
3245 else if (EQ (tem, Qeven))
3246 {
3247 summary[1] = 'E';
3248 attr.c_cflag |= PARENB;
3249 attr.c_iflag |= (IGNPAR | INPCK);
3250 }
3251 else if (EQ (tem, Qodd))
3252 {
3253 summary[1] = 'O';
3254 attr.c_cflag |= (PARENB | PARODD);
3255 attr.c_iflag |= (IGNPAR | INPCK);
3256 }
3257 #else
3258
3259 if (!NILP (tem))
3260 error ("Parity cannot be configured");
3261 #endif
3262 childp2 = plist_put (childp2, QCparity, tem);
3263
3264
3265 if (!NILP (plist_member (contact, QCstopbits)))
3266 tem = plist_get (contact, QCstopbits);
3267 else
3268 tem = plist_get (p->childp, QCstopbits);
3269 if (NILP (tem))
3270 tem = make_fixnum (1);
3271 CHECK_FIXNUM (tem);
3272 if (XFIXNUM (tem) != 1 && XFIXNUM (tem) != 2)
3273 error (":stopbits must be nil (1 stopbit), 1, or 2");
3274 summary[2] = XFIXNUM (tem) + '0';
3275 #if defined (CSTOPB)
3276 attr.c_cflag &= ~CSTOPB;
3277 if (XFIXNUM (tem) == 2)
3278 attr.c_cflag |= CSTOPB;
3279 #else
3280
3281 if (XFIXNUM (tem) != 1)
3282 error ("Stopbits cannot be configured");
3283 #endif
3284 childp2 = plist_put (childp2, QCstopbits, tem);
3285
3286
3287 if (!NILP (plist_member (contact, QCflowcontrol)))
3288 tem = plist_get (contact, QCflowcontrol);
3289 else
3290 tem = plist_get (p->childp, QCflowcontrol);
3291 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
3292 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
3293 #if defined (CRTSCTS)
3294 attr.c_cflag &= ~CRTSCTS;
3295 #endif
3296 #if defined (CNEW_RTSCTS)
3297 attr.c_cflag &= ~CNEW_RTSCTS;
3298 #endif
3299 #if defined (IXON) && defined (IXOFF)
3300 attr.c_iflag &= ~(IXON | IXOFF);
3301 #endif
3302 if (NILP (tem))
3303 {
3304
3305 }
3306 else if (EQ (tem, Qhw))
3307 {
3308 #if defined (CRTSCTS)
3309 attr.c_cflag |= CRTSCTS;
3310 #elif defined (CNEW_RTSCTS)
3311 attr.c_cflag |= CNEW_RTSCTS;
3312 #else
3313 error ("Hardware flowcontrol (RTS/CTS) not supported");
3314 #endif
3315 }
3316 else if (EQ (tem, Qsw))
3317 {
3318 #if defined (IXON) && defined (IXOFF)
3319 attr.c_iflag |= (IXON | IXOFF);
3320 #else
3321 error ("Software flowcontrol (XON/XOFF) not supported");
3322 #endif
3323 }
3324 childp2 = plist_put (childp2, QCflowcontrol, tem);
3325
3326
3327 err = tcsetattr (p->outfd, TCSANOW, &attr);
3328 if (err != 0)
3329 report_file_error ("Failed tcsetattr", Qnil);
3330
3331 childp2 = plist_put (childp2, QCsummary, build_string (summary));
3332 pset_childp (p, childp2);
3333 }
3334 #endif
3335
3336
3337
3338 #ifdef HAVE_PROCFS
3339
3340
3341
3342 Lisp_Object
3343 list_system_processes (void)
3344 {
3345 Lisp_Object procdir, match, proclist, next;
3346 Lisp_Object tail;
3347
3348
3349
3350
3351 procdir = build_string ("/proc");
3352 match = build_string ("[0-9]+");
3353 proclist = directory_files_internal (procdir, Qnil, match, Qt,
3354 false, Qnil, Qnil);
3355
3356
3357
3358 for (tail = proclist; CONSP (tail); tail = next)
3359 {
3360 next = XCDR (tail);
3361 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
3362 }
3363
3364
3365
3366 proclist = Fnreverse (proclist);
3367 return proclist;
3368 }
3369
3370 #elif defined DARWIN_OS || defined __FreeBSD__ || defined __OpenBSD__
3371
3372 Lisp_Object
3373 list_system_processes (void)
3374 {
3375 #ifdef DARWIN_OS
3376 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
3377 #elif defined __OpenBSD__
3378 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0,
3379 sizeof (struct kinfo_proc), 4096};
3380 #else
3381 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC};
3382 #endif
3383 size_t len;
3384 size_t mibsize = sizeof mib / sizeof mib[0];
3385 struct kinfo_proc *procs;
3386 size_t i;
3387
3388 Lisp_Object proclist = Qnil;
3389
3390 if (sysctl (mib, mibsize, NULL, &len, NULL, 0) != 0 || len == 0)
3391 return proclist;
3392
3393 procs = xmalloc (len);
3394 if (sysctl (mib, mibsize, procs, &len, NULL, 0) != 0 || len == 0)
3395 {
3396 xfree (procs);
3397 return proclist;
3398 }
3399
3400 len /= sizeof procs[0];
3401 for (i = 0; i < len; i++)
3402 {
3403 #ifdef DARWIN_OS
3404 proclist = Fcons (INT_TO_INTEGER (procs[i].kp_proc.p_pid), proclist);
3405 #elif defined __OpenBSD__
3406 proclist = Fcons (INT_TO_INTEGER (procs[i].p_pid), proclist);
3407 #else
3408 proclist = Fcons (INT_TO_INTEGER (procs[i].ki_pid), proclist);
3409 #endif
3410 }
3411
3412 xfree (procs);
3413
3414 return proclist;
3415 }
3416
3417
3418
3419
3420 #elif !defined (WINDOWSNT) && !defined (MSDOS) && !defined (HAIKU)
3421
3422 Lisp_Object
3423 list_system_processes (void)
3424 {
3425 return Qnil;
3426 }
3427
3428 #endif
3429
3430 #if (HAVE_GETRUSAGE \
3431 || defined __FreeBSD__ || defined DARWIN_OS || defined __OpenBSD__)
3432
3433 static Lisp_Object
3434 make_lisp_s_us (time_t s, long us)
3435 {
3436 Lisp_Object sec = make_int (s);
3437 Lisp_Object usec = make_fixnum (us);
3438 Lisp_Object hz = make_fixnum (1000000);
3439 Lisp_Object ticks = CALLN (Fplus, CALLN (Ftimes, sec, hz), usec);
3440 return Ftime_convert (Fcons (ticks, hz), Qnil);
3441 }
3442
3443 #endif
3444
3445 #if defined __FreeBSD__ || defined DARWIN_OS
3446
3447 static Lisp_Object
3448 make_lisp_timeval (struct timeval t)
3449 {
3450 return make_lisp_s_us (t.tv_sec, t.tv_usec);
3451 }
3452
3453 #endif
3454
3455 #if defined (GNU_LINUX) || defined (CYGWIN)
3456
3457 static Lisp_Object
3458 time_from_jiffies (unsigned long long ticks, Lisp_Object hz, Lisp_Object form)
3459 {
3460 return Ftime_convert (Fcons (make_uint (ticks), hz), form);
3461 }
3462
3463 static Lisp_Object
3464 put_jiffies (Lisp_Object attrs, Lisp_Object propname,
3465 unsigned long long ticks, Lisp_Object hz)
3466 {
3467 return Fcons (Fcons (propname, time_from_jiffies (ticks, hz, Qnil)), attrs);
3468 }
3469
3470 static Lisp_Object
3471 get_up_time (void)
3472 {
3473 FILE *fup;
3474 Lisp_Object up = Qnil;
3475
3476 block_input ();
3477 fup = emacs_fopen ("/proc/uptime", "r");
3478
3479 if (fup)
3480 {
3481 unsigned long long upsec;
3482 EMACS_UINT upfrac;
3483 int upfrac_start, upfrac_end;
3484
3485 if (fscanf (fup, "%llu.%n%"pI"u%n",
3486 &upsec, &upfrac_start, &upfrac, &upfrac_end)
3487 == 2)
3488 {
3489 EMACS_INT hz = 1;
3490 for (int i = upfrac_start; i < upfrac_end; i++)
3491 hz *= 10;
3492 Lisp_Object sec = make_uint (upsec);
3493 Lisp_Object subsec = Fcons (make_fixnum (upfrac), make_fixnum (hz));
3494 up = Ftime_add (sec, subsec);
3495 }
3496 emacs_fclose (fup);
3497 }
3498 unblock_input ();
3499
3500 return up;
3501 }
3502
3503 # ifdef GNU_LINUX
3504 #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
3505 #define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
3506
3507 static Lisp_Object
3508 procfs_ttyname (int rdev)
3509 {
3510 FILE *fdev;
3511 char name[PATH_MAX];
3512
3513 block_input ();
3514 fdev = emacs_fopen ("/proc/tty/drivers", "r");
3515 name[0] = 0;
3516
3517 if (fdev)
3518 {
3519 unsigned major;
3520 unsigned long minor_beg, minor_end;
3521 char minor[25];
3522 char *endp;
3523
3524 for (; !feof (fdev) && !ferror (fdev); name[0] = 0)
3525 {
3526 if (fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) >= 3
3527 && major == MAJOR (rdev))
3528 {
3529 minor_beg = strtoul (minor, &endp, 0);
3530 if (*endp == '\0')
3531 minor_end = minor_beg;
3532 else if (*endp == '-')
3533 minor_end = strtoul (endp + 1, &endp, 0);
3534 else
3535 continue;
3536
3537 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
3538 {
3539 sprintf (name + strlen (name), "%u", MINOR (rdev));
3540 break;
3541 }
3542 }
3543 }
3544 emacs_fclose (fdev);
3545 }
3546 unblock_input ();
3547 return build_string (name);
3548 }
3549 # endif
3550
3551 static uintmax_t
3552 procfs_get_total_memory (void)
3553 {
3554 FILE *fmem;
3555 uintmax_t retval = 2 * 1024 * 1024;
3556 int c;
3557
3558 block_input ();
3559 fmem = emacs_fopen ("/proc/meminfo", "r");
3560
3561 if (fmem)
3562 {
3563 uintmax_t entry_value;
3564 bool done;
3565
3566 do
3567 switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value))
3568 {
3569 case 1:
3570 retval = entry_value;
3571 done = 1;
3572 break;
3573
3574 case 0:
3575 while ((c = getc (fmem)) != EOF && c != '\n')
3576 continue;
3577 done = c == EOF;
3578 break;
3579
3580 default:
3581 done = 1;
3582 break;
3583 }
3584 while (!done);
3585
3586 emacs_fclose (fmem);
3587 }
3588 unblock_input ();
3589 return retval;
3590 }
3591
3592 Lisp_Object
3593 system_process_attributes (Lisp_Object pid)
3594 {
3595 char procfn[PATH_MAX], fn[PATH_MAX];
3596 struct stat st;
3597 struct passwd *pw;
3598 struct group *gr;
3599 long clocks_per_sec;
3600 char *procfn_end;
3601 char procbuf[1025], *p, *q UNINIT;
3602 int fd;
3603 ssize_t nread;
3604 static char const default_cmd[] = "???";
3605 const char *cmd = default_cmd;
3606 int cmdsize = sizeof default_cmd - 1;
3607 char *cmdline = NULL;
3608 ptrdiff_t cmdline_size;
3609 char c;
3610 intmax_t proc_id;
3611 int ppid, pgrp, sess, tty, tpgid, thcount;
3612 uid_t uid;
3613 gid_t gid;
3614 unsigned long long u_time, s_time, cutime, cstime, start;
3615 long priority, niceness, rss;
3616 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
3617 double pcpu, pmem;
3618 Lisp_Object attrs = Qnil;
3619 Lisp_Object decoded_cmd;
3620
3621 CHECK_NUMBER (pid);
3622 CONS_TO_INTEGER (pid, pid_t, proc_id);
3623 sprintf (procfn, "/proc/%"PRIdMAX, proc_id);
3624 if (stat (procfn, &st) < 0)
3625 return attrs;
3626
3627
3628 uid = st.st_uid;
3629 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (uid)), attrs);
3630 block_input ();
3631 pw = getpwuid (uid);
3632 unblock_input ();
3633 if (pw)
3634 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3635
3636 gid = st.st_gid;
3637 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (gid)), attrs);
3638 block_input ();
3639 gr = getgrgid (gid);
3640 unblock_input ();
3641 if (gr)
3642 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3643
3644 specpdl_ref count = SPECPDL_INDEX ();
3645 strcpy (fn, procfn);
3646 procfn_end = fn + strlen (fn);
3647 strcpy (procfn_end, "/stat");
3648 fd = emacs_open (fn, O_RDONLY, 0);
3649 if (fd < 0)
3650 nread = 0;
3651 else
3652 {
3653 record_unwind_protect_int (close_file_unwind, fd);
3654 nread = emacs_read_quit (fd, procbuf, sizeof procbuf - 1);
3655 }
3656 if (0 < nread)
3657 {
3658 procbuf[nread] = '\0';
3659 p = procbuf;
3660
3661 p = strchr (p, '(');
3662 if (p != NULL)
3663 {
3664 q = strrchr (p + 1, ')');
3665
3666 if (q != NULL)
3667 {
3668 cmd = p + 1;
3669 cmdsize = q - cmd;
3670 }
3671 }
3672 else
3673 q = NULL;
3674
3675 AUTO_STRING_WITH_LEN (cmd_str, cmd, cmdsize);
3676 decoded_cmd = code_convert_string_norecord (cmd_str,
3677 Vlocale_coding_system, 0);
3678 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3679
3680
3681
3682 if (q
3683 && (sscanf (q + 2, ("%c %d %d %d %d %d %*u %lu %lu %lu %lu "
3684 "%llu %llu %llu %llu %ld %ld %d %*d %llu %lu %ld"),
3685 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
3686 &minflt, &cminflt, &majflt, &cmajflt,
3687 &u_time, &s_time, &cutime, &cstime,
3688 &priority, &niceness, &thcount, &start, &vsize, &rss)
3689 == 20))
3690 {
3691 char state_str[2];
3692 state_str[0] = c;
3693 state_str[1] = '\0';
3694 attrs = Fcons (Fcons (Qstate, build_string (state_str)), attrs);
3695 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (ppid)), attrs);
3696 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pgrp)), attrs);
3697 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (sess)), attrs);
3698 # ifdef GNU_LINUX
3699 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
3700 # endif
3701 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (tpgid)), attrs);
3702 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (minflt)), attrs);
3703 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (majflt)), attrs);
3704 attrs = Fcons (Fcons (Qcminflt, INT_TO_INTEGER (cminflt)), attrs);
3705 attrs = Fcons (Fcons (Qcmajflt, INT_TO_INTEGER (cmajflt)), attrs);
3706
3707 clocks_per_sec = sysconf (_SC_CLK_TCK);
3708 if (0 < clocks_per_sec)
3709 {
3710 Lisp_Object hz = make_int (clocks_per_sec);
3711 attrs = put_jiffies (attrs, Qutime, u_time, hz);
3712 attrs = put_jiffies (attrs, Qstime, s_time, hz);
3713 attrs = put_jiffies (attrs, Qtime, s_time + u_time, hz);
3714 attrs = put_jiffies (attrs, Qcutime, cutime, hz);
3715 attrs = put_jiffies (attrs, Qcstime, cstime, hz);
3716 attrs = put_jiffies (attrs, Qctime, cstime + cutime, hz);
3717
3718 Lisp_Object uptime = get_up_time ();
3719 if (!NILP (uptime))
3720 {
3721 Lisp_Object now = Ftime_convert (Qnil, hz);
3722 Lisp_Object boot = Ftime_subtract (now, uptime);
3723 Lisp_Object tstart = time_from_jiffies (start, hz, hz);
3724 Lisp_Object lstart =
3725 Ftime_convert (Ftime_add (boot, tstart), Qnil);
3726 attrs = Fcons (Fcons (Qstart, lstart), attrs);
3727 Lisp_Object etime =
3728 Ftime_convert (Ftime_subtract (uptime, tstart), Qnil);
3729 attrs = Fcons (Fcons (Qetime, etime), attrs);
3730 pcpu = (100.0 * (s_time + u_time)
3731 / (clocks_per_sec * float_time (etime)));
3732 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
3733 }
3734 }
3735
3736 attrs = Fcons (Fcons (Qpri, make_fixnum (priority)), attrs);
3737 attrs = Fcons (Fcons (Qnice, make_fixnum (niceness)), attrs);
3738 attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (thcount)), attrs);
3739 attrs = Fcons (Fcons (Qvsize, INT_TO_INTEGER (vsize / 1024)), attrs);
3740 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (4 * rss)), attrs);
3741 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
3742 if (pmem > 100)
3743 pmem = 100;
3744 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
3745 }
3746 }
3747 unbind_to (count, Qnil);
3748
3749 # ifdef CYGWIN
3750
3751 strcpy (procfn_end, "/ctty");
3752 fd = emacs_open (fn, O_RDONLY, 0);
3753 if (fd < 0)
3754 nread = 0;
3755 else
3756 {
3757 record_unwind_protect_int (close_file_unwind, fd);
3758 nread = emacs_read_quit (fd, procbuf, sizeof procbuf);
3759 }
3760
3761 if (0 < nread && procbuf[nread - 1] == '\n')
3762 procbuf[nread - 1] = '\0';
3763 else
3764 procbuf[0] = '\0';
3765 attrs = Fcons (Fcons (Qttname, build_string (procbuf)), attrs);
3766 unbind_to (count, Qnil);
3767 # endif
3768
3769
3770 strcpy (procfn_end, "/cmdline");
3771 fd = emacs_open (fn, O_RDONLY, 0);
3772 if (fd >= 0)
3773 {
3774 ptrdiff_t readsize, nread_incr;
3775 record_unwind_protect_int (close_file_unwind, fd);
3776 record_unwind_protect_nothing ();
3777 nread = cmdline_size = 0;
3778
3779 do
3780 {
3781 cmdline = xpalloc (cmdline, &cmdline_size, 2, STRING_BYTES_BOUND, 1);
3782 set_unwind_protect_ptr (specpdl_ref_add (count, 1), xfree, cmdline);
3783
3784
3785 readsize = (cmdline_size >> 1) - nread;
3786
3787 nread_incr = emacs_read_quit (fd, cmdline + nread, readsize);
3788 nread += max (0, nread_incr);
3789 }
3790 while (nread_incr == readsize);
3791
3792 if (nread)
3793 {
3794
3795 for (p = cmdline + nread; cmdline < p && !p[-1]; p--)
3796 continue;
3797
3798
3799 q = cmdline + cmdline_size;
3800 while (cmdline < p)
3801 {
3802 char c = *--p;
3803 *--q = c ? c : ' ';
3804 if (c_isspace (c) || c == '\\')
3805 *--q = '\\';
3806 }
3807
3808 nread = cmdline + cmdline_size - q;
3809 }
3810
3811 if (!nread)
3812 {
3813 nread = cmdsize + 2;
3814 cmdline_size = nread + 1;
3815 q = cmdline = xrealloc (cmdline, cmdline_size);
3816 set_unwind_protect_ptr (specpdl_ref_add (count, 1), xfree, cmdline);
3817 sprintf (cmdline, "[%.*s]", cmdsize, cmd);
3818 }
3819
3820 AUTO_STRING_WITH_LEN (cmd_str, q, nread);
3821 decoded_cmd = code_convert_string_norecord (cmd_str,
3822 Vlocale_coding_system, 0);
3823 unbind_to (count, Qnil);
3824 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3825 }
3826
3827 return attrs;
3828 }
3829
3830 #elif defined (SOLARIS2) && defined (HAVE_PROCFS)
3831
3832
3833
3834 #if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
3835 #define PROCFS_FILE_OFFSET_BITS_HACK 1
3836 #undef _FILE_OFFSET_BITS
3837 #else
3838 #define PROCFS_FILE_OFFSET_BITS_HACK 0
3839 #endif
3840
3841 #include <procfs.h>
3842
3843 #if PROCFS_FILE_OFFSET_BITS_HACK == 1
3844 #define _FILE_OFFSET_BITS 64
3845 #ifdef _FILE_OFFSET_BITS
3846 #endif
3847 #endif
3848
3849 Lisp_Object
3850 system_process_attributes (Lisp_Object pid)
3851 {
3852 char procfn[PATH_MAX], fn[PATH_MAX];
3853 struct stat st;
3854 struct passwd *pw;
3855 struct group *gr;
3856 char *procfn_end;
3857 struct psinfo pinfo;
3858 int fd;
3859 ssize_t nread;
3860 intmax_t proc_id;
3861 uid_t uid;
3862 gid_t gid;
3863 Lisp_Object attrs = Qnil;
3864 Lisp_Object decoded_cmd;
3865
3866 CHECK_NUMBER (pid);
3867 CONS_TO_INTEGER (pid, pid_t, proc_id);
3868 sprintf (procfn, "/proc/%"PRIdMAX, proc_id);
3869 if (stat (procfn, &st) < 0)
3870 return attrs;
3871
3872
3873 uid = st.st_uid;
3874 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (uid)), attrs);
3875 block_input ();
3876 pw = getpwuid (uid);
3877 unblock_input ();
3878 if (pw)
3879 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3880
3881 gid = st.st_gid;
3882 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (gid)), attrs);
3883 block_input ();
3884 gr = getgrgid (gid);
3885 unblock_input ();
3886 if (gr)
3887 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3888
3889 specpdl_ref count = SPECPDL_INDEX ();
3890 strcpy (fn, procfn);
3891 procfn_end = fn + strlen (fn);
3892 strcpy (procfn_end, "/psinfo");
3893 fd = emacs_open (fn, O_RDONLY, 0);
3894 if (fd < 0)
3895 nread = 0;
3896 else
3897 {
3898 record_unwind_protect_int (close_file_unwind, fd);
3899 nread = emacs_read_quit (fd, &pinfo, sizeof pinfo);
3900 }
3901
3902 if (nread == sizeof pinfo)
3903 {
3904 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (pinfo.pr_ppid)), attrs);
3905 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pinfo.pr_pgid)), attrs);
3906 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (pinfo.pr_sid)), attrs);
3907
3908 {
3909 char state_str[2];
3910 state_str[0] = pinfo.pr_lwp.pr_sname;
3911 state_str[1] = '\0';
3912 attrs = Fcons (Fcons (Qstate, build_string (state_str)), attrs);
3913 }
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932 attrs = Fcons (Fcons (Qtime, make_lisp_time (pinfo.pr_time)), attrs);
3933 attrs = Fcons (Fcons (Qctime, make_lisp_time (pinfo.pr_ctime)), attrs);
3934 attrs = Fcons (Fcons (Qpri, make_fixnum (pinfo.pr_lwp.pr_pri)), attrs);
3935 attrs = Fcons (Fcons (Qnice, make_fixnum (pinfo.pr_lwp.pr_nice)), attrs);
3936 attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (pinfo.pr_nlwp)), attrs);
3937
3938 attrs = Fcons (Fcons (Qstart, make_lisp_time (pinfo.pr_start)), attrs);
3939 attrs = Fcons (Fcons (Qvsize, INT_TO_INTEGER (pinfo.pr_size)), attrs);
3940 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (pinfo.pr_rssize)), attrs);
3941
3942
3943
3944 attrs = Fcons (Fcons (Qpcpu,
3945 make_float (100.0 / 0x8000 * pinfo.pr_pctcpu)),
3946 attrs);
3947 attrs = Fcons (Fcons (Qpmem,
3948 make_float (100.0 / 0x8000 * pinfo.pr_pctmem)),
3949 attrs);
3950
3951 AUTO_STRING (fname, pinfo.pr_fname);
3952 decoded_cmd = code_convert_string_norecord (fname,
3953 Vlocale_coding_system, 0);
3954 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3955 AUTO_STRING (psargs, pinfo.pr_psargs);
3956 decoded_cmd = code_convert_string_norecord (psargs,
3957 Vlocale_coding_system, 0);
3958 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3959 }
3960 return unbind_to (count, attrs);
3961 }
3962
3963 #elif defined __FreeBSD__
3964
3965 Lisp_Object
3966 system_process_attributes (Lisp_Object pid)
3967 {
3968 int proc_id;
3969 int pagesize = getpagesize ();
3970 unsigned long npages;
3971 int fscale;
3972 struct passwd *pw;
3973 struct group *gr;
3974 char *ttyname;
3975 size_t len;
3976 char args[MAXPATHLEN];
3977
3978 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
3979 struct kinfo_proc proc;
3980 size_t proclen = sizeof proc;
3981
3982 Lisp_Object attrs = Qnil;
3983 Lisp_Object decoded_comm;
3984
3985 CHECK_NUMBER (pid);
3986 CONS_TO_INTEGER (pid, int, proc_id);
3987 mib[3] = proc_id;
3988
3989 if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0 || proclen == 0)
3990 return attrs;
3991
3992 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (proc.ki_uid)), attrs);
3993
3994 block_input ();
3995 pw = getpwuid (proc.ki_uid);
3996 unblock_input ();
3997 if (pw)
3998 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3999
4000 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (proc.ki_svgid)), attrs);
4001
4002 block_input ();
4003 gr = getgrgid (proc.ki_svgid);
4004 unblock_input ();
4005 if (gr)
4006 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
4007
4008 AUTO_STRING (comm, proc.ki_comm);
4009 decoded_comm = code_convert_string_norecord (comm, Vlocale_coding_system, 0);
4010
4011 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
4012 {
4013 char state[2] = {'\0', '\0'};
4014 switch (proc.ki_stat)
4015 {
4016 case SRUN:
4017 state[0] = 'R';
4018 break;
4019
4020 case SSLEEP:
4021 state[0] = 'S';
4022 break;
4023
4024 case SLOCK:
4025 state[0] = 'D';
4026 break;
4027
4028 case SZOMB:
4029 state[0] = 'Z';
4030 break;
4031
4032 case SSTOP:
4033 state[0] = 'T';
4034 break;
4035 }
4036 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
4037 }
4038
4039 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (proc.ki_ppid)), attrs);
4040 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (proc.ki_pgid)), attrs);
4041 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (proc.ki_sid)), attrs);
4042
4043 block_input ();
4044 ttyname = proc.ki_tdev == NODEV ? NULL : devname (proc.ki_tdev, S_IFCHR);
4045 unblock_input ();
4046 if (ttyname)
4047 attrs = Fcons (Fcons (Qttname, build_string (ttyname)), attrs);
4048
4049 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.ki_tpgid)), attrs);
4050 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (proc.ki_rusage.ru_minflt)),
4051 attrs);
4052 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (proc.ki_rusage.ru_majflt)),
4053 attrs);
4054 attrs = Fcons (Fcons (Qcminflt, make_fixnum (proc.ki_rusage_ch.ru_minflt)), attrs);
4055 attrs = Fcons (Fcons (Qcmajflt, make_fixnum (proc.ki_rusage_ch.ru_majflt)), attrs);
4056
4057 Lisp_Object utime = make_lisp_timeval (proc.ki_rusage.ru_utime);
4058 attrs = Fcons (Fcons (Qutime, utime), attrs);
4059 Lisp_Object stime = make_lisp_timeval (proc.ki_rusage.ru_stime);
4060 attrs = Fcons (Fcons (Qstime, stime), attrs);
4061 attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
4062
4063 Lisp_Object cutime = make_lisp_timeval (proc.ki_rusage_ch.ru_utime);
4064 attrs = Fcons (Fcons (Qcutime, cutime), attrs);
4065 Lisp_Object cstime = make_lisp_timeval (proc.ki_rusage_ch.ru_stime);
4066 attrs = Fcons (Fcons (Qcstime, cstime), attrs);
4067 attrs = Fcons (Fcons (Qctime, Ftime_add (cutime, cstime)), attrs);
4068
4069 attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (proc.ki_numthreads)), attrs);
4070 attrs = Fcons (Fcons (Qpri, make_fixnum (proc.ki_pri.pri_native)), attrs);
4071 attrs = Fcons (Fcons (Qnice, make_fixnum (proc.ki_nice)), attrs);
4072 Lisp_Object start = make_lisp_timeval (proc.ki_start);
4073 attrs = Fcons (Fcons (Qstart, start), attrs);
4074 attrs = Fcons (Fcons (Qvsize, make_fixnum (proc.ki_size >> 10)), attrs);
4075 attrs = Fcons (Fcons (Qrss, make_fixnum (proc.ki_rssize * pagesize >> 10)),
4076 attrs);
4077
4078 Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
4079 Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
4080 attrs = Fcons (Fcons (Qetime, etime), attrs);
4081
4082 len = sizeof fscale;
4083 if (sysctlbyname ("kern.fscale", &fscale, &len, NULL, 0) == 0)
4084 {
4085 double pcpu;
4086 fixpt_t ccpu;
4087 len = sizeof ccpu;
4088 if (sysctlbyname ("kern.ccpu", &ccpu, &len, NULL, 0) == 0)
4089 {
4090 pcpu = (100.0 * proc.ki_pctcpu / fscale
4091 / (1 - exp (proc.ki_swtime * log ((double) ccpu / fscale))));
4092 attrs = Fcons (Fcons (Qpcpu, INT_TO_INTEGER (pcpu)), attrs);
4093 }
4094 }
4095
4096 len = sizeof npages;
4097 if (sysctlbyname ("hw.availpages", &npages, &len, NULL, 0) == 0)
4098 {
4099 double pmem = (proc.ki_flag & P_INMEM
4100 ? 100.0 * proc.ki_rssize / npages
4101 : 0);
4102 attrs = Fcons (Fcons (Qpmem, INT_TO_INTEGER (pmem)), attrs);
4103 }
4104
4105 mib[2] = KERN_PROC_ARGS;
4106 len = MAXPATHLEN;
4107 if (sysctl (mib, 4, args, &len, NULL, 0) == 0 && len != 0)
4108 {
4109 int i;
4110 for (i = 0; i < len; i++)
4111 {
4112 if (! args[i] && i < len - 1)
4113 args[i] = ' ';
4114 }
4115
4116 AUTO_STRING (comm, args);
4117 decoded_comm = code_convert_string_norecord (comm,
4118 Vlocale_coding_system, 0);
4119
4120 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
4121 }
4122
4123 return attrs;
4124 }
4125
4126 #elif defined __OpenBSD__
4127
4128 Lisp_Object
4129 system_process_attributes (Lisp_Object pid)
4130 {
4131 int proc_id, fscale, i;
4132 int pagesize = getpagesize ();
4133 int mib[6];
4134 size_t len;
4135 double pct;
4136 char *ttyname, args[ARG_MAX];
4137 struct kinfo_proc proc;
4138 struct passwd *pw;
4139 struct group *gr;
4140 struct uvmexp uvmexp;
4141
4142 Lisp_Object attrs = Qnil;
4143 Lisp_Object decoded_comm;
4144
4145 CHECK_NUMBER (pid);
4146 CONS_TO_INTEGER (pid, int, proc_id);
4147
4148 len = sizeof proc;
4149 mib[0] = CTL_KERN;
4150 mib[1] = KERN_PROC;
4151 mib[2] = KERN_PROC_PID;
4152 mib[3] = proc_id;
4153 mib[4] = len;
4154 mib[5] = 1;
4155 if (sysctl (mib, 6, &proc, &len, NULL, 0) != 0)
4156 return attrs;
4157
4158 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (proc.p_uid)), attrs);
4159
4160 block_input ();
4161 pw = getpwuid (proc.p_uid);
4162 unblock_input ();
4163 if (pw)
4164 attrs = Fcons (Fcons (Quser, build_string(pw->pw_name)), attrs);
4165
4166 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER(proc.p_svgid)), attrs);
4167
4168 block_input ();
4169 gr = getgrgid (proc.p_svgid);
4170 unblock_input ();
4171 if (gr)
4172 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
4173
4174 AUTO_STRING (comm, proc.p_comm);
4175 decoded_comm = code_convert_string_norecord (comm, Vlocale_coding_system, 0);
4176 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
4177
4178 {
4179 char state[2] = {'\0', '\0'};
4180 switch (proc.p_stat) {
4181 case SIDL:
4182 state[0] = 'I';
4183 break;
4184 case SRUN:
4185 state[0] = 'R';
4186 break;
4187 case SSLEEP:
4188 state[0] = 'S';
4189 break;
4190 case SSTOP:
4191 state[0] = 'T';
4192 break;
4193 case SZOMB:
4194 state[0] = 'Z';
4195 break;
4196 case SDEAD:
4197 state[0] = 'D';
4198 break;
4199 }
4200 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
4201 }
4202
4203 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (proc.p_ppid)), attrs);
4204 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (proc.p_gid)), attrs);
4205 attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (proc.p_sid)), attrs);
4206
4207 block_input ();
4208 ttyname = proc.p_tdev == NODEV ? NULL : devname (proc.p_tdev, S_IFCHR);
4209 unblock_input ();
4210 if (ttyname)
4211 attrs = Fcons (Fcons (Qttname, build_string (ttyname)), attrs);
4212
4213 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.p_tpgid)), attrs);
4214 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (proc.p_uru_minflt)),
4215 attrs);
4216 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (proc.p_uru_majflt)),
4217 attrs);
4218
4219
4220
4221 Lisp_Object utime = make_lisp_s_us (proc.p_uutime_sec, proc.p_uutime_usec);
4222 attrs = Fcons (Fcons (Qutime, utime), attrs);
4223 Lisp_Object stime = make_lisp_s_us (proc.p_ustime_sec, proc.p_ustime_usec);
4224 attrs = Fcons (Fcons (Qstime, stime), attrs);
4225 attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
4226
4227 attrs = Fcons (Fcons (Qcutime, make_lisp_s_us (proc.p_uctime_sec,
4228 proc.p_uctime_usec)),
4229 attrs);
4230
4231
4232
4233 attrs = Fcons (Fcons (Qpri, make_fixnum (proc.p_priority)), attrs);
4234 attrs = Fcons (Fcons (Qnice, make_fixnum (proc.p_nice)), attrs);
4235
4236
4237
4238 attrs = Fcons (Fcons (Qstart, make_lisp_s_us (proc.p_ustart_sec,
4239 proc.p_ustart_usec)),
4240 attrs);
4241
4242 len = (proc.p_vm_tsize + proc.p_vm_dsize + proc.p_vm_ssize) * pagesize >> 10;
4243 attrs = Fcons (Fcons (Qvsize, make_fixnum (len)), attrs);
4244
4245 attrs = Fcons (Fcons (Qrss, make_fixnum (proc.p_vm_rssize * pagesize >> 10)),
4246 attrs);
4247
4248 Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
4249 Lisp_Object start = make_lisp_s_us (proc.p_ustart_sec,
4250 proc.p_ustart_usec);
4251 Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
4252 attrs = Fcons (Fcons (Qetime, etime), attrs);
4253
4254 len = sizeof (fscale);
4255 mib[0] = CTL_KERN;
4256 mib[1] = KERN_FSCALE;
4257 if (sysctl (mib, 2, &fscale, &len, NULL, 0) != -1)
4258 {
4259 pct = (double)proc.p_pctcpu / fscale * 100.0;
4260 attrs = Fcons (Fcons (Qpcpu, make_float (pct)), attrs);
4261 }
4262
4263 len = sizeof (uvmexp);
4264 mib[0] = CTL_VM;
4265 mib[1] = VM_UVMEXP;
4266 if (sysctl (mib, 2, &uvmexp, &len, NULL, 0) != -1)
4267 {
4268 pct = (100.0 * (double)proc.p_vm_rssize / uvmexp.npages);
4269 attrs = Fcons (Fcons (Qpmem, make_float (pct)), attrs);
4270 }
4271
4272 len = sizeof args;
4273 mib[0] = CTL_KERN;
4274 mib[1] = KERN_PROC_ARGS;
4275 mib[2] = proc_id;
4276 mib[3] = KERN_PROC_ARGV;
4277 if (sysctl (mib, 4, &args, &len, NULL, 0) == 0 && len != 0)
4278 {
4279 char **argv = (char**)args;
4280
4281
4282
4283
4284
4285 for (i = 0; argv[i] != NULL; ++i)
4286 {
4287 if (argv[i+1] != NULL)
4288 {
4289 len = strlen (argv[i]);
4290 argv[i][len] = ' ';
4291 }
4292 }
4293
4294 AUTO_STRING (comm, *argv);
4295 decoded_comm = code_convert_string_norecord (comm,
4296 Vlocale_coding_system, 0);
4297 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
4298 }
4299
4300 return attrs;
4301 }
4302
4303 #elif defined DARWIN_OS
4304
4305 #define HAVE_RUSAGE_INFO_CURRENT (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
4306 #define HAVE_PROC_PIDINFO (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
4307
4308 Lisp_Object
4309 system_process_attributes (Lisp_Object pid)
4310 {
4311 int proc_id, i;
4312 struct passwd *pw;
4313 struct group *gr;
4314 char *ttyname;
4315 struct timeval starttime;
4316 dev_t tdev;
4317 uid_t uid;
4318 gid_t gid;
4319
4320 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
4321 struct kinfo_proc proc;
4322 size_t len = sizeof proc;
4323
4324 Lisp_Object attrs = Qnil;
4325 Lisp_Object decoded_comm;
4326
4327 CHECK_NUMBER (pid);
4328 CONS_TO_INTEGER (pid, int, proc_id);
4329 mib[3] = proc_id;
4330
4331 if (sysctl (mib, 4, &proc, &len, NULL, 0) != 0 || len == 0)
4332 return attrs;
4333
4334 uid = proc.kp_eproc.e_ucred.cr_uid;
4335 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (uid)), attrs);
4336
4337 block_input ();
4338 pw = getpwuid (uid);
4339 unblock_input ();
4340 if (pw)
4341 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
4342
4343 gid = proc.kp_eproc.e_pcred.p_svgid;
4344 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (gid)), attrs);
4345
4346 block_input ();
4347 gr = getgrgid (gid);
4348 unblock_input ();
4349 if (gr)
4350 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
4351
4352 char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
4353 char *comm;
4354
4355 if (proc_pidpath (proc_id, pathbuf, sizeof(pathbuf)) > 0)
4356 {
4357 if ((comm = strrchr (pathbuf, '/')))
4358 comm++;
4359 else
4360 comm = pathbuf;
4361 }
4362 else
4363 comm = proc.kp_proc.p_comm;
4364
4365 decoded_comm = (code_convert_string_norecord
4366 (build_unibyte_string (comm),
4367 Vlocale_coding_system, 0));
4368 attrs = Fcons (Fcons (Qcomm, decoded_comm), attrs);
4369
4370 {
4371 char state[2] = {'\0', '\0'};
4372 switch (proc.kp_proc.p_stat)
4373 {
4374 case SRUN:
4375 state[0] = 'R';
4376 break;
4377
4378 case SSLEEP:
4379 state[0] = 'S';
4380 break;
4381
4382 case SZOMB:
4383 state[0] = 'Z';
4384 break;
4385
4386 case SSTOP:
4387 state[0] = 'T';
4388 break;
4389
4390 case SIDL:
4391 state[0] = 'I';
4392 break;
4393 }
4394 attrs = Fcons (Fcons (Qstate, build_string (state)), attrs);
4395 }
4396
4397 attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (proc.kp_eproc.e_ppid)), attrs);
4398 attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (proc.kp_eproc.e_pgid)), attrs);
4399
4400 tdev = proc.kp_eproc.e_tdev;
4401 block_input ();
4402 ttyname = tdev == NODEV ? NULL : devname (tdev, S_IFCHR);
4403 unblock_input ();
4404 if (ttyname)
4405 attrs = Fcons (Fcons (Qttname, build_string (ttyname)), attrs);
4406
4407 attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.kp_eproc.e_tpgid)),
4408 attrs);
4409
4410 #if HAVE_RUSAGE_INFO_CURRENT
4411 rusage_info_current ri;
4412 if (proc_pid_rusage(proc_id, RUSAGE_INFO_CURRENT, (rusage_info_t *) &ri) == 0)
4413 {
4414 struct timespec utime = make_timespec (ri.ri_user_time / TIMESPEC_HZ,
4415 ri.ri_user_time % TIMESPEC_HZ);
4416 struct timespec stime = make_timespec (ri.ri_system_time / TIMESPEC_HZ,
4417 ri.ri_system_time % TIMESPEC_HZ);
4418 attrs = Fcons (Fcons (Qutime, make_lisp_time (utime)), attrs);
4419 attrs = Fcons (Fcons (Qstime, make_lisp_time (stime)), attrs);
4420 attrs = Fcons (Fcons (Qtime, make_lisp_time (timespec_add (utime, stime))), attrs);
4421
4422 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (ri.ri_pageins)), attrs);
4423 }
4424 #else
4425 struct rusage *rusage = proc.kp_proc.p_ru;
4426 if (rusage)
4427 {
4428 attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (rusage->ru_minflt)),
4429 attrs);
4430 attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (rusage->ru_majflt)),
4431 attrs);
4432
4433 Lisp_Object utime = make_lisp_timeval (rusage->ru_utime);
4434 Lisp_Object stime = make_lisp_timeval (rusage->ru_stime);
4435 attrs = Fcons (Fcons (Qutime, utime), attrs);
4436 attrs = Fcons (Fcons (Qstime, stime), attrs);
4437 attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
4438 }
4439 #endif
4440
4441 starttime = proc.kp_proc.p_starttime;
4442 attrs = Fcons (Fcons (Qnice, make_fixnum (proc.kp_proc.p_nice)), attrs);
4443 Lisp_Object start = make_lisp_timeval (starttime);
4444 attrs = Fcons (Fcons (Qstart, start), attrs);
4445
4446 Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
4447 Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
4448 attrs = Fcons (Fcons (Qetime, etime), attrs);
4449
4450 #if HAVE_PROC_PIDINFO
4451 struct proc_taskinfo taskinfo;
4452 if (proc_pidinfo (proc_id, PROC_PIDTASKINFO, 0, &taskinfo, sizeof (taskinfo)) > 0)
4453 {
4454 attrs = Fcons (Fcons (Qvsize, make_fixnum (taskinfo.pti_virtual_size / 1024)), attrs);
4455 attrs = Fcons (Fcons (Qrss, make_fixnum (taskinfo.pti_resident_size / 1024)), attrs);
4456 attrs = Fcons (Fcons (Qthcount, make_fixnum (taskinfo.pti_threadnum)), attrs);
4457 }
4458 #endif
4459
4460 #ifdef KERN_PROCARGS2
4461 char args[ARG_MAX];
4462 mib[1] = KERN_PROCARGS2;
4463 mib[2] = proc_id;
4464 len = sizeof args;
4465
4466 if (sysctl (mib, 3, &args, &len, NULL, 0) == 0 && len != 0)
4467 {
4468 char *start, *end;
4469
4470 int argc = *(int*)args;
4471 start = args + sizeof (int);
4472
4473 start += strlen (start) + 1;
4474 while ((start - args < len) && ! *start) start++;
4475
4476
4477 for (i = 0, end = start; i < argc && (end - args) < len; i++)
4478 {
4479 end += strlen (end) + 1;
4480 }
4481
4482 len = end - start;
4483 for (int i = 0; i < len; i++)
4484 {
4485 if (! start[i] && i < len - 1)
4486 start[i] = ' ';
4487 }
4488
4489 AUTO_STRING (comm, start);
4490 decoded_comm = code_convert_string_norecord (comm,
4491 Vlocale_coding_system, 0);
4492 attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
4493 }
4494 #endif
4495
4496 return attrs;
4497 }
4498
4499
4500
4501
4502 #elif !defined (WINDOWSNT) && !defined (MSDOS) && !defined (HAIKU)
4503
4504 Lisp_Object
4505 system_process_attributes (Lisp_Object pid)
4506 {
4507 return Qnil;
4508 }
4509
4510 #endif
4511
4512 DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
4513 0, 0, 0,
4514 doc:
4515
4516
4517
4518 )
4519 (void)
4520 {
4521 #ifdef HAVE_GETRUSAGE
4522 struct rusage usage;
4523 time_t secs;
4524 int usecs;
4525
4526 if (getrusage (RUSAGE_SELF, &usage) < 0)
4527
4528 xsignal0 (Qerror);
4529
4530
4531 secs = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
4532 usecs = usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
4533 if (usecs >= 1000000)
4534 {
4535 usecs -= 1000000;
4536 secs++;
4537 }
4538 return make_lisp_s_us (secs, usecs);
4539 #else
4540 #ifdef WINDOWSNT
4541 return w32_get_internal_run_time ();
4542 #else
4543 return Fcurrent_time ();
4544 #endif
4545 #endif
4546 }
4547
4548
4549
4550 #ifdef __STDC_ISO_10646__
4551 # include <wchar.h>
4552 # include <wctype.h>
4553
4554 # if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE
4555 # include <locale.h>
4556 # endif
4557 # ifndef LC_COLLATE
4558 # define LC_COLLATE 0
4559 # endif
4560 # ifndef LC_COLLATE_MASK
4561 # define LC_COLLATE_MASK 0
4562 # endif
4563 # ifndef LC_CTYPE
4564 # define LC_CTYPE 0
4565 # endif
4566 # ifndef LC_CTYPE_MASK
4567 # define LC_CTYPE_MASK 0
4568 # endif
4569
4570 # ifndef HAVE_NEWLOCALE
4571 # undef freelocale
4572 # undef locale_t
4573 # undef newlocale
4574 # undef wcscoll_l
4575 # undef towlower_l
4576 # define freelocale emacs_freelocale
4577 # define locale_t emacs_locale_t
4578 # define newlocale emacs_newlocale
4579 # define wcscoll_l emacs_wcscoll_l
4580 # define towlower_l emacs_towlower_l
4581
4582 typedef char const *locale_t;
4583
4584 static locale_t
4585 newlocale (int category_mask, char const *locale, locale_t loc)
4586 {
4587 return locale;
4588 }
4589
4590 static void
4591 freelocale (locale_t loc)
4592 {
4593 }
4594
4595 static char *
4596 emacs_setlocale (int category, char const *locale)
4597 {
4598 # ifdef HAVE_SETLOCALE
4599 errno = 0;
4600 char *loc = setlocale (category, locale);
4601 if (loc || errno)
4602 return loc;
4603 errno = EINVAL;
4604 # else
4605 errno = ENOTSUP;
4606 # endif
4607 return 0;
4608 }
4609
4610 static int
4611 wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc)
4612 {
4613 int result = 0;
4614 char *oldloc = emacs_setlocale (LC_COLLATE, NULL);
4615 int err;
4616
4617 if (! oldloc)
4618 err = errno;
4619 else
4620 {
4621 USE_SAFE_ALLOCA;
4622 char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
4623 strcpy (oldcopy, oldloc);
4624 if (! emacs_setlocale (LC_COLLATE, loc))
4625 err = errno;
4626 else
4627 {
4628 errno = 0;
4629 result = wcscoll (a, b);
4630 err = errno;
4631 if (! emacs_setlocale (LC_COLLATE, oldcopy))
4632 err = errno;
4633 }
4634 SAFE_FREE ();
4635 }
4636
4637 errno = err;
4638 return result;
4639 }
4640
4641 static wint_t
4642 towlower_l (wint_t wc, locale_t loc)
4643 {
4644 wint_t result = wc;
4645 char *oldloc = emacs_setlocale (LC_CTYPE, NULL);
4646
4647 if (oldloc)
4648 {
4649 USE_SAFE_ALLOCA;
4650 char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1);
4651 strcpy (oldcopy, oldloc);
4652 if (emacs_setlocale (LC_CTYPE, loc))
4653 {
4654 result = towlower (wc);
4655 emacs_setlocale (LC_COLLATE, oldcopy);
4656 }
4657 SAFE_FREE ();
4658 }
4659
4660 return result;
4661 }
4662 # endif
4663
4664 int
4665 str_collate (Lisp_Object s1, Lisp_Object s2,
4666 Lisp_Object locale, Lisp_Object ignore_case)
4667 {
4668 int res, err;
4669 ptrdiff_t len, i, i_byte;
4670 wchar_t *p1, *p2;
4671
4672 USE_SAFE_ALLOCA;
4673
4674
4675 len = SCHARS (s1); i = i_byte = 0;
4676 SAFE_NALLOCA (p1, 1, len + 1);
4677 while (i < len)
4678 {
4679 wchar_t *p = &p1[i];
4680 *p = fetch_string_char_advance (s1, &i, &i_byte);
4681 }
4682 p1[len] = 0;
4683
4684 len = SCHARS (s2); i = i_byte = 0;
4685 SAFE_NALLOCA (p2, 1, len + 1);
4686 while (i < len)
4687 {
4688 wchar_t *p = &p2[i];
4689 *p = fetch_string_char_advance (s2, &i, &i_byte);
4690 }
4691 p2[len] = 0;
4692
4693 if (STRINGP (locale))
4694 {
4695 locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK,
4696 SSDATA (locale), 0);
4697 if (!loc)
4698 error ("Invalid locale %s: %s", SSDATA (locale), emacs_strerror (errno));
4699
4700 if (! NILP (ignore_case))
4701 for (int i = 1; i < 3; i++)
4702 {
4703 wchar_t *p = (i == 1) ? p1 : p2;
4704 for (; *p; p++)
4705 *p = towlower_l (*p, loc);
4706 }
4707
4708 errno = 0;
4709 res = wcscoll_l (p1, p2, loc);
4710 err = errno;
4711 freelocale (loc);
4712 }
4713 else
4714 {
4715 if (! NILP (ignore_case))
4716 for (int i = 1; i < 3; i++)
4717 {
4718 wchar_t *p = (i == 1) ? p1 : p2;
4719 for (; *p; p++)
4720 *p = towlower (*p);
4721 }
4722
4723 errno = 0;
4724 res = wcscoll (p1, p2);
4725 err = errno;
4726 }
4727 # ifndef HAVE_NEWLOCALE
4728 if (err)
4729 error ("Invalid locale or string for collation: %s", emacs_strerror (err));
4730 # else
4731 if (err)
4732 error ("Invalid string for collation: %s", emacs_strerror (err));
4733 # endif
4734
4735 SAFE_FREE ();
4736 return res;
4737 }
4738 #endif
4739
4740 #ifdef WINDOWSNT
4741 int
4742 str_collate (Lisp_Object s1, Lisp_Object s2,
4743 Lisp_Object locale, Lisp_Object ignore_case)
4744 {
4745
4746 char *loc = STRINGP (locale) ? SSDATA (locale) : NULL;
4747 int res, err = errno;
4748
4749 errno = 0;
4750 res = w32_compare_strings (SSDATA (s1), SSDATA (s2), loc, !NILP (ignore_case));
4751 if (errno)
4752 error ("Invalid string for collation: %s", strerror (errno));
4753
4754 errno = err;
4755 return res;
4756 }
4757 #endif
4758
4759 void
4760 syms_of_sysdep (void)
4761 {
4762 defsubr (&Sget_internal_run_time);
4763 }