Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[bpt/emacs.git] / src / sysdep.c
1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <ctype.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <setjmp.h>
29 #ifdef HAVE_PWD_H
30 #include <pwd.h>
31 #include <grp.h>
32 #endif /* HAVE_PWD_H */
33 #ifdef HAVE_LIMITS_H
34 #include <limits.h>
35 #endif /* HAVE_LIMITS_H */
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include "lisp.h"
41 /* Including stdlib.h isn't necessarily enough to get srandom
42 declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2. */
43
44 /* The w32 build defines select stuff in w32.h, which is included by
45 sys/select.h (included below). */
46 #ifndef WINDOWSNT
47 #include "sysselect.h"
48 #endif
49
50 #include "blockinput.h"
51
52 #ifdef WINDOWSNT
53 #define read sys_read
54 #define write sys_write
55 #include <windows.h>
56 #ifndef NULL
57 #define NULL 0
58 #endif
59 #endif /* not WINDOWSNT */
60
61 #include <sys/types.h>
62 #include <sys/stat.h>
63 #include <errno.h>
64
65 #ifdef HAVE_SETPGID
66 #if !defined (USG)
67 #undef setpgrp
68 #define setpgrp setpgid
69 #endif
70 #endif
71
72 /* Get SI_SRPC_DOMAIN, if it is available. */
73 #ifdef HAVE_SYS_SYSTEMINFO_H
74 #include <sys/systeminfo.h>
75 #endif
76
77 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
78 #include <dos.h>
79 #include "dosfns.h"
80 #include "msdos.h"
81 #include <sys/param.h>
82
83 extern int etext;
84 extern unsigned start __asm__ ("start");
85 #endif
86
87 #include <sys/file.h>
88
89 #ifdef HAVE_FCNTL_H
90 #include <fcntl.h>
91 #endif
92
93 #ifndef MSDOS
94 #include <sys/ioctl.h>
95 #endif
96
97 #include "systty.h"
98 #include "syswait.h"
99
100 #if defined (USG)
101 #include <sys/utsname.h>
102 #include <memory.h>
103 #endif /* USG */
104
105 extern int quit_char;
106
107 #include "keyboard.h"
108 #include "frame.h"
109 #include "window.h"
110 #include "termhooks.h"
111 #include "termchar.h"
112 #include "termopts.h"
113 #include "dispextern.h"
114 #include "process.h"
115 #include "cm.h" /* for reset_sys_modes */
116
117 /* For serial_configure and serial_open. */
118 extern Lisp_Object QCport, QCspeed, QCprocess;
119 extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
120 extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
121
122 #ifdef WINDOWSNT
123 #include <direct.h>
124 /* In process.h which conflicts with the local copy. */
125 #define _P_WAIT 0
126 int _cdecl _spawnlp (int, const char *, const char *, ...);
127 int _cdecl _getpid (void);
128 extern char *getwd (char *);
129 #endif
130
131 #include "syssignal.h"
132 #include "systime.h"
133 #ifdef HAVE_UTIME_H
134 #include <utime.h>
135 #endif
136
137 #ifndef HAVE_UTIMES
138 #ifndef HAVE_STRUCT_UTIMBUF
139 /* We want to use utime rather than utimes, but we couldn't find the
140 structure declaration. We'll use the traditional one. */
141 struct utimbuf {
142 long actime;
143 long modtime;
144 };
145 #endif
146 #endif
147
148 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
149 #ifndef LPASS8
150 #define LPASS8 0
151 #endif
152
153 static const int baud_convert[] =
154 {
155 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
156 1800, 2400, 4800, 9600, 19200, 38400
157 };
158
159 #ifdef HAVE_SPEED_T
160 #include <termios.h>
161 #else
162 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
163 #else
164 #if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
165 #include <termios.h>
166 #endif
167 #endif
168 #endif
169
170 int emacs_ospeed;
171
172 void croak (char *) NO_RETURN;
173
174 /* Temporary used by `sigblock' when defined in terms of signprocmask. */
175
176 SIGMASKTYPE sigprocmask_set;
177
178
179 #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
180
181 /* Return the current working directory. Returns NULL on errors.
182 Any other returned value must be freed with free. This is used
183 only when get_current_dir_name is not defined on the system. */
184 char*
185 get_current_dir_name (void)
186 {
187 char *buf;
188 char *pwd;
189 struct stat dotstat, pwdstat;
190 /* If PWD is accurate, use it instead of calling getwd. PWD is
191 sometimes a nicer name, and using it may avoid a fatal error if a
192 parent directory is searchable but not readable. */
193 if ((pwd = getenv ("PWD")) != 0
194 && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
195 && stat (pwd, &pwdstat) == 0
196 && stat (".", &dotstat) == 0
197 && dotstat.st_ino == pwdstat.st_ino
198 && dotstat.st_dev == pwdstat.st_dev
199 #ifdef MAXPATHLEN
200 && strlen (pwd) < MAXPATHLEN
201 #endif
202 )
203 {
204 buf = (char *) malloc (strlen (pwd) + 1);
205 if (!buf)
206 return NULL;
207 strcpy (buf, pwd);
208 }
209 #ifdef HAVE_GETCWD
210 else
211 {
212 size_t buf_size = 1024;
213 buf = (char *) malloc (buf_size);
214 if (!buf)
215 return NULL;
216 for (;;)
217 {
218 if (getcwd (buf, buf_size) == buf)
219 break;
220 if (errno != ERANGE)
221 {
222 int tmp_errno = errno;
223 free (buf);
224 errno = tmp_errno;
225 return NULL;
226 }
227 buf_size *= 2;
228 buf = (char *) realloc (buf, buf_size);
229 if (!buf)
230 return NULL;
231 }
232 }
233 #else
234 else
235 {
236 /* We need MAXPATHLEN here. */
237 buf = (char *) malloc (MAXPATHLEN + 1);
238 if (!buf)
239 return NULL;
240 if (getwd (buf) == NULL)
241 {
242 int tmp_errno = errno;
243 free (buf);
244 errno = tmp_errno;
245 return NULL;
246 }
247 }
248 #endif
249 return buf;
250 }
251 #endif
252
253 \f
254 /* Discard pending input on all input descriptors. */
255
256 void
257 discard_tty_input (void)
258 {
259 #ifndef WINDOWSNT
260 struct emacs_tty buf;
261
262 if (noninteractive)
263 return;
264
265 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
266 while (dos_keyread () != -1)
267 ;
268 #else /* not MSDOS */
269 {
270 struct tty_display_info *tty;
271 for (tty = tty_list; tty; tty = tty->next)
272 {
273 if (tty->input) /* Is the device suspended? */
274 {
275 EMACS_GET_TTY (fileno (tty->input), &buf);
276 EMACS_SET_TTY (fileno (tty->input), &buf, 0);
277 }
278 }
279 }
280 #endif /* not MSDOS */
281 #endif /* not WINDOWSNT */
282 }
283
284 \f
285 #ifdef SIGTSTP
286
287 /* Arrange for character C to be read as the next input from
288 the terminal.
289 XXX What if we have multiple ttys?
290 */
291
292 void
293 stuff_char (char c)
294 {
295 if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
296 return;
297
298 /* Should perhaps error if in batch mode */
299 #ifdef TIOCSTI
300 ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
301 #else /* no TIOCSTI */
302 error ("Cannot stuff terminal input characters in this version of Unix");
303 #endif /* no TIOCSTI */
304 }
305
306 #endif /* SIGTSTP */
307 \f
308 void
309 init_baud_rate (int fd)
310 {
311 if (noninteractive)
312 emacs_ospeed = 0;
313 else
314 {
315 #ifdef DOS_NT
316 emacs_ospeed = 15;
317 #else /* not DOS_NT */
318 #ifdef HAVE_TERMIOS
319 struct termios sg;
320
321 sg.c_cflag = B9600;
322 tcgetattr (fd, &sg);
323 emacs_ospeed = cfgetospeed (&sg);
324 #else /* not TERMIOS */
325 #ifdef HAVE_TERMIO
326 struct termio sg;
327
328 sg.c_cflag = B9600;
329 #ifdef HAVE_TCATTR
330 tcgetattr (fd, &sg);
331 #else
332 ioctl (fd, TCGETA, &sg);
333 #endif
334 emacs_ospeed = sg.c_cflag & CBAUD;
335 #else /* neither TERMIOS nor TERMIO */
336 struct sgttyb sg;
337
338 sg.sg_ospeed = B9600;
339 if (ioctl (fd, TIOCGETP, &sg) < 0)
340 abort ();
341 emacs_ospeed = sg.sg_ospeed;
342 #endif /* not HAVE_TERMIO */
343 #endif /* not HAVE_TERMIOS */
344 #endif /* not DOS_NT */
345 }
346
347 baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
348 ? baud_convert[emacs_ospeed] : 9600);
349 if (baud_rate == 0)
350 baud_rate = 1200;
351 }
352
353 \f
354 /*ARGSUSED*/
355 void
356 set_exclusive_use (int fd)
357 {
358 #ifdef FIOCLEX
359 ioctl (fd, FIOCLEX, 0);
360 #endif
361 /* Ok to do nothing if this feature does not exist */
362 }
363 \f
364 #ifndef subprocesses
365
366 void
367 wait_without_blocking (void)
368 {
369 croak ("wait_without_blocking");
370 synch_process_alive = 0;
371 }
372
373 #endif /* not subprocesses */
374
375 int wait_debugging; /* Set nonzero to make following function work under dbx
376 (at least for bsd). */
377
378 SIGTYPE
379 wait_for_termination_signal (void)
380 {}
381
382 /* Wait for subprocess with process id `pid' to terminate and
383 make sure it will get eliminated (not remain forever as a zombie) */
384
385 void
386 wait_for_termination (int pid)
387 {
388 while (1)
389 {
390 #ifdef subprocesses
391 #if defined (BSD_SYSTEM) || defined (HPUX)
392 /* Note that kill returns -1 even if the process is just a zombie now.
393 But inevitably a SIGCHLD interrupt should be generated
394 and child_sig will do wait3 and make the process go away. */
395 /* There is some indication that there is a bug involved with
396 termination of subprocesses, perhaps involving a kernel bug too,
397 but no idea what it is. Just as a hunch we signal SIGCHLD to see
398 if that causes the problem to go away or get worse. */
399 sigsetmask (sigmask (SIGCHLD));
400 if (0 > kill (pid, 0))
401 {
402 sigsetmask (SIGEMPTYMASK);
403 kill (getpid (), SIGCHLD);
404 break;
405 }
406 if (wait_debugging)
407 sleep (1);
408 else
409 sigpause (SIGEMPTYMASK);
410 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
411 #ifdef WINDOWSNT
412 wait (0);
413 break;
414 #else /* not WINDOWSNT */
415 sigblock (sigmask (SIGCHLD));
416 errno = 0;
417 if (kill (pid, 0) == -1 && errno == ESRCH)
418 {
419 sigunblock (sigmask (SIGCHLD));
420 break;
421 }
422
423 sigsuspend (&empty_mask);
424 #endif /* not WINDOWSNT */
425 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
426 #else /* not subprocesses */
427 break;
428 #endif /* not subprocesses */
429 }
430 }
431
432 #ifdef subprocesses
433
434 /*
435 * flush any pending output
436 * (may flush input as well; it does not matter the way we use it)
437 */
438
439 void
440 flush_pending_output (int channel)
441 {
442 #ifdef HAVE_TERMIOS
443 /* If we try this, we get hit with SIGTTIN, because
444 the child's tty belongs to the child's pgrp. */
445 #else
446 #ifdef TCFLSH
447 ioctl (channel, TCFLSH, 1);
448 #else
449 #ifdef TIOCFLUSH
450 int zero = 0;
451 /* 3rd arg should be ignored
452 but some 4.2 kernels actually want the address of an int
453 and nonzero means something different. */
454 ioctl (channel, TIOCFLUSH, &zero);
455 #endif
456 #endif
457 #endif
458 }
459 \f
460 /* Set up the terminal at the other end of a pseudo-terminal that
461 we will be controlling an inferior through.
462 It should not echo or do line-editing, since that is done
463 in Emacs. No padding needed for insertion into an Emacs buffer. */
464
465 void
466 child_setup_tty (int out)
467 {
468 #ifndef DOS_NT
469 struct emacs_tty s;
470
471 EMACS_GET_TTY (out, &s);
472
473 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
474 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
475 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
476 #ifdef NLDLY
477 /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
478 Some versions of GNU Hurd do not have FFDLY? */
479 #ifdef FFDLY
480 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
481 /* No output delays */
482 #else
483 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
484 /* No output delays */
485 #endif
486 #endif
487 s.main.c_lflag &= ~ECHO; /* Disable echo */
488 s.main.c_lflag |= ISIG; /* Enable signals */
489 #ifdef IUCLC
490 s.main.c_iflag &= ~IUCLC; /* Disable downcasing on input. */
491 #endif
492 #ifdef ISTRIP
493 s.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
494 #endif
495 #ifdef OLCUC
496 s.main.c_oflag &= ~OLCUC; /* Disable upcasing on output. */
497 #endif
498 s.main.c_oflag &= ~TAB3; /* Disable tab expansion */
499 s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
500 s.main.c_cc[VERASE] = CDISABLE; /* disable erase processing */
501 s.main.c_cc[VKILL] = CDISABLE; /* disable kill processing */
502
503 #ifdef HPUX
504 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
505 #endif /* HPUX */
506
507 #ifdef SIGNALS_VIA_CHARACTERS
508 /* the QUIT and INTR character are used in process_send_signal
509 so set them here to something useful. */
510 if (s.main.c_cc[VQUIT] == CDISABLE)
511 s.main.c_cc[VQUIT] = '\\'&037; /* Control-\ */
512 if (s.main.c_cc[VINTR] == CDISABLE)
513 s.main.c_cc[VINTR] = 'C'&037; /* Control-C */
514 #endif /* not SIGNALS_VIA_CHARACTERS */
515
516 #ifdef AIX
517 /* Also, PTY overloads NUL and BREAK.
518 don't ignore break, but don't signal either, so it looks like NUL. */
519 s.main.c_iflag &= ~IGNBRK;
520 s.main.c_iflag &= ~BRKINT;
521 /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
522 unconditionally. Then a SIGNALS_VIA_CHARACTERS conditional
523 would force it to 0377. That looks like duplicated code. */
524 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
525 #endif /* AIX */
526
527 /* We used to enable ICANON (and set VEOF to 04), but this leads to
528 problems where process.c wants to send EOFs every once in a while
529 to force the output, which leads to weird effects when the
530 subprocess has disabled ICANON and ends up seeing those spurious
531 extra EOFs. So we don't send EOFs any more in
532 process.c:send_process, and instead we disable ICANON by default,
533 so if a subsprocess sets up ICANON, it's his problem (or the Elisp
534 package that talks to it) to deal with lines that are too long. */
535 s.main.c_lflag &= ~ICANON; /* Disable line editing and eof processing */
536 s.main.c_cc[VMIN] = 1;
537 s.main.c_cc[VTIME] = 0;
538
539 #else /* not HAVE_TERMIO */
540
541 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
542 | CBREAK | TANDEM);
543 s.main.sg_flags |= LPASS8;
544 s.main.sg_erase = 0377;
545 s.main.sg_kill = 0377;
546 s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
547
548 #endif /* not HAVE_TERMIO */
549
550 EMACS_SET_TTY (out, &s, 0);
551
552 #endif /* not DOS_NT */
553 }
554
555 #endif /* subprocesses */
556 \f
557 /* Record a signal code and the handler for it. */
558 struct save_signal
559 {
560 int code;
561 SIGTYPE (*handler) (int);
562 };
563
564 static void save_signal_handlers (struct save_signal *);
565 static void restore_signal_handlers (struct save_signal *);
566
567 /* Suspend the Emacs process; give terminal to its superior. */
568
569 void
570 sys_suspend (void)
571 {
572 #if defined (SIGTSTP) && !defined (MSDOS)
573
574 {
575 int pgrp = EMACS_GETPGRP (0);
576 EMACS_KILLPG (pgrp, SIGTSTP);
577 }
578
579 #else /* No SIGTSTP */
580 /* On a system where suspending is not implemented,
581 instead fork a subshell and let it talk directly to the terminal
582 while we wait. */
583 sys_subshell ();
584
585 #endif /* no SIGTSTP */
586 }
587
588 /* Fork a subshell. */
589
590 void
591 sys_subshell (void)
592 {
593 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
594 int st;
595 char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
596 #endif
597 int pid;
598 struct save_signal saved_handlers[5];
599 Lisp_Object dir;
600 unsigned char *str = 0;
601 int len;
602
603 saved_handlers[0].code = SIGINT;
604 saved_handlers[1].code = SIGQUIT;
605 saved_handlers[2].code = SIGTERM;
606 #ifdef SIGIO
607 saved_handlers[3].code = SIGIO;
608 saved_handlers[4].code = 0;
609 #else
610 saved_handlers[3].code = 0;
611 #endif
612
613 /* Mentioning current_buffer->buffer would mean including buffer.h,
614 which somehow wedges the hp compiler. So instead... */
615
616 dir = intern ("default-directory");
617 if (NILP (Fboundp (dir)))
618 goto xyzzy;
619 dir = Fsymbol_value (dir);
620 if (!STRINGP (dir))
621 goto xyzzy;
622
623 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
624 str = (unsigned char *) alloca (SCHARS (dir) + 2);
625 len = SCHARS (dir);
626 memcpy (str, SDATA (dir), len);
627 if (str[len - 1] != '/') str[len++] = '/';
628 str[len] = 0;
629 xyzzy:
630
631 #ifdef DOS_NT
632 pid = 0;
633 save_signal_handlers (saved_handlers);
634 synch_process_alive = 1;
635 #else
636 pid = vfork ();
637 if (pid == -1)
638 error ("Can't spawn subshell");
639 #endif
640
641 if (pid == 0)
642 {
643 char *sh = 0;
644
645 #ifdef DOS_NT /* MW, Aug 1993 */
646 getwd (oldwd);
647 if (sh == 0)
648 sh = (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
649 #endif
650 if (sh == 0)
651 sh = (char *) egetenv ("SHELL");
652 if (sh == 0)
653 sh = "sh";
654
655 /* Use our buffer's default directory for the subshell. */
656 if (str)
657 chdir ((char *) str);
658
659 #ifdef subprocesses
660 close_process_descs (); /* Close Emacs's pipes/ptys */
661 #endif
662
663 #ifdef SET_EMACS_PRIORITY
664 {
665 extern EMACS_INT emacs_priority;
666
667 if (emacs_priority < 0)
668 nice (-emacs_priority);
669 }
670 #endif
671
672 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
673 {
674 char *epwd = getenv ("PWD");
675 char old_pwd[MAXPATHLEN+1+4];
676
677 /* If PWD is set, pass it with corrected value. */
678 if (epwd)
679 {
680 strcpy (old_pwd, epwd);
681 if (str[len - 1] == '/')
682 str[len - 1] = '\0';
683 setenv ("PWD", str, 1);
684 }
685 st = system (sh);
686 chdir (oldwd);
687 if (epwd)
688 putenv (old_pwd); /* restore previous value */
689 }
690 #else /* not MSDOS */
691 #ifdef WINDOWSNT
692 /* Waits for process completion */
693 pid = _spawnlp (_P_WAIT, sh, sh, NULL);
694 chdir (oldwd);
695 if (pid == -1)
696 write (1, "Can't execute subshell", 22);
697 #else /* not WINDOWSNT */
698 execlp (sh, sh, (char *) 0);
699 write (1, "Can't execute subshell", 22);
700 _exit (1);
701 #endif /* not WINDOWSNT */
702 #endif /* not MSDOS */
703 }
704
705 /* Do this now if we did not do it before. */
706 #ifndef MSDOS
707 save_signal_handlers (saved_handlers);
708 synch_process_alive = 1;
709 #endif
710
711 #ifndef DOS_NT
712 wait_for_termination (pid);
713 #endif
714 restore_signal_handlers (saved_handlers);
715 synch_process_alive = 0;
716 }
717
718 static void
719 save_signal_handlers (struct save_signal *saved_handlers)
720 {
721 while (saved_handlers->code)
722 {
723 saved_handlers->handler
724 = (SIGTYPE (*) (int)) signal (saved_handlers->code, SIG_IGN);
725 saved_handlers++;
726 }
727 }
728
729 static void
730 restore_signal_handlers (struct save_signal *saved_handlers)
731 {
732 while (saved_handlers->code)
733 {
734 signal (saved_handlers->code, saved_handlers->handler);
735 saved_handlers++;
736 }
737 }
738 \f
739 #ifndef SIGIO
740 /* If SIGIO is broken, don't do anything. */
741 void
742 init_sigio (int fd)
743 {
744 }
745
746 void
747 reset_sigio (int fd)
748 {
749 }
750
751 void
752 request_sigio (void)
753 {
754 }
755
756 void
757 unrequest_sigio (void)
758 {
759 }
760
761 #else
762 #ifdef F_SETFL
763
764 int old_fcntl_flags[MAXDESC];
765
766 void
767 init_sigio (int fd)
768 {
769 #ifdef FASYNC
770 old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
771 fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
772 #endif
773 interrupts_deferred = 0;
774 }
775
776 void
777 reset_sigio (int fd)
778 {
779 #ifdef FASYNC
780 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
781 #endif
782 }
783
784 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
785 /* XXX Uhm, FASYNC is not used anymore here. */
786 /* XXX Yeah, but you need it for SIGIO, don't you? */
787
788 void
789 request_sigio (void)
790 {
791 if (noninteractive)
792 return;
793
794 #ifdef SIGWINCH
795 sigunblock (sigmask (SIGWINCH));
796 #endif
797 sigunblock (sigmask (SIGIO));
798
799 interrupts_deferred = 0;
800 }
801
802 void
803 unrequest_sigio (void)
804 {
805 if (noninteractive)
806 return;
807
808 #if 0 /* XXX What's wrong with blocking SIGIO under X? */
809 if (x_display_list)
810 return;
811 #endif
812
813 #ifdef SIGWINCH
814 sigblock (sigmask (SIGWINCH));
815 #endif
816 sigblock (sigmask (SIGIO));
817 interrupts_deferred = 1;
818 }
819
820 #else /* no FASYNC */
821 #ifndef MSDOS
822
823 void
824 request_sigio (void)
825 {
826 if (noninteractive || read_socket_hook)
827 return;
828
829 croak ("request_sigio");
830 }
831
832 void
833 unrequest_sigio (void)
834 {
835 if (noninteractive || read_socket_hook)
836 return;
837
838 croak ("unrequest_sigio");
839 }
840
841 #endif /* MSDOS */
842 #endif /* FASYNC */
843 #endif /* F_SETFL */
844 #endif /* SIGIO */
845
846 \f
847 /* Getting and setting emacs_tty structures. */
848
849 /* Set *TC to the parameters associated with the terminal FD.
850 Return zero if all's well, or -1 if we ran into an error we
851 couldn't deal with. */
852 int
853 emacs_get_tty (int fd, struct emacs_tty *settings)
854 {
855 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
856 #ifdef HAVE_TCATTR
857 /* We have those nifty POSIX tcmumbleattr functions. */
858 memset (&settings->main, 0, sizeof (settings->main));
859 if (tcgetattr (fd, &settings->main) < 0)
860 return -1;
861
862 #else
863 #ifdef HAVE_TERMIO
864 /* The SYSV-style interface? */
865 if (ioctl (fd, TCGETA, &settings->main) < 0)
866 return -1;
867
868 #else
869 #ifndef DOS_NT
870 /* I give up - I hope you have the BSD ioctls. */
871 if (ioctl (fd, TIOCGETP, &settings->main) < 0)
872 return -1;
873 #endif /* not DOS_NT */
874 #endif
875 #endif
876
877 /* Suivant - Do we have to get struct ltchars data? */
878 #ifdef HAVE_LTCHARS
879 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
880 return -1;
881 #endif
882
883 /* How about a struct tchars and a wordful of lmode bits? */
884 #ifdef HAVE_TCHARS
885 if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
886 || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
887 return -1;
888 #endif
889
890 /* We have survived the tempest. */
891 return 0;
892 }
893
894
895 /* Set the parameters of the tty on FD according to the contents of
896 *SETTINGS. If FLUSHP is non-zero, we discard input.
897 Return 0 if all went well, and -1 if anything failed. */
898
899 int
900 emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
901 {
902 /* Set the primary parameters - baud rate, character size, etcetera. */
903 #ifdef HAVE_TCATTR
904 int i;
905 /* We have those nifty POSIX tcmumbleattr functions.
906 William J. Smith <wjs@wiis.wang.com> writes:
907 "POSIX 1003.1 defines tcsetattr to return success if it was
908 able to perform any of the requested actions, even if some
909 of the requested actions could not be performed.
910 We must read settings back to ensure tty setup properly.
911 AIX requires this to keep tty from hanging occasionally." */
912 /* This make sure that we don't loop indefinitely in here. */
913 for (i = 0 ; i < 10 ; i++)
914 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
915 {
916 if (errno == EINTR)
917 continue;
918 else
919 return -1;
920 }
921 else
922 {
923 struct termios new;
924
925 memset (&new, 0, sizeof (new));
926 /* Get the current settings, and see if they're what we asked for. */
927 tcgetattr (fd, &new);
928 /* We cannot use memcmp on the whole structure here because under
929 * aix386 the termios structure has some reserved field that may
930 * not be filled in.
931 */
932 if ( new.c_iflag == settings->main.c_iflag
933 && new.c_oflag == settings->main.c_oflag
934 && new.c_cflag == settings->main.c_cflag
935 && new.c_lflag == settings->main.c_lflag
936 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
937 break;
938 else
939 continue;
940 }
941
942 #else
943 #ifdef HAVE_TERMIO
944 /* The SYSV-style interface? */
945 if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
946 return -1;
947
948 #else
949 #ifndef DOS_NT
950 /* I give up - I hope you have the BSD ioctls. */
951 if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
952 return -1;
953 #endif /* not DOS_NT */
954
955 #endif
956 #endif
957
958 /* Suivant - Do we have to get struct ltchars data? */
959 #ifdef HAVE_LTCHARS
960 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
961 return -1;
962 #endif
963
964 /* How about a struct tchars and a wordful of lmode bits? */
965 #ifdef HAVE_TCHARS
966 if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
967 || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
968 return -1;
969 #endif
970
971 /* We have survived the tempest. */
972 return 0;
973 }
974
975 \f
976
977 #ifdef F_SETOWN
978 int old_fcntl_owner[MAXDESC];
979 #endif /* F_SETOWN */
980
981 /* This may also be defined in stdio,
982 but if so, this does no harm,
983 and using the same name avoids wasting the other one's space. */
984
985 #if defined (USG)
986 unsigned char _sobuf[BUFSIZ+8];
987 #else
988 char _sobuf[BUFSIZ];
989 #endif
990
991 #ifdef HAVE_LTCHARS
992 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
993 #endif
994 #ifdef HAVE_TCHARS
995 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
996 #endif
997
998 /* Initialize the terminal mode on all tty devices that are currently
999 open. */
1000
1001 void
1002 init_all_sys_modes (void)
1003 {
1004 struct tty_display_info *tty;
1005 for (tty = tty_list; tty; tty = tty->next)
1006 init_sys_modes (tty);
1007 }
1008
1009 /* Initialize the terminal mode on the given tty device. */
1010
1011 void
1012 init_sys_modes (struct tty_display_info *tty_out)
1013 {
1014 struct emacs_tty tty;
1015
1016 Vtty_erase_char = Qnil;
1017
1018 if (noninteractive)
1019 return;
1020
1021 if (!tty_out->output)
1022 return; /* The tty is suspended. */
1023
1024 if (! tty_out->old_tty)
1025 tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
1026
1027 EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
1028
1029 tty = *tty_out->old_tty;
1030
1031 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1032 XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
1033
1034 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
1035 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
1036 #ifdef INLCR /* I'm just being cautious,
1037 since I can't check how widespread INLCR is--rms. */
1038 tty.main.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
1039 #endif
1040 #ifdef ISTRIP
1041 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
1042 #endif
1043 tty.main.c_lflag &= ~ECHO; /* Disable echo */
1044 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
1045 #ifdef IEXTEN
1046 tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
1047 #endif
1048 tty.main.c_lflag |= ISIG; /* Enable signals */
1049 if (tty_out->flow_control)
1050 {
1051 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
1052 #ifdef IXANY
1053 tty.main.c_iflag &= ~IXANY;
1054 #endif /* IXANY */
1055 }
1056 else
1057 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
1058 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
1059 on output */
1060 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
1061 #ifdef CS8
1062 if (tty_out->meta_key)
1063 {
1064 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
1065 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1066 }
1067 #endif
1068 if (tty_out->input == stdin)
1069 {
1070 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
1071 /* Set up C-g for both SIGQUIT and SIGINT.
1072 We don't know which we will get, but we handle both alike
1073 so which one it really gives us does not matter. */
1074 tty.main.c_cc[VQUIT] = quit_char;
1075 }
1076 else
1077 {
1078 /* We normally don't get interrupt or quit signals from tty
1079 devices other than our controlling terminal; therefore,
1080 we must handle C-g as normal input. Unfortunately, this
1081 means that the interrupt and quit feature must be
1082 disabled on secondary ttys, or we would not even see the
1083 keypress.
1084
1085 Note that even though emacsclient could have special code
1086 to pass SIGINT to Emacs, we should _not_ enable
1087 interrupt/quit keys for emacsclient frames. This means
1088 that we can't break out of loops in C code from a
1089 secondary tty frame, but we can always decide what
1090 display the C-g came from, which is more important from a
1091 usability point of view. (Consider the case when two
1092 people work together using the same Emacs instance.) */
1093 tty.main.c_cc[VINTR] = CDISABLE;
1094 tty.main.c_cc[VQUIT] = CDISABLE;
1095 }
1096 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
1097 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
1098 #ifdef VSWTCH
1099 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
1100 of C-z */
1101 #endif /* VSWTCH */
1102
1103 #if defined (__mips__) || defined (HAVE_TCATTR)
1104 #ifdef VSUSP
1105 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
1106 #endif /* VSUSP */
1107 #ifdef V_DSUSP
1108 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
1109 #endif /* V_DSUSP */
1110 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1111 tty.main.c_cc[VDSUSP] = CDISABLE;
1112 #endif /* VDSUSP */
1113 #ifdef VLNEXT
1114 tty.main.c_cc[VLNEXT] = CDISABLE;
1115 #endif /* VLNEXT */
1116 #ifdef VREPRINT
1117 tty.main.c_cc[VREPRINT] = CDISABLE;
1118 #endif /* VREPRINT */
1119 #ifdef VWERASE
1120 tty.main.c_cc[VWERASE] = CDISABLE;
1121 #endif /* VWERASE */
1122 #ifdef VDISCARD
1123 tty.main.c_cc[VDISCARD] = CDISABLE;
1124 #endif /* VDISCARD */
1125
1126 if (tty_out->flow_control)
1127 {
1128 #ifdef VSTART
1129 tty.main.c_cc[VSTART] = '\021';
1130 #endif /* VSTART */
1131 #ifdef VSTOP
1132 tty.main.c_cc[VSTOP] = '\023';
1133 #endif /* VSTOP */
1134 }
1135 else
1136 {
1137 #ifdef VSTART
1138 tty.main.c_cc[VSTART] = CDISABLE;
1139 #endif /* VSTART */
1140 #ifdef VSTOP
1141 tty.main.c_cc[VSTOP] = CDISABLE;
1142 #endif /* VSTOP */
1143 }
1144 #endif /* mips or HAVE_TCATTR */
1145
1146 #ifdef AIX
1147 tty.main.c_cc[VSTRT] = CDISABLE;
1148 tty.main.c_cc[VSTOP] = CDISABLE;
1149 tty.main.c_cc[VSUSP] = CDISABLE;
1150 tty.main.c_cc[VDSUSP] = CDISABLE;
1151 if (tty_out->flow_control)
1152 {
1153 #ifdef VSTART
1154 tty.main.c_cc[VSTART] = '\021';
1155 #endif /* VSTART */
1156 #ifdef VSTOP
1157 tty.main.c_cc[VSTOP] = '\023';
1158 #endif /* VSTOP */
1159 }
1160 /* Also, PTY overloads NUL and BREAK.
1161 don't ignore break, but don't signal either, so it looks like NUL.
1162 This really serves a purpose only if running in an XTERM window
1163 or via TELNET or the like, but does no harm elsewhere. */
1164 tty.main.c_iflag &= ~IGNBRK;
1165 tty.main.c_iflag &= ~BRKINT;
1166 #endif
1167 #else /* if not HAVE_TERMIO */
1168 #ifndef DOS_NT
1169 XSETINT (Vtty_erase_char, tty.main.sg_erase);
1170 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1171 if (meta_key)
1172 tty.main.sg_flags |= ANYP;
1173 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
1174 #endif /* not DOS_NT */
1175 #endif /* not HAVE_TERMIO */
1176
1177 /* If going to use CBREAK mode, we must request C-g to interrupt
1178 and turn off start and stop chars, etc. If not going to use
1179 CBREAK mode, do this anyway so as to turn off local flow
1180 control for user coming over network on 4.2; in this case,
1181 only t_stopc and t_startc really matter. */
1182 #ifndef HAVE_TERMIO
1183 #ifdef HAVE_TCHARS
1184 /* Note: if not using CBREAK mode, it makes no difference how we
1185 set this */
1186 tty.tchars = new_tchars;
1187 tty.tchars.t_intrc = quit_char;
1188 if (tty_out->flow_control)
1189 {
1190 tty.tchars.t_startc = '\021';
1191 tty.tchars.t_stopc = '\023';
1192 }
1193
1194 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode;
1195
1196 #endif /* HAVE_TCHARS */
1197 #endif /* not HAVE_TERMIO */
1198
1199 #ifdef HAVE_LTCHARS
1200 tty.ltchars = new_ltchars;
1201 #endif /* HAVE_LTCHARS */
1202 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1203 if (!tty_out->term_initted)
1204 internal_terminal_init ();
1205 dos_ttraw (tty_out);
1206 #endif
1207
1208 EMACS_SET_TTY (fileno (tty_out->input), &tty, 0);
1209
1210 /* This code added to insure that, if flow-control is not to be used,
1211 we have an unlocked terminal at the start. */
1212
1213 #ifdef TCXONC
1214 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
1215 #endif
1216 #ifdef TIOCSTART
1217 if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
1218 #endif
1219
1220 #if defined (HAVE_TERMIOS) || defined (HPUX)
1221 #ifdef TCOON
1222 if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
1223 #endif
1224 #endif
1225
1226 #ifdef F_SETFL
1227 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1228 if (interrupt_input)
1229 {
1230 old_fcntl_owner[fileno (tty_out->input)] =
1231 fcntl (fileno (tty_out->input), F_GETOWN, 0);
1232 fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
1233 init_sigio (fileno (tty_out->input));
1234 #ifdef HAVE_GPM
1235 if (gpm_tty == tty_out)
1236 {
1237 /* Arrange for mouse events to give us SIGIO signals. */
1238 fcntl (gpm_fd, F_SETOWN, getpid ());
1239 fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
1240 init_sigio (gpm_fd);
1241 }
1242 #endif /* HAVE_GPM */
1243 }
1244 #endif /* F_GETOWN */
1245 #endif /* F_SETFL */
1246
1247 #ifdef _IOFBF
1248 /* This symbol is defined on recent USG systems.
1249 Someone says without this call USG won't really buffer the file
1250 even with a call to setbuf. */
1251 setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1252 #else
1253 setbuf (tty_out->output, (char *) _sobuf);
1254 #endif
1255
1256 if (tty_out->terminal->set_terminal_modes_hook)
1257 tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
1258
1259 if (!tty_out->term_initted)
1260 {
1261 Lisp_Object tail, frame;
1262 FOR_EACH_FRAME (tail, frame)
1263 {
1264 /* XXX This needs to be revised. */
1265 if (FRAME_TERMCAP_P (XFRAME (frame))
1266 && FRAME_TTY (XFRAME (frame)) == tty_out)
1267 init_frame_faces (XFRAME (frame));
1268 }
1269 }
1270
1271 if (tty_out->term_initted && no_redraw_on_reenter)
1272 {
1273 /* We used to call "direct_output_forward_char(0)" here,
1274 but it's not clear why, since it may not do anything anyway. */
1275 }
1276 else
1277 {
1278 Lisp_Object tail, frame;
1279 frame_garbaged = 1;
1280 FOR_EACH_FRAME (tail, frame)
1281 {
1282 if ((FRAME_TERMCAP_P (XFRAME (frame))
1283 || FRAME_MSDOS_P (XFRAME (frame)))
1284 && FRAME_TTY (XFRAME (frame)) == tty_out)
1285 FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1286 }
1287 }
1288
1289 tty_out->term_initted = 1;
1290 }
1291
1292 /* Return nonzero if safe to use tabs in output.
1293 At the time this is called, init_sys_modes has not been done yet. */
1294
1295 int
1296 tabs_safe_p (int fd)
1297 {
1298 struct emacs_tty etty;
1299
1300 EMACS_GET_TTY (fd, &etty);
1301 return EMACS_TTY_TABS_OK (&etty);
1302 }
1303 \f
1304 /* Get terminal size from system.
1305 Store number of lines into *HEIGHTP and width into *WIDTHP.
1306 We store 0 if there's no valid information. */
1307
1308 void
1309 get_tty_size (int fd, int *widthp, int *heightp)
1310 {
1311
1312 #ifdef TIOCGWINSZ
1313
1314 /* BSD-style. */
1315 struct winsize size;
1316
1317 if (ioctl (fd, TIOCGWINSZ, &size) == -1)
1318 *widthp = *heightp = 0;
1319 else
1320 {
1321 *widthp = size.ws_col;
1322 *heightp = size.ws_row;
1323 }
1324
1325 #else
1326 #ifdef TIOCGSIZE
1327
1328 /* SunOS - style. */
1329 struct ttysize size;
1330
1331 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1332 *widthp = *heightp = 0;
1333 else
1334 {
1335 *widthp = size.ts_cols;
1336 *heightp = size.ts_lines;
1337 }
1338
1339 #else
1340 #ifdef MSDOS
1341 *widthp = ScreenCols ();
1342 *heightp = ScreenRows ();
1343 #else /* system doesn't know size */
1344 *widthp = 0;
1345 *heightp = 0;
1346 #endif
1347 #endif /* not SunOS-style */
1348 #endif /* not BSD-style */
1349 }
1350
1351 /* Set the logical window size associated with descriptor FD
1352 to HEIGHT and WIDTH. This is used mainly with ptys. */
1353
1354 int
1355 set_window_size (int fd, int height, int width)
1356 {
1357 #ifdef TIOCSWINSZ
1358
1359 /* BSD-style. */
1360 struct winsize size;
1361 size.ws_row = height;
1362 size.ws_col = width;
1363
1364 if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1365 return 0; /* error */
1366 else
1367 return 1;
1368
1369 #else
1370 #ifdef TIOCSSIZE
1371
1372 /* SunOS - style. */
1373 struct ttysize size;
1374 size.ts_lines = height;
1375 size.ts_cols = width;
1376
1377 if (ioctl (fd, TIOCGSIZE, &size) == -1)
1378 return 0;
1379 else
1380 return 1;
1381 #else
1382 return -1;
1383 #endif /* not SunOS-style */
1384 #endif /* not BSD-style */
1385 }
1386
1387 \f
1388
1389 /* Prepare all terminal devices for exiting Emacs. */
1390
1391 void
1392 reset_all_sys_modes (void)
1393 {
1394 struct tty_display_info *tty;
1395 for (tty = tty_list; tty; tty = tty->next)
1396 reset_sys_modes (tty);
1397 }
1398
1399 /* Prepare the terminal for closing it; move the cursor to the
1400 bottom of the frame, turn off interrupt-driven I/O, etc. */
1401
1402 void
1403 reset_sys_modes (struct tty_display_info *tty_out)
1404 {
1405 if (noninteractive)
1406 {
1407 fflush (stdout);
1408 return;
1409 }
1410 if (!tty_out->term_initted)
1411 return;
1412
1413 if (!tty_out->output)
1414 return; /* The tty is suspended. */
1415
1416 /* Go to and clear the last line of the terminal. */
1417
1418 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1419
1420 /* Code adapted from tty_clear_end_of_line. */
1421 if (tty_out->TS_clr_line)
1422 {
1423 emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
1424 }
1425 else
1426 { /* have to do it the hard way */
1427 int i;
1428 tty_turn_off_insert (tty_out);
1429
1430 for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
1431 {
1432 fputc (' ', tty_out->output);
1433 }
1434 }
1435
1436 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1437 fflush (tty_out->output);
1438
1439 if (tty_out->terminal->reset_terminal_modes_hook)
1440 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
1441
1442 #ifdef BSD_SYSTEM
1443 /* Avoid possible loss of output when changing terminal modes. */
1444 fsync (fileno (tty_out->output));
1445 #endif
1446
1447 #ifdef F_SETFL
1448 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1449 if (interrupt_input)
1450 {
1451 reset_sigio (fileno (tty_out->input));
1452 fcntl (fileno (tty_out->input), F_SETOWN,
1453 old_fcntl_owner[fileno (tty_out->input)]);
1454 }
1455 #endif /* F_SETOWN */
1456 #ifdef O_NDELAY
1457 fcntl (fileno (tty_out->input), F_SETFL,
1458 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
1459 #endif
1460 #endif /* F_SETFL */
1461
1462 if (tty_out->old_tty)
1463 while (EMACS_SET_TTY (fileno (tty_out->input),
1464 tty_out->old_tty, 0) < 0 && errno == EINTR)
1465 ;
1466
1467 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1468 dos_ttcooked ();
1469 #endif
1470
1471 }
1472 \f
1473 #ifdef HAVE_PTYS
1474
1475 /* Set up the proper status flags for use of a pty. */
1476
1477 void
1478 setup_pty (int fd)
1479 {
1480 /* I'm told that TOICREMOTE does not mean control chars
1481 "can't be sent" but rather that they don't have
1482 input-editing or signaling effects.
1483 That should be good, because we have other ways
1484 to do those things in Emacs.
1485 However, telnet mode seems not to work on 4.2.
1486 So TIOCREMOTE is turned off now. */
1487
1488 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1489 will hang. In particular, the "timeout" feature (which
1490 causes a read to return if there is no data available)
1491 does this. Also it is known that telnet mode will hang
1492 in such a way that Emacs must be stopped (perhaps this
1493 is the same problem).
1494
1495 If TIOCREMOTE is turned off, then there is a bug in
1496 hp-ux which sometimes loses data. Apparently the
1497 code which blocks the master process when the internal
1498 buffer fills up does not work. Other than this,
1499 though, everything else seems to work fine.
1500
1501 Since the latter lossage is more benign, we may as well
1502 lose that way. -- cph */
1503 #ifdef FIONBIO
1504 #if defined(UNIX98_PTYS)
1505 {
1506 int on = 1;
1507 ioctl (fd, FIONBIO, &on);
1508 }
1509 #endif
1510 #endif
1511 }
1512 #endif /* HAVE_PTYS */
1513 \f
1514 #if !defined(CANNOT_DUMP) || !defined(SYSTEM_MALLOC)
1515 /* Some systems that cannot dump also cannot implement these. */
1516
1517 /*
1518 * Return the address of the start of the text segment prior to
1519 * doing an unexec. After unexec the return value is undefined.
1520 * See crt0.c for further explanation and _start.
1521 *
1522 */
1523
1524 #if !(defined (__NetBSD__) && defined (__ELF__))
1525 #ifndef HAVE_TEXT_START
1526 char *
1527 start_of_text (void)
1528 {
1529 #ifdef TEXT_START
1530 return ((char *) TEXT_START);
1531 #else
1532 extern int _start ();
1533 return ((char *) _start);
1534 #endif /* TEXT_START */
1535 }
1536 #endif /* not HAVE_TEXT_START */
1537 #endif
1538
1539 /*
1540 * Return the address of the start of the data segment prior to
1541 * doing an unexec. After unexec the return value is undefined.
1542 * See crt0.c for further information and definition of data_start.
1543 *
1544 * Apparently, on BSD systems this is etext at startup. On
1545 * USG systems (swapping) this is highly mmu dependent and
1546 * is also dependent on whether or not the program is running
1547 * with shared text. Generally there is a (possibly large)
1548 * gap between end of text and start of data with shared text.
1549 *
1550 * On Uniplus+ systems with shared text, data starts at a
1551 * fixed address. Each port (from a given oem) is generally
1552 * different, and the specific value of the start of data can
1553 * be obtained via the UniPlus+ specific "uvar" system call,
1554 * however the method outlined in crt0.c seems to be more portable.
1555 *
1556 * Probably what will have to happen when a USG unexec is available,
1557 * at least on UniPlus, is temacs will have to be made unshared so
1558 * that text and data are contiguous. Then once loadup is complete,
1559 * unexec will produce a shared executable where the data can be
1560 * at the normal shared text boundary and the startofdata variable
1561 * will be patched by unexec to the correct value.
1562 *
1563 */
1564
1565 #ifndef start_of_data
1566 char *
1567 start_of_data (void)
1568 {
1569 #ifdef DATA_START
1570 return ((char *) DATA_START);
1571 #else
1572 #ifdef ORDINARY_LINK
1573 /*
1574 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
1575 * data_start isn't defined. We take the address of environ, which
1576 * is known to live at or near the start of the system crt0.c, and
1577 * we don't sweat the handful of bytes that might lose.
1578 */
1579 extern char **environ;
1580
1581 return ((char *) &environ);
1582 #else
1583 extern int data_start;
1584 return ((char *) &data_start);
1585 #endif /* ORDINARY_LINK */
1586 #endif /* DATA_START */
1587 }
1588 #endif /* start_of_data */
1589 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1590 \f
1591 /* init_system_name sets up the string for the Lisp function
1592 system-name to return. */
1593
1594 extern Lisp_Object Vsystem_name;
1595
1596 #ifdef HAVE_SOCKETS
1597 #include <sys/socket.h>
1598 #include <netdb.h>
1599 #endif /* HAVE_SOCKETS */
1600
1601 #ifdef TRY_AGAIN
1602 #ifndef HAVE_H_ERRNO
1603 extern int h_errno;
1604 #endif
1605 #endif /* TRY_AGAIN */
1606
1607 void
1608 init_system_name (void)
1609 {
1610 #ifndef HAVE_GETHOSTNAME
1611 struct utsname uts;
1612 uname (&uts);
1613 Vsystem_name = build_string (uts.nodename);
1614 #else /* HAVE_GETHOSTNAME */
1615 unsigned int hostname_size = 256;
1616 char *hostname = (char *) alloca (hostname_size);
1617
1618 /* Try to get the host name; if the buffer is too short, try
1619 again. Apparently, the only indication gethostname gives of
1620 whether the buffer was large enough is the presence or absence
1621 of a '\0' in the string. Eech. */
1622 for (;;)
1623 {
1624 gethostname (hostname, hostname_size - 1);
1625 hostname[hostname_size - 1] = '\0';
1626
1627 /* Was the buffer large enough for the '\0'? */
1628 if (strlen (hostname) < hostname_size - 1)
1629 break;
1630
1631 hostname_size <<= 1;
1632 hostname = (char *) alloca (hostname_size);
1633 }
1634 #ifdef HAVE_SOCKETS
1635 /* Turn the hostname into the official, fully-qualified hostname.
1636 Don't do this if we're going to dump; this can confuse system
1637 libraries on some machines and make the dumped emacs core dump. */
1638 #ifndef CANNOT_DUMP
1639 if (initialized)
1640 #endif /* not CANNOT_DUMP */
1641 if (! index (hostname, '.'))
1642 {
1643 int count;
1644 #ifdef HAVE_GETADDRINFO
1645 struct addrinfo *res;
1646 struct addrinfo hints;
1647 int ret;
1648
1649 memset (&hints, 0, sizeof (hints));
1650 hints.ai_socktype = SOCK_STREAM;
1651 hints.ai_flags = AI_CANONNAME;
1652
1653 for (count = 0;; count++)
1654 {
1655 if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
1656 || ret != EAI_AGAIN)
1657 break;
1658
1659 if (count >= 5)
1660 break;
1661 Fsleep_for (make_number (1), Qnil);
1662 }
1663
1664 if (ret == 0)
1665 {
1666 struct addrinfo *it = res;
1667 while (it)
1668 {
1669 char *fqdn = it->ai_canonname;
1670 if (fqdn && index (fqdn, '.')
1671 && strcmp (fqdn, "localhost.localdomain") != 0)
1672 break;
1673 it = it->ai_next;
1674 }
1675 if (it)
1676 {
1677 hostname = alloca (strlen (it->ai_canonname) + 1);
1678 strcpy (hostname, it->ai_canonname);
1679 }
1680 freeaddrinfo (res);
1681 }
1682 #else /* !HAVE_GETADDRINFO */
1683 struct hostent *hp;
1684 for (count = 0;; count++)
1685 {
1686
1687 #ifdef TRY_AGAIN
1688 h_errno = 0;
1689 #endif
1690 hp = gethostbyname (hostname);
1691 #ifdef TRY_AGAIN
1692 if (! (hp == 0 && h_errno == TRY_AGAIN))
1693 #endif
1694
1695 break;
1696
1697 if (count >= 5)
1698 break;
1699 Fsleep_for (make_number (1), Qnil);
1700 }
1701
1702 if (hp)
1703 {
1704 char *fqdn = (char *) hp->h_name;
1705
1706 if (!index (fqdn, '.'))
1707 {
1708 /* We still don't have a fully qualified domain name.
1709 Try to find one in the list of alternate names */
1710 char **alias = hp->h_aliases;
1711 while (*alias
1712 && (!index (*alias, '.')
1713 || !strcmp (*alias, "localhost.localdomain")))
1714 alias++;
1715 if (*alias)
1716 fqdn = *alias;
1717 }
1718 hostname = fqdn;
1719 }
1720 #endif /* !HAVE_GETADDRINFO */
1721 }
1722 #endif /* HAVE_SOCKETS */
1723 Vsystem_name = build_string (hostname);
1724 #endif /* HAVE_GETHOSTNAME */
1725 {
1726 unsigned char *p;
1727 for (p = SDATA (Vsystem_name); *p; p++)
1728 if (*p == ' ' || *p == '\t')
1729 *p = '-';
1730 }
1731 }
1732 \f
1733 #ifndef MSDOS
1734 #if !defined (HAVE_SELECT)
1735
1736 #include "sysselect.h"
1737 #undef select
1738
1739 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
1740 /* Cause explanatory error message at compile time,
1741 since the select emulation is not good enough for X. */
1742 int *x = &x_windows_lose_if_no_select_system_call;
1743 #endif
1744
1745 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1746 * Only checks read descriptors.
1747 */
1748 /* How long to wait between checking fds in select */
1749 #define SELECT_PAUSE 1
1750 int select_alarmed;
1751
1752 /* For longjmp'ing back to read_input_waiting. */
1753
1754 jmp_buf read_alarm_throw;
1755
1756 /* Nonzero if the alarm signal should throw back to read_input_waiting.
1757 The read_socket_hook function sets this to 1 while it is waiting. */
1758
1759 int read_alarm_should_throw;
1760
1761 void
1762 select_alarm (int ignore)
1763 {
1764 select_alarmed = 1;
1765 signal (SIGALRM, SIG_IGN);
1766 SIGNAL_THREAD_CHECK (SIGALRM);
1767 if (read_alarm_should_throw)
1768 longjmp (read_alarm_throw, 1);
1769 }
1770
1771 #ifndef WINDOWSNT
1772 /* Only rfds are checked. */
1773 int
1774 sys_select (int nfds,
1775 SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1776 EMACS_TIME *timeout)
1777 {
1778 /* XXX This needs to be updated for multi-tty support. Is there
1779 anybody who needs to emulate select these days? */
1780 int ravail = 0;
1781 SELECT_TYPE orfds;
1782 int timeoutval;
1783 int *local_timeout;
1784 extern int proc_buffered_char[];
1785 #ifndef subprocesses
1786 int process_tick = 0, update_tick = 0;
1787 #else
1788 extern int process_tick, update_tick;
1789 #endif
1790 unsigned char buf;
1791
1792 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
1793 /* If we're using X, then the native select will work; we only need the
1794 emulation for non-X usage. */
1795 if (!NILP (Vinitial_window_system))
1796 return select (nfds, rfds, wfds, efds, timeout);
1797 #endif
1798 timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
1799 local_timeout = &timeoutval;
1800 FD_ZERO (&orfds);
1801 if (rfds)
1802 {
1803 orfds = *rfds;
1804 FD_ZERO (rfds);
1805 }
1806 if (wfds)
1807 FD_ZERO (wfds);
1808 if (efds)
1809 FD_ZERO (efds);
1810
1811 /* If we are looking only for the terminal, with no timeout,
1812 just read it and wait -- that's more efficient. */
1813 if (*local_timeout == 100000 && process_tick == update_tick
1814 && FD_ISSET (0, &orfds))
1815 {
1816 int fd;
1817 for (fd = 1; fd < nfds; ++fd)
1818 if (FD_ISSET (fd, &orfds))
1819 goto hardway;
1820 if (! detect_input_pending ())
1821 read_input_waiting ();
1822 FD_SET (0, rfds);
1823 return 1;
1824 }
1825
1826 hardway:
1827 /* Once a second, till the timer expires, check all the flagged read
1828 * descriptors to see if any input is available. If there is some then
1829 * set the corresponding bit in the return copy of rfds.
1830 */
1831 while (1)
1832 {
1833 register int to_check, fd;
1834
1835 if (rfds)
1836 {
1837 for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
1838 {
1839 if (FD_ISSET (fd, &orfds))
1840 {
1841 int avail = 0, status = 0;
1842
1843 if (fd == 0)
1844 avail = detect_input_pending (); /* Special keyboard handler */
1845 else
1846 {
1847 #ifdef FIONREAD
1848 status = ioctl (fd, FIONREAD, &avail);
1849 #else /* no FIONREAD */
1850 /* Hoping it will return -1 if nothing available
1851 or 0 if all 0 chars requested are read. */
1852 if (proc_buffered_char[fd] >= 0)
1853 avail = 1;
1854 else
1855 {
1856 avail = read (fd, &buf, 1);
1857 if (avail > 0)
1858 proc_buffered_char[fd] = buf;
1859 }
1860 #endif /* no FIONREAD */
1861 }
1862 if (status >= 0 && avail > 0)
1863 {
1864 FD_SET (fd, rfds);
1865 ravail++;
1866 }
1867 }
1868 }
1869 }
1870 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1871 break;
1872
1873 turn_on_atimers (0);
1874 signal (SIGALRM, select_alarm);
1875 select_alarmed = 0;
1876 alarm (SELECT_PAUSE);
1877
1878 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1879 while (select_alarmed == 0 && *local_timeout != 0
1880 && process_tick == update_tick)
1881 {
1882 /* If we are interested in terminal input,
1883 wait by reading the terminal.
1884 That makes instant wakeup for terminal input at least. */
1885 if (FD_ISSET (0, &orfds))
1886 {
1887 read_input_waiting ();
1888 if (detect_input_pending ())
1889 select_alarmed = 1;
1890 }
1891 else
1892 pause ();
1893 }
1894 (*local_timeout) -= SELECT_PAUSE;
1895
1896 /* Reset the old alarm if there was one. */
1897 turn_on_atimers (1);
1898
1899 if (*local_timeout == 0) /* Stop on timer being cleared */
1900 break;
1901 }
1902 return ravail;
1903 }
1904 #endif /* not WINDOWSNT */
1905
1906 /* Read keyboard input into the standard buffer,
1907 waiting for at least one character. */
1908
1909 void
1910 read_input_waiting (void)
1911 {
1912 /* XXX This needs to be updated for multi-tty support. Is there
1913 anybody who needs to emulate select these days? */
1914 int nread, i;
1915 extern int quit_char;
1916
1917 if (read_socket_hook)
1918 {
1919 struct input_event hold_quit;
1920
1921 EVENT_INIT (hold_quit);
1922 hold_quit.kind = NO_EVENT;
1923
1924 read_alarm_should_throw = 0;
1925 if (! setjmp (read_alarm_throw))
1926 nread = (*read_socket_hook) (0, 1, &hold_quit);
1927 else
1928 nread = -1;
1929
1930 if (hold_quit.kind != NO_EVENT)
1931 kbd_buffer_store_event (&hold_quit);
1932 }
1933 else
1934 {
1935 struct input_event e;
1936 char buf[3];
1937 nread = read (fileno (stdin), buf, 1);
1938 EVENT_INIT (e);
1939
1940 /* Scan the chars for C-g and store them in kbd_buffer. */
1941 e.kind = ASCII_KEYSTROKE_EVENT;
1942 e.frame_or_window = selected_frame;
1943 e.modifiers = 0;
1944 for (i = 0; i < nread; i++)
1945 {
1946 /* Convert chars > 0177 to meta events if desired.
1947 We do this under the same conditions that read_avail_input does. */
1948 if (read_socket_hook == 0)
1949 {
1950 /* If the user says she has a meta key, then believe her. */
1951 if (meta_key == 1 && (buf[i] & 0x80))
1952 e.modifiers = meta_modifier;
1953 if (meta_key != 2)
1954 buf[i] &= ~0x80;
1955 }
1956
1957 XSETINT (e.code, buf[i]);
1958 kbd_buffer_store_event (&e);
1959 /* Don't look at input that follows a C-g too closely.
1960 This reduces lossage due to autorepeat on C-g. */
1961 if (buf[i] == quit_char)
1962 break;
1963 }
1964 }
1965 }
1966
1967 #if !defined (HAVE_SELECT)
1968 #define select sys_select
1969 #endif
1970
1971 #endif /* not HAVE_SELECT */
1972 #endif /* not MSDOS */
1973 \f
1974 /* POSIX signals support - DJB */
1975 /* Anyone with POSIX signals should have ANSI C declarations */
1976
1977 sigset_t empty_mask, full_mask;
1978
1979 #ifndef WINDOWSNT
1980
1981 signal_handler_t
1982 sys_signal (int signal_number, signal_handler_t action)
1983 {
1984 struct sigaction new_action, old_action;
1985 sigemptyset (&new_action.sa_mask);
1986 new_action.sa_handler = action;
1987 new_action.sa_flags = 0;
1988 #if defined (SA_RESTART)
1989 /* Emacs mostly works better with restartable system services. If this
1990 flag exists, we probably want to turn it on here.
1991 However, on some systems this resets the timeout of `select'
1992 which means that `select' never finishes if it keeps getting signals.
1993 BROKEN_SA_RESTART is defined on those systems. */
1994 /* It's not clear why the comment above says "mostly works better". --Stef
1995 When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
1996 for pending input so we need long-running syscalls to be interrupted
1997 after a signal that sets the interrupt_input_pending flag. */
1998 /* Non-interactive keyboard input goes through stdio, where we always
1999 want restartable system calls. */
2000 # if defined (BROKEN_SA_RESTART) || defined(SYNC_INPUT)
2001 if (noninteractive)
2002 # endif
2003 new_action.sa_flags = SA_RESTART;
2004 #endif
2005 sigaction (signal_number, &new_action, &old_action);
2006 return (old_action.sa_handler);
2007 }
2008
2009 #endif /* WINDOWSNT */
2010
2011 #ifndef __GNUC__
2012 /* If we're compiling with GCC, we don't need this function, since it
2013 can be written as a macro. */
2014 sigset_t
2015 sys_sigmask (int sig)
2016 {
2017 sigset_t mask;
2018 sigemptyset (&mask);
2019 sigaddset (&mask, sig);
2020 return mask;
2021 }
2022 #endif
2023
2024 /* I'd like to have these guys return pointers to the mask storage in here,
2025 but there'd be trouble if the code was saving multiple masks. I'll be
2026 safe and pass the structure. It normally won't be more than 2 bytes
2027 anyhow. - DJB */
2028
2029 sigset_t
2030 sys_sigblock (sigset_t new_mask)
2031 {
2032 sigset_t old_mask;
2033 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2034 return (old_mask);
2035 }
2036
2037 sigset_t
2038 sys_sigunblock (sigset_t new_mask)
2039 {
2040 sigset_t old_mask;
2041 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2042 return (old_mask);
2043 }
2044
2045 sigset_t
2046 sys_sigsetmask (sigset_t new_mask)
2047 {
2048 sigset_t old_mask;
2049 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2050 return (old_mask);
2051 }
2052
2053 \f
2054 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
2055 static char *my_sys_siglist[NSIG];
2056 # ifdef sys_siglist
2057 # undef sys_siglist
2058 # endif
2059 # define sys_siglist my_sys_siglist
2060 #endif
2061
2062 void
2063 init_signals (void)
2064 {
2065 sigemptyset (&empty_mask);
2066 sigfillset (&full_mask);
2067
2068 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
2069 if (! initialized)
2070 {
2071 # ifdef SIGABRT
2072 sys_siglist[SIGABRT] = "Aborted";
2073 # endif
2074 # ifdef SIGAIO
2075 sys_siglist[SIGAIO] = "LAN I/O interrupt";
2076 # endif
2077 # ifdef SIGALRM
2078 sys_siglist[SIGALRM] = "Alarm clock";
2079 # endif
2080 # ifdef SIGBUS
2081 sys_siglist[SIGBUS] = "Bus error";
2082 # endif
2083 # ifdef SIGCLD
2084 sys_siglist[SIGCLD] = "Child status changed";
2085 # endif
2086 # ifdef SIGCHLD
2087 sys_siglist[SIGCHLD] = "Child status changed";
2088 # endif
2089 # ifdef SIGCONT
2090 sys_siglist[SIGCONT] = "Continued";
2091 # endif
2092 # ifdef SIGDANGER
2093 sys_siglist[SIGDANGER] = "Swap space dangerously low";
2094 # endif
2095 # ifdef SIGDGNOTIFY
2096 sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
2097 # endif
2098 # ifdef SIGEMT
2099 sys_siglist[SIGEMT] = "Emulation trap";
2100 # endif
2101 # ifdef SIGFPE
2102 sys_siglist[SIGFPE] = "Arithmetic exception";
2103 # endif
2104 # ifdef SIGFREEZE
2105 sys_siglist[SIGFREEZE] = "SIGFREEZE";
2106 # endif
2107 # ifdef SIGGRANT
2108 sys_siglist[SIGGRANT] = "Monitor mode granted";
2109 # endif
2110 # ifdef SIGHUP
2111 sys_siglist[SIGHUP] = "Hangup";
2112 # endif
2113 # ifdef SIGILL
2114 sys_siglist[SIGILL] = "Illegal instruction";
2115 # endif
2116 # ifdef SIGINT
2117 sys_siglist[SIGINT] = "Interrupt";
2118 # endif
2119 # ifdef SIGIO
2120 sys_siglist[SIGIO] = "I/O possible";
2121 # endif
2122 # ifdef SIGIOINT
2123 sys_siglist[SIGIOINT] = "I/O intervention required";
2124 # endif
2125 # ifdef SIGIOT
2126 sys_siglist[SIGIOT] = "IOT trap";
2127 # endif
2128 # ifdef SIGKILL
2129 sys_siglist[SIGKILL] = "Killed";
2130 # endif
2131 # ifdef SIGLOST
2132 sys_siglist[SIGLOST] = "Resource lost";
2133 # endif
2134 # ifdef SIGLWP
2135 sys_siglist[SIGLWP] = "SIGLWP";
2136 # endif
2137 # ifdef SIGMSG
2138 sys_siglist[SIGMSG] = "Monitor mode data available";
2139 # endif
2140 # ifdef SIGPHONE
2141 sys_siglist[SIGWIND] = "SIGPHONE";
2142 # endif
2143 # ifdef SIGPIPE
2144 sys_siglist[SIGPIPE] = "Broken pipe";
2145 # endif
2146 # ifdef SIGPOLL
2147 sys_siglist[SIGPOLL] = "Pollable event occurred";
2148 # endif
2149 # ifdef SIGPROF
2150 sys_siglist[SIGPROF] = "Profiling timer expired";
2151 # endif
2152 # ifdef SIGPTY
2153 sys_siglist[SIGPTY] = "PTY I/O interrupt";
2154 # endif
2155 # ifdef SIGPWR
2156 sys_siglist[SIGPWR] = "Power-fail restart";
2157 # endif
2158 # ifdef SIGQUIT
2159 sys_siglist[SIGQUIT] = "Quit";
2160 # endif
2161 # ifdef SIGRETRACT
2162 sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
2163 # endif
2164 # ifdef SIGSAK
2165 sys_siglist[SIGSAK] = "Secure attention";
2166 # endif
2167 # ifdef SIGSEGV
2168 sys_siglist[SIGSEGV] = "Segmentation violation";
2169 # endif
2170 # ifdef SIGSOUND
2171 sys_siglist[SIGSOUND] = "Sound completed";
2172 # endif
2173 # ifdef SIGSTOP
2174 sys_siglist[SIGSTOP] = "Stopped (signal)";
2175 # endif
2176 # ifdef SIGSTP
2177 sys_siglist[SIGSTP] = "Stopped (user)";
2178 # endif
2179 # ifdef SIGSYS
2180 sys_siglist[SIGSYS] = "Bad argument to system call";
2181 # endif
2182 # ifdef SIGTERM
2183 sys_siglist[SIGTERM] = "Terminated";
2184 # endif
2185 # ifdef SIGTHAW
2186 sys_siglist[SIGTHAW] = "SIGTHAW";
2187 # endif
2188 # ifdef SIGTRAP
2189 sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
2190 # endif
2191 # ifdef SIGTSTP
2192 sys_siglist[SIGTSTP] = "Stopped (user)";
2193 # endif
2194 # ifdef SIGTTIN
2195 sys_siglist[SIGTTIN] = "Stopped (tty input)";
2196 # endif
2197 # ifdef SIGTTOU
2198 sys_siglist[SIGTTOU] = "Stopped (tty output)";
2199 # endif
2200 # ifdef SIGURG
2201 sys_siglist[SIGURG] = "Urgent I/O condition";
2202 # endif
2203 # ifdef SIGUSR1
2204 sys_siglist[SIGUSR1] = "User defined signal 1";
2205 # endif
2206 # ifdef SIGUSR2
2207 sys_siglist[SIGUSR2] = "User defined signal 2";
2208 # endif
2209 # ifdef SIGVTALRM
2210 sys_siglist[SIGVTALRM] = "Virtual timer expired";
2211 # endif
2212 # ifdef SIGWAITING
2213 sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
2214 # endif
2215 # ifdef SIGWINCH
2216 sys_siglist[SIGWINCH] = "Window size changed";
2217 # endif
2218 # ifdef SIGWIND
2219 sys_siglist[SIGWIND] = "SIGWIND";
2220 # endif
2221 # ifdef SIGXCPU
2222 sys_siglist[SIGXCPU] = "CPU time limit exceeded";
2223 # endif
2224 # ifdef SIGXFSZ
2225 sys_siglist[SIGXFSZ] = "File size limit exceeded";
2226 # endif
2227 }
2228 #endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
2229 }
2230 \f
2231 #ifndef HAVE_RANDOM
2232 #ifdef random
2233 #define HAVE_RANDOM
2234 #endif
2235 #endif
2236
2237 /* Figure out how many bits the system's random number generator uses.
2238 `random' and `lrand48' are assumed to return 31 usable bits.
2239 BSD `rand' returns a 31 bit value but the low order bits are unusable;
2240 so we'll shift it and treat it like the 15-bit USG `rand'. */
2241
2242 #ifndef RAND_BITS
2243 # ifdef HAVE_RANDOM
2244 # define RAND_BITS 31
2245 # else /* !HAVE_RANDOM */
2246 # ifdef HAVE_LRAND48
2247 # define RAND_BITS 31
2248 # define random lrand48
2249 # else /* !HAVE_LRAND48 */
2250 # define RAND_BITS 15
2251 # if RAND_MAX == 32767
2252 # define random rand
2253 # else /* RAND_MAX != 32767 */
2254 # if RAND_MAX == 2147483647
2255 # define random() (rand () >> 16)
2256 # else /* RAND_MAX != 2147483647 */
2257 # ifdef USG
2258 # define random rand
2259 # else
2260 # define random() (rand () >> 16)
2261 # endif /* !USG */
2262 # endif /* RAND_MAX != 2147483647 */
2263 # endif /* RAND_MAX != 32767 */
2264 # endif /* !HAVE_LRAND48 */
2265 # endif /* !HAVE_RANDOM */
2266 #endif /* !RAND_BITS */
2267
2268 void
2269 seed_random (long int arg)
2270 {
2271 #ifdef HAVE_RANDOM
2272 srandom ((unsigned int)arg);
2273 #else
2274 # ifdef HAVE_LRAND48
2275 srand48 (arg);
2276 # else
2277 srand ((unsigned int)arg);
2278 # endif
2279 #endif
2280 }
2281
2282 /*
2283 * Build a full Emacs-sized word out of whatever we've got.
2284 * This suffices even for a 64-bit architecture with a 15-bit rand.
2285 */
2286 long
2287 get_random (void)
2288 {
2289 long val = random ();
2290 #if VALBITS > RAND_BITS
2291 val = (val << RAND_BITS) ^ random ();
2292 #if VALBITS > 2*RAND_BITS
2293 val = (val << RAND_BITS) ^ random ();
2294 #if VALBITS > 3*RAND_BITS
2295 val = (val << RAND_BITS) ^ random ();
2296 #if VALBITS > 4*RAND_BITS
2297 val = (val << RAND_BITS) ^ random ();
2298 #endif /* need at least 5 */
2299 #endif /* need at least 4 */
2300 #endif /* need at least 3 */
2301 #endif /* need at least 2 */
2302 return val & ((1L << VALBITS) - 1);
2303 }
2304
2305 #ifndef HAVE_STRERROR
2306 #ifndef WINDOWSNT
2307 char *
2308 strerror (errnum)
2309 int errnum;
2310 {
2311 extern char *sys_errlist[];
2312 extern int sys_nerr;
2313
2314 if (errnum >= 0 && errnum < sys_nerr)
2315 return sys_errlist[errnum];
2316 return (char *) "Unknown error";
2317 }
2318 #endif /* not WINDOWSNT */
2319 #endif /* ! HAVE_STRERROR */
2320 \f
2321 int
2322 emacs_open (const char *path, int oflag, int mode)
2323 {
2324 register int rtnval;
2325
2326 while ((rtnval = open (path, oflag, mode)) == -1
2327 && (errno == EINTR))
2328 QUIT;
2329 return (rtnval);
2330 }
2331
2332 int
2333 emacs_close (int fd)
2334 {
2335 int did_retry = 0;
2336 register int rtnval;
2337
2338 while ((rtnval = close (fd)) == -1
2339 && (errno == EINTR))
2340 did_retry = 1;
2341
2342 /* If close is interrupted SunOS 4.1 may or may not have closed the
2343 file descriptor. If it did the second close will fail with
2344 errno = EBADF. That means we have succeeded. */
2345 if (rtnval == -1 && did_retry && errno == EBADF)
2346 return 0;
2347
2348 return rtnval;
2349 }
2350
2351 int
2352 emacs_read (int fildes, char *buf, unsigned int nbyte)
2353 {
2354 register int rtnval;
2355
2356 while ((rtnval = read (fildes, buf, nbyte)) == -1
2357 && (errno == EINTR))
2358 QUIT;
2359 return (rtnval);
2360 }
2361
2362 int
2363 emacs_write (int fildes, const char *buf, unsigned int nbyte)
2364 {
2365 register int rtnval, bytes_written;
2366
2367 bytes_written = 0;
2368
2369 while (nbyte > 0)
2370 {
2371 rtnval = write (fildes, buf, nbyte);
2372
2373 if (rtnval == -1)
2374 {
2375 if (errno == EINTR)
2376 {
2377 #ifdef SYNC_INPUT
2378 /* I originally used `QUIT' but that might causes files to
2379 be truncated if you hit C-g in the middle of it. --Stef */
2380 process_pending_signals ();
2381 #endif
2382 continue;
2383 }
2384 else
2385 return (bytes_written ? bytes_written : -1);
2386 }
2387
2388 buf += rtnval;
2389 nbyte -= rtnval;
2390 bytes_written += rtnval;
2391 }
2392 return (bytes_written);
2393 }
2394 \f
2395 #ifdef USG
2396 /*
2397 * All of the following are for USG.
2398 *
2399 * On USG systems the system calls are INTERRUPTIBLE by signals
2400 * that the user program has elected to catch. Thus the system call
2401 * must be retried in these cases. To handle this without massive
2402 * changes in the source code, we remap the standard system call names
2403 * to names for our own functions in sysdep.c that do the system call
2404 * with retries. Actually, for portability reasons, it is good
2405 * programming practice, as this example shows, to limit all actual
2406 * system calls to a single occurrence in the source. Sure, this
2407 * adds an extra level of function call overhead but it is almost
2408 * always negligible. Fred Fish, Unisoft Systems Inc.
2409 */
2410
2411 /*
2412 * Warning, this function may not duplicate 4.2 action properly
2413 * under error conditions.
2414 */
2415
2416 #ifndef MAXPATHLEN
2417 /* In 4.1, param.h fails to define this. */
2418 #define MAXPATHLEN 1024
2419 #endif
2420
2421 #ifndef HAVE_GETWD
2422
2423 char *
2424 getwd (char *pathname)
2425 {
2426 char *npath, *spath;
2427 extern char *getcwd (char *, size_t);
2428
2429 BLOCK_INPUT; /* getcwd uses malloc */
2430 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2431 if (spath == 0)
2432 {
2433 UNBLOCK_INPUT;
2434 return spath;
2435 }
2436 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2437 up to first slash. Should be harmless on other systems. */
2438 while (*npath && *npath != '/')
2439 npath++;
2440 strcpy (pathname, npath);
2441 free (spath); /* getcwd uses malloc */
2442 UNBLOCK_INPUT;
2443 return pathname;
2444 }
2445
2446 #endif /* HAVE_GETWD */
2447
2448 /*
2449 * Emulate rename using unlink/link. Note that this is
2450 * only partially correct. Also, doesn't enforce restriction
2451 * that files be of same type (regular->regular, dir->dir, etc).
2452 */
2453
2454 #ifndef HAVE_RENAME
2455
2456 int
2457 rename (const char *from, const char *to)
2458 {
2459 if (access (from, 0) == 0)
2460 {
2461 unlink (to);
2462 if (link (from, to) == 0)
2463 if (unlink (from) == 0)
2464 return (0);
2465 }
2466 return (-1);
2467 }
2468
2469 #endif
2470
2471
2472 #if defined(HPUX) && !defined(HAVE_PERROR)
2473
2474 /* HPUX curses library references perror, but as far as we know
2475 it won't be called. Anyway this definition will do for now. */
2476
2477 void
2478 perror (void)
2479 {
2480 }
2481 #endif /* HPUX and not HAVE_PERROR */
2482
2483 #ifndef HAVE_DUP2
2484
2485 /*
2486 * Emulate BSD dup2. First close newd if it already exists.
2487 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2488 * until we are, then close the unsuccessful ones.
2489 */
2490
2491 int
2492 dup2 (int oldd, int newd)
2493 {
2494 register int fd, ret;
2495
2496 emacs_close (newd);
2497
2498 #ifdef F_DUPFD
2499 return fcntl (oldd, F_DUPFD, newd);
2500 #else
2501 fd = dup (old);
2502 if (fd == -1)
2503 return -1;
2504 if (fd == new)
2505 return new;
2506 ret = dup2 (old,new);
2507 emacs_close (fd);
2508 return ret;
2509 #endif
2510 }
2511
2512 #endif /* not HAVE_DUP2 */
2513
2514 /*
2515 * Gettimeofday. Simulate as much as possible. Only accurate
2516 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2517 * Only needed when subprocesses are defined.
2518 */
2519
2520 #ifdef subprocesses
2521 #ifndef HAVE_GETTIMEOFDAY
2522 #ifdef HAVE_TIMEVAL
2523
2524 /* ARGSUSED */
2525 int
2526 gettimeofday (struct timeval *tp, struct timezone *tzp)
2527 {
2528 extern long time (long);
2529
2530 tp->tv_sec = time ((long *)0);
2531 tp->tv_usec = 0;
2532 if (tzp != 0)
2533 tzp->tz_minuteswest = -1;
2534 return 0;
2535 }
2536
2537 #endif
2538 #endif
2539 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
2540
2541 /*
2542 * This function will go away as soon as all the stubs fixed. (fnf)
2543 */
2544
2545 void
2546 croak (char *badfunc)
2547 {
2548 printf ("%s not yet implemented\r\n", badfunc);
2549 reset_all_sys_modes ();
2550 exit (1);
2551 }
2552
2553 #endif /* USG */
2554 \f
2555 /* Directory routines for systems that don't have them. */
2556
2557 #ifdef SYSV_SYSTEM_DIR
2558
2559 #include <dirent.h>
2560
2561 #if !defined (HAVE_CLOSEDIR)
2562
2563 int
2564 closedir (DIR *dirp /* stream from opendir */)
2565 {
2566 int rtnval;
2567
2568 rtnval = emacs_close (dirp->dd_fd);
2569 xfree ((char *) dirp);
2570
2571 return rtnval;
2572 }
2573 #endif /* not HAVE_CLOSEDIR */
2574 #endif /* SYSV_SYSTEM_DIR */
2575
2576 \f
2577 int
2578 set_file_times (const char *filename, EMACS_TIME atime, EMACS_TIME mtime)
2579 {
2580 #ifdef HAVE_UTIMES
2581 struct timeval tv[2];
2582 tv[0] = atime;
2583 tv[1] = mtime;
2584 return utimes (filename, tv);
2585 #else /* not HAVE_UTIMES */
2586 struct utimbuf utb;
2587 utb.actime = EMACS_SECS (atime);
2588 utb.modtime = EMACS_SECS (mtime);
2589 return utime (filename, &utb);
2590 #endif /* not HAVE_UTIMES */
2591 }
2592 \f
2593 /* mkdir and rmdir functions, for systems which don't have them. */
2594
2595 #ifndef HAVE_MKDIR
2596 /*
2597 * Written by Robert Rother, Mariah Corporation, August 1985.
2598 *
2599 * If you want it, it's yours. All I ask in return is that if you
2600 * figure out how to do this in a Bourne Shell script you send me
2601 * a copy.
2602 * sdcsvax!rmr or rmr@uscd
2603 *
2604 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
2605 * subroutine. 11Mar86; hoptoad!gnu
2606 *
2607 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
2608 * subroutine didn't return EEXIST. It does now.
2609 */
2610
2611 /*
2612 * Make a directory.
2613 */
2614 int
2615 mkdir (char *dpath, int dmode)
2616 {
2617 int cpid, status, fd;
2618 struct stat statbuf;
2619
2620 if (stat (dpath, &statbuf) == 0)
2621 {
2622 errno = EEXIST; /* Stat worked, so it already exists */
2623 return -1;
2624 }
2625
2626 /* If stat fails for a reason other than non-existence, return error */
2627 if (errno != ENOENT)
2628 return -1;
2629
2630 synch_process_alive = 1;
2631 switch (cpid = fork ())
2632 {
2633
2634 case -1: /* Error in fork */
2635 return (-1); /* Errno is set already */
2636
2637 case 0: /* Child process */
2638 /*
2639 * Cheap hack to set mode of new directory. Since this
2640 * child process is going away anyway, we zap its umask.
2641 * FIXME, this won't suffice to set SUID, SGID, etc. on this
2642 * directory. Does anybody care?
2643 */
2644 status = umask (0); /* Get current umask */
2645 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
2646 fd = emacs_open ("/dev/null", O_RDWR, 0);
2647 if (fd >= 0)
2648 {
2649 dup2 (fd, 0);
2650 dup2 (fd, 1);
2651 dup2 (fd, 2);
2652 }
2653 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
2654 _exit (-1); /* Can't exec /bin/mkdir */
2655
2656 default: /* Parent process */
2657 wait_for_termination (cpid);
2658 }
2659
2660 if (synch_process_death != 0 || synch_process_retcode != 0
2661 || synch_process_termsig != 0)
2662 {
2663 errno = EIO; /* We don't know why, but */
2664 return -1; /* /bin/mkdir failed */
2665 }
2666
2667 return 0;
2668 }
2669 #endif /* not HAVE_MKDIR */
2670
2671 #ifndef HAVE_RMDIR
2672 int
2673 rmdir (char *dpath)
2674 {
2675 int cpid, status, fd;
2676 struct stat statbuf;
2677
2678 if (stat (dpath, &statbuf) != 0)
2679 {
2680 /* Stat just set errno. We don't have to */
2681 return -1;
2682 }
2683
2684 synch_process_alive = 1;
2685 switch (cpid = fork ())
2686 {
2687
2688 case -1: /* Error in fork */
2689 return (-1); /* Errno is set already */
2690
2691 case 0: /* Child process */
2692 fd = emacs_open ("/dev/null", O_RDWR, 0);
2693 if (fd >= 0)
2694 {
2695 dup2 (fd, 0);
2696 dup2 (fd, 1);
2697 dup2 (fd, 2);
2698 }
2699 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
2700 _exit (-1); /* Can't exec /bin/rmdir */
2701
2702 default: /* Parent process */
2703 wait_for_termination (cpid);
2704 }
2705
2706 if (synch_process_death != 0 || synch_process_retcode != 0
2707 || synch_process_termsig != 0)
2708 {
2709 errno = EIO; /* We don't know why, but */
2710 return -1; /* /bin/rmdir failed */
2711 }
2712
2713 return 0;
2714 }
2715 #endif /* !HAVE_RMDIR */
2716
2717 \f
2718 #ifndef HAVE_MEMSET
2719 void *
2720 memset (void *b, int n, size_t length)
2721 {
2722 unsigned char *p = b;
2723 while (length-- > 0)
2724 *p++ = n;
2725 return b;
2726 }
2727 #endif /* !HAVE_MEMSET */
2728
2729 #ifndef HAVE_MEMCPY
2730 void *
2731 memcpy (void *b1, void *b2, size_t length)
2732 {
2733 unsigned char *p1 = b1, *p2 = b2;
2734 while (length-- > 0)
2735 *p1++ = *p2++;
2736 return b1;
2737 }
2738 #endif /* !HAVE_MEMCPY */
2739
2740 #ifndef HAVE_MEMMOVE
2741 void *
2742 memmove (void *b1, void *b2, size_t length)
2743 {
2744 unsigned char *p1 = b1, *p2 = b2;
2745 if (p1 < p2 || p1 >= p2 + length)
2746 while (length-- > 0)
2747 *p1++ = *p2++;
2748 else
2749 {
2750 p1 += length;
2751 p2 += length;
2752 while (length-- > 0)
2753 *--p1 = *--p2;
2754 }
2755 return b1;
2756 }
2757 #endif /* !HAVE_MEMCPY */
2758
2759 #ifndef HAVE_MEMCMP
2760 int
2761 memcmp (void *b1, void *b2, size_t length)
2762 {
2763 unsigned char *p1 = b1, *p2 = b2;
2764 while (length-- > 0)
2765 if (*p1++ != *p2++)
2766 return p1[-1] < p2[-1] ? -1 : 1;
2767 return 0;
2768 }
2769 #endif /* !HAVE_MEMCMP */
2770 \f
2771 #ifndef HAVE_STRSIGNAL
2772 char *
2773 strsignal (int code)
2774 {
2775 char *signame = 0;
2776
2777 if (0 <= code && code < NSIG)
2778 {
2779 /* Cast to suppress warning if the table has const char *. */
2780 signame = (char *) sys_siglist[code];
2781 }
2782
2783 return signame;
2784 }
2785 #endif /* HAVE_STRSIGNAL */
2786 \f
2787 #ifdef HAVE_TERMIOS
2788 /* For make-serial-process */
2789 int
2790 serial_open (char *port)
2791 {
2792 int fd = -1;
2793
2794 fd = emacs_open ((char*) port,
2795 O_RDWR
2796 #ifdef O_NONBLOCK
2797 | O_NONBLOCK
2798 #else
2799 | O_NDELAY
2800 #endif
2801 #ifdef O_NOCTTY
2802 | O_NOCTTY
2803 #endif
2804 , 0);
2805 if (fd < 0)
2806 {
2807 error ("Could not open %s: %s",
2808 port, emacs_strerror (errno));
2809 }
2810 #ifdef TIOCEXCL
2811 ioctl (fd, TIOCEXCL, (char *) 0);
2812 #endif
2813
2814 return fd;
2815 }
2816 #endif /* TERMIOS */
2817
2818 #ifdef HAVE_TERMIOS
2819
2820 #if !defined (HAVE_CFMAKERAW)
2821 /* Workaround for targets which are missing cfmakeraw. */
2822 /* Pasted from man page. */
2823 static void
2824 cfmakeraw (struct termios *termios_p)
2825 {
2826 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
2827 termios_p->c_oflag &= ~OPOST;
2828 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
2829 termios_p->c_cflag &= ~(CSIZE|PARENB);
2830 termios_p->c_cflag |= CS8;
2831 }
2832 #endif /* !defined (HAVE_CFMAKERAW */
2833
2834 #if !defined (HAVE_CFSETSPEED)
2835 /* Workaround for targets which are missing cfsetspeed. */
2836 static int
2837 cfsetspeed (struct termios *termios_p, speed_t vitesse)
2838 {
2839 return (cfsetispeed (termios_p, vitesse)
2840 + cfsetospeed (termios_p, vitesse));
2841 }
2842 #endif
2843
2844 /* For serial-process-configure */
2845 void
2846 serial_configure (struct Lisp_Process *p,
2847 Lisp_Object contact)
2848 {
2849 Lisp_Object childp2 = Qnil;
2850 Lisp_Object tem = Qnil;
2851 struct termios attr;
2852 int err = -1;
2853 char summary[4] = "???"; /* This usually becomes "8N1". */
2854
2855 childp2 = Fcopy_sequence (p->childp);
2856
2857 /* Read port attributes and prepare default configuration. */
2858 err = tcgetattr (p->outfd, &attr);
2859 if (err != 0)
2860 error ("tcgetattr() failed: %s", emacs_strerror (errno));
2861 cfmakeraw (&attr);
2862 #if defined (CLOCAL)
2863 attr.c_cflag |= CLOCAL;
2864 #endif
2865 #if defined (CREAD)
2866 attr.c_cflag |= CREAD;
2867 #endif
2868
2869 /* Configure speed. */
2870 if (!NILP (Fplist_member (contact, QCspeed)))
2871 tem = Fplist_get (contact, QCspeed);
2872 else
2873 tem = Fplist_get (p->childp, QCspeed);
2874 CHECK_NUMBER (tem);
2875 err = cfsetspeed (&attr, XINT (tem));
2876 if (err != 0)
2877 error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
2878 childp2 = Fplist_put (childp2, QCspeed, tem);
2879
2880 /* Configure bytesize. */
2881 if (!NILP (Fplist_member (contact, QCbytesize)))
2882 tem = Fplist_get (contact, QCbytesize);
2883 else
2884 tem = Fplist_get (p->childp, QCbytesize);
2885 if (NILP (tem))
2886 tem = make_number (8);
2887 CHECK_NUMBER (tem);
2888 if (XINT (tem) != 7 && XINT (tem) != 8)
2889 error (":bytesize must be nil (8), 7, or 8");
2890 summary[0] = XINT (tem) + '0';
2891 #if defined (CSIZE) && defined (CS7) && defined (CS8)
2892 attr.c_cflag &= ~CSIZE;
2893 attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
2894 #else
2895 /* Don't error on bytesize 8, which should be set by cfmakeraw. */
2896 if (XINT (tem) != 8)
2897 error ("Bytesize cannot be changed");
2898 #endif
2899 childp2 = Fplist_put (childp2, QCbytesize, tem);
2900
2901 /* Configure parity. */
2902 if (!NILP (Fplist_member (contact, QCparity)))
2903 tem = Fplist_get (contact, QCparity);
2904 else
2905 tem = Fplist_get (p->childp, QCparity);
2906 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
2907 error (":parity must be nil (no parity), `even', or `odd'");
2908 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
2909 attr.c_cflag &= ~(PARENB | PARODD);
2910 attr.c_iflag &= ~(IGNPAR | INPCK);
2911 if (NILP (tem))
2912 {
2913 summary[1] = 'N';
2914 }
2915 else if (EQ (tem, Qeven))
2916 {
2917 summary[1] = 'E';
2918 attr.c_cflag |= PARENB;
2919 attr.c_iflag |= (IGNPAR | INPCK);
2920 }
2921 else if (EQ (tem, Qodd))
2922 {
2923 summary[1] = 'O';
2924 attr.c_cflag |= (PARENB | PARODD);
2925 attr.c_iflag |= (IGNPAR | INPCK);
2926 }
2927 #else
2928 /* Don't error on no parity, which should be set by cfmakeraw. */
2929 if (!NILP (tem))
2930 error ("Parity cannot be configured");
2931 #endif
2932 childp2 = Fplist_put (childp2, QCparity, tem);
2933
2934 /* Configure stopbits. */
2935 if (!NILP (Fplist_member (contact, QCstopbits)))
2936 tem = Fplist_get (contact, QCstopbits);
2937 else
2938 tem = Fplist_get (p->childp, QCstopbits);
2939 if (NILP (tem))
2940 tem = make_number (1);
2941 CHECK_NUMBER (tem);
2942 if (XINT (tem) != 1 && XINT (tem) != 2)
2943 error (":stopbits must be nil (1 stopbit), 1, or 2");
2944 summary[2] = XINT (tem) + '0';
2945 #if defined (CSTOPB)
2946 attr.c_cflag &= ~CSTOPB;
2947 if (XINT (tem) == 2)
2948 attr.c_cflag |= CSTOPB;
2949 #else
2950 /* Don't error on 1 stopbit, which should be set by cfmakeraw. */
2951 if (XINT (tem) != 1)
2952 error ("Stopbits cannot be configured");
2953 #endif
2954 childp2 = Fplist_put (childp2, QCstopbits, tem);
2955
2956 /* Configure flowcontrol. */
2957 if (!NILP (Fplist_member (contact, QCflowcontrol)))
2958 tem = Fplist_get (contact, QCflowcontrol);
2959 else
2960 tem = Fplist_get (p->childp, QCflowcontrol);
2961 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
2962 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
2963 #if defined (CRTSCTS)
2964 attr.c_cflag &= ~CRTSCTS;
2965 #endif
2966 #if defined (CNEW_RTSCTS)
2967 attr.c_cflag &= ~CNEW_RTSCTS;
2968 #endif
2969 #if defined (IXON) && defined (IXOFF)
2970 attr.c_iflag &= ~(IXON | IXOFF);
2971 #endif
2972 if (NILP (tem))
2973 {
2974 /* Already configured. */
2975 }
2976 else if (EQ (tem, Qhw))
2977 {
2978 #if defined (CRTSCTS)
2979 attr.c_cflag |= CRTSCTS;
2980 #elif defined (CNEW_RTSCTS)
2981 attr.c_cflag |= CNEW_RTSCTS;
2982 #else
2983 error ("Hardware flowcontrol (RTS/CTS) not supported");
2984 #endif
2985 }
2986 else if (EQ (tem, Qsw))
2987 {
2988 #if defined (IXON) && defined (IXOFF)
2989 attr.c_iflag |= (IXON | IXOFF);
2990 #else
2991 error ("Software flowcontrol (XON/XOFF) not supported");
2992 #endif
2993 }
2994 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
2995
2996 /* Activate configuration. */
2997 err = tcsetattr (p->outfd, TCSANOW, &attr);
2998 if (err != 0)
2999 error ("tcsetattr() failed: %s", emacs_strerror (errno));
3000
3001 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
3002 p->childp = childp2;
3003
3004 }
3005 #endif /* TERMIOS */
3006 \f
3007 /* System depended enumeration of and access to system processes a-la ps(1). */
3008
3009 #ifdef HAVE_PROCFS
3010
3011 /* Process enumeration and access via /proc. */
3012
3013 Lisp_Object
3014 list_system_processes (void)
3015 {
3016 Lisp_Object procdir, match, proclist, next;
3017 struct gcpro gcpro1, gcpro2;
3018 register Lisp_Object tail;
3019
3020 GCPRO2 (procdir, match);
3021 /* For every process on the system, there's a directory in the
3022 "/proc" pseudo-directory whose name is the numeric ID of that
3023 process. */
3024 procdir = build_string ("/proc");
3025 match = build_string ("[0-9]+");
3026 proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
3027
3028 /* `proclist' gives process IDs as strings. Destructively convert
3029 each string into a number. */
3030 for (tail = proclist; CONSP (tail); tail = next)
3031 {
3032 next = XCDR (tail);
3033 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
3034 }
3035 UNGCPRO;
3036
3037 /* directory_files_internal returns the files in reverse order; undo
3038 that. */
3039 proclist = Fnreverse (proclist);
3040 return proclist;
3041 }
3042
3043 /* The WINDOWSNT implementation is in w32.c.
3044 The MSDOS implementation is in dosfns.c. */
3045 #elif !defined (WINDOWSNT) && !defined (MSDOS)
3046
3047 Lisp_Object
3048 list_system_processes (void)
3049 {
3050 return Qnil;
3051 }
3052
3053 #endif /* !defined (WINDOWSNT) */
3054
3055 #ifdef GNU_LINUX
3056 static void
3057 time_from_jiffies (unsigned long long tval, long hz,
3058 time_t *sec, unsigned *usec)
3059 {
3060 unsigned long long ullsec;
3061
3062 *sec = tval / hz;
3063 ullsec = *sec;
3064 tval -= ullsec * hz;
3065 /* Careful: if HZ > 1 million, then integer division by it yields zero. */
3066 if (hz <= 1000000)
3067 *usec = tval * 1000000 / hz;
3068 else
3069 *usec = tval / (hz / 1000000);
3070 }
3071
3072 static Lisp_Object
3073 ltime_from_jiffies (unsigned long long tval, long hz)
3074 {
3075 time_t sec;
3076 unsigned usec;
3077
3078 time_from_jiffies (tval, hz, &sec, &usec);
3079
3080 return list3 (make_number ((sec >> 16) & 0xffff),
3081 make_number (sec & 0xffff),
3082 make_number (usec));
3083 }
3084
3085 static void
3086 get_up_time (time_t *sec, unsigned *usec)
3087 {
3088 FILE *fup;
3089
3090 *sec = *usec = 0;
3091
3092 BLOCK_INPUT;
3093 fup = fopen ("/proc/uptime", "r");
3094
3095 if (fup)
3096 {
3097 double uptime, idletime;
3098
3099 /* The numbers in /proc/uptime use C-locale decimal point, but
3100 we already set ourselves to the C locale (see `fixup_locale'
3101 in emacs.c). */
3102 if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
3103 {
3104 *sec = uptime;
3105 *usec = (uptime - *sec) * 1000000;
3106 }
3107 fclose (fup);
3108 }
3109 UNBLOCK_INPUT;
3110 }
3111
3112 #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
3113 #define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
3114
3115 static Lisp_Object
3116 procfs_ttyname (int rdev)
3117 {
3118 FILE *fdev = NULL;
3119 char name[PATH_MAX];
3120
3121 BLOCK_INPUT;
3122 fdev = fopen ("/proc/tty/drivers", "r");
3123
3124 if (fdev)
3125 {
3126 unsigned major;
3127 unsigned long minor_beg, minor_end;
3128 char minor[25]; /* 2 32-bit numbers + dash */
3129 char *endp;
3130
3131 while (!feof (fdev) && !ferror (fdev))
3132 {
3133 if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
3134 && major == MAJOR (rdev))
3135 {
3136 minor_beg = strtoul (minor, &endp, 0);
3137 if (*endp == '\0')
3138 minor_end = minor_beg;
3139 else if (*endp == '-')
3140 minor_end = strtoul (endp + 1, &endp, 0);
3141 else
3142 continue;
3143
3144 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
3145 {
3146 sprintf (name + strlen (name), "%u", MINOR (rdev));
3147 break;
3148 }
3149 }
3150 }
3151 fclose (fdev);
3152 }
3153 UNBLOCK_INPUT;
3154 return build_string (name);
3155 }
3156
3157 static unsigned long
3158 procfs_get_total_memory (void)
3159 {
3160 FILE *fmem = NULL;
3161 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
3162
3163 BLOCK_INPUT;
3164 fmem = fopen ("/proc/meminfo", "r");
3165
3166 if (fmem)
3167 {
3168 unsigned long entry_value;
3169 char entry_name[20]; /* the longest I saw is 13+1 */
3170
3171 while (!feof (fmem) && !ferror (fmem))
3172 {
3173 if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
3174 && strcmp (entry_name, "MemTotal:") == 0)
3175 {
3176 retval = entry_value;
3177 break;
3178 }
3179 }
3180 fclose (fmem);
3181 }
3182 UNBLOCK_INPUT;
3183 return retval;
3184 }
3185
3186 Lisp_Object
3187 system_process_attributes (Lisp_Object pid)
3188 {
3189 char procfn[PATH_MAX], fn[PATH_MAX];
3190 struct stat st;
3191 struct passwd *pw;
3192 struct group *gr;
3193 long clocks_per_sec;
3194 char *procfn_end;
3195 char procbuf[1025], *p, *q;
3196 int fd;
3197 ssize_t nread;
3198 const char *cmd = NULL;
3199 char *cmdline = NULL;
3200 size_t cmdsize = 0, cmdline_size;
3201 unsigned char c;
3202 int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
3203 unsigned long long utime, stime, cutime, cstime, start;
3204 long priority, nice, rss;
3205 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
3206 time_t sec;
3207 unsigned usec;
3208 EMACS_TIME tnow, tstart, tboot, telapsed;
3209 double pcpu, pmem;
3210 Lisp_Object attrs = Qnil;
3211 Lisp_Object cmd_str, decoded_cmd, tem;
3212 struct gcpro gcpro1, gcpro2;
3213 EMACS_INT uid_eint, gid_eint;
3214
3215 CHECK_NUMBER_OR_FLOAT (pid);
3216 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3217 sprintf (procfn, "/proc/%u", proc_id);
3218 if (stat (procfn, &st) < 0)
3219 return attrs;
3220
3221 GCPRO2 (attrs, decoded_cmd);
3222
3223 /* euid egid */
3224 uid = st.st_uid;
3225 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
3226 uid_eint = uid;
3227 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3228 BLOCK_INPUT;
3229 pw = getpwuid (uid);
3230 UNBLOCK_INPUT;
3231 if (pw)
3232 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3233
3234 gid = st.st_gid;
3235 gid_eint = gid;
3236 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3237 BLOCK_INPUT;
3238 gr = getgrgid (gid);
3239 UNBLOCK_INPUT;
3240 if (gr)
3241 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3242
3243 strcpy (fn, procfn);
3244 procfn_end = fn + strlen (fn);
3245 strcpy (procfn_end, "/stat");
3246 fd = emacs_open (fn, O_RDONLY, 0);
3247 if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof (procbuf) - 1)) > 0)
3248 {
3249 procbuf[nread] = '\0';
3250 p = procbuf;
3251
3252 p = strchr (p, '(');
3253 if (p != NULL)
3254 {
3255 q = strrchr (p + 1, ')');
3256 /* comm */
3257 if (q != NULL)
3258 {
3259 cmd = p + 1;
3260 cmdsize = q - cmd;
3261 }
3262 }
3263 else
3264 q = NULL;
3265 if (cmd == NULL)
3266 {
3267 cmd = "???";
3268 cmdsize = 3;
3269 }
3270 /* Command name is encoded in locale-coding-system; decode it. */
3271 cmd_str = make_unibyte_string (cmd, cmdsize);
3272 decoded_cmd = code_convert_string_norecord (cmd_str,
3273 Vlocale_coding_system, 0);
3274 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3275
3276 if (q)
3277 {
3278 EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
3279 p = q + 2;
3280 /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
3281 sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
3282 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
3283 &minflt, &cminflt, &majflt, &cmajflt,
3284 &utime, &stime, &cutime, &cstime,
3285 &priority, &nice, &thcount, &start, &vsize, &rss);
3286 {
3287 char state_str[2];
3288
3289 state_str[0] = c;
3290 state_str[1] = '\0';
3291 tem = build_string (state_str);
3292 attrs = Fcons (Fcons (Qstate, tem), attrs);
3293 }
3294 /* Stops GCC whining about limited range of data type. */
3295 ppid_eint = ppid;
3296 pgrp_eint = pgrp;
3297 sess_eint = sess;
3298 tpgid_eint = tpgid;
3299 thcount_eint = thcount;
3300 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
3301 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
3302 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
3303 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
3304 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
3305 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
3306 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
3307 attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
3308 attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
3309 clocks_per_sec = sysconf (_SC_CLK_TCK);
3310 if (clocks_per_sec < 0)
3311 clocks_per_sec = 100;
3312 attrs = Fcons (Fcons (Qutime,
3313 ltime_from_jiffies (utime, clocks_per_sec)),
3314 attrs);
3315 attrs = Fcons (Fcons (Qstime,
3316 ltime_from_jiffies (stime, clocks_per_sec)),
3317 attrs);
3318 attrs = Fcons (Fcons (Qtime,
3319 ltime_from_jiffies (stime+utime, clocks_per_sec)),
3320 attrs);
3321 attrs = Fcons (Fcons (Qcutime,
3322 ltime_from_jiffies (cutime, clocks_per_sec)),
3323 attrs);
3324 attrs = Fcons (Fcons (Qcstime,
3325 ltime_from_jiffies (cstime, clocks_per_sec)),
3326 attrs);
3327 attrs = Fcons (Fcons (Qctime,
3328 ltime_from_jiffies (cstime+cutime, clocks_per_sec)),
3329 attrs);
3330 attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
3331 attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
3332 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
3333 EMACS_GET_TIME (tnow);
3334 get_up_time (&sec, &usec);
3335 EMACS_SET_SECS (telapsed, sec);
3336 EMACS_SET_USECS (telapsed, usec);
3337 EMACS_SUB_TIME (tboot, tnow, telapsed);
3338 time_from_jiffies (start, clocks_per_sec, &sec, &usec);
3339 EMACS_SET_SECS (tstart, sec);
3340 EMACS_SET_USECS (tstart, usec);
3341 EMACS_ADD_TIME (tstart, tboot, tstart);
3342 attrs = Fcons (Fcons (Qstart,
3343 list3 (make_number
3344 ((EMACS_SECS (tstart) >> 16) & 0xffff),
3345 make_number
3346 (EMACS_SECS (tstart) & 0xffff),
3347 make_number
3348 (EMACS_USECS (tstart)))),
3349 attrs);
3350 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
3351 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
3352 EMACS_SUB_TIME (telapsed, tnow, tstart);
3353 attrs = Fcons (Fcons (Qetime,
3354 list3 (make_number
3355 ((EMACS_SECS (telapsed) >> 16) & 0xffff),
3356 make_number
3357 (EMACS_SECS (telapsed) & 0xffff),
3358 make_number
3359 (EMACS_USECS (telapsed)))),
3360 attrs);
3361 time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
3362 pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
3363 if (pcpu > 1.0)
3364 pcpu = 1.0;
3365 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
3366 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
3367 if (pmem > 100)
3368 pmem = 100;
3369 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
3370 }
3371 }
3372 if (fd >= 0)
3373 emacs_close (fd);
3374
3375 /* args */
3376 strcpy (procfn_end, "/cmdline");
3377 fd = emacs_open (fn, O_RDONLY, 0);
3378 if (fd >= 0)
3379 {
3380 for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
3381 {
3382 if (isspace (c) || c == '\\')
3383 cmdline_size++; /* for later quoting, see below */
3384 }
3385 if (cmdline_size)
3386 {
3387 cmdline = xmalloc (cmdline_size + 1);
3388 lseek (fd, 0L, SEEK_SET);
3389 cmdline[0] = '\0';
3390 if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
3391 cmdline[nread++] = '\0';
3392 else
3393 {
3394 /* Assigning zero to `nread' makes us skip the following
3395 two loops, assign zero to cmdline_size, and enter the
3396 following `if' clause that handles unknown command
3397 lines. */
3398 nread = 0;
3399 }
3400 /* We don't want trailing null characters. */
3401 for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
3402 nread--;
3403 for (p = cmdline; p < cmdline + nread; p++)
3404 {
3405 /* Escape-quote whitespace and backslashes. */
3406 if (isspace (*p) || *p == '\\')
3407 {
3408 memmove (p + 1, p, nread - (p - cmdline));
3409 nread++;
3410 *p++ = '\\';
3411 }
3412 else if (*p == '\0')
3413 *p = ' ';
3414 }
3415 cmdline_size = nread;
3416 }
3417 if (!cmdline_size)
3418 {
3419 if (!cmd)
3420 cmd = "???";
3421 if (!cmdsize)
3422 cmdsize = strlen (cmd);
3423 cmdline_size = cmdsize + 2;
3424 cmdline = xmalloc (cmdline_size + 1);
3425 strcpy (cmdline, "[");
3426 strcat (strncat (cmdline, cmd, cmdsize), "]");
3427 }
3428 emacs_close (fd);
3429 /* Command line is encoded in locale-coding-system; decode it. */
3430 cmd_str = make_unibyte_string (cmdline, cmdline_size);
3431 decoded_cmd = code_convert_string_norecord (cmd_str,
3432 Vlocale_coding_system, 0);
3433 xfree (cmdline);
3434 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3435 }
3436
3437 UNGCPRO;
3438 return attrs;
3439 }
3440
3441 #elif defined (SOLARIS2) && defined (HAVE_PROCFS)
3442
3443 /* The <procfs.h> header does not like to be included if _LP64 is defined and
3444 __FILE_OFFSET_BITS == 64. This is an ugly workaround that. */
3445 #if !defined (_LP64) && defined (_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
3446 #define PROCFS_FILE_OFFSET_BITS_HACK 1
3447 #undef _FILE_OFFSET_BITS
3448 #else
3449 #define PROCFS_FILE_OFFSET_BITS_HACK 0
3450 #endif
3451
3452 #include <procfs.h>
3453
3454 #if PROCFS_FILE_OFFSET_BITS_HACK == 1
3455 #define _FILE_OFFSET_BITS 64
3456 #endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
3457
3458 Lisp_Object
3459 system_process_attributes (Lisp_Object pid)
3460 {
3461 char procfn[PATH_MAX], fn[PATH_MAX];
3462 struct stat st;
3463 struct passwd *pw;
3464 struct group *gr;
3465 char *procfn_end;
3466 struct psinfo pinfo;
3467 int fd;
3468 ssize_t nread;
3469 int proc_id, uid, gid;
3470 Lisp_Object attrs = Qnil;
3471 Lisp_Object decoded_cmd, tem;
3472 struct gcpro gcpro1, gcpro2;
3473 EMACS_INT uid_eint, gid_eint;
3474
3475 CHECK_NUMBER_OR_FLOAT (pid);
3476 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3477 sprintf (procfn, "/proc/%u", proc_id);
3478 if (stat (procfn, &st) < 0)
3479 return attrs;
3480
3481 GCPRO2 (attrs, decoded_cmd);
3482
3483 /* euid egid */
3484 uid = st.st_uid;
3485 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
3486 uid_eint = uid;
3487 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3488 BLOCK_INPUT;
3489 pw = getpwuid (uid);
3490 UNBLOCK_INPUT;
3491 if (pw)
3492 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3493
3494 gid = st.st_gid;
3495 gid_eint = gid;
3496 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3497 BLOCK_INPUT;
3498 gr = getgrgid (gid);
3499 UNBLOCK_INPUT;
3500 if (gr)
3501 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3502
3503 strcpy (fn, procfn);
3504 procfn_end = fn + strlen (fn);
3505 strcpy (procfn_end, "/psinfo");
3506 fd = emacs_open (fn, O_RDONLY, 0);
3507 if (fd >= 0
3508 && (nread = read (fd, (char*)&pinfo, sizeof (struct psinfo)) > 0))
3509 {
3510 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs);
3511 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs);
3512 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (pinfo.pr_sid)), attrs);
3513
3514 {
3515 char state_str[2];
3516 state_str[0] = pinfo.pr_lwp.pr_sname;
3517 state_str[1] = '\0';
3518 tem = build_string (state_str);
3519 attrs = Fcons (Fcons (Qstate, tem), attrs);
3520 }
3521
3522 /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t,
3523 need to get a string from it. */
3524
3525 /* FIXME: missing: Qtpgid */
3526
3527 /* FIXME: missing:
3528 Qminflt
3529 Qmajflt
3530 Qcminflt
3531 Qcmajflt
3532
3533 Qutime
3534 Qcutime
3535 Qstime
3536 Qcstime
3537 Are they available? */
3538
3539 attrs = Fcons (Fcons (Qtime,
3540 list3 (make_number (pinfo.pr_time.tv_sec >> 16),
3541 make_number (pinfo.pr_time.tv_sec & 0xffff),
3542 make_number (pinfo.pr_time.tv_nsec))),
3543 attrs);
3544
3545 attrs = Fcons (Fcons (Qctime,
3546 list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
3547 make_number (pinfo.pr_ctime.tv_sec & 0xffff),
3548 make_number (pinfo.pr_ctime.tv_nsec))),
3549 attrs);
3550
3551 attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
3552 attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
3553 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
3554
3555 attrs = Fcons (Fcons (Qstart,
3556 list3 (make_number (pinfo.pr_start.tv_sec >> 16),
3557 make_number (pinfo.pr_start.tv_sec & 0xffff),
3558 make_number (pinfo.pr_start.tv_nsec))),
3559 attrs);
3560 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
3561 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
3562
3563 /* pr_pctcpu and pr_pctmem are encoded as a fixed point 16 bit number in [0 ... 1]. */
3564 attrs = Fcons (Fcons (Qpcpu, (pinfo.pr_pctcpu * 100.0) / (double)0x8000), attrs);
3565 attrs = Fcons (Fcons (Qpmem, (pinfo.pr_pctmem * 100.0) / (double)0x8000), attrs);
3566
3567 decoded_cmd
3568 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
3569 strlen (pinfo.pr_fname)),
3570 Vlocale_coding_system, 0);
3571 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3572 decoded_cmd
3573 = code_convert_string_norecord (make_unibyte_string (pinfo.pr_psargs,
3574 strlen (pinfo.pr_psargs)),
3575 Vlocale_coding_system, 0);
3576 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3577 }
3578
3579 if (fd >= 0)
3580 emacs_close (fd);
3581
3582 UNGCPRO;
3583 return attrs;
3584 }
3585
3586 /* The WINDOWSNT implementation is in w32.c.
3587 The MSDOS implementation is in dosfns.c. */
3588 #elif !defined (WINDOWSNT) && !defined (MSDOS)
3589
3590 Lisp_Object
3591 system_process_attributes (Lisp_Object pid)
3592 {
3593 return Qnil;
3594 }
3595
3596 #endif /* !defined (WINDOWSNT) */
3597
3598
3599 /* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
3600 (do not change this comment) */