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