1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 86,87,88,93,94,95, 1999 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
30 #include "blockinput.h"
35 __sigfun
sys_signal (int signal
, __sigfun signal_func
);
37 __signal_func_ptr
sys_signal (int signal
, __signal_func_ptr signal_func
);
42 /* Nonzero means delete a process right away if it exits (process.c). */
43 static int delete_exited_processes
;
45 #ifndef HAVE_X_WINDOWS
46 /* Search path for bitmap files (xfns.c). */
47 Lisp_Object Vx_bitmap_file_path
;
49 #endif /* macintosh */
51 #define min(x,y) ((x) > (y) ? (y) : (x))
55 #define write sys_write
58 #endif /* not WINDOWSNT */
60 /* Does anyone other than VMS need this? */
62 #define sys_fwrite fwrite
72 #include <sys/types.h>
76 /* Get _POSIX_VDISABLE, if it is available. */
86 #if !defined (USG) || defined (BSD_PGRPS)
87 #define setpgrp setpgid
91 /* Get SI_SRPC_DOMAIN, if it is available. */
92 #ifdef HAVE_SYS_SYSTEMINFO_H
93 #include <sys/systeminfo.h>
96 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
100 #include <sys/param.h>
104 extern unsigned start
__asm__ ("start");
124 #include <sys/file.h>
132 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
136 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
137 because the vms compiler doesn't grok `defined' */
145 #endif /* not 4.1 bsd */
148 #include <sys/ioctl.h>
154 #ifdef BROKEN_TIOCGWINSZ
159 #if defined (USG) || defined (DGUX)
160 #include <sys/utsname.h>
162 #ifndef MEMORY_IN_STRING_H
165 #if defined (TIOCGWINSZ) || defined (ISC4_0)
167 #include <sys/sioctl.h>
170 #include <sys/stream.h>
171 #include <sys/ptem.h>
173 #endif /* TIOCGWINSZ or ISC4_0 */
174 #endif /* USG or DGUX */
176 extern int quit_char
;
180 #include "termhooks.h"
181 #include "termchar.h"
182 #include "termopts.h"
183 #include "dispextern.h"
188 /* In process.h which conflicts with the local copy. */
190 int _CRTAPI1
_spawnlp (int, const char *, const char *, ...);
191 int _CRTAPI1
_getpid (void);
194 #ifdef NONSYSTEM_DIR_LIBRARY
196 #endif /* NONSYSTEM_DIR_LIBRARY */
198 #include "syssignal.h"
205 #ifndef HAVE_STRUCT_UTIMBUF
206 /* We want to use utime rather than utimes, but we couldn't find the
207 structure declaration. We'll use the traditional one. */
215 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
221 #define LNOFLSH 0100000
224 static int baud_convert
[] =
229 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
230 1800, 2400, 4800, 9600, 19200, 38400
236 extern speed_t ospeed
;
238 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
241 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
243 /* HJL's version of libc is said to need this on the Alpha.
244 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
245 extern speed_t ospeed
;
252 /* The file descriptor for Emacs's input terminal.
253 Under Unix, this is normally zero except when using X;
254 under VMS, we place the input channel number here. */
257 void croak
P_ ((char *));
265 /* Specify a different file descriptor for further input operations. */
274 /* Discard pending input on descriptor input_fd. */
280 struct emacs_tty buf
;
285 /* Discarding input is not safe when the input could contain
286 replies from the X server. So don't do it. */
287 if (read_socket_hook
)
292 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
293 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
299 ioctl (input_fd
, TIOCFLUSH
, &zero
);
301 #else /* not Apollo */
302 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
303 while (dos_keyread () != -1)
305 #else /* not MSDOS */
306 EMACS_GET_TTY (input_fd
, &buf
);
307 EMACS_SET_TTY (input_fd
, &buf
, 0);
308 #endif /* not MSDOS */
309 #endif /* not Apollo */
311 #endif /* not WINDOWSNT */
316 /* Arrange for character C to be read as the next input from
323 if (read_socket_hook
)
326 /* Should perhaps error if in batch mode */
328 ioctl (input_fd
, TIOCSTI
, &c
);
329 #else /* no TIOCSTI */
330 error ("Cannot stuff terminal input characters in this version of Unix");
331 #endif /* no TIOCSTI */
343 #ifdef INIT_BAUD_RATE
348 #else /* not DOS_NT */
352 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
353 &sg
.class, 12, 0, 0, 0, 0 );
354 ospeed
= sg
.xmit_baud
;
360 tcgetattr (input_fd
, &sg
);
361 ospeed
= cfgetospeed (&sg
);
362 #if defined (USE_GETOBAUD) && defined (getobaud)
363 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
365 ospeed
= getobaud (sg
.c_cflag
);
367 #else /* neither VMS nor TERMIOS */
373 tcgetattr (input_fd
, &sg
);
375 ioctl (input_fd
, TCGETA
, &sg
);
377 ospeed
= sg
.c_cflag
& CBAUD
;
378 #else /* neither VMS nor TERMIOS nor TERMIO */
381 sg
.sg_ospeed
= B9600
;
382 if (ioctl (input_fd
, TIOCGETP
, &sg
) < 0)
384 ospeed
= sg
.sg_ospeed
;
385 #endif /* not HAVE_TERMIO */
386 #endif /* not HAVE_TERMIOS */
388 #endif /* not DOS_NT */
389 #endif /* not INIT_BAUD_RATE */
392 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
393 ? baud_convert
[ospeed
] : 9600);
400 set_exclusive_use (fd
)
404 ioctl (fd
, FIOCLEX
, 0);
406 /* Ok to do nothing if this feature does not exist */
411 wait_without_blocking ()
414 wait3 (0, WNOHANG
| WUNTRACED
, 0);
416 croak ("wait_without_blocking");
418 synch_process_alive
= 0;
421 #endif /* not subprocesses */
423 int wait_debugging
; /* Set nonzero to make following function work under dbx
424 (at least for bsd). */
427 wait_for_termination_signal ()
430 /* Wait for subprocess with process id `pid' to terminate and
431 make sure it will get eliminated (not remain forever as a zombie) */
434 wait_for_termination (pid
)
443 status
= SYS$
FORCEX (&pid
, 0, 0);
446 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
447 /* Note that kill returns -1 even if the process is just a zombie now.
448 But inevitably a SIGCHLD interrupt should be generated
449 and child_sig will do wait3 and make the process go away. */
450 /* There is some indication that there is a bug involved with
451 termination of subprocesses, perhaps involving a kernel bug too,
452 but no idea what it is. Just as a hunch we signal SIGCHLD to see
453 if that causes the problem to go away or get worse. */
454 sigsetmask (sigmask (SIGCHLD
));
455 if (0 > kill (pid
, 0))
457 sigsetmask (SIGEMPTYMASK
);
458 kill (getpid (), SIGCHLD
);
464 sigpause (SIGEMPTYMASK
);
465 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
466 #if defined (UNIPLUS)
467 if (0 > kill (pid
, 0))
470 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
471 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
472 sigblock (sigmask (SIGCHLD
));
473 if (0 > kill (pid
, 0))
475 sigunblock (sigmask (SIGCHLD
));
478 sigpause (SIGEMPTYMASK
);
479 #else /* not POSIX_SIGNALS */
480 #ifdef HAVE_SYSV_SIGPAUSE
482 if (0 > kill (pid
, 0))
488 #else /* not HAVE_SYSV_SIGPAUSE */
492 #else /* not WINDOWSNT */
493 if (0 > kill (pid
, 0))
495 /* Using sleep instead of pause avoids timing error.
496 If the inferior dies just before the sleep,
497 we lose just one second. */
499 #endif /* not WINDOWSNT */
500 #endif /* not HAVE_SYSV_SIGPAUSE */
501 #endif /* not POSIX_SIGNALS */
502 #endif /* not UNIPLUS */
503 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
505 #else /* not subprocesses */
508 #else /* not __DJGPP__ > 1 */
510 if (kill (pid
, 0) < 0)
516 if (status
== pid
|| status
== -1)
519 #endif /* not __DJGPP__ > 1*/
520 #endif /* not subprocesses */
527 * flush any pending output
528 * (may flush input as well; it does not matter the way we use it)
532 flush_pending_output (channel
)
536 /* If we try this, we get hit with SIGTTIN, because
537 the child's tty belongs to the child's pgrp. */
540 ioctl (channel
, TCFLSH
, 1);
544 /* 3rd arg should be ignored
545 but some 4.2 kernels actually want the address of an int
546 and nonzero means something different. */
547 ioctl (channel
, TIOCFLUSH
, &zero
);
554 /* Set up the terminal at the other end of a pseudo-terminal that
555 we will be controlling an inferior through.
556 It should not echo or do line-editing, since that is done
557 in Emacs. No padding needed for insertion into an Emacs buffer. */
560 child_setup_tty (out
)
566 EMACS_GET_TTY (out
, &s
);
568 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
569 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
570 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
572 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
573 /* No output delays */
575 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
576 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
578 s
.main
.c_iflag
&= ~IUCLC
; /* Disable downcasing on input. */
581 s
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
584 s
.main
.c_oflag
&= ~OLCUC
; /* Disable upcasing on output. */
586 s
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
587 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CSIZE
) | CS8
; /* Don't strip 8th bit */
589 /* Said to be unnecessary: */
590 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
591 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
594 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
595 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
596 s
.main
.c_cc
[VERASE
] = CDISABLE
; /* disable erase processing */
597 s
.main
.c_cc
[VKILL
] = CDISABLE
; /* disable kill processing */
600 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
604 /* AIX enhanced edit loses NULs, so disable it */
607 s
.main
.c_iflag
&= ~ASCEDIT
;
609 /* Also, PTY overloads NUL and BREAK.
610 don't ignore break, but don't signal either, so it looks like NUL. */
611 s
.main
.c_iflag
&= ~IGNBRK
;
612 s
.main
.c_iflag
&= ~BRKINT
;
613 /* QUIT and INTR work better as signals, so disable character forms */
614 s
.main
.c_cc
[VINTR
] = 0377;
615 #ifdef SIGNALS_VIA_CHARACTERS
616 /* the QUIT and INTR character are used in process_send_signal
617 so set them here to something useful. */
618 if (s
.main
.c_cc
[VQUIT
] == 0377)
619 s
.main
.c_cc
[VQUIT
] = '\\'&037; /* Control-\ */
620 if (s
.main
.c_cc
[VINTR
] == 0377)
621 s
.main
.c_cc
[VINTR
] = 'C'&037; /* Control-C */
622 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
623 /* QUIT and INTR work better as signals, so disable character forms */
624 s
.main
.c_cc
[VQUIT
] = 0377;
625 s
.main
.c_cc
[VINTR
] = 0377;
626 s
.main
.c_lflag
&= ~ISIG
;
627 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
628 s
.main
.c_cc
[VEOL
] = 0377;
629 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
632 #else /* not HAVE_TERMIO */
634 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
636 s
.main
.sg_flags
|= LPASS8
;
637 s
.main
.sg_erase
= 0377;
638 s
.main
.sg_kill
= 0377;
639 s
.lmode
= LLITOUT
| s
.lmode
; /* Don't strip 8th bit */
641 #endif /* not HAVE_TERMIO */
643 EMACS_SET_TTY (out
, &s
, 0);
652 ioctl (out
, FIOASYNC
, &zero
);
655 #endif /* not DOS_NT */
659 #endif /* subprocesses */
661 /* Record a signal code and the handler for it. */
665 SIGTYPE (*handler
) P_ ((int));
668 static void save_signal_handlers
P_ ((struct save_signal
*));
669 static void restore_signal_handlers
P_ ((struct save_signal
*));
671 /* Suspend the Emacs process; give terminal to its superior. */
677 /* "Foster" parentage allows emacs to return to a subprocess that attached
678 to the current emacs as a cheaper than starting a whole new process. This
679 is set up by KEPTEDITOR.COM. */
680 unsigned long parent_id
, foster_parent_id
;
683 fpid_string
= getenv ("EMACS_PARENT_PID");
684 if (fpid_string
!= NULL
)
686 sscanf (fpid_string
, "%x", &foster_parent_id
);
687 if (foster_parent_id
!= 0)
688 parent_id
= foster_parent_id
;
690 parent_id
= getppid ();
693 parent_id
= getppid ();
695 xfree (fpid_string
); /* On VMS, this was malloc'd */
697 if (parent_id
&& parent_id
!= 0xffffffff)
699 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
700 int status
= LIB$
ATTACH (&parent_id
) & 1;
701 signal (SIGINT
, oldsig
);
710 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
711 d_prompt
.a
= "Emacs: "; /* Just a reminder */
712 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
717 #if defined (SIGTSTP) && !defined (MSDOS)
720 int pgrp
= EMACS_GETPGRP (0);
721 EMACS_KILLPG (pgrp
, SIGTSTP
);
724 #else /* No SIGTSTP */
725 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
726 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
727 kill (getpid (), SIGQUIT
);
729 #else /* No SIGTSTP or USG_JOBCTRL */
731 /* On a system where suspending is not implemented,
732 instead fork a subshell and let it talk directly to the terminal
736 #endif /* no USG_JOBCTRL */
737 #endif /* no SIGTSTP */
741 /* Fork a subshell. */
747 error ("Can't spawn subshell");
750 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
752 char oldwd
[MAXPATHLEN
+1]; /* Fixed length is safe on MSDOS. */
755 struct save_signal saved_handlers
[5];
757 unsigned char *str
= 0;
760 saved_handlers
[0].code
= SIGINT
;
761 saved_handlers
[1].code
= SIGQUIT
;
762 saved_handlers
[2].code
= SIGTERM
;
764 saved_handlers
[3].code
= SIGIO
;
765 saved_handlers
[4].code
= 0;
767 saved_handlers
[3].code
= 0;
770 /* Mentioning current_buffer->buffer would mean including buffer.h,
771 which somehow wedges the hp compiler. So instead... */
773 dir
= intern ("default-directory");
774 if (NILP (Fboundp (dir
)))
776 dir
= Fsymbol_value (dir
);
780 dir
= expand_and_dir_to_file (Funhandled_file_name_directory (dir
), Qnil
);
781 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
782 len
= XSTRING (dir
)->size
;
783 bcopy (XSTRING (dir
)->data
, str
, len
);
784 if (str
[len
- 1] != '/') str
[len
++] = '/';
791 save_signal_handlers (saved_handlers
);
792 synch_process_alive
= 1;
793 #endif /* __DJGPP__ > 1 */
797 error ("Can't spawn subshell");
804 #ifdef DOS_NT /* MW, Aug 1993 */
807 sh
= (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
810 sh
= (char *) egetenv ("SHELL");
814 /* Use our buffer's default directory for the subshell. */
816 chdir ((char *) str
);
819 close_process_descs (); /* Close Emacs's pipes/ptys */
822 #ifdef SET_EMACS_PRIORITY
824 extern int emacs_priority
;
826 if (emacs_priority
< 0)
827 nice (-emacs_priority
);
831 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
834 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
836 report_file_error ("Can't execute subshell", Fcons (build_string (sh
), Qnil
));
838 #else /* not MSDOS */
840 /* Waits for process completion */
841 pid
= _spawnlp (_P_WAIT
, sh
, sh
, NULL
);
844 write (1, "Can't execute subshell", 22);
845 #else /* not WINDOWSNT */
847 write (1, "Can't execute subshell", 22);
849 #endif /* not WINDOWSNT */
850 #endif /* not MSDOS */
853 /* Do this now if we did not do it before. */
854 #if !defined (MSDOS) || __DJGPP__ == 1
855 save_signal_handlers (saved_handlers
);
856 synch_process_alive
= 1;
860 wait_for_termination (pid
);
862 restore_signal_handlers (saved_handlers
);
863 synch_process_alive
= 0;
865 #endif /* !macintosh */
869 save_signal_handlers (saved_handlers
)
870 struct save_signal
*saved_handlers
;
872 while (saved_handlers
->code
)
874 saved_handlers
->handler
875 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers
->code
, SIG_IGN
);
881 restore_signal_handlers (saved_handlers
)
882 struct save_signal
*saved_handlers
;
884 while (saved_handlers
->code
)
886 signal (saved_handlers
->code
, saved_handlers
->handler
);
900 old_fcntl_flags
= fcntl (fd
, F_GETFL
, 0) & ~FASYNC
;
901 fcntl (fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
903 interrupts_deferred
= 0;
912 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
917 if (read_socket_hook
)
921 sigunblock (sigmask (SIGWINCH
));
923 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
925 interrupts_deferred
= 0;
931 if (read_socket_hook
)
935 sigblock (sigmask (SIGWINCH
));
937 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
);
938 interrupts_deferred
= 1;
941 #else /* no FASYNC */
942 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
949 if (read_socket_hook
)
952 ioctl (input_fd
, FIOASYNC
, &on
);
953 interrupts_deferred
= 0;
961 if (read_socket_hook
)
964 ioctl (input_fd
, FIOASYNC
, &off
);
965 interrupts_deferred
= 1;
968 #else /* not FASYNC, not STRIDE */
980 if (read_socket_hook
)
984 sigaddset (&st
, SIGIO
);
985 ioctl (input_fd
, FIOASYNC
, &on
);
986 interrupts_deferred
= 0;
987 sigprocmask (SIG_UNBLOCK
, &st
, (sigset_t
*)0);
995 if (read_socket_hook
)
998 ioctl (input_fd
, FIOASYNC
, &off
);
999 interrupts_deferred
= 1;
1002 #else /* ! _CX_UX */
1007 if (read_socket_hook
)
1010 croak ("request_sigio");
1016 if (read_socket_hook
)
1019 croak ("unrequest_sigio");
1025 #endif /* F_SETFL */
1027 /* Saving and restoring the process group of Emacs's terminal. */
1031 /* The process group of which Emacs was a member when it initially
1034 If Emacs was in its own process group (i.e. inherited_pgroup ==
1035 getpid ()), then we know we're running under a shell with job
1036 control (Emacs would never be run as part of a pipeline).
1039 If Emacs was not in its own process group, then we know we're
1040 running under a shell (or a caller) that doesn't know how to
1041 separate itself from Emacs (like sh). Emacs must be in its own
1042 process group in order to receive SIGIO correctly. In this
1043 situation, we put ourselves in our own pgroup, forcibly set the
1044 tty's pgroup to our pgroup, and make sure to restore and reinstate
1045 the tty's pgroup just like any other terminal setting. If
1046 inherited_group was not the tty's pgroup, then we'll get a
1047 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1048 it goes foreground in the future, which is what should happen. */
1049 int inherited_pgroup
;
1051 /* Split off the foreground process group to Emacs alone.
1052 When we are in the foreground, but not started in our own process
1053 group, redirect the TTY to point to our own process group. We need
1054 to be in our own process group to receive SIGIO properly. */
1056 narrow_foreground_group ()
1060 setpgrp (0, inherited_pgroup
);
1061 if (inherited_pgroup
!= me
)
1062 EMACS_SET_TTY_PGRP (input_fd
, &me
);
1066 /* Set the tty to our original foreground group. */
1068 widen_foreground_group ()
1070 if (inherited_pgroup
!= getpid ())
1071 EMACS_SET_TTY_PGRP (input_fd
, &inherited_pgroup
);
1072 setpgrp (0, inherited_pgroup
);
1075 #endif /* BSD_PGRPS */
1077 /* Getting and setting emacs_tty structures. */
1079 /* Set *TC to the parameters associated with the terminal FD.
1080 Return zero if all's well, or -1 if we ran into an error we
1081 couldn't deal with. */
1083 emacs_get_tty (fd
, settings
)
1085 struct emacs_tty
*settings
;
1087 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1089 /* We have those nifty POSIX tcmumbleattr functions. */
1090 bzero (&settings
->main
, sizeof (settings
->main
));
1091 if (tcgetattr (fd
, &settings
->main
) < 0)
1096 /* The SYSV-style interface? */
1097 if (ioctl (fd
, TCGETA
, &settings
->main
) < 0)
1102 /* Vehemently Monstrous System? :-) */
1103 if (! (SYS$
QIOW (0, fd
, IO$_SENSEMODE
, settings
, 0, 0,
1104 &settings
->main
.class, 12, 0, 0, 0, 0)
1110 /* I give up - I hope you have the BSD ioctls. */
1111 if (ioctl (fd
, TIOCGETP
, &settings
->main
) < 0)
1113 #endif /* not DOS_NT */
1118 /* Suivant - Do we have to get struct ltchars data? */
1120 if (ioctl (fd
, TIOCGLTC
, &settings
->ltchars
) < 0)
1124 /* How about a struct tchars and a wordful of lmode bits? */
1126 if (ioctl (fd
, TIOCGETC
, &settings
->tchars
) < 0
1127 || ioctl (fd
, TIOCLGET
, &settings
->lmode
) < 0)
1131 /* We have survived the tempest. */
1136 /* Set the parameters of the tty on FD according to the contents of
1137 *SETTINGS. If FLUSHP is non-zero, we discard input.
1138 Return 0 if all went well, and -1 if anything failed. */
1141 emacs_set_tty (fd
, settings
, flushp
)
1143 struct emacs_tty
*settings
;
1146 /* Set the primary parameters - baud rate, character size, etcetera. */
1149 /* We have those nifty POSIX tcmumbleattr functions.
1150 William J. Smith <wjs@wiis.wang.com> writes:
1151 "POSIX 1003.1 defines tcsetattr to return success if it was
1152 able to perform any of the requested actions, even if some
1153 of the requested actions could not be performed.
1154 We must read settings back to ensure tty setup properly.
1155 AIX requires this to keep tty from hanging occasionally." */
1156 /* This make sure that we don't loop indefinitely in here. */
1157 for (i
= 0 ; i
< 10 ; i
++)
1158 if (tcsetattr (fd
, flushp
? TCSAFLUSH
: TCSADRAIN
, &settings
->main
) < 0)
1169 bzero (&new, sizeof (new));
1170 /* Get the current settings, and see if they're what we asked for. */
1171 tcgetattr (fd
, &new);
1172 /* We cannot use memcmp on the whole structure here because under
1173 * aix386 the termios structure has some reserved field that may
1176 if ( new.c_iflag
== settings
->main
.c_iflag
1177 && new.c_oflag
== settings
->main
.c_oflag
1178 && new.c_cflag
== settings
->main
.c_cflag
1179 && new.c_lflag
== settings
->main
.c_lflag
1180 && memcmp (new.c_cc
, settings
->main
.c_cc
, NCCS
) == 0)
1188 /* The SYSV-style interface? */
1189 if (ioctl (fd
, flushp
? TCSETAF
: TCSETAW
, &settings
->main
) < 0)
1194 /* Vehemently Monstrous System? :-) */
1195 if (! (SYS$
QIOW (0, fd
, IO$_SETMODE
, &input_iosb
, 0, 0,
1196 &settings
->main
.class, 12, 0, 0, 0, 0)
1202 /* I give up - I hope you have the BSD ioctls. */
1203 if (ioctl (fd
, (flushp
) ? TIOCSETP
: TIOCSETN
, &settings
->main
) < 0)
1205 #endif /* not DOS_NT */
1211 /* Suivant - Do we have to get struct ltchars data? */
1213 if (ioctl (fd
, TIOCSLTC
, &settings
->ltchars
) < 0)
1217 /* How about a struct tchars and a wordful of lmode bits? */
1219 if (ioctl (fd
, TIOCSETC
, &settings
->tchars
) < 0
1220 || ioctl (fd
, TIOCLSET
, &settings
->lmode
) < 0)
1224 /* We have survived the tempest. */
1229 /* The initial tty mode bits */
1230 struct emacs_tty old_tty
;
1232 /* 1 if we have been through init_sys_modes. */
1235 /* 1 if outer tty status has been recorded. */
1239 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1244 #ifndef F_SETOWN_BUG
1246 int old_fcntl_owner
;
1247 #endif /* F_SETOWN */
1248 #endif /* F_SETOWN_BUG */
1250 /* This may also be defined in stdio,
1251 but if so, this does no harm,
1252 and using the same name avoids wasting the other one's space. */
1255 extern char *_sobuf
;
1257 #if defined (USG) || defined (DGUX)
1258 unsigned char _sobuf
[BUFSIZ
+8];
1260 char _sobuf
[BUFSIZ
];
1265 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
1268 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
1274 struct emacs_tty tty
;
1277 Vwindow_system
= intern ("mac");
1278 Vwindow_system_version
= make_number (1);
1280 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1281 #ifndef subprocesses
1282 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
1283 "*Non-nil means delete processes immediately when they exit.\n\
1284 nil means don't delete them until `list-processes' is run.");
1285 delete_exited_processes
= 0;
1288 #ifndef HAVE_X_WINDOWS
1289 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
1290 "List of directories to search for bitmap files for X.");
1291 Vx_bitmap_file_path
= decode_env_path ((char *) 0, ".");
1294 #endif /* not macintosh */
1298 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
1299 extern int (*interrupt_signal
) ();
1303 Vtty_erase_char
= Qnil
;
1310 input_ef
= get_kbd_event_flag ();
1311 /* LIB$GET_EF (&input_ef); */
1312 SYS$
CLREF (input_ef
);
1313 waiting_for_ast
= 0;
1315 timer_ef
= get_timer_event_flag ();
1316 /* LIB$GET_EF (&timer_ef); */
1317 SYS$
CLREF (timer_ef
);
1321 LIB$
GET_EF (&process_ef
);
1322 SYS$
CLREF (process_ef
);
1324 if (input_ef
/ 32 != process_ef
/ 32)
1325 croak ("Input and process event flags in different clusters.");
1327 if (input_ef
/ 32 != timer_ef
/ 32)
1328 croak ("Input and timer event flags in different clusters.");
1330 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1331 ((unsigned) 1 << (process_ef
% 32));
1333 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1334 ((unsigned) 1 << (timer_ef
% 32));
1336 sys_access_reinit ();
1338 #endif /* not VMS */
1341 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1342 narrow_foreground_group ();
1345 #ifdef HAVE_WINDOW_SYSTEM
1346 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1347 needs the initialization code below. */
1348 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1351 EMACS_GET_TTY (input_fd
, &old_tty
);
1357 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1358 XSETINT (Vtty_erase_char
, old_tty
.main
.c_cc
[VERASE
]);
1361 /* This allows meta to be sent on 8th bit. */
1362 tty
.main
.c_iflag
&= ~INPCK
; /* don't check input for parity */
1364 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
1365 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
1366 #ifdef INLCR /* I'm just being cautious,
1367 since I can't check how widespread INLCR is--rms. */
1368 tty
.main
.c_iflag
&= ~INLCR
; /* Disable map of NL to CR on input */
1371 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
1373 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
1374 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
1376 tty
.main
.c_lflag
&= ~IEXTEN
; /* Disable other editing characters. */
1378 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
1381 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
1383 tty
.main
.c_iflag
&= ~IXANY
;
1387 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
1388 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
1390 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
1394 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
1395 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
1398 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
1399 /* Set up C-g for both SIGQUIT and SIGINT.
1400 We don't know which we will get, but we handle both alike
1401 so which one it really gives us does not matter. */
1402 tty
.main
.c_cc
[VQUIT
] = quit_char
;
1403 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
1404 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
1406 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
1410 #if defined (mips) || defined (HAVE_TCATTR)
1412 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
1415 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
1416 #endif /* V_DSUSP */
1417 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1418 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
1421 tty
.main
.c_cc
[VLNEXT
] = CDISABLE
;
1424 tty
.main
.c_cc
[VREPRINT
] = CDISABLE
;
1425 #endif /* VREPRINT */
1427 tty
.main
.c_cc
[VWERASE
] = CDISABLE
;
1428 #endif /* VWERASE */
1430 tty
.main
.c_cc
[VDISCARD
] = CDISABLE
;
1431 #endif /* VDISCARD */
1436 tty
.main
.c_cc
[VSTART
] = '\021';
1439 tty
.main
.c_cc
[VSTOP
] = '\023';
1445 tty
.main
.c_cc
[VSTART
] = CDISABLE
;
1448 tty
.main
.c_cc
[VSTOP
] = CDISABLE
;
1451 #endif /* mips or HAVE_TCATTR */
1453 #ifdef SET_LINE_DISCIPLINE
1454 /* Need to explicitly request TERMIODISC line discipline or
1455 Ultrix's termios does not work correctly. */
1456 tty
.main
.c_line
= SET_LINE_DISCIPLINE
;
1460 /* AIX enhanced edit loses NULs, so disable it. */
1461 tty
.main
.c_line
= 0;
1462 tty
.main
.c_iflag
&= ~ASCEDIT
;
1464 tty
.main
.c_cc
[VSTRT
] = 255;
1465 tty
.main
.c_cc
[VSTOP
] = 255;
1466 tty
.main
.c_cc
[VSUSP
] = 255;
1467 tty
.main
.c_cc
[VDSUSP
] = 255;
1468 #endif /* IBMR2AIX */
1472 tty
.main
.c_cc
[VSTART
] = '\021';
1475 tty
.main
.c_cc
[VSTOP
] = '\023';
1478 /* Also, PTY overloads NUL and BREAK.
1479 don't ignore break, but don't signal either, so it looks like NUL.
1480 This really serves a purpose only if running in an XTERM window
1481 or via TELNET or the like, but does no harm elsewhere. */
1482 tty
.main
.c_iflag
&= ~IGNBRK
;
1483 tty
.main
.c_iflag
&= ~BRKINT
;
1485 #else /* if not HAVE_TERMIO */
1487 tty
.main
.tt_char
|= TT$M_NOECHO
;
1489 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
1491 tty
.main
.tt_char
|= TT$M_TTSYNC
;
1493 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
1494 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
1495 #else /* not VMS (BSD, that is) */
1497 XSETINT (Vtty_erase_char
, tty
.main
.sg_erase
);
1498 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
1500 tty
.main
.sg_flags
|= ANYP
;
1501 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
1502 #endif /* not DOS_NT */
1503 #endif /* not VMS (BSD, that is) */
1504 #endif /* not HAVE_TERMIO */
1506 /* If going to use CBREAK mode, we must request C-g to interrupt
1507 and turn off start and stop chars, etc. If not going to use
1508 CBREAK mode, do this anyway so as to turn off local flow
1509 control for user coming over network on 4.2; in this case,
1510 only t_stopc and t_startc really matter. */
1513 /* Note: if not using CBREAK mode, it makes no difference how we
1515 tty
.tchars
= new_tchars
;
1516 tty
.tchars
.t_intrc
= quit_char
;
1519 tty
.tchars
.t_startc
= '\021';
1520 tty
.tchars
.t_stopc
= '\023';
1523 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
1525 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1526 anything, and leaving it in breaks the meta key. Go figure. */
1527 tty
.lmode
&= ~LLITOUT
;
1534 #endif /* HAVE_TCHARS */
1535 #endif /* not HAVE_TERMIO */
1538 tty
.ltchars
= new_ltchars
;
1539 #endif /* HAVE_LTCHARS */
1540 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1542 internal_terminal_init ();
1546 EMACS_SET_TTY (input_fd
, &tty
, 0);
1548 /* This code added to insure that, if flow-control is not to be used,
1549 we have an unlocked terminal at the start. */
1552 if (!flow_control
) ioctl (input_fd
, TCXONC
, 1);
1556 if (!flow_control
) ioctl (input_fd
, TIOCSTART
, 0);
1560 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1562 if (!flow_control
) tcflow (input_fd
, TCOON
);
1570 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1571 to be only LF. This is the way that is done. */
1574 if (ioctl (1, HFTGETID
, &tty
) != -1)
1575 write (1, "\033[20l", 5);
1581 /* Appears to do nothing when in PASTHRU mode.
1582 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1583 interrupt_signal, oob_chars, 0, 0, 0, 0);
1585 queue_kbd_input (0);
1590 #ifndef F_SETOWN_BUG
1591 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1593 && ! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1595 old_fcntl_owner
= fcntl (input_fd
, F_GETOWN
, 0);
1596 fcntl (input_fd
, F_SETOWN
, getpid ());
1597 init_sigio (input_fd
);
1599 #endif /* F_GETOWN */
1600 #endif /* F_SETOWN_BUG */
1601 #endif /* F_SETFL */
1604 if (interrupt_input
)
1605 init_sigio (input_fd
);
1608 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1612 /* This symbol is defined on recent USG systems.
1613 Someone says without this call USG won't really buffer the file
1614 even with a call to setbuf. */
1615 setvbuf (stdout
, (char *) _sobuf
, _IOFBF
, sizeof _sobuf
);
1617 setbuf (stdout
, (char *) _sobuf
);
1619 #ifdef HAVE_WINDOW_SYSTEM
1620 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1621 needs the initialization code below. */
1622 if (EQ (Vwindow_system
, Qnil
)
1624 /* When running in tty mode on NT/Win95, we have a read_socket
1625 hook, but still need the rest of the initialization code below. */
1626 && (! read_socket_hook
)
1630 set_terminal_modes ();
1633 && FRAMEP (Vterminal_frame
)
1634 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame
)))
1635 init_frame_faces (XFRAME (Vterminal_frame
));
1637 if (term_initted
&& no_redraw_on_reenter
)
1639 if (display_completed
)
1640 direct_output_forward_char (0);
1645 if (FRAMEP (Vterminal_frame
))
1646 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
1652 /* Return nonzero if safe to use tabs in output.
1653 At the time this is called, init_sys_modes has not been done yet. */
1658 struct emacs_tty tty
;
1660 EMACS_GET_TTY (input_fd
, &tty
);
1661 return EMACS_TTY_TABS_OK (&tty
);
1664 /* Get terminal size from system.
1665 Store number of lines into *HEIGHTP and width into *WIDTHP.
1666 We store 0 if there's no valid information. */
1669 get_frame_size (widthp
, heightp
)
1670 int *widthp
, *heightp
;
1676 struct winsize size
;
1678 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1679 *widthp
= *heightp
= 0;
1682 *widthp
= size
.ws_col
;
1683 *heightp
= size
.ws_row
;
1689 /* SunOS - style. */
1690 struct ttysize size
;
1692 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1693 *widthp
= *heightp
= 0;
1696 *widthp
= size
.ts_cols
;
1697 *heightp
= size
.ts_lines
;
1703 struct sensemode tty
;
1705 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1706 &tty
.class, 12, 0, 0, 0, 0);
1707 *widthp
= tty
.scr_wid
;
1708 *heightp
= tty
.scr_len
;
1712 *widthp
= ScreenCols ();
1713 *heightp
= ScreenRows ();
1714 #else /* system doesn't know size */
1719 #endif /* not VMS */
1720 #endif /* not SunOS-style */
1721 #endif /* not BSD-style */
1724 /* Set the logical window size associated with descriptor FD
1725 to HEIGHT and WIDTH. This is used mainly with ptys. */
1728 set_window_size (fd
, height
, width
)
1729 int fd
, height
, width
;
1734 struct winsize size
;
1735 size
.ws_row
= height
;
1736 size
.ws_col
= width
;
1738 if (ioctl (fd
, TIOCSWINSZ
, &size
) == -1)
1739 return 0; /* error */
1746 /* SunOS - style. */
1747 struct ttysize size
;
1748 size
.ts_lines
= height
;
1749 size
.ts_cols
= width
;
1751 if (ioctl (fd
, TIOCGSIZE
, &size
) == -1)
1757 #endif /* not SunOS-style */
1758 #endif /* not BSD-style */
1762 /* Prepare the terminal for exiting Emacs; move the cursor to the
1763 bottom of the frame, turn off interrupt-driven I/O, etc. */
1776 #ifdef HAVE_WINDOW_SYSTEM
1777 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1778 needs the clean-up code below. */
1779 if (!EQ (Vwindow_system
, Qnil
)
1781 /* When running in tty mode on NT/Win95, we have a read_socket
1782 hook, but still need the rest of the clean-up code below. */
1788 sf
= SELECTED_FRAME ();
1789 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1790 clear_end_of_line (FRAME_WIDTH (sf
));
1791 /* clear_end_of_line may move the cursor */
1792 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1793 #if defined (IBMR2AIX) && defined (AIXHFT)
1795 /* HFT devices normally use ^J as a LF/CR. We forced it to
1796 do the LF only. Now, we need to reset it. */
1799 if (ioctl (1, HFTGETID
, &tty
) != -1)
1800 write (1, "\033[20h", 5);
1804 reset_terminal_modes ();
1808 /* Avoid possible loss of output when changing terminal modes. */
1809 fsync (fileno (stdout
));
1814 #ifndef F_SETOWN_BUG
1815 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1816 if (interrupt_input
)
1819 fcntl (input_fd
, F_SETOWN
, old_fcntl_owner
);
1821 #endif /* F_SETOWN */
1822 #endif /* F_SETOWN_BUG */
1824 fcntl (input_fd
, F_SETFL
, fcntl (input_fd
, F_GETFL
, 0) & ~O_NDELAY
);
1826 #endif /* F_SETFL */
1828 if (interrupt_input
)
1833 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1836 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1840 #ifdef SET_LINE_DISCIPLINE
1841 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1842 A different old line discipline is therefore not restored, yet.
1843 Restore the old line discipline by hand. */
1844 ioctl (0, TIOCSETD
, &old_tty
.main
.c_line
);
1852 widen_foreground_group ();
1858 /* Set up the proper status flags for use of a pty. */
1864 /* I'm told that TOICREMOTE does not mean control chars
1865 "can't be sent" but rather that they don't have
1866 input-editing or signaling effects.
1867 That should be good, because we have other ways
1868 to do those things in Emacs.
1869 However, telnet mode seems not to work on 4.2.
1870 So TIOCREMOTE is turned off now. */
1872 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1873 will hang. In particular, the "timeout" feature (which
1874 causes a read to return if there is no data available)
1875 does this. Also it is known that telnet mode will hang
1876 in such a way that Emacs must be stopped (perhaps this
1877 is the same problem).
1879 If TIOCREMOTE is turned off, then there is a bug in
1880 hp-ux which sometimes loses data. Apparently the
1881 code which blocks the master process when the internal
1882 buffer fills up does not work. Other than this,
1883 though, everything else seems to work fine.
1885 Since the latter lossage is more benign, we may as well
1886 lose that way. -- cph */
1888 #if defined(SYSV_PTYS) || defined(UNIX98_PTYS)
1891 ioctl (fd
, FIONBIO
, &on
);
1896 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1897 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1898 /* cause EMACS not to die when it should, i.e., when its own controlling */
1899 /* tty goes away. I've complained to the AIX developers, and they may */
1900 /* change this behavior, but I'm not going to hold my breath. */
1901 signal (SIGHUP
, SIG_IGN
);
1904 #endif /* HAVE_PTYS */
1908 /* Assigning an input channel is done at the start of Emacs execution.
1909 This is called each time Emacs is resumed, also, but does nothing
1910 because input_chain is no longer zero. */
1919 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1925 /* Deassigning the input channel is done before exiting. */
1930 return SYS$
DASSGN (input_fd
);
1935 /* Request reading one character into the keyboard buffer.
1936 This is done as soon as the buffer becomes empty. */
1942 extern kbd_input_ast ();
1944 waiting_for_ast
= 0;
1946 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1947 &input_iosb
, kbd_input_ast
, 1,
1948 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1953 /* Ast routine that is called when keyboard input comes in
1954 in accord with the SYS$QIO above. */
1959 register int c
= -1;
1960 int old_errno
= errno
;
1961 extern EMACS_TIME
*input_available_clear_time
;
1963 if (waiting_for_ast
)
1964 SYS$
SETEF (input_ef
);
1965 waiting_for_ast
= 0;
1968 if (input_count
== 25)
1970 printf ("Ast # %d,", input_count
);
1971 printf (" iosb = %x, %x, %x, %x",
1972 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1975 if (input_iosb
.offset
)
1979 printf (", char = 0%o", c
);
1991 struct input_event e
;
1992 e
.kind
= ascii_keystroke
;
1993 XSETINT (e
.code
, c
);
1994 e
.frame_or_window
= selected_frame
;
1995 kbd_buffer_store_event (&e
);
1997 if (input_available_clear_time
)
1998 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
2002 /* Wait until there is something in kbd_buffer. */
2005 wait_for_kbd_input ()
2007 extern int have_process_input
, process_exited
;
2009 /* If already something, avoid doing system calls. */
2010 if (detect_input_pending ())
2014 /* Clear a flag, and tell ast routine above to set it. */
2015 SYS$
CLREF (input_ef
);
2016 waiting_for_ast
= 1;
2017 /* Check for timing error: ast happened while we were doing that. */
2018 if (!detect_input_pending ())
2020 /* No timing error: wait for flag to be set. */
2021 set_waiting_for_input (0);
2022 SYS$
WFLOR (input_ef
, input_eflist
);
2023 clear_waiting_for_input (0);
2024 if (!detect_input_pending ())
2025 /* Check for subprocess input availability */
2027 int dsp
= have_process_input
|| process_exited
;
2029 SYS$
CLREF (process_ef
);
2030 if (have_process_input
)
2031 process_command_input ();
2036 update_mode_lines
++;
2037 prepare_menu_bars ();
2038 redisplay_preserve_echo_area ();
2042 waiting_for_ast
= 0;
2045 /* Get rid of any pending QIO, when we are about to suspend
2046 or when we want to throw away pending input.
2047 We wait for a positive sign that the AST routine has run
2048 and therefore there is no I/O request queued when we return.
2049 SYS$SETAST is used to avoid a timing error. */
2055 printf ("At end_kbd_input.\n");
2059 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2061 SYS$
CANCEL (input_fd
);
2066 /* Clear a flag, and tell ast routine above to set it. */
2067 SYS$
CLREF (input_ef
);
2068 waiting_for_ast
= 1;
2070 SYS$
CANCEL (input_fd
);
2072 SYS$
WAITFR (input_ef
);
2073 waiting_for_ast
= 0;
2076 /* Wait for either input available or time interval expiry. */
2079 input_wait_timeout (timeval
)
2080 int timeval
; /* Time to wait, in seconds */
2083 static int zero
= 0;
2084 static int large
= -10000000;
2086 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2088 /* If already something, avoid doing system calls. */
2089 if (detect_input_pending ())
2093 /* Clear a flag, and tell ast routine above to set it. */
2094 SYS$
CLREF (input_ef
);
2095 waiting_for_ast
= 1;
2096 /* Check for timing error: ast happened while we were doing that. */
2097 if (!detect_input_pending ())
2099 /* No timing error: wait for flag to be set. */
2101 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2102 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
2104 waiting_for_ast
= 0;
2107 /* The standard `sleep' routine works some other way
2108 and it stops working if you have ever quit out of it.
2109 This one continues to work. */
2115 static int zero
= 0;
2116 static int large
= -10000000;
2118 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2121 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2122 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
2140 croak ("request sigio");
2146 croak ("unrequest sigio");
2151 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2156 #ifndef SYSTEM_MALLOC
2163 /* Some systems that cannot dump also cannot implement these. */
2166 * Return the address of the start of the text segment prior to
2167 * doing an unexec. After unexec the return value is undefined.
2168 * See crt0.c for further explanation and _start.
2172 #if !(defined (__NetBSD__) && defined (__ELF__))
2173 #ifndef HAVE_TEXT_START
2178 return ((char *) TEXT_START
);
2182 return ((char *) csrt
);
2183 #else /* not GOULD */
2184 extern int _start ();
2185 return ((char *) _start
);
2187 #endif /* TEXT_START */
2189 #endif /* not HAVE_TEXT_START */
2193 * Return the address of the start of the data segment prior to
2194 * doing an unexec. After unexec the return value is undefined.
2195 * See crt0.c for further information and definition of data_start.
2197 * Apparently, on BSD systems this is etext at startup. On
2198 * USG systems (swapping) this is highly mmu dependent and
2199 * is also dependent on whether or not the program is running
2200 * with shared text. Generally there is a (possibly large)
2201 * gap between end of text and start of data with shared text.
2203 * On Uniplus+ systems with shared text, data starts at a
2204 * fixed address. Each port (from a given oem) is generally
2205 * different, and the specific value of the start of data can
2206 * be obtained via the UniPlus+ specific "uvar" system call,
2207 * however the method outlined in crt0.c seems to be more portable.
2209 * Probably what will have to happen when a USG unexec is available,
2210 * at least on UniPlus, is temacs will have to be made unshared so
2211 * that text and data are contiguous. Then once loadup is complete,
2212 * unexec will produce a shared executable where the data can be
2213 * at the normal shared text boundary and the startofdata variable
2214 * will be patched by unexec to the correct value.
2222 return ((char *) DATA_START
);
2224 #ifdef ORDINARY_LINK
2226 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2227 * data_start isn't defined. We take the address of environ, which
2228 * is known to live at or near the start of the system crt0.c, and
2229 * we don't sweat the handful of bytes that might lose.
2231 extern char **environ
;
2233 return ((char *) &environ
);
2235 extern int data_start
;
2236 return ((char *) &data_start
);
2237 #endif /* ORDINARY_LINK */
2238 #endif /* DATA_START */
2240 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2243 /* Some systems that cannot dump also cannot implement these. */
2246 * Return the address of the end of the text segment prior to
2247 * doing an unexec. After unexec the return value is undefined.
2254 return ((char *) TEXT_END
);
2257 return ((char *) &etext
);
2262 * Return the address of the end of the data segment prior to
2263 * doing an unexec. After unexec the return value is undefined.
2270 return ((char *) DATA_END
);
2273 return ((char *) &edata
);
2277 #endif /* not CANNOT_DUMP */
2279 /* init_system_name sets up the string for the Lisp function
2280 system-name to return. */
2286 extern Lisp_Object Vsystem_name
;
2291 #include <sys/socket.h>
2293 #endif /* HAVE_SOCKETS */
2294 #endif /* not VMS */
2295 #endif /* not BSD4_1 */
2301 Vsystem_name
= build_string (sysname
);
2305 if ((sp
= egetenv ("SYS$NODE")) == 0)
2306 Vsystem_name
= build_string ("vax-vms");
2307 else if ((end
= index (sp
, ':')) == 0)
2308 Vsystem_name
= build_string (sp
);
2310 Vsystem_name
= make_string (sp
, end
- sp
);
2312 #ifndef HAVE_GETHOSTNAME
2315 Vsystem_name
= build_string (uts
.nodename
);
2316 #else /* HAVE_GETHOSTNAME */
2317 unsigned int hostname_size
= 256;
2318 char *hostname
= (char *) alloca (hostname_size
);
2320 /* Try to get the host name; if the buffer is too short, try
2321 again. Apparently, the only indication gethostname gives of
2322 whether the buffer was large enough is the presence or absence
2323 of a '\0' in the string. Eech. */
2326 gethostname (hostname
, hostname_size
- 1);
2327 hostname
[hostname_size
- 1] = '\0';
2329 /* Was the buffer large enough for the '\0'? */
2330 if (strlen (hostname
) < hostname_size
- 1)
2333 hostname_size
<<= 1;
2334 hostname
= (char *) alloca (hostname_size
);
2337 /* Turn the hostname into the official, fully-qualified hostname.
2338 Don't do this if we're going to dump; this can confuse system
2339 libraries on some machines and make the dumped emacs core dump. */
2342 #endif /* not CANNOT_DUMP */
2343 if (! index (hostname
, '.'))
2347 for (count
= 0;; count
++)
2352 hp
= gethostbyname (hostname
);
2354 if (! (hp
== 0 && h_errno
== TRY_AGAIN
))
2359 Fsleep_for (make_number (1), Qnil
);
2363 char *fqdn
= (char *) hp
->h_name
;
2366 if (!index (fqdn
, '.'))
2368 /* We still don't have a fully qualified domain name.
2369 Try to find one in the list of alternate names */
2370 char **alias
= hp
->h_aliases
;
2371 while (*alias
&& !index (*alias
, '.'))
2378 /* Convert the host name to lower case. */
2379 /* Using ctype.h here would introduce a possible locale
2380 dependence that is probably wrong for hostnames. */
2384 if (*p
>= 'A' && *p
<= 'Z')
2391 #endif /* HAVE_SOCKETS */
2392 /* We used to try using getdomainname here,
2393 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2394 getdomainname gets the NIS/YP domain which often is not the same
2395 as in Internet domain name. */
2396 #if 0 /* Turned off because sysinfo is not really likely to return the
2397 correct Internet domain. */
2398 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2399 if (! index (hostname
, '.'))
2401 /* The hostname is not fully qualified. Append the domain name. */
2403 int hostlen
= strlen (hostname
);
2404 int domain_size
= 256;
2408 char *domain
= (char *) alloca (domain_size
+ 1);
2409 char *fqdn
= (char *) alloca (hostlen
+ 1 + domain_size
+ 1);
2410 int sys_domain_size
= sysinfo (SI_SRPC_DOMAIN
, domain
, domain_size
);
2411 if (sys_domain_size
<= 0)
2413 if (domain_size
< sys_domain_size
)
2415 domain_size
= sys_domain_size
;
2418 strcpy (fqdn
, hostname
);
2419 if (domain
[0] == '.')
2420 strcpy (fqdn
+ hostlen
, domain
);
2421 else if (domain
[0] != 0)
2423 fqdn
[hostlen
] = '.';
2424 strcpy (fqdn
+ hostlen
+ 1, domain
);
2430 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2432 Vsystem_name
= build_string (hostname
);
2433 #endif /* HAVE_GETHOSTNAME */
2438 for (p
= XSTRING (Vsystem_name
)->data
; *p
; p
++)
2439 if (*p
== ' ' || *p
== '\t')
2446 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2448 #include "sysselect.h"
2451 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2452 /* Cause explanatory error message at compile time,
2453 since the select emulation is not good enough for X. */
2454 int *x
= &x_windows_lose_if_no_select_system_call
;
2457 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2458 * Only checks read descriptors.
2460 /* How long to wait between checking fds in select */
2461 #define SELECT_PAUSE 1
2464 /* For longjmp'ing back to read_input_waiting. */
2466 jmp_buf read_alarm_throw
;
2468 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2469 The read_socket_hook function sets this to 1 while it is waiting. */
2471 int read_alarm_should_throw
;
2479 #else /* not BSD4_1 */
2480 signal (SIGALRM
, SIG_IGN
);
2481 #endif /* not BSD4_1 */
2482 if (read_alarm_should_throw
)
2483 longjmp (read_alarm_throw
, 1);
2487 /* Only rfds are checked. */
2489 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2491 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2492 EMACS_TIME
*timeout
;
2498 extern int proc_buffered_char
[];
2499 #ifndef subprocesses
2500 int process_tick
= 0, update_tick
= 0;
2502 extern int process_tick
, update_tick
;
2506 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2507 /* If we're using X, then the native select will work; we only need the
2508 emulation for non-X usage. */
2509 if (!NILP (Vwindow_system
))
2510 return select (nfds
, rfds
, wfds
, efds
, timeout
);
2512 timeoutval
= timeout
? EMACS_SECS (*timeout
) : 100000;
2513 local_timeout
= &timeoutval
;
2525 /* If we are looking only for the terminal, with no timeout,
2526 just read it and wait -- that's more efficient. */
2527 if (*local_timeout
== 100000 && process_tick
== update_tick
2528 && FD_ISSET (0, &orfds
))
2531 for (fd
= 1; fd
< nfds
; ++fd
)
2532 if (FD_ISSET (fd
, &orfds
))
2534 if (! detect_input_pending ())
2535 read_input_waiting ();
2541 /* Once a second, till the timer expires, check all the flagged read
2542 * descriptors to see if any input is available. If there is some then
2543 * set the corresponding bit in the return copy of rfds.
2547 register int to_check
, fd
;
2551 for (to_check
= nfds
, fd
= 0; --to_check
>= 0; fd
++)
2553 if (FD_ISSET (fd
, &orfds
))
2555 int avail
= 0, status
= 0;
2558 avail
= detect_input_pending (); /* Special keyboard handler */
2562 status
= ioctl (fd
, FIONREAD
, &avail
);
2563 #else /* no FIONREAD */
2564 /* Hoping it will return -1 if nothing available
2565 or 0 if all 0 chars requested are read. */
2566 if (proc_buffered_char
[fd
] >= 0)
2570 avail
= read (fd
, &buf
, 1);
2572 proc_buffered_char
[fd
] = buf
;
2574 #endif /* no FIONREAD */
2576 if (status
>= 0 && avail
> 0)
2584 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
2587 turn_on_atimers (0);
2588 signal (SIGALRM
, select_alarm
);
2590 alarm (SELECT_PAUSE
);
2592 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2593 while (select_alarmed
== 0 && *local_timeout
!= 0
2594 && process_tick
== update_tick
)
2596 /* If we are interested in terminal input,
2597 wait by reading the terminal.
2598 That makes instant wakeup for terminal input at least. */
2599 if (FD_ISSET (0, &orfds
))
2601 read_input_waiting ();
2602 if (detect_input_pending ())
2608 (*local_timeout
) -= SELECT_PAUSE
;
2610 /* Reset the old alarm if there was one. */
2611 turn_on_atimers (1);
2613 if (*local_timeout
== 0) /* Stop on timer being cleared */
2618 #endif /* not WINDOWSNT */
2620 /* Read keyboard input into the standard buffer,
2621 waiting for at least one character. */
2623 /* Make all keyboard buffers much bigger when using a window system. */
2624 #ifdef HAVE_WINDOW_SYSTEM
2625 #define BUFFER_SIZE_FACTOR 16
2627 #define BUFFER_SIZE_FACTOR 1
2631 read_input_waiting ()
2633 struct input_event e
;
2635 extern int quit_char
;
2637 if (read_socket_hook
)
2639 struct input_event buf
[256];
2641 read_alarm_should_throw
= 0;
2642 if (! setjmp (read_alarm_throw
))
2643 nread
= (*read_socket_hook
) (0, buf
, 256, 1);
2647 /* Scan the chars for C-g and store them in kbd_buffer. */
2648 for (i
= 0; i
< nread
; i
++)
2650 kbd_buffer_store_event (&buf
[i
]);
2651 /* Don't look at input that follows a C-g too closely.
2652 This reduces lossage due to autorepeat on C-g. */
2653 if (buf
[i
].kind
== ascii_keystroke
2654 && buf
[i
].code
== quit_char
)
2661 nread
= read (fileno (stdin
), buf
, 1);
2663 /* Scan the chars for C-g and store them in kbd_buffer. */
2664 e
.kind
= ascii_keystroke
;
2665 e
.frame_or_window
= selected_frame
;
2667 for (i
= 0; i
< nread
; i
++)
2669 /* Convert chars > 0177 to meta events if desired.
2670 We do this under the same conditions that read_avail_input does. */
2671 if (read_socket_hook
== 0)
2673 /* If the user says she has a meta key, then believe her. */
2674 if (meta_key
== 1 && (buf
[i
] & 0x80))
2675 e
.modifiers
= meta_modifier
;
2680 XSETINT (e
.code
, buf
[i
]);
2681 kbd_buffer_store_event (&e
);
2682 /* Don't look at input that follows a C-g too closely.
2683 This reduces lossage due to autorepeat on C-g. */
2684 if (buf
[i
] == quit_char
)
2690 #endif /* not HAVE_SELECT */
2691 #endif /* not VMS */
2692 #endif /* not MSDOS */
2701 lmode
= LINTRUP
| lmode
;
2702 ioctl (fd
, TIOCLSET
, &lmode
);
2710 lmode
= ~LINTRUP
& lmode
;
2711 ioctl (0, TIOCLSET
, &lmode
);
2719 interrupts_deferred
= 0;
2727 interrupts_deferred
= 1;
2730 /* still inside #ifdef BSD4_1 */
2733 int sigheld
; /* Mask of held signals */
2739 sigheld
|= sigbit (signum
);
2747 sigheld
|= sigbit (signum
);
2754 sigheld
&= ~sigbit (signum
);
2759 sigfree () /* Free all held signals */
2762 for (i
= 0; i
< NSIG
; i
++)
2763 if (sigheld
& sigbit (i
))
2771 return 1 << (i
- 1);
2773 #endif /* subprocesses */
2776 /* POSIX signals support - DJB */
2777 /* Anyone with POSIX signals should have ANSI C declarations */
2779 #ifdef POSIX_SIGNALS
2781 sigset_t empty_mask
, full_mask
;
2784 sys_signal (int signal_number
, signal_handler_t action
)
2786 struct sigaction new_action
, old_action
;
2787 sigemptyset (&new_action
.sa_mask
);
2788 new_action
.sa_handler
= action
;
2790 /* Emacs mostly works better with restartable system services. If this
2791 * flag exists, we probably want to turn it on here.
2793 new_action
.sa_flags
= SA_RESTART
;
2795 new_action
.sa_flags
= 0;
2797 sigaction (signal_number
, &new_action
, &old_action
);
2798 return (old_action
.sa_handler
);
2802 /* If we're compiling with GCC, we don't need this function, since it
2803 can be written as a macro. */
2805 sys_sigmask (int sig
)
2808 sigemptyset (&mask
);
2809 sigaddset (&mask
, sig
);
2814 /* I'd like to have these guys return pointers to the mask storage in here,
2815 but there'd be trouble if the code was saving multiple masks. I'll be
2816 safe and pass the structure. It normally won't be more than 2 bytes
2820 sys_sigblock (sigset_t new_mask
)
2823 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
2828 sys_sigunblock (sigset_t new_mask
)
2831 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
2836 sys_sigsetmask (sigset_t new_mask
)
2839 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
2843 #endif /* POSIX_SIGNALS */
2845 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2846 static char *my_sys_siglist
[NSIG
];
2850 # define sys_siglist my_sys_siglist
2856 #ifdef POSIX_SIGNALS
2857 sigemptyset (&empty_mask
);
2858 sigfillset (&full_mask
);
2861 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2865 sys_siglist
[SIGABRT
] = "Aborted";
2868 sys_siglist
[SIGAIO
] = "LAN I/O interrupt";
2871 sys_siglist
[SIGALRM
] = "Alarm clock";
2874 sys_siglist
[SIGBUS
] = "Bus error";
2877 sys_siglist
[SIGCLD
] = "Child status changed";
2880 sys_siglist
[SIGCHLD
] = "Child status changed";
2883 sys_siglist
[SIGCONT
] = "Continued";
2886 sys_siglist
[SIGDANGER
] = "Swap space dangerously low";
2889 sys_siglist
[SIGDGNOTIFY
] = "Notification message in queue";
2892 sys_siglist
[SIGEMT
] = "Emulation trap";
2895 sys_siglist
[SIGFPE
] = "Arithmetic exception";
2898 sys_siglist
[SIGFREEZE
] = "SIGFREEZE";
2901 sys_siglist
[SIGGRANT
] = "Monitor mode granted";
2904 sys_siglist
[SIGHUP
] = "Hangup";
2907 sys_siglist
[SIGILL
] = "Illegal instruction";
2910 sys_siglist
[SIGINT
] = "Interrupt";
2913 sys_siglist
[SIGIO
] = "I/O possible";
2916 sys_siglist
[SIGIOINT
] = "I/O intervention required";
2919 sys_siglist
[SIGIOT
] = "IOT trap";
2922 sys_siglist
[SIGKILL
] = "Killed";
2925 sys_siglist
[SIGLOST
] = "Resource lost";
2928 sys_siglist
[SIGLWP
] = "SIGLWP";
2931 sys_siglist
[SIGMSG
] = "Monitor mode data available";
2934 sys_siglist
[SIGWIND
] = "SIGPHONE";
2937 sys_siglist
[SIGPIPE
] = "Broken pipe";
2940 sys_siglist
[SIGPOLL
] = "Pollable event occurred";
2943 sys_siglist
[SIGPROF
] = "Profiling timer expired";
2946 sys_siglist
[SIGPTY
] = "PTY I/O interrupt";
2949 sys_siglist
[SIGPWR
] = "Power-fail restart";
2952 sys_siglist
[SIGQUIT
] = "Quit";
2955 sys_siglist
[SIGRETRACT
] = "Need to relinguish monitor mode";
2958 sys_siglist
[SIGSAK
] = "Secure attention";
2961 sys_siglist
[SIGSEGV
] = "Segmentation violation";
2964 sys_siglist
[SIGSOUND
] = "Sound completed";
2967 sys_siglist
[SIGSTOP
] = "Stopped (signal)";
2970 sys_siglist
[SIGSTP
] = "Stopped (user)";
2973 sys_siglist
[SIGSYS
] = "Bad argument to system call";
2976 sys_siglist
[SIGTERM
] = "Terminated";
2979 sys_siglist
[SIGTHAW
] = "SIGTHAW";
2982 sys_siglist
[SIGTRAP
] = "Trace/breakpoint trap";
2985 sys_siglist
[SIGTSTP
] = "Stopped (user)";
2988 sys_siglist
[SIGTTIN
] = "Stopped (tty input)";
2991 sys_siglist
[SIGTTOU
] = "Stopped (tty output)";
2994 sys_siglist
[SIGURG
] = "Urgent I/O condition";
2997 sys_siglist
[SIGUSR1
] = "User defined signal 1";
3000 sys_siglist
[SIGUSR2
] = "User defined signal 2";
3003 sys_siglist
[SIGVTALRM
] = "Virtual timer expired";
3006 sys_siglist
[SIGWAITING
] = "Process's LWPs are blocked";
3009 sys_siglist
[SIGWINCH
] = "Window size changed";
3012 sys_siglist
[SIGWIND
] = "SIGWIND";
3015 sys_siglist
[SIGXCPU
] = "CPU time limit exceeded";
3018 sys_siglist
[SIGXFSZ
] = "File size limit exceeded";
3021 #endif /* !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED */
3030 /* Figure out how many bits the system's random number generator uses.
3031 `random' and `lrand48' are assumed to return 31 usable bits.
3032 BSD `rand' returns a 31 bit value but the low order bits are unusable;
3033 so we'll shift it and treat it like the 15-bit USG `rand'. */
3037 # define RAND_BITS 31
3038 # else /* !HAVE_RANDOM */
3039 # ifdef HAVE_LRAND48
3040 # define RAND_BITS 31
3041 # define random lrand48
3042 # else /* !HAVE_LRAND48 */
3043 # define RAND_BITS 15
3044 # if RAND_MAX == 32767
3045 # define random rand
3046 # else /* RAND_MAX != 32767 */
3047 # if RAND_MAX == 2147483647
3048 # define random() (rand () >> 16)
3049 # else /* RAND_MAX != 2147483647 */
3051 # define random rand
3053 # define random() (rand () >> 16)
3055 # endif /* RAND_MAX != 2147483647 */
3056 # endif /* RAND_MAX != 32767 */
3057 # endif /* !HAVE_LRAND48 */
3058 # endif /* !HAVE_RANDOM */
3059 #endif /* !RAND_BITS */
3066 srandom ((unsigned int)arg
);
3068 # ifdef HAVE_LRAND48
3071 srand ((unsigned int)arg
);
3077 * Build a full Emacs-sized word out of whatever we've got.
3078 * This suffices even for a 64-bit architecture with a 15-bit rand.
3083 long val
= random ();
3084 #if VALBITS > RAND_BITS
3085 val
= (val
<< RAND_BITS
) ^ random ();
3086 #if VALBITS > 2*RAND_BITS
3087 val
= (val
<< RAND_BITS
) ^ random ();
3088 #if VALBITS > 3*RAND_BITS
3089 val
= (val
<< RAND_BITS
) ^ random ();
3090 #if VALBITS > 4*RAND_BITS
3091 val
= (val
<< RAND_BITS
) ^ random ();
3092 #endif /* need at least 5 */
3093 #endif /* need at least 4 */
3094 #endif /* need at least 3 */
3095 #endif /* need at least 2 */
3096 return val
& ((1L << VALBITS
) - 1);
3099 #ifdef WRONG_NAME_INSQUE
3112 /* If any place else asks for the TERM variable,
3113 allow it to be overridden with the EMACS_TERM variable
3114 before attempting to translate the logical name TERM. As a last
3115 resort, ask for VAX C's special idea of the TERM variable. */
3122 static char buf
[256];
3123 static struct dsc$descriptor_s equiv
3124 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
3125 static struct dsc$descriptor_s d_name
3126 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
3129 if (!strcmp (name
, "TERM"))
3131 val
= (char *) getenv ("EMACS_TERM");
3136 d_name
.dsc$w_length
= strlen (name
);
3137 d_name
.dsc$a_pointer
= name
;
3138 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
3140 char *str
= (char *) xmalloc (eqlen
+ 1);
3141 bcopy (buf
, str
, eqlen
);
3143 /* This is a storage leak, but a pain to fix. With luck,
3144 no one will ever notice. */
3147 return (char *) getenv (name
);
3152 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3153 to force a call on the debugger from within the image. */
3158 LIB$
SIGNAL (SS$_DEBUG
);
3164 #ifdef LINK_CRTL_SHARE
3165 #ifdef SHARABLE_LIB_BUG
3166 /* Variables declared noshare and initialized in sharable libraries
3167 cannot be shared. The VMS linker incorrectly forces you to use a private
3168 version which is uninitialized... If not for this "feature", we
3169 could use the C library definition of sys_nerr and sys_errlist. */
3171 char *sys_errlist
[] =
3175 "no such file or directory",
3177 "interrupted system call",
3179 "no such device or address",
3180 "argument list too long",
3181 "exec format error",
3184 "no more processes",
3185 "not enough memory",
3186 "permission denied",
3188 "block device required",
3189 "mount devices busy",
3191 "cross-device link",
3196 "file table overflow",
3197 "too many open files",
3201 "no space left on device",
3203 "read-only file system",
3209 "vax/vms specific error code nontranslatable error"
3211 #endif /* SHARABLE_LIB_BUG */
3212 #endif /* LINK_CRTL_SHARE */
3215 #ifndef HAVE_STRERROR
3221 extern char *sys_errlist
[];
3222 extern int sys_nerr
;
3224 if (errnum
>= 0 && errnum
< sys_nerr
)
3225 return sys_errlist
[errnum
];
3226 return (char *) "Unknown error";
3228 #endif /* not WINDOWSNT */
3229 #endif /* ! HAVE_STRERROR */
3232 emacs_open (path
, oflag
, mode
)
3236 register int rtnval
;
3239 if (oflag
& O_CREAT
)
3240 return creat (path
, mode
);
3243 while ((rtnval
= open (path
, oflag
, mode
)) == -1
3244 && (errno
== EINTR
));
3253 register int rtnval
;
3255 while ((rtnval
= close (fd
)) == -1
3256 && (errno
== EINTR
))
3259 /* If close is interrupted SunOS 4.1 may or may not have closed the
3260 file descriptor. If it did the second close will fail with
3261 errno = EBADF. That means we have succeeded. */
3262 if (rtnval
== -1 && did_retry
&& errno
== EBADF
)
3269 emacs_read (fildes
, buf
, nbyte
)
3274 register int rtnval
;
3276 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
3277 && (errno
== EINTR
));
3282 emacs_write (fildes
, buf
, nbyte
)
3287 register int rtnval
, bytes_written
;
3293 rtnval
= write (fildes
, buf
, nbyte
);
3300 return (bytes_written
? bytes_written
: -1);
3305 bytes_written
+= rtnval
;
3307 return (bytes_written
);
3312 * All of the following are for USG.
3314 * On USG systems the system calls are INTERRUPTIBLE by signals
3315 * that the user program has elected to catch. Thus the system call
3316 * must be retried in these cases. To handle this without massive
3317 * changes in the source code, we remap the standard system call names
3318 * to names for our own functions in sysdep.c that do the system call
3319 * with retries. Actually, for portability reasons, it is good
3320 * programming practice, as this example shows, to limit all actual
3321 * system calls to a single occurrence in the source. Sure, this
3322 * adds an extra level of function call overhead but it is almost
3323 * always negligible. Fred Fish, Unisoft Systems Inc.
3327 * Warning, this function may not duplicate 4.2 action properly
3328 * under error conditions.
3332 /* In 4.1, param.h fails to define this. */
3333 #define MAXPATHLEN 1024
3342 char *npath
, *spath
;
3343 extern char *getcwd ();
3345 BLOCK_INPUT
; /* getcwd uses malloc */
3346 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
3349 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3350 up to first slash. Should be harmless on other systems. */
3351 while (*npath
&& *npath
!= '/')
3353 strcpy (pathname
, npath
);
3354 free (spath
); /* getcwd uses malloc */
3359 #endif /* HAVE_GETWD */
3362 * Emulate rename using unlink/link. Note that this is
3363 * only partially correct. Also, doesn't enforce restriction
3364 * that files be of same type (regular->regular, dir->dir, etc).
3373 if (access (from
, 0) == 0)
3376 if (link (from
, to
) == 0)
3377 if (unlink (from
) == 0)
3389 /* HPUX curses library references perror, but as far as we know
3390 it won't be called. Anyway this definition will do for now. */
3396 #endif /* not HAVE_PERROR */
3402 * Emulate BSD dup2. First close newd if it already exists.
3403 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3404 * until we are, then close the unsuccessful ones.
3411 register int fd
, ret
;
3416 return fcntl (oldd
, F_DUPFD
, newd
);
3423 ret
= dup2 (old
,new);
3429 #endif /* not HAVE_DUP2 */
3432 * Gettimeofday. Simulate as much as possible. Only accurate
3433 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3434 * Only needed when subprocesses are defined.
3439 #ifndef HAVE_GETTIMEOFDAY
3444 gettimeofday (tp
, tzp
)
3446 struct timezone
*tzp
;
3448 extern long time ();
3450 tp
->tv_sec
= time ((long *)0);
3453 tzp
->tz_minuteswest
= -1;
3460 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3463 * This function will go away as soon as all the stubs fixed. (fnf)
3470 printf ("%s not yet implemented\r\n", badfunc
);
3477 /* Directory routines for systems that don't have them. */
3479 #ifdef SYSV_SYSTEM_DIR
3483 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3487 register DIR *dirp
; /* stream from opendir */
3491 rtnval
= emacs_close (dirp
->dd_fd
);
3493 /* Some systems (like Solaris) allocate the buffer and the DIR all
3494 in one block. Why in the world are we freeing this ourselves
3496 #if ! (defined (sun) && defined (USG5_4))
3497 xfree ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
3499 xfree ((char *) dirp
);
3503 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3504 #endif /* SYSV_SYSTEM_DIR */
3506 #ifdef NONSYSTEM_DIR_LIBRARY
3510 char *filename
; /* name of directory */
3512 register DIR *dirp
; /* -> malloc'ed storage */
3513 register int fd
; /* file descriptor for read */
3514 struct stat sbuf
; /* result of fstat */
3516 fd
= emacs_open (filename
, O_RDONLY
, 0);
3521 if (fstat (fd
, &sbuf
) < 0
3522 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
3523 || (dirp
= (DIR *) malloc (sizeof (DIR))) == 0)
3527 return 0; /* bad luck today */
3532 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
3539 register DIR *dirp
; /* stream from opendir */
3541 emacs_close (dirp
->dd_fd
);
3542 xfree ((char *) dirp
);
3550 ino_t od_ino
; /* inode */
3551 char od_name
[DIRSIZ
]; /* filename */
3553 #endif /* not VMS */
3555 struct direct dir_static
; /* simulated directory contents */
3560 register DIR *dirp
; /* stream from opendir */
3563 register struct olddir
*dp
; /* -> directory data */
3565 register struct dir$_name
*dp
; /* -> directory data */
3566 register struct dir$_version
*dv
; /* -> version data */
3571 if (dirp
->dd_loc
>= dirp
->dd_size
)
3572 dirp
->dd_loc
= dirp
->dd_size
= 0;
3574 if (dirp
->dd_size
== 0 /* refill buffer */
3575 && (dirp
->dd_size
= emacs_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3579 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
3580 dirp
->dd_loc
+= sizeof (struct olddir
);
3582 if (dp
->od_ino
!= 0) /* not deleted entry */
3584 dir_static
.d_ino
= dp
->od_ino
;
3585 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
3586 dir_static
.d_name
[DIRSIZ
] = '\0';
3587 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3588 dir_static
.d_reclen
= sizeof (struct direct
)
3590 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3591 return &dir_static
; /* -> simulated structure */
3594 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3595 if (dirp
->dd_loc
== 0)
3596 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
3597 : dp
->dir$b_namecount
;
3598 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
3599 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3600 dir_static
.d_namlen
= dp
->dir$b_namecount
;
3601 dir_static
.d_reclen
= sizeof (struct direct
)
3603 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3604 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3605 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
3606 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
3613 /* readdirver is just like readdir except it returns all versions of a file
3614 as separate entries. */
3619 register DIR *dirp
; /* stream from opendir */
3621 register struct dir$_name
*dp
; /* -> directory data */
3622 register struct dir$_version
*dv
; /* -> version data */
3624 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
3625 dirp
->dd_loc
= dirp
->dd_size
= 0;
3627 if (dirp
->dd_size
== 0 /* refill buffer */
3628 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3631 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3632 if (dirp
->dd_loc
== 0)
3633 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
3634 : dp
->dir$b_namecount
;
3635 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
3636 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3637 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
3638 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3639 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3640 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
3641 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3642 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
3648 #endif /* NONSYSTEM_DIR_LIBRARY */
3652 set_file_times (filename
, atime
, mtime
)
3654 EMACS_TIME atime
, mtime
;
3657 struct timeval tv
[2];
3660 return utimes (filename
, tv
);
3661 #else /* not HAVE_UTIMES */
3663 utb
.actime
= EMACS_SECS (atime
);
3664 utb
.modtime
= EMACS_SECS (mtime
);
3665 return utime (filename
, &utb
);
3666 #endif /* not HAVE_UTIMES */
3669 /* mkdir and rmdir functions, for systems which don't have them. */
3673 * Written by Robert Rother, Mariah Corporation, August 1985.
3675 * If you want it, it's yours. All I ask in return is that if you
3676 * figure out how to do this in a Bourne Shell script you send me
3678 * sdcsvax!rmr or rmr@uscd
3680 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3681 * subroutine. 11Mar86; hoptoad!gnu
3683 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3684 * subroutine didn't return EEXIST. It does now.
3690 #ifdef MKDIR_PROTOTYPE
3694 mkdir (dpath
, dmode
)
3699 int cpid
, status
, fd
;
3700 struct stat statbuf
;
3702 if (stat (dpath
, &statbuf
) == 0)
3704 errno
= EEXIST
; /* Stat worked, so it already exists */
3708 /* If stat fails for a reason other than non-existence, return error */
3709 if (errno
!= ENOENT
)
3712 synch_process_alive
= 1;
3713 switch (cpid
= fork ())
3716 case -1: /* Error in fork */
3717 return (-1); /* Errno is set already */
3719 case 0: /* Child process */
3721 * Cheap hack to set mode of new directory. Since this
3722 * child process is going away anyway, we zap its umask.
3723 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3724 * directory. Does anybody care?
3726 status
= umask (0); /* Get current umask */
3727 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
3728 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3735 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
3736 _exit (-1); /* Can't exec /bin/mkdir */
3738 default: /* Parent process */
3739 wait_for_termination (cpid
);
3742 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3744 errno
= EIO
; /* We don't know why, but */
3745 return -1; /* /bin/mkdir failed */
3750 #endif /* not HAVE_MKDIR */
3757 int cpid
, status
, fd
;
3758 struct stat statbuf
;
3760 if (stat (dpath
, &statbuf
) != 0)
3762 /* Stat just set errno. We don't have to */
3766 synch_process_alive
= 1;
3767 switch (cpid
= fork ())
3770 case -1: /* Error in fork */
3771 return (-1); /* Errno is set already */
3773 case 0: /* Child process */
3774 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3781 execl ("/bin/rmdir", "rmdir", dpath
, (char *) 0);
3782 _exit (-1); /* Can't exec /bin/rmdir */
3784 default: /* Parent process */
3785 wait_for_termination (cpid
);
3788 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3790 errno
= EIO
; /* We don't know why, but */
3791 return -1; /* /bin/rmdir failed */
3796 #endif /* !HAVE_RMDIR */
3800 /* Functions for VMS */
3802 #include "vms-pwd.h"
3807 /* Return as a string the VMS error string pertaining to STATUS.
3808 Reuses the same static buffer each time it is called. */
3812 int status
; /* VMS status code */
3816 static char buf
[257];
3818 bufadr
[0] = sizeof buf
- 1;
3819 bufadr
[1] = (int) buf
;
3820 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
3821 return "untranslatable VMS error status";
3829 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3830 * not work correctly. (It also doesn't work well in version 2.3.)
3835 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3836 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3840 unsigned short s_buflen
;
3841 unsigned short s_code
;
3843 unsigned short *s_retlenadr
;
3847 #define buflen s.s_buflen
3848 #define code s.s_code
3849 #define bufadr s.s_bufadr
3850 #define retlenadr s.s_retlenadr
3852 #define R_OK 4 /* test for read permission */
3853 #define W_OK 2 /* test for write permission */
3854 #define X_OK 1 /* test for execute (search) permission */
3855 #define F_OK 0 /* test for presence of file */
3858 sys_access (path
, mode
)
3862 static char *user
= NULL
;
3865 /* translate possible directory spec into .DIR file name, so brain-dead
3866 * access can treat the directory like a file. */
3867 if (directory_file_name (path
, dir_fn
))
3871 return access (path
, mode
);
3872 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
3878 unsigned short int dummy
;
3880 static int constant
= ACL$C_FILE
;
3881 DESCRIPTOR (path_desc
, path
);
3882 DESCRIPTOR (user_desc
, user
);
3886 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
3889 acces
|= CHP$M_READ
;
3891 acces
|= CHP$M_WRITE
;
3892 itemlst
[0].buflen
= sizeof (int);
3893 itemlst
[0].code
= CHP$_FLAGS
;
3894 itemlst
[0].bufadr
= (char *) &flags
;
3895 itemlst
[0].retlenadr
= &dummy
;
3896 itemlst
[1].buflen
= sizeof (int);
3897 itemlst
[1].code
= CHP$_ACCESS
;
3898 itemlst
[1].bufadr
= (char *) &acces
;
3899 itemlst
[1].retlenadr
= &dummy
;
3900 itemlst
[2].end
= CHP$_END
;
3901 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
3902 return stat
== SS$_NORMAL
? 0 : -1;
3906 #else /* not VMS4_4 */
3909 #define ACE$M_WRITE 2
3910 #define ACE$C_KEYID 1
3912 static unsigned short memid
, grpid
;
3913 static unsigned int uic
;
3915 /* Called from init_sys_modes, so it happens not very often
3916 but at least each time Emacs is loaded. */
3918 sys_access_reinit ()
3924 sys_access (filename
, type
)
3930 int status
, size
, i
, typecode
, acl_controlled
;
3931 unsigned int *aclptr
, *aclend
, aclbuf
[60];
3932 union prvdef prvmask
;
3934 /* Get UIC and GRP values for protection checking. */
3937 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
3940 memid
= uic
& 0xFFFF;
3944 if (type
!= 2) /* not checking write access */
3945 return access (filename
, type
);
3947 /* Check write protection. */
3949 #define CHECKPRIV(bit) (prvmask.bit)
3950 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3952 /* Find privilege bits */
3953 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
3955 error ("Unable to find privileges: %s", vmserrstr (status
));
3956 if (CHECKPRIV (PRV$V_BYPASS
))
3957 return 0; /* BYPASS enabled */
3959 fab
.fab$b_fac
= FAB$M_GET
;
3960 fab
.fab$l_fna
= filename
;
3961 fab
.fab$b_fns
= strlen (filename
);
3962 fab
.fab$l_xab
= &xab
;
3963 xab
= cc$rms_xabpro
;
3964 xab
.xab$l_aclbuf
= aclbuf
;
3965 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
3966 status
= SYS$
OPEN (&fab
, 0, 0);
3969 SYS$
CLOSE (&fab
, 0, 0);
3970 /* Check system access */
3971 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITABLE (XAB$V_SYS
))
3973 /* Check ACL entries, if any */
3975 if (xab
.xab$w_acllen
> 0)
3978 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
3979 while (*aclptr
&& aclptr
< aclend
)
3981 size
= (*aclptr
& 0xff) / 4;
3982 typecode
= (*aclptr
>> 8) & 0xff;
3983 if (typecode
== ACE$C_KEYID
)
3984 for (i
= size
- 1; i
> 1; i
--)
3985 if (aclptr
[i
] == uic
)
3988 if (aclptr
[1] & ACE$M_WRITE
)
3989 return 0; /* Write access through ACL */
3991 aclptr
= &aclptr
[size
];
3993 if (acl_controlled
) /* ACL specified, prohibits write access */
3996 /* No ACL entries specified, check normal protection */
3997 if (WRITABLE (XAB$V_WLD
)) /* World writable */
3999 if (WRITABLE (XAB$V_GRP
) &&
4000 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
4001 return 0; /* Group writable */
4002 if (WRITABLE (XAB$V_OWN
) &&
4003 (xab
.xab$l_uic
& 0xFFFF) == memid
)
4004 return 0; /* Owner writable */
4006 return -1; /* Not writable */
4008 #endif /* not VMS4_4 */
4011 static char vtbuf
[NAM$C_MAXRSS
+1];
4013 /* translate a vms file spec to a unix path */
4015 sys_translate_vms (vfile
)
4026 /* leading device or logical name is a root directory */
4027 if (p
= strchr (vfile
, ':'))
4036 if (*p
== '[' || *p
== '<')
4038 while (*++vfile
!= *p
+ 2)
4042 if (vfile
[-1] == *p
)
4065 static char utbuf
[NAM$C_MAXRSS
+1];
4067 /* translate a unix path to a VMS file spec */
4069 sys_translate_unix (ufile
)
4092 if (index (&ufile
[1], '/'))
4099 if (index (&ufile
[1], '/'))
4106 if (strncmp (ufile
, "./", 2) == 0)
4113 ufile
++; /* skip the dot */
4114 if (index (&ufile
[1], '/'))
4119 else if (strncmp (ufile
, "../", 3) == 0)
4127 ufile
+= 2; /* skip the dots */
4128 if (index (&ufile
[1], '/'))
4153 extern char *getcwd ();
4155 #define MAXPATHLEN 1024
4157 ptr
= xmalloc (MAXPATHLEN
);
4158 val
= getcwd (ptr
, MAXPATHLEN
);
4164 strcpy (pathname
, ptr
);
4173 long item_code
= JPI$_OWNER
;
4174 unsigned long parent_id
;
4177 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
4180 vaxc$errno
= status
;
4190 return (getgid () << 16) | getuid ();
4195 sys_read (fildes
, buf
, nbyte
)
4200 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
4205 sys_write (fildes
, buf
, nbyte
)
4210 register int nwrote
, rtnval
= 0;
4212 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
4218 return rtnval
? rtnval
: -1;
4219 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
4220 return rtnval
? rtnval
: -1;
4221 return (rtnval
+ nwrote
);
4226 * VAX/VMS VAX C RTL really loses. It insists that records
4227 * end with a newline (carriage return) character, and if they
4228 * don't it adds one (nice of it isn't it!)
4230 * Thus we do this stupidity below.
4235 sys_write (fildes
, buf
, nbytes
)
4238 unsigned int nbytes
;
4245 fstat (fildes
, &st
);
4251 /* Handle fixed-length files with carriage control. */
4252 if (st
.st_fab_rfm
== FAB$C_FIX
4253 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
4255 len
= st
.st_fab_mrs
;
4256 retval
= write (fildes
, p
, min (len
, nbytes
));
4259 retval
++; /* This skips the implied carriage control */
4263 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4264 while (*e
!= '\n' && e
> p
) e
--;
4265 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
4266 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4268 retval
= write (fildes
, p
, len
);
4279 /* Create file NEW copying its attributes from file OLD. If
4280 OLD is 0 or does not exist, create based on the value of
4283 /* Protection value the file should ultimately have.
4284 Set by create_copy_attrs, and use by rename_sansversions. */
4285 static unsigned short int fab_final_pro
;
4288 creat_copy_attrs (old
, new)
4291 struct FAB fab
= cc$rms_fab
;
4292 struct XABPRO xabpro
;
4293 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
4294 extern int vms_stmlf_recfm
;
4298 fab
.fab$b_fac
= FAB$M_GET
;
4299 fab
.fab$l_fna
= old
;
4300 fab
.fab$b_fns
= strlen (old
);
4301 fab
.fab$l_xab
= (char *) &xabpro
;
4302 xabpro
= cc$rms_xabpro
;
4303 xabpro
.xab$l_aclbuf
= aclbuf
;
4304 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
4305 /* Call $OPEN to fill in the fab & xabpro fields. */
4306 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4308 SYS$
CLOSE (&fab
, 0, 0);
4309 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
4310 if (xabpro
.xab$w_acllen
> 0)
4312 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
4313 /* If the acl buffer was too short, redo open with longer one.
4314 Wouldn't need to do this if there were some system imposed
4315 limit on the size of an ACL, but I can't find any such. */
4317 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
4318 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
4319 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4320 SYS$
CLOSE (&fab
, 0, 0);
4326 xabpro
.xab$l_aclbuf
= 0;
4331 fab
.fab$l_fna
= new;
4332 fab
.fab$b_fns
= strlen (new);
4336 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
4337 fab
.fab$b_rat
= FAB$M_CR
;
4340 /* Set the file protections such that we will be able to manipulate
4341 this file. Once we are done writing and renaming it, we will set
4342 the protections back. */
4344 fab_final_pro
= xabpro
.xab$w_pro
;
4346 SYS$
SETDFPROT (0, &fab_final_pro
);
4347 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
4349 /* Create the new file with either default attrs or attrs copied
4351 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
4353 SYS$
CLOSE (&fab
, 0, 0);
4354 /* As this is a "replacement" for creat, return a file descriptor
4355 opened for writing. */
4356 return open (new, O_WRONLY
);
4361 #include <varargs.h>
4364 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4369 sys_creat (va_alist
)
4372 va_list list_incrementer
;
4375 int rfd
; /* related file descriptor */
4376 int fd
; /* Our new file descriptor */
4383 extern int vms_stmlf_recfm
;
4386 va_start (list_incrementer
);
4387 name
= va_arg (list_incrementer
, char *);
4388 mode
= va_arg (list_incrementer
, int);
4390 rfd
= va_arg (list_incrementer
, int);
4391 va_end (list_incrementer
);
4394 /* Use information from the related file descriptor to set record
4395 format of the newly created file. */
4396 fstat (rfd
, &st_buf
);
4397 switch (st_buf
.st_fab_rfm
)
4400 strcpy (rfm
, "rfm = fix");
4401 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
4402 strcpy (rat
, "rat = ");
4403 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4405 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4406 strcat (rat
, "ftn");
4407 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4408 strcat (rat
, "prn");
4409 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4410 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4411 strcat (rat
, ", blk");
4413 strcat (rat
, "blk");
4414 return creat (name
, 0, rfm
, rat
, mrs
);
4417 strcpy (rfm
, "rfm = vfc");
4418 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
4419 strcpy (rat
, "rat = ");
4420 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4422 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4423 strcat (rat
, "ftn");
4424 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4425 strcat (rat
, "prn");
4426 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4427 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4428 strcat (rat
, ", blk");
4430 strcat (rat
, "blk");
4431 return creat (name
, 0, rfm
, rat
, fsz
);
4434 strcpy (rfm
, "rfm = stm");
4438 strcpy (rfm
, "rfm = stmcr");
4442 strcpy (rfm
, "rfm = stmlf");
4446 strcpy (rfm
, "rfm = udf");
4450 strcpy (rfm
, "rfm = var");
4453 strcpy (rat
, "rat = ");
4454 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4456 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4457 strcat (rat
, "ftn");
4458 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4459 strcat (rat
, "prn");
4460 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4461 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4462 strcat (rat
, ", blk");
4464 strcat (rat
, "blk");
4468 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
4469 strcpy (rat
, "rat=cr");
4471 /* Until the VAX C RTL fixes the many bugs with modes, always use
4472 mode 0 to get the user's default protection. */
4473 fd
= creat (name
, 0, rfm
, rat
);
4474 if (fd
< 0 && errno
== EEXIST
)
4476 if (unlink (name
) < 0)
4477 report_file_error ("delete", build_string (name
));
4478 fd
= creat (name
, 0, rfm
, rat
);
4484 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4486 sys_fwrite (ptr
, size
, num
, fp
)
4487 register char * ptr
;
4490 register int tot
= num
* size
;
4498 * The VMS C library routine creat actually creates a new version of an
4499 * existing file rather than truncating the old version. There are times
4500 * when this is not the desired behavior, for instance, when writing an
4501 * auto save file (you only want one version), or when you don't have
4502 * write permission in the directory containing the file (but the file
4503 * itself is writable). Hence this routine, which is equivalent to
4504 * "close (creat (fn, 0));" on Unix if fn already exists.
4510 struct FAB xfab
= cc$rms_fab
;
4511 struct RAB xrab
= cc$rms_rab
;
4514 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
4515 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
4516 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
4517 xfab
.fab$l_fna
= fn
;
4518 xfab
.fab$b_fns
= strlen (fn
);
4519 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
4521 xrab
.rab$l_fab
= &xfab
;
4523 /* This gibberish opens the file, positions to the first record, and
4524 deletes all records from there until the end of file. */
4525 if ((SYS$
OPEN (&xfab
) & 01) == 01)
4527 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
4528 (SYS$
FIND (&xrab
) & 01) == 01 &&
4529 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
4540 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4541 SYSPRV or a readable SYSUAF.DAT. */
4547 * Routine to read the VMS User Authorization File and return
4548 * a specific user's record.
4551 static struct UAF retuaf
;
4554 get_uaf_name (uname
)
4561 uaf_fab
= cc$rms_fab
;
4562 uaf_rab
= cc$rms_rab
;
4563 /* initialize fab fields */
4564 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4565 uaf_fab
.fab$b_fns
= 21;
4566 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4567 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4568 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4569 /* initialize rab fields */
4570 uaf_rab
.rab$l_fab
= &uaf_fab
;
4571 /* open the User Authorization File */
4572 status
= SYS$
OPEN (&uaf_fab
);
4576 vaxc$errno
= status
;
4579 status
= SYS$
CONNECT (&uaf_rab
);
4583 vaxc$errno
= status
;
4586 /* read the requested record - index is in uname */
4587 uaf_rab
.rab$l_kbf
= uname
;
4588 uaf_rab
.rab$b_ksz
= strlen (uname
);
4589 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4590 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4591 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4592 status
= SYS$
GET (&uaf_rab
);
4596 vaxc$errno
= status
;
4599 /* close the User Authorization File */
4600 status
= SYS$
DISCONNECT (&uaf_rab
);
4604 vaxc$errno
= status
;
4607 status
= SYS$
CLOSE (&uaf_fab
);
4611 vaxc$errno
= status
;
4625 uaf_fab
= cc$rms_fab
;
4626 uaf_rab
= cc$rms_rab
;
4627 /* initialize fab fields */
4628 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4629 uaf_fab
.fab$b_fns
= 21;
4630 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4631 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4632 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4633 /* initialize rab fields */
4634 uaf_rab
.rab$l_fab
= &uaf_fab
;
4635 /* open the User Authorization File */
4636 status
= SYS$
OPEN (&uaf_fab
);
4640 vaxc$errno
= status
;
4643 status
= SYS$
CONNECT (&uaf_rab
);
4647 vaxc$errno
= status
;
4650 /* read the requested record - index is in uic */
4651 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
4652 uaf_rab
.rab$l_kbf
= (char *) &uic
;
4653 uaf_rab
.rab$b_ksz
= sizeof uic
;
4654 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4655 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4656 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4657 status
= SYS$
GET (&uaf_rab
);
4661 vaxc$errno
= status
;
4664 /* close the User Authorization File */
4665 status
= SYS$
DISCONNECT (&uaf_rab
);
4669 vaxc$errno
= status
;
4672 status
= SYS$
CLOSE (&uaf_fab
);
4676 vaxc$errno
= status
;
4682 static struct passwd retpw
;
4690 /* copy these out first because if the username is 32 chars, the next
4691 section will overwrite the first byte of the UIC */
4692 retpw
.pw_uid
= up
->uaf$w_mem
;
4693 retpw
.pw_gid
= up
->uaf$w_grp
;
4695 /* I suppose this is not the best style, to possibly overwrite one
4696 byte beyond the end of the field, but what the heck... */
4697 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
4698 while (ptr
[-1] == ' ')
4701 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
4703 /* the rest of these are counted ascii strings */
4704 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
4705 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
4706 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
4707 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
4708 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
4709 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
4710 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
4711 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
4715 #else /* not READ_SYSUAF */
4716 static struct passwd retpw
;
4717 #endif /* not READ_SYSUAF */
4728 unsigned char * full
;
4729 #endif /* READ_SYSUAF */
4734 if ('a' <= *ptr
&& *ptr
<= 'z')
4739 if (!(up
= get_uaf_name (name
)))
4741 return cnv_uaf_pw (up
);
4743 if (strcmp (name
, getenv ("USER")) == 0)
4745 retpw
.pw_uid
= getuid ();
4746 retpw
.pw_gid
= getgid ();
4747 strcpy (retpw
.pw_name
, name
);
4748 if (full
= egetenv ("FULLNAME"))
4749 strcpy (retpw
.pw_gecos
, full
);
4751 *retpw
.pw_gecos
= '\0';
4752 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
4753 *retpw
.pw_shell
= '\0';
4758 #endif /* not READ_SYSUAF */
4768 if (!(up
= get_uaf_uic (uid
)))
4770 return cnv_uaf_pw (up
);
4772 if (uid
== sys_getuid ())
4773 return getpwnam (egetenv ("USER"));
4776 #endif /* not READ_SYSUAF */
4779 /* return total address space available to the current process. This is
4780 the sum of the current p0 size, p1 size and free page table entries
4786 unsigned long free_pages
;
4787 unsigned long frep0va
;
4788 unsigned long frep1va
;
4791 item_code
= JPI$_FREPTECNT
;
4792 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
4795 vaxc$errno
= status
;
4800 item_code
= JPI$_FREP0VA
;
4801 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
4804 vaxc$errno
= status
;
4807 item_code
= JPI$_FREP1VA
;
4808 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
4811 vaxc$errno
= status
;
4815 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
4819 define_logical_name (varname
, string
)
4823 struct dsc$descriptor_s strdsc
=
4824 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
4825 struct dsc$descriptor_s envdsc
=
4826 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4827 struct dsc$descriptor_s lnmdsc
=
4828 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4830 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
4834 delete_logical_name (varname
)
4837 struct dsc$descriptor_s envdsc
=
4838 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4839 struct dsc$descriptor_s lnmdsc
=
4840 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4842 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
4860 error ("execvp system call not implemented");
4869 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
4870 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
4871 char from_esn
[NAM$C_MAXRSS
];
4872 char to_esn
[NAM$C_MAXRSS
];
4874 from_fab
.fab$l_fna
= from
;
4875 from_fab
.fab$b_fns
= strlen (from
);
4876 from_fab
.fab$l_nam
= &from_nam
;
4877 from_fab
.fab$l_fop
= FAB$M_NAM
;
4879 from_nam
.nam$l_esa
= from_esn
;
4880 from_nam
.nam$b_ess
= sizeof from_esn
;
4882 to_fab
.fab$l_fna
= to
;
4883 to_fab
.fab$b_fns
= strlen (to
);
4884 to_fab
.fab$l_nam
= &to_nam
;
4885 to_fab
.fab$l_fop
= FAB$M_NAM
;
4887 to_nam
.nam$l_esa
= to_esn
;
4888 to_nam
.nam$b_ess
= sizeof to_esn
;
4890 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
4896 if (status
== RMS$_DEV
)
4900 vaxc$errno
= status
;
4905 /* This function renames a file like `rename', but it strips
4906 the version number from the "to" filename, such that the "to" file is
4907 will always be a new version. It also sets the file protection once it is
4908 finished. The protection that we will use is stored in fab_final_pro,
4909 and was set when we did a creat_copy_attrs to create the file that we
4912 We could use the chmod function, but Eunichs uses 3 bits per user category
4913 to describe the protection, and VMS uses 4 (write and delete are separate
4914 bits). To maintain portability, the VMS implementation of `chmod' wires
4915 the W and D bits together. */
4918 static struct fibdef fib
; /* We need this initialized to zero */
4919 char vms_file_written
[NAM$C_MAXRSS
];
4922 rename_sans_version (from
,to
)
4929 struct FAB to_fab
= cc$rms_fab
;
4930 struct NAM to_nam
= cc$rms_nam
;
4931 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
4932 struct dsc$descriptor fib_attr
[2]
4933 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
4934 char to_esn
[NAM$C_MAXRSS
];
4936 $
DESCRIPTOR (disk
,to_esn
);
4938 to_fab
.fab$l_fna
= to
;
4939 to_fab
.fab$b_fns
= strlen (to
);
4940 to_fab
.fab$l_nam
= &to_nam
;
4941 to_fab
.fab$l_fop
= FAB$M_NAM
;
4943 to_nam
.nam$l_esa
= to_esn
;
4944 to_nam
.nam$b_ess
= sizeof to_esn
;
4946 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
4948 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
4949 *(to_nam
.nam$l_ver
) = '\0';
4951 stat
= rename (from
, to_esn
);
4955 strcpy (vms_file_written
, to_esn
);
4957 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
4958 to_fab
.fab$b_fns
= strlen (vms_file_written
);
4960 /* Now set the file protection to the correct value */
4961 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
4963 /* Copy these fields into the fib */
4964 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
4965 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
4966 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
4968 SYS$
CLOSE (&to_fab
, 0, 0);
4970 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
4973 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
4974 0, 0, 0, &fib_attr
, 0);
4977 stat
= SYS$
DASSGN (chan
);
4980 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
4991 unsigned short fid
[3];
4992 char esa
[NAM$C_MAXRSS
];
4995 fab
.fab$l_fop
= FAB$M_OFP
;
4996 fab
.fab$l_fna
= file
;
4997 fab
.fab$b_fns
= strlen (file
);
4998 fab
.fab$l_nam
= &nam
;
5001 nam
.nam$l_esa
= esa
;
5002 nam
.nam$b_ess
= NAM$C_MAXRSS
;
5004 status
= SYS$
PARSE (&fab
);
5005 if ((status
& 1) == 0)
5008 vaxc$errno
= status
;
5011 status
= SYS$
SEARCH (&fab
);
5012 if ((status
& 1) == 0)
5015 vaxc$errno
= status
;
5019 fid
[0] = nam
.nam$w_fid
[0];
5020 fid
[1] = nam
.nam$w_fid
[1];
5021 fid
[2] = nam
.nam$w_fid
[2];
5023 fab
.fab$l_fna
= new;
5024 fab
.fab$b_fns
= strlen (new);
5026 status
= SYS$
PARSE (&fab
);
5027 if ((status
& 1) == 0)
5030 vaxc$errno
= status
;
5034 nam
.nam$w_fid
[0] = fid
[0];
5035 nam
.nam$w_fid
[1] = fid
[1];
5036 nam
.nam$w_fid
[2] = fid
[2];
5038 nam
.nam$l_esa
= nam
.nam$l_name
;
5039 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
5041 status
= SYS$
ENTER (&fab
);
5042 if ((status
& 1) == 0)
5045 vaxc$errno
= status
;
5056 printf ("%s not yet implemented\r\n", badfunc
);
5064 /* Arrange to return a range centered on zero. */
5065 return rand () - (1 << 30);
5077 /* Called from init_sys_modes. */
5083 /* If we're not on an HFT we shouldn't do any of this. We determine
5084 if we are on an HFT by trying to get an HFT error code. If this
5085 call fails, we're not on an HFT. */
5087 if (ioctl (0, HFQERROR
, &junk
) < 0)
5089 #else /* not IBMR2AIX */
5090 if (ioctl (0, HFQEIO
, 0) < 0)
5092 #endif /* not IBMR2AIX */
5094 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5095 as the rubout key's ASCII code. Here this is changed. The bug is that
5096 there's no way to determine the old mapping, so in reset_sys_modes
5097 we need to assume that the normal map had been present. Of course, this
5098 code also doesn't help if on a terminal emulator which doesn't understand
5102 struct hfkeymap keymap
;
5104 buf
.hf_bufp
= (char *)&keymap
;
5105 buf
.hf_buflen
= sizeof (keymap
);
5106 keymap
.hf_nkeys
= 2;
5107 keymap
.hfkey
[0].hf_kpos
= 15;
5108 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5110 keymap
.hfkey
[0].hf_keyidh
= '<';
5111 #else /* not IBMR2AIX */
5112 keymap
.hfkey
[0].hf_page
= '<';
5113 #endif /* not IBMR2AIX */
5114 keymap
.hfkey
[0].hf_char
= 127;
5115 keymap
.hfkey
[1].hf_kpos
= 15;
5116 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5118 keymap
.hfkey
[1].hf_keyidh
= '<';
5119 #else /* not IBMR2AIX */
5120 keymap
.hfkey
[1].hf_page
= '<';
5121 #endif /* not IBMR2AIX */
5122 keymap
.hfkey
[1].hf_char
= 127;
5123 hftctl (0, HFSKBD
, &buf
);
5125 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5127 line_ins_del_ok
= char_ins_del_ok
= 0;
5130 /* Reset the rubout key to backspace. */
5136 struct hfkeymap keymap
;
5140 if (ioctl (0, HFQERROR
, &junk
) < 0)
5142 #else /* not IBMR2AIX */
5143 if (ioctl (0, HFQEIO
, 0) < 0)
5145 #endif /* not IBMR2AIX */
5147 buf
.hf_bufp
= (char *)&keymap
;
5148 buf
.hf_buflen
= sizeof (keymap
);
5149 keymap
.hf_nkeys
= 2;
5150 keymap
.hfkey
[0].hf_kpos
= 15;
5151 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5153 keymap
.hfkey
[0].hf_keyidh
= '<';
5154 #else /* not IBMR2AIX */
5155 keymap
.hfkey
[0].hf_page
= '<';
5156 #endif /* not IBMR2AIX */
5157 keymap
.hfkey
[0].hf_char
= 8;
5158 keymap
.hfkey
[1].hf_kpos
= 15;
5159 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5161 keymap
.hfkey
[1].hf_keyidh
= '<';
5162 #else /* not IBMR2AIX */
5163 keymap
.hfkey
[1].hf_page
= '<';
5164 #endif /* not IBMR2AIX */
5165 keymap
.hfkey
[1].hf_char
= 8;
5166 hftctl (0, HFSKBD
, &buf
);
5173 /* These are included on Sunos 4.1 when we do not use shared libraries.
5174 X11 libraries may refer to these functions but (we hope) do not
5175 actually call them. */
5195 #endif /* USE_DL_STUBS */
5204 register int length
;
5208 long max_str
= 65535;
5210 while (length
> max_str
) {
5211 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5216 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5218 while (length
-- > 0)
5220 #endif /* not VMS */
5223 #endif /* no bzero */
5224 #endif /* BSTRING */
5226 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5229 /* Saying `void' requires a declaration, above, where bcopy is used
5230 and that declaration causes pain for systems where bcopy is a macro. */
5231 bcopy (b1
, b2
, length
)
5234 register int length
;
5237 long max_str
= 65535;
5239 while (length
> max_str
) {
5240 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
5246 (void) LIB$
MOVC3 (&length
, b1
, b2
);
5248 while (length
-- > 0)
5250 #endif /* not VMS */
5252 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5257 bcmp (b1
, b2
, length
) /* This could be a macro! */
5260 register int length
;
5263 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
5264 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
5266 return STR$
COMPARE (&src1
, &src2
);
5268 while (length
-- > 0)
5273 #endif /* not VMS */
5275 #endif /* no bcmp */
5276 #endif /* not BSTRING */
5278 #ifndef HAVE_STRSIGNAL
5285 if (0 <= code
&& code
< NSIG
)
5288 signame
= sys_errlist
[code
];
5290 /* Cast to suppress warning if the table has const char *. */
5291 signame
= (char *) sys_siglist
[code
];
5297 #endif /* HAVE_STRSIGNAL */
5299 /* All the Macintosh stuffs go here */
5304 #include <MacTypes.h>
5305 #include <TextUtils.h>
5306 #include <Folders.h>
5309 #include <sys/stat.h>
5312 #include <sys/param.h>
5314 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5315 that does not begin with a ':' and contains at least one ':'. A Mac
5316 full pathname causes an '/' to be prepended to the Unix pathname.
5317 The algorithm for the rest of the pathname is as follows:
5318 For each segment between two ':',
5319 if it is non-null, copy as is and then add a '/' at the end,
5320 otherwise, insert a "../" into the Unix pathname.
5321 Returns 1 if successful; 0 if fails. */
5324 Mac2UnixPathname (const char *mfn
, char *ufn
, int ufnbuflen
)
5326 const char *p
, *q
, *pe
;
5333 p
= strchr (mfn
, ':');
5334 if (p
!= 0 && p
!= mfn
) /* full pathname */
5341 pe
= mfn
+ strlen (mfn
);
5344 q
= strchr (p
, ':');
5348 { /* two consecutive ':' */
5349 if (strlen (ufn
) + 3 >= ufnbuflen
)
5351 strcat (ufn
, "../");
5355 if (strlen (ufn
) + (q
- p
) + 1 >= ufnbuflen
)
5357 strncat (ufn
, p
, q
- p
);
5364 if (strlen (ufn
) + (pe
- p
) >= ufnbuflen
)
5366 strncat (ufn
, p
, pe
- p
); /* no separator for last one */
5374 extern char *GetTempDirName ();
5376 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5377 above in algorithm. */
5379 Unix2MacPathname (const char *ufn
, char *mfn
, int mfnbuflen
)
5381 const char *p
, *q
, *pe
;
5382 char expandedPathname
[MAXPATHLEN
+1];
5391 /* Check for and handle volume names. Last comparison: strangely
5392 somewhere `/.emacs' is passed. A temporary fix for now. */
5393 if (*p
== '/' && strchr (p
+1, '/') == NULL
&& strcmp (p
, "/.emacs") != 0)
5395 if (strlen (p
) + 1 > mfnbuflen
)
5402 if (strncmp (p
, "~emacs/", 7) == 0)
5403 { /* expand to emacs dir found by InitEmacsPasswdDir */
5404 struct passwd
*pw
= getpwnam ("emacs");
5406 if (strlen (pw
->pw_dir
) + strlen (p
) > MAXPATHLEN
)
5408 strcpy (expandedPathname
, pw
->pw_dir
);
5409 strcat (expandedPathname
, p
);
5410 p
= expandedPathname
;
5411 /* Now p points to the pathname with emacs dir prefix. */
5413 else if (strncmp (p
, "/tmp/", 5) == 0)
5415 char *t
= GetTempDirName ();
5417 if (strlen (t
) + strlen (p
) > MAXPATHLEN
)
5419 strcpy (expandedPathname
, t
);
5420 strcat (expandedPathname
, p
);
5421 p
= expandedPathname
;
5422 /* Now p points to the pathname with emacs dir prefix. */
5424 else if (*p
!= '/') /* relative pathname */
5430 pe
= p
+ strlen (p
);
5433 q
= strchr (p
, '/');
5436 if (q
- p
== 2 && *p
== '.' && *(p
+1) == '.')
5438 if (strlen (mfn
) + 1 >= mfnbuflen
)
5444 if (strlen (mfn
) + (q
- p
) + 1 >= mfnbuflen
)
5446 strncat (mfn
, p
, q
- p
);
5453 if (strlen (mfn
) + (pe
- p
) >= mfnbuflen
)
5455 strncat (mfn
, p
, pe
- p
);
5463 /* The following functions with "sys_" prefix are stubs to Unix
5464 functions that have already been implemented by CW or MPW. The
5465 calls to them in Emacs source course are #define'd to call the sys_
5466 versions by the header files s-mac.h. In these stubs pathnames are
5467 converted between their Unix and Mac forms. */
5468 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5470 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5472 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5474 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5476 /* Define our own stat function for both MrC and CW. The reason for
5477 doing this: "stat" is both the name of a struct and function name:
5478 we can't #define stat to something else to
5479 redirect Emacs's calls to our own version that converts Unix style
5480 filenames to Mac style filename because all sorts of compilation
5481 errors will be generated if stat is #define'd to be something else. */
5484 stat (const char *path
, struct stat
*buf
)
5486 char MacPathname
[MAXPATHLEN
+1];
5489 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5492 c2pstr (MacPathname
);
5493 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5494 cipb
.hFileInfo
.ioVRefNum
= 0;
5495 cipb
.hFileInfo
.ioDirID
= 0;
5496 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5498 errno
= PBGetCatInfo (&cipb
, false);
5499 if (errno
== -43) /* -43: fnfErr defined in Errors.h */
5504 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5505 { /* bit 4 = 1 for directories */
5506 buf
->st_mode
= S_IFDIR
| S_IREAD
| S_IEXEC
;
5507 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5508 buf
->st_mode
|= S_IWRITE
;
5509 buf
->st_ino
= cipb
.dirInfo
.ioDrDirID
;
5510 buf
->st_dev
= cipb
.dirInfo
.ioVRefNum
;
5511 buf
->st_size
= cipb
.dirInfo
.ioDrNmFls
; /* size of dir = number of files and dirs */
5512 buf
->st_atime
= buf
->st_mtime
= cipb
.dirInfo
.ioDrMdDat
- MAC_UNIX_EPOCH_DIFF
;
5513 buf
->st_ctime
= cipb
.dirInfo
.ioDrCrDat
- MAC_UNIX_EPOCH_DIFF
;
5517 buf
->st_mode
= S_IFREG
| S_IREAD
;
5518 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5519 buf
->st_mode
|= S_IWRITE
;
5520 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5521 buf
->st_mode
|= S_IEXEC
;
5522 buf
->st_ino
= cipb
.hFileInfo
.ioDirID
;
5523 buf
->st_dev
= cipb
.hFileInfo
.ioVRefNum
;
5524 buf
->st_size
= cipb
.hFileInfo
.ioFlLgLen
;
5525 buf
->st_atime
= buf
->st_mtime
= cipb
.hFileInfo
.ioFlMdDat
- MAC_UNIX_EPOCH_DIFF
;
5526 buf
->st_ctime
= cipb
.hFileInfo
.ioFlCrDat
- MAC_UNIX_EPOCH_DIFF
;
5529 buf
->st_uid
= getuid ();
5530 buf
->st_gid
= getgid ();
5538 /* CW defines fstat in stat.mac.c while MPW does not provide this
5539 function. Without the information of how to get from a file
5540 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5541 to implement this function. Fortunately, there is only one place
5542 where this function is called in our configuration: in fileio.c,
5543 where only the st_dev and st_ino fields are used to determine
5544 whether two fildes point to different i-nodes to prevent copying
5545 a file onto itself equal. What we have here probably needs
5548 fstat (int fildes
, struct stat
*buf
)
5551 buf
->st_ino
= fildes
;
5552 return 0; /* success */
5555 #endif /* __MRC__ */
5557 /* From Think Reference code example */
5559 mkdir (const char *dirname
, int mode
)
5561 #pragma unused (mode)
5564 char MacPathname
[MAXPATHLEN
+1];
5566 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5569 c2pstr (MacPathname
);
5570 hfpb
.ioNamePtr
= MacPathname
;
5571 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5572 hfpb
.ioDirID
= 0; /*parent is the root */
5574 /* Just return the Mac OSErr code for now. */
5575 errno
= PBDirCreate ((HParmBlkPtr
) &hfpb
, false);
5576 return errno
== noErr
? 0 : -1;
5580 rmdir (const char *dirname
)
5583 char MacPathname
[MAXPATHLEN
+1];
5585 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5588 c2pstr (MacPathname
);
5589 hfpb
.ioNamePtr
= MacPathname
;
5590 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5591 hfpb
.ioDirID
= 0; /*parent is the root */
5593 errno
= PBHDelete ((HParmBlkPtr
) &hfpb
, false);
5594 return errno
== noErr
? 0 : -1;
5599 /* No implementation yet. */
5601 execvp (const char *path
, ...)
5606 #endif /* __MRC__ */
5609 utime (const char *path
, const struct utimbuf
*times
)
5611 char MacPathname
[MAXPATHLEN
+1];
5614 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5617 c2pstr (MacPathname
);
5618 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5619 cipb
.hFileInfo
.ioVRefNum
= 0;
5620 cipb
.hFileInfo
.ioDirID
= 0;
5621 /* Set to 0 to get information about specific dir or file. */
5622 cipb
.hFileInfo
.ioFDirIndex
= 0;
5624 errno
= PBGetCatInfo (&cipb
, false);
5628 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5629 { /* bit 4 = 1 for directories */
5631 cipb
.dirInfo
.ioDrMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5633 GetDateTime (&cipb
.dirInfo
.ioDrMdDat
);
5638 cipb
.hFileInfo
.ioFlMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5640 GetDateTime (&cipb
.hFileInfo
.ioFlMdDat
);
5643 errno
= PBSetCatInfo (&cipb
, false);
5644 return errno
== noErr
? 0 : -1;
5651 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5653 access (const char *path
, int mode
)
5655 char MacPathname
[MAXPATHLEN
+1];
5658 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5661 c2pstr (MacPathname
);
5662 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5663 cipb
.hFileInfo
.ioVRefNum
= 0;
5664 cipb
.hFileInfo
.ioDirID
= 0;
5665 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5667 errno
= PBGetCatInfo (&cipb
, false);
5671 if (mode
== F_OK
) /* got this far, file exists */
5675 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* path refers to a directory */
5679 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5686 return (cipb
.hFileInfo
.ioFlAttrib
& 0x1) ? -1 : 0; /* don't allow if lock bit on */
5691 #define DEV_NULL_FD 0x10000
5695 sys_open (const char *path
, int oflag
)
5697 char MacPathname
[MAXPATHLEN
+1];
5699 if (strcmp (path
, "/dev/null") == 0)
5700 return DEV_NULL_FD
; /* some bogus fd to be ignored in write */
5702 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5705 return open (MacPathname
, oflag
);
5710 sys_creat (const char *path
, mode_t mode
)
5712 char MacPathname
[MAXPATHLEN
+1];
5714 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5717 return creat (MacPathname
, mode
);
5722 sys_unlink (const char *path
)
5724 char MacPathname
[MAXPATHLEN
+1];
5726 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5729 return unlink (MacPathname
);
5734 sys_read (int fildes
, char *buf
, int count
)
5737 { /* if stdin, call (non-echoing) "getch" in console.h */
5738 if (MacKeyPending ())
5739 { /* don't wait for a key if none has been pressed */
5740 *buf
= MacGetChar ();
5747 return read (fildes
, buf
, count
);
5752 sys_write (int fildes
, char *buf
, int count
)
5754 if (fildes
== DEV_NULL_FD
)
5757 return write (fildes
, buf
, count
);
5762 sys_rename (const char * old_name
, const char * new_name
)
5764 char MacOldName
[MAXPATHLEN
+1], MacNewName
[MAXPATHLEN
+1];
5766 if (strcmp (old_name
, new_name
) == 0)
5769 if (Unix2MacPathname (old_name
, MacOldName
, MAXPATHLEN
+1) == 0)
5772 if (Unix2MacPathname (new_name
, MacNewName
, MAXPATHLEN
+1) == 0)
5775 return rename (MacOldName
, MacNewName
);
5779 extern FILE *fopen (const char *name
, const char *mode
);
5781 sys_fopen (const char *name
, const char *mode
)
5783 char MacPathname
[MAXPATHLEN
+1];
5785 if (Unix2MacPathname (name
, MacPathname
, MAXPATHLEN
+1) == 0)
5788 return fopen (MacPathname
, mode
);
5793 long targetTicks
= 0;
5796 __sigfun alarm_signal_func
= (__sigfun
) 0;
5798 __signal_func_ptr alarm_signal_func
= (__signal_func_ptr
) 0;
5803 /* These functions simulate SIG_ALRM. The stub for function signal
5804 stores the signal handler function in alarm_signal_func if a
5805 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5806 which emacs calls periodically. A pending alarm is represented by
5807 a non-zero targetTicks value. CheckAlarm calls the handler
5808 function pointed to by alarm_signal_func if one has been set up and
5809 an alarm is pending. */
5813 if (targetTicks
&& TickCount () > targetTicks
)
5816 if (alarm_signal_func
)
5817 (*alarm_signal_func
)(SIGALRM
);
5821 /* Called in sys_select to wait for an alarm signal to arrive. */
5825 unsigned long finalTick
;
5827 if (!targetTicks
) /* no alarm pending */
5830 while (TickCount () <= targetTicks
)
5831 Delay (1UL, &finalTick
); /* wait for 1/60 second before trying again */
5834 if (alarm_signal_func
)
5835 (*alarm_signal_func
)(SIGALRM
);
5843 long remaining
= targetTicks
? (TickCount () - targetTicks
) / 60 : 0;
5845 targetTicks
= seconds
? TickCount () + 60 * seconds
: 0;
5847 return (remaining
< 0) ? 0 : (unsigned int) remaining
;
5852 extern __sigfun
signal (int signal
, __sigfun signal_func
);
5854 sys_signal (int signal_num
, __sigfun signal_func
)
5856 extern __signal_func_ptr
signal (int signal
, __signal_func_ptr signal_func
);
5858 sys_signal (int signal_num
, __signal_func_ptr signal_func
)
5863 if (signal_num
!= SIGALRM
)
5864 return signal (signal_num
, signal_func
);
5868 __sigfun old_signal_func
;
5870 __signal_func_ptr old_signal_func
;
5874 old_signal_func
= alarm_signal_func
;
5875 alarm_signal_func
= signal_func
;
5876 return old_signal_func
;
5880 /* The time functions adjust time values according to the difference
5881 between the Unix and CW epoches. */
5884 extern struct tm
*gmtime (const time_t *);
5886 sys_gmtime (const time_t *timer
)
5888 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5890 return gmtime (&unixTime
);
5894 extern struct tm
*localtime (const time_t *);
5896 sys_localtime (const time_t *timer
)
5898 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5900 return localtime (&unixTime
);
5904 extern char *ctime (const time_t *);
5906 sys_ctime (const time_t *timer
)
5908 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5910 return ctime (&unixTime
);
5914 extern time_t time (time_t *);
5916 sys_time (time_t *timer
)
5918 time_t macTime
= time (NULL
) - CW_UNIX_EPOCH_DIFF
;
5926 /* no subprocesses, empty wait */
5934 croak (char *badfunc
)
5936 printf ("%s not yet implemented\r\n", badfunc
);
5941 index (const char * str
, int chr
)
5943 return strchr (str
, chr
);
5947 char **environ
= &e
[0];
5950 mktemp (char *template)
5955 len
= strlen (template);
5957 while (k
>= 0 && template[k
] == 'X')
5960 k
++; /* make k index of first 'X' */
5964 /* Zero filled, number of digits equal to the number of X's. */
5965 sprintf (&template[k
], "%0*d", len
-k
, seqnum
++);
5973 /* Emulate getpwuid, getpwnam and others. */
5975 #define PASSWD_FIELD_SIZE 256
5977 static char myPasswdName
[PASSWD_FIELD_SIZE
];
5978 static char myPasswdDir
[MAXPATHLEN
+1];
5980 static struct passwd myPasswd
=
5986 /* Initialized by main () in macterm.c to pathname of emacs directory. */
5987 char emacsPasswdDir
[MAXPATHLEN
+1];
5990 InitEmacsPasswdDir ()
5994 if (getwd (emacsPasswdDir
) && getwd (myPasswdDir
))
5996 /* Need pathname of first ancestor that begins with `emacs' since
5997 Mac emacs application is somewhere in the emacs-20.3 tree. */
5998 int len
= strlen (emacsPasswdDir
);
5999 /* J points to the "/" following the directory name being compared. */
6002 while (i
>= 0 && !found
)
6004 while (i
>= 0 && emacsPasswdDir
[i
] != '/')
6006 if (emacsPasswdDir
[i
] == '/' && i
+5 < len
)
6007 found
= (strncmp (&(emacsPasswdDir
[i
+1]), "emacs", 5) == 0);
6009 emacsPasswdDir
[j
+1] = '\0';
6019 { /* setting to "/" probably won't work,
6020 but set it to something anyway. */
6021 strcpy (emacsPasswdDir
, "/");
6022 strcpy (myPasswdDir
, "/");
6026 static struct passwd emacsPasswd
=
6032 static int myPasswdInited
= 0;
6039 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6040 where Emacs was started. */
6042 ownerName
= (char **) GetResource ('STR ',-16096);
6046 BlockMove ((unsigned char *) *ownerName
,
6047 (unsigned char *) myPasswdName
, *ownerName
[0] + 1);
6048 HUnlock (ownerName
);
6049 p2cstr ((unsigned char *) myPasswdName
);
6052 myPasswdName
[0] = 0;
6056 getpwuid (uid_t uid
)
6058 if (!myPasswdInited
)
6068 getpwnam (const char *name
)
6070 if (strcmp (name
, "emacs") == 0)
6071 return &emacsPasswd
;
6073 if (!myPasswdInited
)
6082 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6083 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6111 request_sigio (void)
6122 unrequest_sigio (void)
6126 /* djgpp does not implement pipe either. */
6128 pipe (int _fildes
[2])
6134 /* Hard and symbolic links. */
6136 symlink (const char *name1
, const char *name2
)
6143 link (const char *name1
, const char *name2
)
6150 lstat (const char *path
, struct stat
*sb
)
6152 return stat (path
, sb
);
6156 readlink (const char *path
, char *buf
, int bufsiz
)
6163 umask (mode_t numask
)
6165 static mode_t mask
= 022;
6166 mode_t oldmask
= mask
;
6172 chmod (const char *path
, mode_t mode
)
6174 /* say it always succeed for now */
6182 return fcntl (oldd
, F_DUPFD
, 0);
6184 /* current implementation of fcntl in fcntl.mac.c simply returns old
6186 return fcntl (oldd
, F_DUPFD
);
6192 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6193 newd if it already exists. Then, attempt to dup oldd. If not
6194 successful, call dup2 recursively until we are, then close the
6195 unsuccessful ones. */
6197 dup2 (int oldd
, int newd
)
6208 ret
= dup2 (oldd
, newd
);
6213 /* let it fail for now */
6227 ioctl (int d
, int request
, void *argp
)
6236 if (fildes
>=0 && fildes
<= 2)
6267 sleep (unsigned int seconds
)
6269 unsigned long finalTick
;
6271 Delay (seconds
* 60UL, &finalTick
);
6274 #endif /* __MRC__ */
6283 #endif /* __MWERKS__ */
6285 /* Return the path to the directory in which Emacs can create
6286 temporary files. The MacOS "temporary items" directory cannot be
6287 used because it removes the file written by a process when it
6288 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6289 again not exactly). And of course Emacs needs to read back the
6290 files written by its subprocesses. So here we write the files to a
6291 directory "Emacs" in the Preferences Folder. This directory is
6292 created if it does not exist. */
6296 static char *TempDirName
= NULL
;
6300 Str255 dirName
, fullPath
;
6302 char unixDirName
[MAXPATHLEN
+1];
6305 /* Cache directory name with pointer TempDirName.
6306 Look for it only the first time. */
6309 err
= FindFolder (kOnSystemDisk
, kPreferencesFolderType
,
6310 kCreateFolder
, &vRefNum
, &dirID
);
6315 cpb
.dirInfo
.ioNamePtr
= dirName
;
6316 cpb
.dirInfo
.ioDrParID
= dirID
;
6318 /* Standard ref num to full path name loop */
6320 cpb
.dirInfo
.ioVRefNum
= vRefNum
;
6321 cpb
.dirInfo
.ioFDirIndex
= -1;
6322 cpb
.dirInfo
.ioDrDirID
= cpb
.dirInfo
.ioDrParID
;
6324 err
= PBGetCatInfo (&cpb
, false);
6327 strcat (dirName
, ":");
6328 if (strlen (fullPath
) + strlen (dirName
) <= MAXPATHLEN
)
6330 strcat (dirName
, fullPath
);
6331 strcpy (fullPath
, dirName
);
6336 while (cpb
.dirInfo
.ioDrDirID
!= fsRtDirID
&& err
== noErr
);
6338 if (strlen (fullPath
) + 6 <= MAXPATHLEN
)
6339 strcat (fullPath
, "Emacs:");
6343 if (Mac2UnixPathname (fullPath
, unixDirName
, MAXPATHLEN
+1) == 0)
6346 dir
= opendir (unixDirName
); /* check whether temp directory exists */
6349 else if (mkdir (unixDirName
, 0700) != 0) /* create it if not */
6352 TempDirName
= (char *) malloc (strlen (unixDirName
) + 1);
6353 strcpy (TempDirName
, unixDirName
);
6360 getenv (const char * name
)
6362 if (strcmp (name
, "TERM") == 0)
6364 else if (strcmp (name
, "TERMCAP") == 0)
6365 /* for debugging purpose when code was still outputting to dumb terminal */
6366 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6367 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6368 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6369 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6370 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6371 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6372 else if (strcmp (name
, "TMPDIR") == 0)
6373 return GetTempDirName ();
6379 #include <utsname.h>
6382 uname (struct utsname
*name
)
6385 systemName
= GetString (-16413); /* IM - Resource Manager Reference */
6388 BlockMove (*systemName
, name
->nodename
, (*systemName
)[0]+1);
6389 p2cstr (name
->nodename
);
6396 #include <Processes.h>
6399 /* Event class of HLE sent to subprocess. */
6400 const OSType kEmacsSubprocessSend
= 'ESND';
6401 /* Event class of HLE sent back from subprocess. */
6402 const OSType kEmacsSubprocessReply
= 'ERPY';
6405 mystrchr (char *s
, char c
)
6407 while (*s
&& *s
!= c
)
6433 mystrcpy (char *to
, char *from
)
6444 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6445 terminated). The process should run with the default directory
6446 "workdir", read input from "infn", and write output and error to
6447 "outfn" and "errfn", resp. The Process Manager call
6448 LaunchApplication is used to start the subprocess. We use high
6449 level events as the mechanism to pass arguments to the subprocess
6450 and to make Emacs wait for the subprocess to terminate and pass
6451 back a result code. The bulk of the code here packs the arguments
6452 into one message to be passed together with the high level event.
6453 Emacs also sometimes starts a subprocess using a shell to perform
6454 wildcard filename expansion. Since we don't really have a shell on
6455 the Mac, this case is detected and the starting of the shell is
6456 by-passed. We really need to add code here to do filename
6457 expansion to support such functionality. */
6459 run_mac_command (argv
, workdir
, infn
, outfn
, errfn
)
6460 unsigned char **argv
;
6461 const char *workdir
;
6462 const char *infn
, *outfn
, errfn
;
6464 char macappname
[MAXPATHLEN
+1], macworkdir
[MAXPATHLEN
+1];
6465 char macinfn
[MAXPATHLEN
+1], macoutfn
[MAXPATHLEN
+1], macerrfn
[MAXPATHLEN
+1];
6466 int paramlen
, argc
, newargc
, j
, retries
;
6467 char **newargv
, *param
, *p
;
6470 LaunchParamBlockRec lpbr
;
6471 EventRecord sendEvent
, replyEvent
;
6472 RgnHandle cursorRegionHdl
;
6474 unsigned long refCon
, len
;
6476 if (Unix2MacPathname (workdir
, macworkdir
, MAXPATHLEN
+1) == 0)
6478 if (Unix2MacPathname (infn
, macinfn
, MAXPATHLEN
+1) == 0)
6480 if (Unix2MacPathname (outfn
, macoutfn
, MAXPATHLEN
+1) == 0)
6482 if (Unix2MacPathname (errfn
, macerrfn
, MAXPATHLEN
+1) == 0)
6485 paramlen
= strlen (macworkdir
) + strlen (macinfn
) + strlen (macoutfn
) + strlen (macerrfn
) + 4;
6486 /* count nulls at end of strings */
6495 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6496 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6497 j
= strlen (argv
[0]);
6498 if (j
>= 3 && strcmp (argv
[0]+j
-3, "/sh") == 0 && argc
== 3 && strcmp (argv
[1], "-c") == 0)
6500 char *command
, *t
, tempmacpathname
[MAXPATHLEN
+1];
6502 /* The arguments for the command in argv[2] are separated by spaces. Count them and put
6503 the count in newargc. */
6504 command
= (char *) alloca (strlen (argv
[2])+2);
6505 strcpy (command
, argv
[2]);
6506 if (command
[strlen (command
) - 1] != ' ')
6507 strcat (command
, " ");
6511 t
= mystrchr (t
, ' ');
6515 t
= mystrchr (t
+1, ' ');
6518 newargv
= (char **) alloca (sizeof (char *) * newargc
);
6521 for (j
= 0; j
< newargc
; j
++)
6523 newargv
[j
] = (char *) alloca (strlen (t
) + 1);
6524 mystrcpy (newargv
[j
], t
);
6527 paramlen
+= strlen (newargv
[j
]) + 1;
6530 if (strncmp (newargv
[0], "~emacs/", 7) == 0)
6532 if (Unix2MacPathname (newargv
[0], tempmacpathname
, MAXPATHLEN
+1) == 0)
6536 { /* sometimes Emacs call "sh" without a path for the command */
6538 char *t
= (char *) alloca (strlen (newargv
[0]) + 7 + 1);
6539 strcpy (t
, "~emacs/");
6540 strcat (t
, newargv
[0]);
6543 openp (Vexec_path
, build_string (newargv
[0]), EXEC_SUFFIXES
, &path
, 1);
6547 if (Unix2MacPathname (XSTRING (path
)->data
, tempmacpathname
, MAXPATHLEN
+1) == 0)
6550 strcpy (macappname
, tempmacpathname
);
6554 if (Unix2MacPathname (argv
[0], macappname
, MAXPATHLEN
+1) == 0)
6557 newargv
= (char **) alloca (sizeof (char *) * argc
);
6559 for (j
= 1; j
< argc
; j
++)
6561 if (strncmp (argv
[j
], "~emacs/", 7) == 0)
6563 char *t
= strchr (argv
[j
], ' ');
6566 char tempcmdname
[MAXPATHLEN
+1], tempmaccmdname
[MAXPATHLEN
+1];
6567 strncpy (tempcmdname
, argv
[j
], t
-argv
[j
]);
6568 tempcmdname
[t
-argv
[j
]] = '\0';
6569 if (Unix2MacPathname (tempcmdname
, tempmaccmdname
, MAXPATHLEN
+1) == 0)
6571 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
) + strlen (t
) + 1);
6572 strcpy (newargv
[j
], tempmaccmdname
);
6573 strcat (newargv
[j
], t
);
6577 char tempmaccmdname
[MAXPATHLEN
+1];
6578 if (Unix2MacPathname (argv
[j
], tempmaccmdname
, MAXPATHLEN
+1) == 0)
6580 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
)+1);
6581 strcpy (newargv
[j
], tempmaccmdname
);
6585 newargv
[j
] = argv
[j
];
6586 paramlen
+= strlen (newargv
[j
]) + 1;
6590 /* After expanding all the arguments, we now know the length of the parameter block to be
6591 sent to the subprocess as a message attached to the HLE. */
6592 param
= (char *) malloc (paramlen
+ 1);
6597 *p
++ = newargc
; /* first byte of message contains number of arguments for command */
6598 strcpy (p
, macworkdir
);
6599 p
+= strlen (macworkdir
);
6600 *p
++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6601 strcpy (p
, macinfn
);
6602 p
+= strlen (macinfn
);
6604 strcpy (p
, macoutfn
);
6605 p
+= strlen (macoutfn
);
6607 strcpy (p
, macerrfn
);
6608 p
+= strlen (macerrfn
);
6610 for (j
= 1; j
< newargc
; j
++) {
6611 strcpy (p
, newargv
[j
]);
6612 p
+= strlen (newargv
[j
]);
6616 c2pstr (macappname
);
6618 iErr
= FSMakeFSSpec (0, 0, macappname
, &spec
);
6620 if (iErr
!= noErr
) {
6625 lpbr
.launchBlockID
= extendedBlock
;
6626 lpbr
.launchEPBLength
= extendedBlockLen
;
6627 lpbr
.launchControlFlags
= launchContinue
+ launchNoFileFlags
;
6628 lpbr
.launchAppSpec
= &spec
;
6629 lpbr
.launchAppParameters
= NULL
;
6631 iErr
= LaunchApplication (&lpbr
); /* call the subprocess */
6632 if (iErr
!= noErr
) {
6637 sendEvent
.what
= kHighLevelEvent
;
6638 sendEvent
.message
= kEmacsSubprocessSend
; /* Event ID stored in "where" unused */
6641 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6642 iErr
= PostHighLevelEvent (&sendEvent
, &lpbr
.launchProcessSN
, 0, param
, paramlen
+ 1, receiverIDisPSN
);
6644 while (iErr
== sessClosedErr
&& retries
-- > 0);
6646 if (iErr
!= noErr
) {
6651 cursorRegionHdl
= NewRgn ();
6653 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6655 if (WaitNextEvent (highLevelEventMask
, &replyEvent
, 180, cursorRegionHdl
) && replyEvent
.message
== kEmacsSubprocessReply
)
6658 /* The return code is sent through the refCon */
6659 iErr
= AcceptHighLevelEvent (&targ
, &refCon
, NULL
, &len
);
6660 if (iErr
!= noErr
) {
6661 DisposeHandle ((Handle
) cursorRegionHdl
);
6666 DisposeHandle ((Handle
) cursorRegionHdl
);
6673 opendir (const char *dirname
)
6675 char MacPathname
[MAXPATHLEN
+1];
6680 dirp
= (DIR *) malloc (sizeof (DIR));
6684 /* Handle special case when dirname is "/": sets up for readir to
6685 get all mount volumes. */
6686 if (strcmp (dirname
, "/") == 0) {
6687 dirp
->getting_volumes
= 1; /* special all mounted volumes DIR struct */
6688 dirp
->current_index
= 1; /* index for first volume */
6692 /* Handle typical cases: not accessing all mounted volumes. */
6693 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
6696 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6697 len
= strlen (MacPathname
);
6698 if (MacPathname
[len
- 1] != ':' && len
< MAXPATHLEN
)
6699 strcat (MacPathname
, ":");
6701 c2pstr (MacPathname
);
6702 cipb
.hFileInfo
.ioNamePtr
= MacPathname
; /* using full pathname so vRefNum and dirID ignored */
6703 cipb
.hFileInfo
.ioVRefNum
= 0;
6704 cipb
.hFileInfo
.ioDirID
= 0;
6705 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
6707 errno
= PBGetCatInfo (&cipb
, false);
6708 if (errno
!= noErr
) {
6713 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x10)) /* bit 4 = 1 for directories */
6714 return 0; /* not a directory */
6716 dirp
->dir_id
= cipb
.dirInfo
.ioDrDirID
; /* used later in readdir */
6717 dirp
->getting_volumes
= 0;
6718 dirp
->current_index
= 1; /* index for first file/directory */
6734 HParamBlockRec HPBlock
;
6736 static struct dirent s_dirent
;
6737 static Str255 s_name
;
6740 /* Handle the root directory containing the mounted volumes. Call
6741 PBHGetVInfo specifying an index to obtain the info for a volume.
6742 PBHGetVInfo returns an error when it receives an index beyond the
6743 last volume, at which time we should return a nil dirent struct
6745 if (dp
->getting_volumes
) {
6746 HPBlock
.volumeParam
.ioNamePtr
= s_name
;
6747 HPBlock
.volumeParam
.ioVRefNum
= 0;
6748 HPBlock
.volumeParam
.ioVolIndex
= dp
->current_index
;
6750 errno
= PBHGetVInfo (&HPBlock
, false);
6751 if (errno
!= noErr
) {
6757 strcat (s_name
, "/"); /* need "/" for stat to work correctly */
6759 dp
->current_index
++;
6761 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
;
6762 s_dirent
.d_name
= s_name
;
6767 cipb
.hFileInfo
.ioVRefNum
= 0;
6768 cipb
.hFileInfo
.ioNamePtr
= s_name
; /* location to receive filename returned */
6770 /* return only visible files */
6773 cipb
.hFileInfo
.ioDirID
= dp
->dir_id
; /* directory ID found by opendir */
6774 cipb
.hFileInfo
.ioFDirIndex
= dp
->current_index
;
6776 errno
= PBGetCatInfo (&cipb
, false);
6777 if (errno
!= noErr
) {
6782 /* insist on an visibile entry */
6783 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* directory? */
6784 done
= !(cipb
.dirInfo
.ioDrUsrWds
.frFlags
& fInvisible
);
6786 done
= !(cipb
.hFileInfo
.ioFlFndrInfo
.fdFlags
& fInvisible
);
6788 dp
->current_index
++;
6793 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
; /* value unimportant: non-zero for valid file */
6794 s_dirent
.d_name
= s_name
;
6803 char MacPathname
[MAXPATHLEN
+1];
6804 Str255 directoryName
;
6808 MacPathname
[0] = '\0';
6809 directoryName
[0] = '\0';
6810 cipb
.dirInfo
.ioDrParID
= 0;
6811 cipb
.dirInfo
.ioNamePtr
= directoryName
; /* empty string = default directory */
6814 cipb
.dirInfo
.ioVRefNum
= 0;
6815 cipb
.dirInfo
.ioFDirIndex
= -1;
6816 cipb
.dirInfo
.ioDrDirID
= cipb
.dirInfo
.ioDrParID
; /* go up to parent each time */
6818 errno
= PBGetCatInfo (&cipb
, false);
6819 if (errno
!= noErr
) {
6824 p2cstr (directoryName
);
6825 strcat (directoryName
, ":");
6826 strcat (directoryName
, MacPathname
); /* attach to front since going up directory tree */
6827 strcpy (MacPathname
, directoryName
);
6828 } while (cipb
.dirInfo
.ioDrDirID
!= fsRtDirID
); /* until volume's root directory */
6830 if (Mac2UnixPathname (MacPathname
, path
, MAXPATHLEN
+1) == 0)
6836 #endif /* macintosh */