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
60 #endif /* not WINDOWSNT */
62 /* Does anyone other than VMS need this? */
64 #define sys_fwrite fwrite
74 #include <sys/types.h>
78 /* Get _POSIX_VDISABLE, if it is available. */
88 #if !defined (USG) || defined (BSD_PGRPS)
90 #define setpgrp setpgid
94 /* Get SI_SRPC_DOMAIN, if it is available. */
95 #ifdef HAVE_SYS_SYSTEMINFO_H
96 #include <sys/systeminfo.h>
99 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
103 #include <sys/param.h>
107 extern unsigned start
__asm__ ("start");
129 #include <sys/file.h>
137 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
141 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
142 because the vms compiler doesn't grok `defined' */
150 #endif /* not 4.1 bsd */
153 #include <sys/ioctl.h>
159 #ifdef BROKEN_TIOCGWINSZ
164 #if defined (USG) || defined (DGUX)
165 #include <sys/utsname.h>
167 #ifndef MEMORY_IN_STRING_H
170 #if defined (TIOCGWINSZ) || defined (ISC4_0)
172 #include <sys/sioctl.h>
175 #include <sys/stream.h>
176 #include <sys/ptem.h>
178 #endif /* TIOCGWINSZ or ISC4_0 */
179 #endif /* USG or DGUX */
181 extern int quit_char
;
183 #include "keyboard.h"
186 #include "termhooks.h"
187 #include "termchar.h"
188 #include "termopts.h"
189 #include "dispextern.h"
194 /* In process.h which conflicts with the local copy. */
196 int _CRTAPI1
_spawnlp (int, const char *, const char *, ...);
197 int _CRTAPI1
_getpid (void);
200 #ifdef NONSYSTEM_DIR_LIBRARY
202 #endif /* NONSYSTEM_DIR_LIBRARY */
204 #include "syssignal.h"
211 #ifndef HAVE_STRUCT_UTIMBUF
212 /* We want to use utime rather than utimes, but we couldn't find the
213 structure declaration. We'll use the traditional one. */
221 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
227 #define LNOFLSH 0100000
230 static int baud_convert
[] =
235 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
236 1800, 2400, 4800, 9600, 19200, 38400
242 extern speed_t ospeed
;
244 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
247 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
249 /* HJL's version of libc is said to need this on the Alpha.
250 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
251 extern speed_t ospeed
;
258 /* The file descriptor for Emacs's input terminal.
259 Under Unix, this is normally zero except when using X;
260 under VMS, we place the input channel number here. */
263 void croak
P_ ((char *));
270 /* Temporary used by `sigblock' when defined in terms of signprocmask. */
272 SIGMASKTYPE sigprocmask_set
;
275 /* Specify a different file descriptor for further input operations. */
284 /* Discard pending input on descriptor input_fd. */
290 struct emacs_tty buf
;
295 /* Discarding input is not safe when the input could contain
296 replies from the X server. So don't do it. */
297 if (read_socket_hook
)
302 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
303 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
309 ioctl (input_fd
, TIOCFLUSH
, &zero
);
311 #else /* not Apollo */
312 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
313 while (dos_keyread () != -1)
315 #else /* not MSDOS */
316 EMACS_GET_TTY (input_fd
, &buf
);
317 EMACS_SET_TTY (input_fd
, &buf
, 0);
318 #endif /* not MSDOS */
319 #endif /* not Apollo */
321 #endif /* not WINDOWSNT */
326 /* Arrange for character C to be read as the next input from
333 if (read_socket_hook
)
336 /* Should perhaps error if in batch mode */
338 ioctl (input_fd
, TIOCSTI
, &c
);
339 #else /* no TIOCSTI */
340 error ("Cannot stuff terminal input characters in this version of Unix");
341 #endif /* no TIOCSTI */
353 #ifdef INIT_BAUD_RATE
358 #else /* not DOS_NT */
362 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
363 &sg
.class, 12, 0, 0, 0, 0 );
364 ospeed
= sg
.xmit_baud
;
370 tcgetattr (input_fd
, &sg
);
371 ospeed
= cfgetospeed (&sg
);
372 #if defined (USE_GETOBAUD) && defined (getobaud)
373 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
375 ospeed
= getobaud (sg
.c_cflag
);
377 #else /* neither VMS nor TERMIOS */
383 tcgetattr (input_fd
, &sg
);
385 ioctl (input_fd
, TCGETA
, &sg
);
387 ospeed
= sg
.c_cflag
& CBAUD
;
388 #else /* neither VMS nor TERMIOS nor TERMIO */
391 sg
.sg_ospeed
= B9600
;
392 if (ioctl (input_fd
, TIOCGETP
, &sg
) < 0)
394 ospeed
= sg
.sg_ospeed
;
395 #endif /* not HAVE_TERMIO */
396 #endif /* not HAVE_TERMIOS */
398 #endif /* not DOS_NT */
399 #endif /* not INIT_BAUD_RATE */
402 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
403 ? baud_convert
[ospeed
] : 9600);
410 set_exclusive_use (fd
)
414 ioctl (fd
, FIOCLEX
, 0);
416 /* Ok to do nothing if this feature does not exist */
421 wait_without_blocking ()
424 wait3 (0, WNOHANG
| WUNTRACED
, 0);
426 croak ("wait_without_blocking");
428 synch_process_alive
= 0;
431 #endif /* not subprocesses */
433 int wait_debugging
; /* Set nonzero to make following function work under dbx
434 (at least for bsd). */
437 wait_for_termination_signal ()
440 /* Wait for subprocess with process id `pid' to terminate and
441 make sure it will get eliminated (not remain forever as a zombie) */
444 wait_for_termination (pid
)
453 status
= SYS$
FORCEX (&pid
, 0, 0);
456 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
457 /* Note that kill returns -1 even if the process is just a zombie now.
458 But inevitably a SIGCHLD interrupt should be generated
459 and child_sig will do wait3 and make the process go away. */
460 /* There is some indication that there is a bug involved with
461 termination of subprocesses, perhaps involving a kernel bug too,
462 but no idea what it is. Just as a hunch we signal SIGCHLD to see
463 if that causes the problem to go away or get worse. */
464 sigsetmask (sigmask (SIGCHLD
));
465 if (0 > kill (pid
, 0))
467 sigsetmask (SIGEMPTYMASK
);
468 kill (getpid (), SIGCHLD
);
474 sigpause (SIGEMPTYMASK
);
475 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
476 #if defined (UNIPLUS)
477 if (0 > kill (pid
, 0))
480 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
481 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
482 sigblock (sigmask (SIGCHLD
));
483 if (0 > kill (pid
, 0))
485 sigunblock (sigmask (SIGCHLD
));
488 sigpause (SIGEMPTYMASK
);
489 #else /* not POSIX_SIGNALS */
490 #ifdef HAVE_SYSV_SIGPAUSE
492 if (0 > kill (pid
, 0))
498 #else /* not HAVE_SYSV_SIGPAUSE */
502 #else /* not WINDOWSNT */
503 if (0 > kill (pid
, 0))
505 /* Using sleep instead of pause avoids timing error.
506 If the inferior dies just before the sleep,
507 we lose just one second. */
509 #endif /* not WINDOWSNT */
510 #endif /* not HAVE_SYSV_SIGPAUSE */
511 #endif /* not POSIX_SIGNALS */
512 #endif /* not UNIPLUS */
513 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
515 #else /* not subprocesses */
518 #else /* not __DJGPP__ > 1 */
520 if (kill (pid
, 0) < 0)
526 if (status
== pid
|| status
== -1)
529 #endif /* not __DJGPP__ > 1*/
530 #endif /* not subprocesses */
537 * flush any pending output
538 * (may flush input as well; it does not matter the way we use it)
542 flush_pending_output (channel
)
546 /* If we try this, we get hit with SIGTTIN, because
547 the child's tty belongs to the child's pgrp. */
550 ioctl (channel
, TCFLSH
, 1);
554 /* 3rd arg should be ignored
555 but some 4.2 kernels actually want the address of an int
556 and nonzero means something different. */
557 ioctl (channel
, TIOCFLUSH
, &zero
);
564 /* Set up the terminal at the other end of a pseudo-terminal that
565 we will be controlling an inferior through.
566 It should not echo or do line-editing, since that is done
567 in Emacs. No padding needed for insertion into an Emacs buffer. */
570 child_setup_tty (out
)
576 EMACS_GET_TTY (out
, &s
);
578 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
579 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
580 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
582 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
583 /* No output delays */
585 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
586 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
588 s
.main
.c_iflag
&= ~IUCLC
; /* Disable downcasing on input. */
591 s
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
594 s
.main
.c_oflag
&= ~OLCUC
; /* Disable upcasing on output. */
596 s
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
597 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CSIZE
) | CS8
; /* Don't strip 8th bit */
599 /* Said to be unnecessary: */
600 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
601 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
604 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
605 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
606 s
.main
.c_cc
[VERASE
] = CDISABLE
; /* disable erase processing */
607 s
.main
.c_cc
[VKILL
] = CDISABLE
; /* disable kill processing */
610 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
614 /* AIX enhanced edit loses NULs, so disable it */
617 s
.main
.c_iflag
&= ~ASCEDIT
;
619 /* Also, PTY overloads NUL and BREAK.
620 don't ignore break, but don't signal either, so it looks like NUL. */
621 s
.main
.c_iflag
&= ~IGNBRK
;
622 s
.main
.c_iflag
&= ~BRKINT
;
623 /* QUIT and INTR work better as signals, so disable character forms */
624 s
.main
.c_cc
[VINTR
] = 0377;
625 #ifdef SIGNALS_VIA_CHARACTERS
626 /* the QUIT and INTR character are used in process_send_signal
627 so set them here to something useful. */
628 if (s
.main
.c_cc
[VQUIT
] == 0377)
629 s
.main
.c_cc
[VQUIT
] = '\\'&037; /* Control-\ */
630 if (s
.main
.c_cc
[VINTR
] == 0377)
631 s
.main
.c_cc
[VINTR
] = 'C'&037; /* Control-C */
632 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
633 /* QUIT and INTR work better as signals, so disable character forms */
634 s
.main
.c_cc
[VQUIT
] = 0377;
635 s
.main
.c_cc
[VINTR
] = 0377;
636 s
.main
.c_lflag
&= ~ISIG
;
637 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
638 s
.main
.c_cc
[VEOL
] = 0377;
639 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
642 #else /* not HAVE_TERMIO */
644 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
646 s
.main
.sg_flags
|= LPASS8
;
647 s
.main
.sg_erase
= 0377;
648 s
.main
.sg_kill
= 0377;
649 s
.lmode
= LLITOUT
| s
.lmode
; /* Don't strip 8th bit */
651 #endif /* not HAVE_TERMIO */
653 EMACS_SET_TTY (out
, &s
, 0);
662 ioctl (out
, FIOASYNC
, &zero
);
665 #endif /* not DOS_NT */
669 #endif /* subprocesses */
671 /* Record a signal code and the handler for it. */
675 SIGTYPE (*handler
) P_ ((int));
678 static void save_signal_handlers
P_ ((struct save_signal
*));
679 static void restore_signal_handlers
P_ ((struct save_signal
*));
681 /* Suspend the Emacs process; give terminal to its superior. */
687 /* "Foster" parentage allows emacs to return to a subprocess that attached
688 to the current emacs as a cheaper than starting a whole new process. This
689 is set up by KEPTEDITOR.COM. */
690 unsigned long parent_id
, foster_parent_id
;
693 fpid_string
= getenv ("EMACS_PARENT_PID");
694 if (fpid_string
!= NULL
)
696 sscanf (fpid_string
, "%x", &foster_parent_id
);
697 if (foster_parent_id
!= 0)
698 parent_id
= foster_parent_id
;
700 parent_id
= getppid ();
703 parent_id
= getppid ();
705 xfree (fpid_string
); /* On VMS, this was malloc'd */
707 if (parent_id
&& parent_id
!= 0xffffffff)
709 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
710 int status
= LIB$
ATTACH (&parent_id
) & 1;
711 signal (SIGINT
, oldsig
);
720 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
721 d_prompt
.a
= "Emacs: "; /* Just a reminder */
722 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
727 #if defined (SIGTSTP) && !defined (MSDOS)
730 int pgrp
= EMACS_GETPGRP (0);
731 EMACS_KILLPG (pgrp
, SIGTSTP
);
734 #else /* No SIGTSTP */
735 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
736 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
737 kill (getpid (), SIGQUIT
);
739 #else /* No SIGTSTP or USG_JOBCTRL */
741 /* On a system where suspending is not implemented,
742 instead fork a subshell and let it talk directly to the terminal
746 #endif /* no USG_JOBCTRL */
747 #endif /* no SIGTSTP */
751 /* Fork a subshell. */
757 error ("Can't spawn subshell");
760 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
762 char oldwd
[MAXPATHLEN
+1]; /* Fixed length is safe on MSDOS. */
765 struct save_signal saved_handlers
[5];
767 unsigned char *str
= 0;
770 saved_handlers
[0].code
= SIGINT
;
771 saved_handlers
[1].code
= SIGQUIT
;
772 saved_handlers
[2].code
= SIGTERM
;
774 saved_handlers
[3].code
= SIGIO
;
775 saved_handlers
[4].code
= 0;
777 saved_handlers
[3].code
= 0;
780 /* Mentioning current_buffer->buffer would mean including buffer.h,
781 which somehow wedges the hp compiler. So instead... */
783 dir
= intern ("default-directory");
784 if (NILP (Fboundp (dir
)))
786 dir
= Fsymbol_value (dir
);
790 dir
= expand_and_dir_to_file (Funhandled_file_name_directory (dir
), Qnil
);
791 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
792 len
= XSTRING (dir
)->size
;
793 bcopy (XSTRING (dir
)->data
, str
, len
);
794 if (str
[len
- 1] != '/') str
[len
++] = '/';
801 save_signal_handlers (saved_handlers
);
802 synch_process_alive
= 1;
803 #endif /* __DJGPP__ > 1 */
807 error ("Can't spawn subshell");
814 #ifdef DOS_NT /* MW, Aug 1993 */
817 sh
= (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
820 sh
= (char *) egetenv ("SHELL");
824 /* Use our buffer's default directory for the subshell. */
826 chdir ((char *) str
);
829 close_process_descs (); /* Close Emacs's pipes/ptys */
832 #ifdef SET_EMACS_PRIORITY
834 extern int emacs_priority
;
836 if (emacs_priority
< 0)
837 nice (-emacs_priority
);
841 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
844 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
846 report_file_error ("Can't execute subshell", Fcons (build_string (sh
), Qnil
));
848 #else /* not MSDOS */
850 /* Waits for process completion */
851 pid
= _spawnlp (_P_WAIT
, sh
, sh
, NULL
);
854 write (1, "Can't execute subshell", 22);
855 #else /* not WINDOWSNT */
857 write (1, "Can't execute subshell", 22);
859 #endif /* not WINDOWSNT */
860 #endif /* not MSDOS */
863 /* Do this now if we did not do it before. */
864 #if !defined (MSDOS) || __DJGPP__ == 1
865 save_signal_handlers (saved_handlers
);
866 synch_process_alive
= 1;
870 wait_for_termination (pid
);
872 restore_signal_handlers (saved_handlers
);
873 synch_process_alive
= 0;
875 #endif /* !macintosh */
879 save_signal_handlers (saved_handlers
)
880 struct save_signal
*saved_handlers
;
882 while (saved_handlers
->code
)
884 saved_handlers
->handler
885 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers
->code
, SIG_IGN
);
891 restore_signal_handlers (saved_handlers
)
892 struct save_signal
*saved_handlers
;
894 while (saved_handlers
->code
)
896 signal (saved_handlers
->code
, saved_handlers
->handler
);
910 old_fcntl_flags
= fcntl (fd
, F_GETFL
, 0) & ~FASYNC
;
911 fcntl (fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
913 interrupts_deferred
= 0;
922 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
927 if (read_socket_hook
)
931 sigunblock (sigmask (SIGWINCH
));
933 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
935 interrupts_deferred
= 0;
941 if (read_socket_hook
)
945 sigblock (sigmask (SIGWINCH
));
947 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
);
948 interrupts_deferred
= 1;
951 #else /* no FASYNC */
952 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
959 if (read_socket_hook
)
962 ioctl (input_fd
, FIOASYNC
, &on
);
963 interrupts_deferred
= 0;
971 if (read_socket_hook
)
974 ioctl (input_fd
, FIOASYNC
, &off
);
975 interrupts_deferred
= 1;
978 #else /* not FASYNC, not STRIDE */
990 if (read_socket_hook
)
994 sigaddset (&st
, SIGIO
);
995 ioctl (input_fd
, FIOASYNC
, &on
);
996 interrupts_deferred
= 0;
997 sigprocmask (SIG_UNBLOCK
, &st
, (sigset_t
*)0);
1005 if (read_socket_hook
)
1008 ioctl (input_fd
, FIOASYNC
, &off
);
1009 interrupts_deferred
= 1;
1012 #else /* ! _CX_UX */
1017 if (read_socket_hook
)
1020 croak ("request_sigio");
1026 if (read_socket_hook
)
1029 croak ("unrequest_sigio");
1035 #endif /* F_SETFL */
1037 /* Saving and restoring the process group of Emacs's terminal. */
1041 /* The process group of which Emacs was a member when it initially
1044 If Emacs was in its own process group (i.e. inherited_pgroup ==
1045 getpid ()), then we know we're running under a shell with job
1046 control (Emacs would never be run as part of a pipeline).
1049 If Emacs was not in its own process group, then we know we're
1050 running under a shell (or a caller) that doesn't know how to
1051 separate itself from Emacs (like sh). Emacs must be in its own
1052 process group in order to receive SIGIO correctly. In this
1053 situation, we put ourselves in our own pgroup, forcibly set the
1054 tty's pgroup to our pgroup, and make sure to restore and reinstate
1055 the tty's pgroup just like any other terminal setting. If
1056 inherited_group was not the tty's pgroup, then we'll get a
1057 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1058 it goes foreground in the future, which is what should happen. */
1059 int inherited_pgroup
;
1061 /* Split off the foreground process group to Emacs alone.
1062 When we are in the foreground, but not started in our own process
1063 group, redirect the TTY to point to our own process group. We need
1064 to be in our own process group to receive SIGIO properly. */
1066 narrow_foreground_group ()
1070 setpgrp (0, inherited_pgroup
);
1071 if (inherited_pgroup
!= me
)
1072 EMACS_SET_TTY_PGRP (input_fd
, &me
);
1076 /* Set the tty to our original foreground group. */
1078 widen_foreground_group ()
1080 if (inherited_pgroup
!= getpid ())
1081 EMACS_SET_TTY_PGRP (input_fd
, &inherited_pgroup
);
1082 setpgrp (0, inherited_pgroup
);
1085 #endif /* BSD_PGRPS */
1087 /* Getting and setting emacs_tty structures. */
1089 /* Set *TC to the parameters associated with the terminal FD.
1090 Return zero if all's well, or -1 if we ran into an error we
1091 couldn't deal with. */
1093 emacs_get_tty (fd
, settings
)
1095 struct emacs_tty
*settings
;
1097 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1099 /* We have those nifty POSIX tcmumbleattr functions. */
1100 bzero (&settings
->main
, sizeof (settings
->main
));
1101 if (tcgetattr (fd
, &settings
->main
) < 0)
1106 /* The SYSV-style interface? */
1107 if (ioctl (fd
, TCGETA
, &settings
->main
) < 0)
1112 /* Vehemently Monstrous System? :-) */
1113 if (! (SYS$
QIOW (0, fd
, IO$_SENSEMODE
, settings
, 0, 0,
1114 &settings
->main
.class, 12, 0, 0, 0, 0)
1120 /* I give up - I hope you have the BSD ioctls. */
1121 if (ioctl (fd
, TIOCGETP
, &settings
->main
) < 0)
1123 #endif /* not DOS_NT */
1128 /* Suivant - Do we have to get struct ltchars data? */
1130 if (ioctl (fd
, TIOCGLTC
, &settings
->ltchars
) < 0)
1134 /* How about a struct tchars and a wordful of lmode bits? */
1136 if (ioctl (fd
, TIOCGETC
, &settings
->tchars
) < 0
1137 || ioctl (fd
, TIOCLGET
, &settings
->lmode
) < 0)
1141 /* We have survived the tempest. */
1146 /* Set the parameters of the tty on FD according to the contents of
1147 *SETTINGS. If FLUSHP is non-zero, we discard input.
1148 Return 0 if all went well, and -1 if anything failed. */
1151 emacs_set_tty (fd
, settings
, flushp
)
1153 struct emacs_tty
*settings
;
1156 /* Set the primary parameters - baud rate, character size, etcetera. */
1159 /* We have those nifty POSIX tcmumbleattr functions.
1160 William J. Smith <wjs@wiis.wang.com> writes:
1161 "POSIX 1003.1 defines tcsetattr to return success if it was
1162 able to perform any of the requested actions, even if some
1163 of the requested actions could not be performed.
1164 We must read settings back to ensure tty setup properly.
1165 AIX requires this to keep tty from hanging occasionally." */
1166 /* This make sure that we don't loop indefinitely in here. */
1167 for (i
= 0 ; i
< 10 ; i
++)
1168 if (tcsetattr (fd
, flushp
? TCSAFLUSH
: TCSADRAIN
, &settings
->main
) < 0)
1179 bzero (&new, sizeof (new));
1180 /* Get the current settings, and see if they're what we asked for. */
1181 tcgetattr (fd
, &new);
1182 /* We cannot use memcmp on the whole structure here because under
1183 * aix386 the termios structure has some reserved field that may
1186 if ( new.c_iflag
== settings
->main
.c_iflag
1187 && new.c_oflag
== settings
->main
.c_oflag
1188 && new.c_cflag
== settings
->main
.c_cflag
1189 && new.c_lflag
== settings
->main
.c_lflag
1190 && memcmp (new.c_cc
, settings
->main
.c_cc
, NCCS
) == 0)
1198 /* The SYSV-style interface? */
1199 if (ioctl (fd
, flushp
? TCSETAF
: TCSETAW
, &settings
->main
) < 0)
1204 /* Vehemently Monstrous System? :-) */
1205 if (! (SYS$
QIOW (0, fd
, IO$_SETMODE
, &input_iosb
, 0, 0,
1206 &settings
->main
.class, 12, 0, 0, 0, 0)
1212 /* I give up - I hope you have the BSD ioctls. */
1213 if (ioctl (fd
, (flushp
) ? TIOCSETP
: TIOCSETN
, &settings
->main
) < 0)
1215 #endif /* not DOS_NT */
1221 /* Suivant - Do we have to get struct ltchars data? */
1223 if (ioctl (fd
, TIOCSLTC
, &settings
->ltchars
) < 0)
1227 /* How about a struct tchars and a wordful of lmode bits? */
1229 if (ioctl (fd
, TIOCSETC
, &settings
->tchars
) < 0
1230 || ioctl (fd
, TIOCLSET
, &settings
->lmode
) < 0)
1234 /* We have survived the tempest. */
1239 /* The initial tty mode bits */
1240 struct emacs_tty old_tty
;
1242 /* 1 if we have been through init_sys_modes. */
1245 /* 1 if outer tty status has been recorded. */
1249 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1254 #ifndef F_SETOWN_BUG
1256 int old_fcntl_owner
;
1257 #endif /* F_SETOWN */
1258 #endif /* F_SETOWN_BUG */
1260 /* This may also be defined in stdio,
1261 but if so, this does no harm,
1262 and using the same name avoids wasting the other one's space. */
1265 extern char *_sobuf
;
1267 #if defined (USG) || defined (DGUX)
1268 unsigned char _sobuf
[BUFSIZ
+8];
1270 char _sobuf
[BUFSIZ
];
1275 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
1278 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
1284 struct emacs_tty tty
;
1287 Vwindow_system
= intern ("mac");
1288 Vwindow_system_version
= make_number (1);
1290 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1291 #ifndef subprocesses
1292 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
1293 "*Non-nil means delete processes immediately when they exit.\n\
1294 nil means don't delete them until `list-processes' is run.");
1295 delete_exited_processes
= 0;
1298 #ifndef HAVE_X_WINDOWS
1299 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
1300 "List of directories to search for bitmap files for X.");
1301 Vx_bitmap_file_path
= decode_env_path ((char *) 0, ".");
1304 #endif /* not macintosh */
1308 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
1309 extern int (*interrupt_signal
) ();
1313 Vtty_erase_char
= Qnil
;
1320 input_ef
= get_kbd_event_flag ();
1321 /* LIB$GET_EF (&input_ef); */
1322 SYS$
CLREF (input_ef
);
1323 waiting_for_ast
= 0;
1325 timer_ef
= get_timer_event_flag ();
1326 /* LIB$GET_EF (&timer_ef); */
1327 SYS$
CLREF (timer_ef
);
1331 LIB$
GET_EF (&process_ef
);
1332 SYS$
CLREF (process_ef
);
1334 if (input_ef
/ 32 != process_ef
/ 32)
1335 croak ("Input and process event flags in different clusters.");
1337 if (input_ef
/ 32 != timer_ef
/ 32)
1338 croak ("Input and timer event flags in different clusters.");
1340 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1341 ((unsigned) 1 << (process_ef
% 32));
1343 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1344 ((unsigned) 1 << (timer_ef
% 32));
1346 sys_access_reinit ();
1348 #endif /* not VMS */
1351 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1352 narrow_foreground_group ();
1355 #ifdef HAVE_WINDOW_SYSTEM
1356 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1357 needs the initialization code below. */
1358 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1361 EMACS_GET_TTY (input_fd
, &old_tty
);
1367 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1368 XSETINT (Vtty_erase_char
, old_tty
.main
.c_cc
[VERASE
]);
1371 /* This allows meta to be sent on 8th bit. */
1372 tty
.main
.c_iflag
&= ~INPCK
; /* don't check input for parity */
1374 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
1375 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
1376 #ifdef INLCR /* I'm just being cautious,
1377 since I can't check how widespread INLCR is--rms. */
1378 tty
.main
.c_iflag
&= ~INLCR
; /* Disable map of NL to CR on input */
1381 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
1383 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
1384 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
1386 tty
.main
.c_lflag
&= ~IEXTEN
; /* Disable other editing characters. */
1388 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
1391 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
1393 tty
.main
.c_iflag
&= ~IXANY
;
1397 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
1398 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
1400 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
1404 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
1405 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
1408 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
1409 /* Set up C-g for both SIGQUIT and SIGINT.
1410 We don't know which we will get, but we handle both alike
1411 so which one it really gives us does not matter. */
1412 tty
.main
.c_cc
[VQUIT
] = quit_char
;
1413 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
1414 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
1416 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
1420 #if defined (mips) || defined (HAVE_TCATTR)
1422 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
1425 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
1426 #endif /* V_DSUSP */
1427 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1428 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
1431 tty
.main
.c_cc
[VLNEXT
] = CDISABLE
;
1434 tty
.main
.c_cc
[VREPRINT
] = CDISABLE
;
1435 #endif /* VREPRINT */
1437 tty
.main
.c_cc
[VWERASE
] = CDISABLE
;
1438 #endif /* VWERASE */
1440 tty
.main
.c_cc
[VDISCARD
] = CDISABLE
;
1441 #endif /* VDISCARD */
1446 tty
.main
.c_cc
[VSTART
] = '\021';
1449 tty
.main
.c_cc
[VSTOP
] = '\023';
1455 tty
.main
.c_cc
[VSTART
] = CDISABLE
;
1458 tty
.main
.c_cc
[VSTOP
] = CDISABLE
;
1461 #endif /* mips or HAVE_TCATTR */
1463 #ifdef SET_LINE_DISCIPLINE
1464 /* Need to explicitly request TERMIODISC line discipline or
1465 Ultrix's termios does not work correctly. */
1466 tty
.main
.c_line
= SET_LINE_DISCIPLINE
;
1470 /* AIX enhanced edit loses NULs, so disable it. */
1471 tty
.main
.c_line
= 0;
1472 tty
.main
.c_iflag
&= ~ASCEDIT
;
1474 tty
.main
.c_cc
[VSTRT
] = 255;
1475 tty
.main
.c_cc
[VSTOP
] = 255;
1476 tty
.main
.c_cc
[VSUSP
] = 255;
1477 tty
.main
.c_cc
[VDSUSP
] = 255;
1478 #endif /* IBMR2AIX */
1482 tty
.main
.c_cc
[VSTART
] = '\021';
1485 tty
.main
.c_cc
[VSTOP
] = '\023';
1488 /* Also, PTY overloads NUL and BREAK.
1489 don't ignore break, but don't signal either, so it looks like NUL.
1490 This really serves a purpose only if running in an XTERM window
1491 or via TELNET or the like, but does no harm elsewhere. */
1492 tty
.main
.c_iflag
&= ~IGNBRK
;
1493 tty
.main
.c_iflag
&= ~BRKINT
;
1495 #else /* if not HAVE_TERMIO */
1497 tty
.main
.tt_char
|= TT$M_NOECHO
;
1499 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
1501 tty
.main
.tt_char
|= TT$M_TTSYNC
;
1503 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
1504 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
1505 #else /* not VMS (BSD, that is) */
1507 XSETINT (Vtty_erase_char
, tty
.main
.sg_erase
);
1508 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
1510 tty
.main
.sg_flags
|= ANYP
;
1511 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
1512 #endif /* not DOS_NT */
1513 #endif /* not VMS (BSD, that is) */
1514 #endif /* not HAVE_TERMIO */
1516 /* If going to use CBREAK mode, we must request C-g to interrupt
1517 and turn off start and stop chars, etc. If not going to use
1518 CBREAK mode, do this anyway so as to turn off local flow
1519 control for user coming over network on 4.2; in this case,
1520 only t_stopc and t_startc really matter. */
1523 /* Note: if not using CBREAK mode, it makes no difference how we
1525 tty
.tchars
= new_tchars
;
1526 tty
.tchars
.t_intrc
= quit_char
;
1529 tty
.tchars
.t_startc
= '\021';
1530 tty
.tchars
.t_stopc
= '\023';
1533 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
1535 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1536 anything, and leaving it in breaks the meta key. Go figure. */
1537 tty
.lmode
&= ~LLITOUT
;
1544 #endif /* HAVE_TCHARS */
1545 #endif /* not HAVE_TERMIO */
1548 tty
.ltchars
= new_ltchars
;
1549 #endif /* HAVE_LTCHARS */
1550 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1552 internal_terminal_init ();
1556 EMACS_SET_TTY (input_fd
, &tty
, 0);
1558 /* This code added to insure that, if flow-control is not to be used,
1559 we have an unlocked terminal at the start. */
1562 if (!flow_control
) ioctl (input_fd
, TCXONC
, 1);
1566 if (!flow_control
) ioctl (input_fd
, TIOCSTART
, 0);
1570 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1572 if (!flow_control
) tcflow (input_fd
, TCOON
);
1580 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1581 to be only LF. This is the way that is done. */
1584 if (ioctl (1, HFTGETID
, &tty
) != -1)
1585 write (1, "\033[20l", 5);
1591 /* Appears to do nothing when in PASTHRU mode.
1592 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1593 interrupt_signal, oob_chars, 0, 0, 0, 0);
1595 queue_kbd_input (0);
1600 #ifndef F_SETOWN_BUG
1601 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1603 && ! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1605 old_fcntl_owner
= fcntl (input_fd
, F_GETOWN
, 0);
1606 fcntl (input_fd
, F_SETOWN
, getpid ());
1607 init_sigio (input_fd
);
1609 #endif /* F_GETOWN */
1610 #endif /* F_SETOWN_BUG */
1611 #endif /* F_SETFL */
1614 if (interrupt_input
)
1615 init_sigio (input_fd
);
1618 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1622 /* This symbol is defined on recent USG systems.
1623 Someone says without this call USG won't really buffer the file
1624 even with a call to setbuf. */
1625 setvbuf (stdout
, (char *) _sobuf
, _IOFBF
, sizeof _sobuf
);
1627 setbuf (stdout
, (char *) _sobuf
);
1629 #ifdef HAVE_WINDOW_SYSTEM
1630 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1631 needs the initialization code below. */
1632 if (EQ (Vwindow_system
, Qnil
)
1634 /* When running in tty mode on NT/Win95, we have a read_socket
1635 hook, but still need the rest of the initialization code below. */
1636 && (! read_socket_hook
)
1640 set_terminal_modes ();
1643 && FRAMEP (Vterminal_frame
)
1644 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame
)))
1645 init_frame_faces (XFRAME (Vterminal_frame
));
1647 if (term_initted
&& no_redraw_on_reenter
)
1649 if (display_completed
)
1650 direct_output_forward_char (0);
1655 if (FRAMEP (Vterminal_frame
))
1656 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
1662 /* Return nonzero if safe to use tabs in output.
1663 At the time this is called, init_sys_modes has not been done yet. */
1668 struct emacs_tty tty
;
1670 EMACS_GET_TTY (input_fd
, &tty
);
1671 return EMACS_TTY_TABS_OK (&tty
);
1674 /* Get terminal size from system.
1675 Store number of lines into *HEIGHTP and width into *WIDTHP.
1676 We store 0 if there's no valid information. */
1679 get_frame_size (widthp
, heightp
)
1680 int *widthp
, *heightp
;
1686 struct winsize size
;
1688 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1689 *widthp
= *heightp
= 0;
1692 *widthp
= size
.ws_col
;
1693 *heightp
= size
.ws_row
;
1699 /* SunOS - style. */
1700 struct ttysize size
;
1702 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1703 *widthp
= *heightp
= 0;
1706 *widthp
= size
.ts_cols
;
1707 *heightp
= size
.ts_lines
;
1713 struct sensemode tty
;
1715 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1716 &tty
.class, 12, 0, 0, 0, 0);
1717 *widthp
= tty
.scr_wid
;
1718 *heightp
= tty
.scr_len
;
1722 *widthp
= ScreenCols ();
1723 *heightp
= ScreenRows ();
1724 #else /* system doesn't know size */
1729 #endif /* not VMS */
1730 #endif /* not SunOS-style */
1731 #endif /* not BSD-style */
1734 /* Set the logical window size associated with descriptor FD
1735 to HEIGHT and WIDTH. This is used mainly with ptys. */
1738 set_window_size (fd
, height
, width
)
1739 int fd
, height
, width
;
1744 struct winsize size
;
1745 size
.ws_row
= height
;
1746 size
.ws_col
= width
;
1748 if (ioctl (fd
, TIOCSWINSZ
, &size
) == -1)
1749 return 0; /* error */
1756 /* SunOS - style. */
1757 struct ttysize size
;
1758 size
.ts_lines
= height
;
1759 size
.ts_cols
= width
;
1761 if (ioctl (fd
, TIOCGSIZE
, &size
) == -1)
1767 #endif /* not SunOS-style */
1768 #endif /* not BSD-style */
1772 /* Prepare the terminal for exiting Emacs; move the cursor to the
1773 bottom of the frame, turn off interrupt-driven I/O, etc. */
1786 #ifdef HAVE_WINDOW_SYSTEM
1787 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1788 needs the clean-up code below. */
1789 if (!EQ (Vwindow_system
, Qnil
)
1791 /* When running in tty mode on NT/Win95, we have a read_socket
1792 hook, but still need the rest of the clean-up code below. */
1798 sf
= SELECTED_FRAME ();
1799 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1800 clear_end_of_line (FRAME_WIDTH (sf
));
1801 /* clear_end_of_line may move the cursor */
1802 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1803 #if defined (IBMR2AIX) && defined (AIXHFT)
1805 /* HFT devices normally use ^J as a LF/CR. We forced it to
1806 do the LF only. Now, we need to reset it. */
1809 if (ioctl (1, HFTGETID
, &tty
) != -1)
1810 write (1, "\033[20h", 5);
1814 reset_terminal_modes ();
1818 /* Avoid possible loss of output when changing terminal modes. */
1819 fsync (fileno (stdout
));
1824 #ifndef F_SETOWN_BUG
1825 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1826 if (interrupt_input
)
1829 fcntl (input_fd
, F_SETOWN
, old_fcntl_owner
);
1831 #endif /* F_SETOWN */
1832 #endif /* F_SETOWN_BUG */
1834 fcntl (input_fd
, F_SETFL
, fcntl (input_fd
, F_GETFL
, 0) & ~O_NDELAY
);
1836 #endif /* F_SETFL */
1838 if (interrupt_input
)
1843 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1846 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1850 #ifdef SET_LINE_DISCIPLINE
1851 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1852 A different old line discipline is therefore not restored, yet.
1853 Restore the old line discipline by hand. */
1854 ioctl (0, TIOCSETD
, &old_tty
.main
.c_line
);
1862 widen_foreground_group ();
1868 /* Set up the proper status flags for use of a pty. */
1874 /* I'm told that TOICREMOTE does not mean control chars
1875 "can't be sent" but rather that they don't have
1876 input-editing or signaling effects.
1877 That should be good, because we have other ways
1878 to do those things in Emacs.
1879 However, telnet mode seems not to work on 4.2.
1880 So TIOCREMOTE is turned off now. */
1882 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1883 will hang. In particular, the "timeout" feature (which
1884 causes a read to return if there is no data available)
1885 does this. Also it is known that telnet mode will hang
1886 in such a way that Emacs must be stopped (perhaps this
1887 is the same problem).
1889 If TIOCREMOTE is turned off, then there is a bug in
1890 hp-ux which sometimes loses data. Apparently the
1891 code which blocks the master process when the internal
1892 buffer fills up does not work. Other than this,
1893 though, everything else seems to work fine.
1895 Since the latter lossage is more benign, we may as well
1896 lose that way. -- cph */
1898 #if defined(SYSV_PTYS) || defined(UNIX98_PTYS)
1901 ioctl (fd
, FIONBIO
, &on
);
1906 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1907 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1908 /* cause EMACS not to die when it should, i.e., when its own controlling */
1909 /* tty goes away. I've complained to the AIX developers, and they may */
1910 /* change this behavior, but I'm not going to hold my breath. */
1911 signal (SIGHUP
, SIG_IGN
);
1914 #endif /* HAVE_PTYS */
1918 /* Assigning an input channel is done at the start of Emacs execution.
1919 This is called each time Emacs is resumed, also, but does nothing
1920 because input_chain is no longer zero. */
1929 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1935 /* Deassigning the input channel is done before exiting. */
1940 return SYS$
DASSGN (input_fd
);
1945 /* Request reading one character into the keyboard buffer.
1946 This is done as soon as the buffer becomes empty. */
1952 extern kbd_input_ast ();
1954 waiting_for_ast
= 0;
1956 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1957 &input_iosb
, kbd_input_ast
, 1,
1958 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1963 /* Ast routine that is called when keyboard input comes in
1964 in accord with the SYS$QIO above. */
1969 register int c
= -1;
1970 int old_errno
= errno
;
1971 extern EMACS_TIME
*input_available_clear_time
;
1973 if (waiting_for_ast
)
1974 SYS$
SETEF (input_ef
);
1975 waiting_for_ast
= 0;
1978 if (input_count
== 25)
1980 printf ("Ast # %d,", input_count
);
1981 printf (" iosb = %x, %x, %x, %x",
1982 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1985 if (input_iosb
.offset
)
1989 printf (", char = 0%o", c
);
2001 struct input_event e
;
2002 e
.kind
= ascii_keystroke
;
2003 XSETINT (e
.code
, c
);
2004 e
.frame_or_window
= selected_frame
;
2005 kbd_buffer_store_event (&e
);
2007 if (input_available_clear_time
)
2008 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
2012 /* Wait until there is something in kbd_buffer. */
2015 wait_for_kbd_input ()
2017 extern int have_process_input
, process_exited
;
2019 /* If already something, avoid doing system calls. */
2020 if (detect_input_pending ())
2024 /* Clear a flag, and tell ast routine above to set it. */
2025 SYS$
CLREF (input_ef
);
2026 waiting_for_ast
= 1;
2027 /* Check for timing error: ast happened while we were doing that. */
2028 if (!detect_input_pending ())
2030 /* No timing error: wait for flag to be set. */
2031 set_waiting_for_input (0);
2032 SYS$
WFLOR (input_ef
, input_eflist
);
2033 clear_waiting_for_input (0);
2034 if (!detect_input_pending ())
2035 /* Check for subprocess input availability */
2037 int dsp
= have_process_input
|| process_exited
;
2039 SYS$
CLREF (process_ef
);
2040 if (have_process_input
)
2041 process_command_input ();
2046 update_mode_lines
++;
2047 prepare_menu_bars ();
2048 redisplay_preserve_echo_area ();
2052 waiting_for_ast
= 0;
2055 /* Get rid of any pending QIO, when we are about to suspend
2056 or when we want to throw away pending input.
2057 We wait for a positive sign that the AST routine has run
2058 and therefore there is no I/O request queued when we return.
2059 SYS$SETAST is used to avoid a timing error. */
2065 printf ("At end_kbd_input.\n");
2069 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2071 SYS$
CANCEL (input_fd
);
2076 /* Clear a flag, and tell ast routine above to set it. */
2077 SYS$
CLREF (input_ef
);
2078 waiting_for_ast
= 1;
2080 SYS$
CANCEL (input_fd
);
2082 SYS$
WAITFR (input_ef
);
2083 waiting_for_ast
= 0;
2086 /* Wait for either input available or time interval expiry. */
2089 input_wait_timeout (timeval
)
2090 int timeval
; /* Time to wait, in seconds */
2093 static int zero
= 0;
2094 static int large
= -10000000;
2096 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2098 /* If already something, avoid doing system calls. */
2099 if (detect_input_pending ())
2103 /* Clear a flag, and tell ast routine above to set it. */
2104 SYS$
CLREF (input_ef
);
2105 waiting_for_ast
= 1;
2106 /* Check for timing error: ast happened while we were doing that. */
2107 if (!detect_input_pending ())
2109 /* No timing error: wait for flag to be set. */
2111 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2112 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
2114 waiting_for_ast
= 0;
2117 /* The standard `sleep' routine works some other way
2118 and it stops working if you have ever quit out of it.
2119 This one continues to work. */
2125 static int zero
= 0;
2126 static int large
= -10000000;
2128 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2131 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2132 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
2150 croak ("request sigio");
2156 croak ("unrequest sigio");
2161 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2166 #ifndef SYSTEM_MALLOC
2173 /* Some systems that cannot dump also cannot implement these. */
2176 * Return the address of the start of the text segment prior to
2177 * doing an unexec. After unexec the return value is undefined.
2178 * See crt0.c for further explanation and _start.
2182 #if !(defined (__NetBSD__) && defined (__ELF__))
2183 #ifndef HAVE_TEXT_START
2188 return ((char *) TEXT_START
);
2192 return ((char *) csrt
);
2193 #else /* not GOULD */
2194 extern int _start ();
2195 return ((char *) _start
);
2197 #endif /* TEXT_START */
2199 #endif /* not HAVE_TEXT_START */
2203 * Return the address of the start of the data segment prior to
2204 * doing an unexec. After unexec the return value is undefined.
2205 * See crt0.c for further information and definition of data_start.
2207 * Apparently, on BSD systems this is etext at startup. On
2208 * USG systems (swapping) this is highly mmu dependent and
2209 * is also dependent on whether or not the program is running
2210 * with shared text. Generally there is a (possibly large)
2211 * gap between end of text and start of data with shared text.
2213 * On Uniplus+ systems with shared text, data starts at a
2214 * fixed address. Each port (from a given oem) is generally
2215 * different, and the specific value of the start of data can
2216 * be obtained via the UniPlus+ specific "uvar" system call,
2217 * however the method outlined in crt0.c seems to be more portable.
2219 * Probably what will have to happen when a USG unexec is available,
2220 * at least on UniPlus, is temacs will have to be made unshared so
2221 * that text and data are contiguous. Then once loadup is complete,
2222 * unexec will produce a shared executable where the data can be
2223 * at the normal shared text boundary and the startofdata variable
2224 * will be patched by unexec to the correct value.
2232 return ((char *) DATA_START
);
2234 #ifdef ORDINARY_LINK
2236 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2237 * data_start isn't defined. We take the address of environ, which
2238 * is known to live at or near the start of the system crt0.c, and
2239 * we don't sweat the handful of bytes that might lose.
2241 extern char **environ
;
2243 return ((char *) &environ
);
2245 extern int data_start
;
2246 return ((char *) &data_start
);
2247 #endif /* ORDINARY_LINK */
2248 #endif /* DATA_START */
2250 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2253 /* Some systems that cannot dump also cannot implement these. */
2256 * Return the address of the end of the text segment prior to
2257 * doing an unexec. After unexec the return value is undefined.
2264 return ((char *) TEXT_END
);
2267 return ((char *) &etext
);
2272 * Return the address of the end of the data segment prior to
2273 * doing an unexec. After unexec the return value is undefined.
2280 return ((char *) DATA_END
);
2283 return ((char *) &edata
);
2287 #endif /* not CANNOT_DUMP */
2289 /* init_system_name sets up the string for the Lisp function
2290 system-name to return. */
2296 extern Lisp_Object Vsystem_name
;
2301 #include <sys/socket.h>
2303 #endif /* HAVE_SOCKETS */
2304 #endif /* not VMS */
2305 #endif /* not BSD4_1 */
2311 Vsystem_name
= build_string (sysname
);
2315 if ((sp
= egetenv ("SYS$NODE")) == 0)
2316 Vsystem_name
= build_string ("vax-vms");
2317 else if ((end
= index (sp
, ':')) == 0)
2318 Vsystem_name
= build_string (sp
);
2320 Vsystem_name
= make_string (sp
, end
- sp
);
2322 #ifndef HAVE_GETHOSTNAME
2325 Vsystem_name
= build_string (uts
.nodename
);
2326 #else /* HAVE_GETHOSTNAME */
2327 unsigned int hostname_size
= 256;
2328 char *hostname
= (char *) alloca (hostname_size
);
2330 /* Try to get the host name; if the buffer is too short, try
2331 again. Apparently, the only indication gethostname gives of
2332 whether the buffer was large enough is the presence or absence
2333 of a '\0' in the string. Eech. */
2336 gethostname (hostname
, hostname_size
- 1);
2337 hostname
[hostname_size
- 1] = '\0';
2339 /* Was the buffer large enough for the '\0'? */
2340 if (strlen (hostname
) < hostname_size
- 1)
2343 hostname_size
<<= 1;
2344 hostname
= (char *) alloca (hostname_size
);
2347 /* Turn the hostname into the official, fully-qualified hostname.
2348 Don't do this if we're going to dump; this can confuse system
2349 libraries on some machines and make the dumped emacs core dump. */
2352 #endif /* not CANNOT_DUMP */
2353 if (! index (hostname
, '.'))
2357 for (count
= 0;; count
++)
2362 hp
= gethostbyname (hostname
);
2364 if (! (hp
== 0 && h_errno
== TRY_AGAIN
))
2369 Fsleep_for (make_number (1), Qnil
);
2373 char *fqdn
= (char *) hp
->h_name
;
2376 if (!index (fqdn
, '.'))
2378 /* We still don't have a fully qualified domain name.
2379 Try to find one in the list of alternate names */
2380 char **alias
= hp
->h_aliases
;
2381 while (*alias
&& !index (*alias
, '.'))
2388 /* Convert the host name to lower case. */
2389 /* Using ctype.h here would introduce a possible locale
2390 dependence that is probably wrong for hostnames. */
2394 if (*p
>= 'A' && *p
<= 'Z')
2401 #endif /* HAVE_SOCKETS */
2402 /* We used to try using getdomainname here,
2403 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2404 getdomainname gets the NIS/YP domain which often is not the same
2405 as in Internet domain name. */
2406 #if 0 /* Turned off because sysinfo is not really likely to return the
2407 correct Internet domain. */
2408 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2409 if (! index (hostname
, '.'))
2411 /* The hostname is not fully qualified. Append the domain name. */
2413 int hostlen
= strlen (hostname
);
2414 int domain_size
= 256;
2418 char *domain
= (char *) alloca (domain_size
+ 1);
2419 char *fqdn
= (char *) alloca (hostlen
+ 1 + domain_size
+ 1);
2420 int sys_domain_size
= sysinfo (SI_SRPC_DOMAIN
, domain
, domain_size
);
2421 if (sys_domain_size
<= 0)
2423 if (domain_size
< sys_domain_size
)
2425 domain_size
= sys_domain_size
;
2428 strcpy (fqdn
, hostname
);
2429 if (domain
[0] == '.')
2430 strcpy (fqdn
+ hostlen
, domain
);
2431 else if (domain
[0] != 0)
2433 fqdn
[hostlen
] = '.';
2434 strcpy (fqdn
+ hostlen
+ 1, domain
);
2440 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2442 Vsystem_name
= build_string (hostname
);
2443 #endif /* HAVE_GETHOSTNAME */
2448 for (p
= XSTRING (Vsystem_name
)->data
; *p
; p
++)
2449 if (*p
== ' ' || *p
== '\t')
2456 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2458 #include "sysselect.h"
2461 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2462 /* Cause explanatory error message at compile time,
2463 since the select emulation is not good enough for X. */
2464 int *x
= &x_windows_lose_if_no_select_system_call
;
2467 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2468 * Only checks read descriptors.
2470 /* How long to wait between checking fds in select */
2471 #define SELECT_PAUSE 1
2474 /* For longjmp'ing back to read_input_waiting. */
2476 jmp_buf read_alarm_throw
;
2478 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2479 The read_socket_hook function sets this to 1 while it is waiting. */
2481 int read_alarm_should_throw
;
2489 #else /* not BSD4_1 */
2490 signal (SIGALRM
, SIG_IGN
);
2491 #endif /* not BSD4_1 */
2492 if (read_alarm_should_throw
)
2493 longjmp (read_alarm_throw
, 1);
2497 /* Only rfds are checked. */
2499 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2501 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2502 EMACS_TIME
*timeout
;
2508 extern int proc_buffered_char
[];
2509 #ifndef subprocesses
2510 int process_tick
= 0, update_tick
= 0;
2512 extern int process_tick
, update_tick
;
2516 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2517 /* If we're using X, then the native select will work; we only need the
2518 emulation for non-X usage. */
2519 if (!NILP (Vwindow_system
))
2520 return select (nfds
, rfds
, wfds
, efds
, timeout
);
2522 timeoutval
= timeout
? EMACS_SECS (*timeout
) : 100000;
2523 local_timeout
= &timeoutval
;
2535 /* If we are looking only for the terminal, with no timeout,
2536 just read it and wait -- that's more efficient. */
2537 if (*local_timeout
== 100000 && process_tick
== update_tick
2538 && FD_ISSET (0, &orfds
))
2541 for (fd
= 1; fd
< nfds
; ++fd
)
2542 if (FD_ISSET (fd
, &orfds
))
2544 if (! detect_input_pending ())
2545 read_input_waiting ();
2551 /* Once a second, till the timer expires, check all the flagged read
2552 * descriptors to see if any input is available. If there is some then
2553 * set the corresponding bit in the return copy of rfds.
2557 register int to_check
, fd
;
2561 for (to_check
= nfds
, fd
= 0; --to_check
>= 0; fd
++)
2563 if (FD_ISSET (fd
, &orfds
))
2565 int avail
= 0, status
= 0;
2568 avail
= detect_input_pending (); /* Special keyboard handler */
2572 status
= ioctl (fd
, FIONREAD
, &avail
);
2573 #else /* no FIONREAD */
2574 /* Hoping it will return -1 if nothing available
2575 or 0 if all 0 chars requested are read. */
2576 if (proc_buffered_char
[fd
] >= 0)
2580 avail
= read (fd
, &buf
, 1);
2582 proc_buffered_char
[fd
] = buf
;
2584 #endif /* no FIONREAD */
2586 if (status
>= 0 && avail
> 0)
2594 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
2597 turn_on_atimers (0);
2598 signal (SIGALRM
, select_alarm
);
2600 alarm (SELECT_PAUSE
);
2602 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2603 while (select_alarmed
== 0 && *local_timeout
!= 0
2604 && process_tick
== update_tick
)
2606 /* If we are interested in terminal input,
2607 wait by reading the terminal.
2608 That makes instant wakeup for terminal input at least. */
2609 if (FD_ISSET (0, &orfds
))
2611 read_input_waiting ();
2612 if (detect_input_pending ())
2618 (*local_timeout
) -= SELECT_PAUSE
;
2620 /* Reset the old alarm if there was one. */
2621 turn_on_atimers (1);
2623 if (*local_timeout
== 0) /* Stop on timer being cleared */
2628 #endif /* not WINDOWSNT */
2630 /* Read keyboard input into the standard buffer,
2631 waiting for at least one character. */
2633 /* Make all keyboard buffers much bigger when using a window system. */
2634 #ifdef HAVE_WINDOW_SYSTEM
2635 #define BUFFER_SIZE_FACTOR 16
2637 #define BUFFER_SIZE_FACTOR 1
2641 read_input_waiting ()
2643 struct input_event e
;
2645 extern int quit_char
;
2647 if (read_socket_hook
)
2649 struct input_event buf
[256];
2651 read_alarm_should_throw
= 0;
2652 if (! setjmp (read_alarm_throw
))
2653 nread
= (*read_socket_hook
) (0, buf
, 256, 1);
2657 /* Scan the chars for C-g and store them in kbd_buffer. */
2658 for (i
= 0; i
< nread
; i
++)
2660 kbd_buffer_store_event (&buf
[i
]);
2661 /* Don't look at input that follows a C-g too closely.
2662 This reduces lossage due to autorepeat on C-g. */
2663 if (buf
[i
].kind
== ascii_keystroke
2664 && buf
[i
].code
== quit_char
)
2671 nread
= read (fileno (stdin
), buf
, 1);
2673 /* Scan the chars for C-g and store them in kbd_buffer. */
2674 e
.kind
= ascii_keystroke
;
2675 e
.frame_or_window
= selected_frame
;
2677 for (i
= 0; i
< nread
; i
++)
2679 /* Convert chars > 0177 to meta events if desired.
2680 We do this under the same conditions that read_avail_input does. */
2681 if (read_socket_hook
== 0)
2683 /* If the user says she has a meta key, then believe her. */
2684 if (meta_key
== 1 && (buf
[i
] & 0x80))
2685 e
.modifiers
= meta_modifier
;
2690 XSETINT (e
.code
, buf
[i
]);
2691 kbd_buffer_store_event (&e
);
2692 /* Don't look at input that follows a C-g too closely.
2693 This reduces lossage due to autorepeat on C-g. */
2694 if (buf
[i
] == quit_char
)
2700 #endif /* not HAVE_SELECT */
2701 #endif /* not VMS */
2702 #endif /* not MSDOS */
2711 lmode
= LINTRUP
| lmode
;
2712 ioctl (fd
, TIOCLSET
, &lmode
);
2720 lmode
= ~LINTRUP
& lmode
;
2721 ioctl (0, TIOCLSET
, &lmode
);
2729 interrupts_deferred
= 0;
2737 interrupts_deferred
= 1;
2740 /* still inside #ifdef BSD4_1 */
2743 int sigheld
; /* Mask of held signals */
2749 sigheld
|= sigbit (signum
);
2757 sigheld
|= sigbit (signum
);
2764 sigheld
&= ~sigbit (signum
);
2769 sigfree () /* Free all held signals */
2772 for (i
= 0; i
< NSIG
; i
++)
2773 if (sigheld
& sigbit (i
))
2781 return 1 << (i
- 1);
2783 #endif /* subprocesses */
2786 /* POSIX signals support - DJB */
2787 /* Anyone with POSIX signals should have ANSI C declarations */
2789 #ifdef POSIX_SIGNALS
2791 sigset_t empty_mask
, full_mask
;
2794 sys_signal (int signal_number
, signal_handler_t action
)
2796 struct sigaction new_action
, old_action
;
2797 sigemptyset (&new_action
.sa_mask
);
2798 new_action
.sa_handler
= action
;
2800 /* Emacs mostly works better with restartable system services. If this
2801 * flag exists, we probably want to turn it on here.
2803 new_action
.sa_flags
= SA_RESTART
;
2805 new_action
.sa_flags
= 0;
2807 sigaction (signal_number
, &new_action
, &old_action
);
2808 return (old_action
.sa_handler
);
2812 /* If we're compiling with GCC, we don't need this function, since it
2813 can be written as a macro. */
2815 sys_sigmask (int sig
)
2818 sigemptyset (&mask
);
2819 sigaddset (&mask
, sig
);
2824 /* I'd like to have these guys return pointers to the mask storage in here,
2825 but there'd be trouble if the code was saving multiple masks. I'll be
2826 safe and pass the structure. It normally won't be more than 2 bytes
2830 sys_sigblock (sigset_t new_mask
)
2833 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
2838 sys_sigunblock (sigset_t new_mask
)
2841 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
2846 sys_sigsetmask (sigset_t new_mask
)
2849 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
2853 #endif /* POSIX_SIGNALS */
2855 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2856 static char *my_sys_siglist
[NSIG
];
2860 # define sys_siglist my_sys_siglist
2866 #ifdef POSIX_SIGNALS
2867 sigemptyset (&empty_mask
);
2868 sigfillset (&full_mask
);
2871 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2875 sys_siglist
[SIGABRT
] = "Aborted";
2878 sys_siglist
[SIGAIO
] = "LAN I/O interrupt";
2881 sys_siglist
[SIGALRM
] = "Alarm clock";
2884 sys_siglist
[SIGBUS
] = "Bus error";
2887 sys_siglist
[SIGCLD
] = "Child status changed";
2890 sys_siglist
[SIGCHLD
] = "Child status changed";
2893 sys_siglist
[SIGCONT
] = "Continued";
2896 sys_siglist
[SIGDANGER
] = "Swap space dangerously low";
2899 sys_siglist
[SIGDGNOTIFY
] = "Notification message in queue";
2902 sys_siglist
[SIGEMT
] = "Emulation trap";
2905 sys_siglist
[SIGFPE
] = "Arithmetic exception";
2908 sys_siglist
[SIGFREEZE
] = "SIGFREEZE";
2911 sys_siglist
[SIGGRANT
] = "Monitor mode granted";
2914 sys_siglist
[SIGHUP
] = "Hangup";
2917 sys_siglist
[SIGILL
] = "Illegal instruction";
2920 sys_siglist
[SIGINT
] = "Interrupt";
2923 sys_siglist
[SIGIO
] = "I/O possible";
2926 sys_siglist
[SIGIOINT
] = "I/O intervention required";
2929 sys_siglist
[SIGIOT
] = "IOT trap";
2932 sys_siglist
[SIGKILL
] = "Killed";
2935 sys_siglist
[SIGLOST
] = "Resource lost";
2938 sys_siglist
[SIGLWP
] = "SIGLWP";
2941 sys_siglist
[SIGMSG
] = "Monitor mode data available";
2944 sys_siglist
[SIGWIND
] = "SIGPHONE";
2947 sys_siglist
[SIGPIPE
] = "Broken pipe";
2950 sys_siglist
[SIGPOLL
] = "Pollable event occurred";
2953 sys_siglist
[SIGPROF
] = "Profiling timer expired";
2956 sys_siglist
[SIGPTY
] = "PTY I/O interrupt";
2959 sys_siglist
[SIGPWR
] = "Power-fail restart";
2962 sys_siglist
[SIGQUIT
] = "Quit";
2965 sys_siglist
[SIGRETRACT
] = "Need to relinguish monitor mode";
2968 sys_siglist
[SIGSAK
] = "Secure attention";
2971 sys_siglist
[SIGSEGV
] = "Segmentation violation";
2974 sys_siglist
[SIGSOUND
] = "Sound completed";
2977 sys_siglist
[SIGSTOP
] = "Stopped (signal)";
2980 sys_siglist
[SIGSTP
] = "Stopped (user)";
2983 sys_siglist
[SIGSYS
] = "Bad argument to system call";
2986 sys_siglist
[SIGTERM
] = "Terminated";
2989 sys_siglist
[SIGTHAW
] = "SIGTHAW";
2992 sys_siglist
[SIGTRAP
] = "Trace/breakpoint trap";
2995 sys_siglist
[SIGTSTP
] = "Stopped (user)";
2998 sys_siglist
[SIGTTIN
] = "Stopped (tty input)";
3001 sys_siglist
[SIGTTOU
] = "Stopped (tty output)";
3004 sys_siglist
[SIGURG
] = "Urgent I/O condition";
3007 sys_siglist
[SIGUSR1
] = "User defined signal 1";
3010 sys_siglist
[SIGUSR2
] = "User defined signal 2";
3013 sys_siglist
[SIGVTALRM
] = "Virtual timer expired";
3016 sys_siglist
[SIGWAITING
] = "Process's LWPs are blocked";
3019 sys_siglist
[SIGWINCH
] = "Window size changed";
3022 sys_siglist
[SIGWIND
] = "SIGWIND";
3025 sys_siglist
[SIGXCPU
] = "CPU time limit exceeded";
3028 sys_siglist
[SIGXFSZ
] = "File size limit exceeded";
3031 #endif /* !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED */
3040 /* Figure out how many bits the system's random number generator uses.
3041 `random' and `lrand48' are assumed to return 31 usable bits.
3042 BSD `rand' returns a 31 bit value but the low order bits are unusable;
3043 so we'll shift it and treat it like the 15-bit USG `rand'. */
3047 # define RAND_BITS 31
3048 # else /* !HAVE_RANDOM */
3049 # ifdef HAVE_LRAND48
3050 # define RAND_BITS 31
3051 # define random lrand48
3052 # else /* !HAVE_LRAND48 */
3053 # define RAND_BITS 15
3054 # if RAND_MAX == 32767
3055 # define random rand
3056 # else /* RAND_MAX != 32767 */
3057 # if RAND_MAX == 2147483647
3058 # define random() (rand () >> 16)
3059 # else /* RAND_MAX != 2147483647 */
3061 # define random rand
3063 # define random() (rand () >> 16)
3065 # endif /* RAND_MAX != 2147483647 */
3066 # endif /* RAND_MAX != 32767 */
3067 # endif /* !HAVE_LRAND48 */
3068 # endif /* !HAVE_RANDOM */
3069 #endif /* !RAND_BITS */
3076 srandom ((unsigned int)arg
);
3078 # ifdef HAVE_LRAND48
3081 srand ((unsigned int)arg
);
3087 * Build a full Emacs-sized word out of whatever we've got.
3088 * This suffices even for a 64-bit architecture with a 15-bit rand.
3093 long val
= random ();
3094 #if VALBITS > RAND_BITS
3095 val
= (val
<< RAND_BITS
) ^ random ();
3096 #if VALBITS > 2*RAND_BITS
3097 val
= (val
<< RAND_BITS
) ^ random ();
3098 #if VALBITS > 3*RAND_BITS
3099 val
= (val
<< RAND_BITS
) ^ random ();
3100 #if VALBITS > 4*RAND_BITS
3101 val
= (val
<< RAND_BITS
) ^ random ();
3102 #endif /* need at least 5 */
3103 #endif /* need at least 4 */
3104 #endif /* need at least 3 */
3105 #endif /* need at least 2 */
3106 return val
& ((1L << VALBITS
) - 1);
3109 #ifdef WRONG_NAME_INSQUE
3122 /* If any place else asks for the TERM variable,
3123 allow it to be overridden with the EMACS_TERM variable
3124 before attempting to translate the logical name TERM. As a last
3125 resort, ask for VAX C's special idea of the TERM variable. */
3132 static char buf
[256];
3133 static struct dsc$descriptor_s equiv
3134 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
3135 static struct dsc$descriptor_s d_name
3136 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
3139 if (!strcmp (name
, "TERM"))
3141 val
= (char *) getenv ("EMACS_TERM");
3146 d_name
.dsc$w_length
= strlen (name
);
3147 d_name
.dsc$a_pointer
= name
;
3148 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
3150 char *str
= (char *) xmalloc (eqlen
+ 1);
3151 bcopy (buf
, str
, eqlen
);
3153 /* This is a storage leak, but a pain to fix. With luck,
3154 no one will ever notice. */
3157 return (char *) getenv (name
);
3162 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3163 to force a call on the debugger from within the image. */
3168 LIB$
SIGNAL (SS$_DEBUG
);
3174 #ifdef LINK_CRTL_SHARE
3175 #ifdef SHARABLE_LIB_BUG
3176 /* Variables declared noshare and initialized in sharable libraries
3177 cannot be shared. The VMS linker incorrectly forces you to use a private
3178 version which is uninitialized... If not for this "feature", we
3179 could use the C library definition of sys_nerr and sys_errlist. */
3181 char *sys_errlist
[] =
3185 "no such file or directory",
3187 "interrupted system call",
3189 "no such device or address",
3190 "argument list too long",
3191 "exec format error",
3194 "no more processes",
3195 "not enough memory",
3196 "permission denied",
3198 "block device required",
3199 "mount devices busy",
3201 "cross-device link",
3206 "file table overflow",
3207 "too many open files",
3211 "no space left on device",
3213 "read-only file system",
3219 "vax/vms specific error code nontranslatable error"
3221 #endif /* SHARABLE_LIB_BUG */
3222 #endif /* LINK_CRTL_SHARE */
3225 #ifndef HAVE_STRERROR
3231 extern char *sys_errlist
[];
3232 extern int sys_nerr
;
3234 if (errnum
>= 0 && errnum
< sys_nerr
)
3235 return sys_errlist
[errnum
];
3236 return (char *) "Unknown error";
3238 #endif /* not WINDOWSNT */
3239 #endif /* ! HAVE_STRERROR */
3242 emacs_open (path
, oflag
, mode
)
3246 register int rtnval
;
3249 if (oflag
& O_CREAT
)
3250 return creat (path
, mode
);
3253 while ((rtnval
= open (path
, oflag
, mode
)) == -1
3254 && (errno
== EINTR
));
3263 register int rtnval
;
3265 while ((rtnval
= close (fd
)) == -1
3266 && (errno
== EINTR
))
3269 /* If close is interrupted SunOS 4.1 may or may not have closed the
3270 file descriptor. If it did the second close will fail with
3271 errno = EBADF. That means we have succeeded. */
3272 if (rtnval
== -1 && did_retry
&& errno
== EBADF
)
3279 emacs_read (fildes
, buf
, nbyte
)
3284 register int rtnval
;
3286 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
3287 && (errno
== EINTR
));
3292 emacs_write (fildes
, buf
, nbyte
)
3297 register int rtnval
, bytes_written
;
3303 rtnval
= write (fildes
, buf
, nbyte
);
3310 return (bytes_written
? bytes_written
: -1);
3315 bytes_written
+= rtnval
;
3317 return (bytes_written
);
3322 * All of the following are for USG.
3324 * On USG systems the system calls are INTERRUPTIBLE by signals
3325 * that the user program has elected to catch. Thus the system call
3326 * must be retried in these cases. To handle this without massive
3327 * changes in the source code, we remap the standard system call names
3328 * to names for our own functions in sysdep.c that do the system call
3329 * with retries. Actually, for portability reasons, it is good
3330 * programming practice, as this example shows, to limit all actual
3331 * system calls to a single occurrence in the source. Sure, this
3332 * adds an extra level of function call overhead but it is almost
3333 * always negligible. Fred Fish, Unisoft Systems Inc.
3337 * Warning, this function may not duplicate 4.2 action properly
3338 * under error conditions.
3342 /* In 4.1, param.h fails to define this. */
3343 #define MAXPATHLEN 1024
3352 char *npath
, *spath
;
3353 extern char *getcwd ();
3355 BLOCK_INPUT
; /* getcwd uses malloc */
3356 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
3359 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3360 up to first slash. Should be harmless on other systems. */
3361 while (*npath
&& *npath
!= '/')
3363 strcpy (pathname
, npath
);
3364 free (spath
); /* getcwd uses malloc */
3369 #endif /* HAVE_GETWD */
3372 * Emulate rename using unlink/link. Note that this is
3373 * only partially correct. Also, doesn't enforce restriction
3374 * that files be of same type (regular->regular, dir->dir, etc).
3383 if (access (from
, 0) == 0)
3386 if (link (from
, to
) == 0)
3387 if (unlink (from
) == 0)
3399 /* HPUX curses library references perror, but as far as we know
3400 it won't be called. Anyway this definition will do for now. */
3406 #endif /* not HAVE_PERROR */
3412 * Emulate BSD dup2. First close newd if it already exists.
3413 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3414 * until we are, then close the unsuccessful ones.
3421 register int fd
, ret
;
3426 return fcntl (oldd
, F_DUPFD
, newd
);
3433 ret
= dup2 (old
,new);
3439 #endif /* not HAVE_DUP2 */
3442 * Gettimeofday. Simulate as much as possible. Only accurate
3443 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3444 * Only needed when subprocesses are defined.
3449 #ifndef HAVE_GETTIMEOFDAY
3454 gettimeofday (tp
, tzp
)
3456 struct timezone
*tzp
;
3458 extern long time ();
3460 tp
->tv_sec
= time ((long *)0);
3463 tzp
->tz_minuteswest
= -1;
3470 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3473 * This function will go away as soon as all the stubs fixed. (fnf)
3480 printf ("%s not yet implemented\r\n", badfunc
);
3487 /* Directory routines for systems that don't have them. */
3489 #ifdef SYSV_SYSTEM_DIR
3493 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3497 register DIR *dirp
; /* stream from opendir */
3501 rtnval
= emacs_close (dirp
->dd_fd
);
3503 /* Some systems (like Solaris) allocate the buffer and the DIR all
3504 in one block. Why in the world are we freeing this ourselves
3506 #if ! (defined (sun) && defined (USG5_4))
3507 xfree ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
3509 xfree ((char *) dirp
);
3513 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3514 #endif /* SYSV_SYSTEM_DIR */
3516 #ifdef NONSYSTEM_DIR_LIBRARY
3520 char *filename
; /* name of directory */
3522 register DIR *dirp
; /* -> malloc'ed storage */
3523 register int fd
; /* file descriptor for read */
3524 struct stat sbuf
; /* result of fstat */
3526 fd
= emacs_open (filename
, O_RDONLY
, 0);
3531 if (fstat (fd
, &sbuf
) < 0
3532 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
3533 || (dirp
= (DIR *) xmalloc (sizeof (DIR))) == 0)
3537 return 0; /* bad luck today */
3542 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
3549 register DIR *dirp
; /* stream from opendir */
3551 emacs_close (dirp
->dd_fd
);
3552 xfree ((char *) dirp
);
3560 ino_t od_ino
; /* inode */
3561 char od_name
[DIRSIZ
]; /* filename */
3563 #endif /* not VMS */
3565 struct direct dir_static
; /* simulated directory contents */
3570 register DIR *dirp
; /* stream from opendir */
3573 register struct olddir
*dp
; /* -> directory data */
3575 register struct dir$_name
*dp
; /* -> directory data */
3576 register struct dir$_version
*dv
; /* -> version data */
3581 if (dirp
->dd_loc
>= dirp
->dd_size
)
3582 dirp
->dd_loc
= dirp
->dd_size
= 0;
3584 if (dirp
->dd_size
== 0 /* refill buffer */
3585 && (dirp
->dd_size
= emacs_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3589 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
3590 dirp
->dd_loc
+= sizeof (struct olddir
);
3592 if (dp
->od_ino
!= 0) /* not deleted entry */
3594 dir_static
.d_ino
= dp
->od_ino
;
3595 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
3596 dir_static
.d_name
[DIRSIZ
] = '\0';
3597 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3598 dir_static
.d_reclen
= sizeof (struct direct
)
3600 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3601 return &dir_static
; /* -> simulated structure */
3604 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3605 if (dirp
->dd_loc
== 0)
3606 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
3607 : dp
->dir$b_namecount
;
3608 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
3609 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3610 dir_static
.d_namlen
= dp
->dir$b_namecount
;
3611 dir_static
.d_reclen
= sizeof (struct direct
)
3613 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3614 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3615 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
3616 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
3623 /* readdirver is just like readdir except it returns all versions of a file
3624 as separate entries. */
3629 register DIR *dirp
; /* stream from opendir */
3631 register struct dir$_name
*dp
; /* -> directory data */
3632 register struct dir$_version
*dv
; /* -> version data */
3634 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
3635 dirp
->dd_loc
= dirp
->dd_size
= 0;
3637 if (dirp
->dd_size
== 0 /* refill buffer */
3638 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3641 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3642 if (dirp
->dd_loc
== 0)
3643 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
3644 : dp
->dir$b_namecount
;
3645 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
3646 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3647 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
3648 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3649 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3650 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
3651 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3652 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
3658 #endif /* NONSYSTEM_DIR_LIBRARY */
3662 set_file_times (filename
, atime
, mtime
)
3664 EMACS_TIME atime
, mtime
;
3667 struct timeval tv
[2];
3670 return utimes (filename
, tv
);
3671 #else /* not HAVE_UTIMES */
3673 utb
.actime
= EMACS_SECS (atime
);
3674 utb
.modtime
= EMACS_SECS (mtime
);
3675 return utime (filename
, &utb
);
3676 #endif /* not HAVE_UTIMES */
3679 /* mkdir and rmdir functions, for systems which don't have them. */
3683 * Written by Robert Rother, Mariah Corporation, August 1985.
3685 * If you want it, it's yours. All I ask in return is that if you
3686 * figure out how to do this in a Bourne Shell script you send me
3688 * sdcsvax!rmr or rmr@uscd
3690 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3691 * subroutine. 11Mar86; hoptoad!gnu
3693 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3694 * subroutine didn't return EEXIST. It does now.
3700 #ifdef MKDIR_PROTOTYPE
3704 mkdir (dpath
, dmode
)
3709 int cpid
, status
, fd
;
3710 struct stat statbuf
;
3712 if (stat (dpath
, &statbuf
) == 0)
3714 errno
= EEXIST
; /* Stat worked, so it already exists */
3718 /* If stat fails for a reason other than non-existence, return error */
3719 if (errno
!= ENOENT
)
3722 synch_process_alive
= 1;
3723 switch (cpid
= fork ())
3726 case -1: /* Error in fork */
3727 return (-1); /* Errno is set already */
3729 case 0: /* Child process */
3731 * Cheap hack to set mode of new directory. Since this
3732 * child process is going away anyway, we zap its umask.
3733 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3734 * directory. Does anybody care?
3736 status
= umask (0); /* Get current umask */
3737 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
3738 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3745 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
3746 _exit (-1); /* Can't exec /bin/mkdir */
3748 default: /* Parent process */
3749 wait_for_termination (cpid
);
3752 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3754 errno
= EIO
; /* We don't know why, but */
3755 return -1; /* /bin/mkdir failed */
3760 #endif /* not HAVE_MKDIR */
3767 int cpid
, status
, fd
;
3768 struct stat statbuf
;
3770 if (stat (dpath
, &statbuf
) != 0)
3772 /* Stat just set errno. We don't have to */
3776 synch_process_alive
= 1;
3777 switch (cpid
= fork ())
3780 case -1: /* Error in fork */
3781 return (-1); /* Errno is set already */
3783 case 0: /* Child process */
3784 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3791 execl ("/bin/rmdir", "rmdir", dpath
, (char *) 0);
3792 _exit (-1); /* Can't exec /bin/rmdir */
3794 default: /* Parent process */
3795 wait_for_termination (cpid
);
3798 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3800 errno
= EIO
; /* We don't know why, but */
3801 return -1; /* /bin/rmdir failed */
3806 #endif /* !HAVE_RMDIR */
3810 /* Functions for VMS */
3812 #include "vms-pwd.h"
3817 /* Return as a string the VMS error string pertaining to STATUS.
3818 Reuses the same static buffer each time it is called. */
3822 int status
; /* VMS status code */
3826 static char buf
[257];
3828 bufadr
[0] = sizeof buf
- 1;
3829 bufadr
[1] = (int) buf
;
3830 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
3831 return "untranslatable VMS error status";
3839 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3840 * not work correctly. (It also doesn't work well in version 2.3.)
3845 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3846 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3850 unsigned short s_buflen
;
3851 unsigned short s_code
;
3853 unsigned short *s_retlenadr
;
3857 #define buflen s.s_buflen
3858 #define code s.s_code
3859 #define bufadr s.s_bufadr
3860 #define retlenadr s.s_retlenadr
3862 #define R_OK 4 /* test for read permission */
3863 #define W_OK 2 /* test for write permission */
3864 #define X_OK 1 /* test for execute (search) permission */
3865 #define F_OK 0 /* test for presence of file */
3868 sys_access (path
, mode
)
3872 static char *user
= NULL
;
3875 /* translate possible directory spec into .DIR file name, so brain-dead
3876 * access can treat the directory like a file. */
3877 if (directory_file_name (path
, dir_fn
))
3881 return access (path
, mode
);
3882 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
3888 unsigned short int dummy
;
3890 static int constant
= ACL$C_FILE
;
3891 DESCRIPTOR (path_desc
, path
);
3892 DESCRIPTOR (user_desc
, user
);
3896 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
3899 acces
|= CHP$M_READ
;
3901 acces
|= CHP$M_WRITE
;
3902 itemlst
[0].buflen
= sizeof (int);
3903 itemlst
[0].code
= CHP$_FLAGS
;
3904 itemlst
[0].bufadr
= (char *) &flags
;
3905 itemlst
[0].retlenadr
= &dummy
;
3906 itemlst
[1].buflen
= sizeof (int);
3907 itemlst
[1].code
= CHP$_ACCESS
;
3908 itemlst
[1].bufadr
= (char *) &acces
;
3909 itemlst
[1].retlenadr
= &dummy
;
3910 itemlst
[2].end
= CHP$_END
;
3911 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
3912 return stat
== SS$_NORMAL
? 0 : -1;
3916 #else /* not VMS4_4 */
3919 #define ACE$M_WRITE 2
3920 #define ACE$C_KEYID 1
3922 static unsigned short memid
, grpid
;
3923 static unsigned int uic
;
3925 /* Called from init_sys_modes, so it happens not very often
3926 but at least each time Emacs is loaded. */
3928 sys_access_reinit ()
3934 sys_access (filename
, type
)
3940 int status
, size
, i
, typecode
, acl_controlled
;
3941 unsigned int *aclptr
, *aclend
, aclbuf
[60];
3942 union prvdef prvmask
;
3944 /* Get UIC and GRP values for protection checking. */
3947 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
3950 memid
= uic
& 0xFFFF;
3954 if (type
!= 2) /* not checking write access */
3955 return access (filename
, type
);
3957 /* Check write protection. */
3959 #define CHECKPRIV(bit) (prvmask.bit)
3960 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3962 /* Find privilege bits */
3963 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
3965 error ("Unable to find privileges: %s", vmserrstr (status
));
3966 if (CHECKPRIV (PRV$V_BYPASS
))
3967 return 0; /* BYPASS enabled */
3969 fab
.fab$b_fac
= FAB$M_GET
;
3970 fab
.fab$l_fna
= filename
;
3971 fab
.fab$b_fns
= strlen (filename
);
3972 fab
.fab$l_xab
= &xab
;
3973 xab
= cc$rms_xabpro
;
3974 xab
.xab$l_aclbuf
= aclbuf
;
3975 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
3976 status
= SYS$
OPEN (&fab
, 0, 0);
3979 SYS$
CLOSE (&fab
, 0, 0);
3980 /* Check system access */
3981 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITABLE (XAB$V_SYS
))
3983 /* Check ACL entries, if any */
3985 if (xab
.xab$w_acllen
> 0)
3988 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
3989 while (*aclptr
&& aclptr
< aclend
)
3991 size
= (*aclptr
& 0xff) / 4;
3992 typecode
= (*aclptr
>> 8) & 0xff;
3993 if (typecode
== ACE$C_KEYID
)
3994 for (i
= size
- 1; i
> 1; i
--)
3995 if (aclptr
[i
] == uic
)
3998 if (aclptr
[1] & ACE$M_WRITE
)
3999 return 0; /* Write access through ACL */
4001 aclptr
= &aclptr
[size
];
4003 if (acl_controlled
) /* ACL specified, prohibits write access */
4006 /* No ACL entries specified, check normal protection */
4007 if (WRITABLE (XAB$V_WLD
)) /* World writable */
4009 if (WRITABLE (XAB$V_GRP
) &&
4010 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
4011 return 0; /* Group writable */
4012 if (WRITABLE (XAB$V_OWN
) &&
4013 (xab
.xab$l_uic
& 0xFFFF) == memid
)
4014 return 0; /* Owner writable */
4016 return -1; /* Not writable */
4018 #endif /* not VMS4_4 */
4021 static char vtbuf
[NAM$C_MAXRSS
+1];
4023 /* translate a vms file spec to a unix path */
4025 sys_translate_vms (vfile
)
4036 /* leading device or logical name is a root directory */
4037 if (p
= strchr (vfile
, ':'))
4046 if (*p
== '[' || *p
== '<')
4048 while (*++vfile
!= *p
+ 2)
4052 if (vfile
[-1] == *p
)
4075 static char utbuf
[NAM$C_MAXRSS
+1];
4077 /* translate a unix path to a VMS file spec */
4079 sys_translate_unix (ufile
)
4102 if (index (&ufile
[1], '/'))
4109 if (index (&ufile
[1], '/'))
4116 if (strncmp (ufile
, "./", 2) == 0)
4123 ufile
++; /* skip the dot */
4124 if (index (&ufile
[1], '/'))
4129 else if (strncmp (ufile
, "../", 3) == 0)
4137 ufile
+= 2; /* skip the dots */
4138 if (index (&ufile
[1], '/'))
4163 extern char *getcwd ();
4165 #define MAXPATHLEN 1024
4167 ptr
= xmalloc (MAXPATHLEN
);
4168 val
= getcwd (ptr
, MAXPATHLEN
);
4174 strcpy (pathname
, ptr
);
4183 long item_code
= JPI$_OWNER
;
4184 unsigned long parent_id
;
4187 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
4190 vaxc$errno
= status
;
4200 return (getgid () << 16) | getuid ();
4205 sys_read (fildes
, buf
, nbyte
)
4210 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
4215 sys_write (fildes
, buf
, nbyte
)
4220 register int nwrote
, rtnval
= 0;
4222 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
4228 return rtnval
? rtnval
: -1;
4229 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
4230 return rtnval
? rtnval
: -1;
4231 return (rtnval
+ nwrote
);
4236 * VAX/VMS VAX C RTL really loses. It insists that records
4237 * end with a newline (carriage return) character, and if they
4238 * don't it adds one (nice of it isn't it!)
4240 * Thus we do this stupidity below.
4245 sys_write (fildes
, buf
, nbytes
)
4248 unsigned int nbytes
;
4255 fstat (fildes
, &st
);
4261 /* Handle fixed-length files with carriage control. */
4262 if (st
.st_fab_rfm
== FAB$C_FIX
4263 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
4265 len
= st
.st_fab_mrs
;
4266 retval
= write (fildes
, p
, min (len
, nbytes
));
4269 retval
++; /* This skips the implied carriage control */
4273 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4274 while (*e
!= '\n' && e
> p
) e
--;
4275 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
4276 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4278 retval
= write (fildes
, p
, len
);
4289 /* Create file NEW copying its attributes from file OLD. If
4290 OLD is 0 or does not exist, create based on the value of
4293 /* Protection value the file should ultimately have.
4294 Set by create_copy_attrs, and use by rename_sansversions. */
4295 static unsigned short int fab_final_pro
;
4298 creat_copy_attrs (old
, new)
4301 struct FAB fab
= cc$rms_fab
;
4302 struct XABPRO xabpro
;
4303 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
4304 extern int vms_stmlf_recfm
;
4308 fab
.fab$b_fac
= FAB$M_GET
;
4309 fab
.fab$l_fna
= old
;
4310 fab
.fab$b_fns
= strlen (old
);
4311 fab
.fab$l_xab
= (char *) &xabpro
;
4312 xabpro
= cc$rms_xabpro
;
4313 xabpro
.xab$l_aclbuf
= aclbuf
;
4314 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
4315 /* Call $OPEN to fill in the fab & xabpro fields. */
4316 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4318 SYS$
CLOSE (&fab
, 0, 0);
4319 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
4320 if (xabpro
.xab$w_acllen
> 0)
4322 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
4323 /* If the acl buffer was too short, redo open with longer one.
4324 Wouldn't need to do this if there were some system imposed
4325 limit on the size of an ACL, but I can't find any such. */
4327 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
4328 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
4329 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4330 SYS$
CLOSE (&fab
, 0, 0);
4336 xabpro
.xab$l_aclbuf
= 0;
4341 fab
.fab$l_fna
= new;
4342 fab
.fab$b_fns
= strlen (new);
4346 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
4347 fab
.fab$b_rat
= FAB$M_CR
;
4350 /* Set the file protections such that we will be able to manipulate
4351 this file. Once we are done writing and renaming it, we will set
4352 the protections back. */
4354 fab_final_pro
= xabpro
.xab$w_pro
;
4356 SYS$
SETDFPROT (0, &fab_final_pro
);
4357 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
4359 /* Create the new file with either default attrs or attrs copied
4361 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
4363 SYS$
CLOSE (&fab
, 0, 0);
4364 /* As this is a "replacement" for creat, return a file descriptor
4365 opened for writing. */
4366 return open (new, O_WRONLY
);
4371 #include <varargs.h>
4374 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4379 sys_creat (va_alist
)
4382 va_list list_incrementer
;
4385 int rfd
; /* related file descriptor */
4386 int fd
; /* Our new file descriptor */
4393 extern int vms_stmlf_recfm
;
4396 va_start (list_incrementer
);
4397 name
= va_arg (list_incrementer
, char *);
4398 mode
= va_arg (list_incrementer
, int);
4400 rfd
= va_arg (list_incrementer
, int);
4401 va_end (list_incrementer
);
4404 /* Use information from the related file descriptor to set record
4405 format of the newly created file. */
4406 fstat (rfd
, &st_buf
);
4407 switch (st_buf
.st_fab_rfm
)
4410 strcpy (rfm
, "rfm = fix");
4411 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
4412 strcpy (rat
, "rat = ");
4413 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4415 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4416 strcat (rat
, "ftn");
4417 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4418 strcat (rat
, "prn");
4419 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4420 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4421 strcat (rat
, ", blk");
4423 strcat (rat
, "blk");
4424 return creat (name
, 0, rfm
, rat
, mrs
);
4427 strcpy (rfm
, "rfm = vfc");
4428 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
4429 strcpy (rat
, "rat = ");
4430 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4432 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4433 strcat (rat
, "ftn");
4434 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4435 strcat (rat
, "prn");
4436 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4437 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4438 strcat (rat
, ", blk");
4440 strcat (rat
, "blk");
4441 return creat (name
, 0, rfm
, rat
, fsz
);
4444 strcpy (rfm
, "rfm = stm");
4448 strcpy (rfm
, "rfm = stmcr");
4452 strcpy (rfm
, "rfm = stmlf");
4456 strcpy (rfm
, "rfm = udf");
4460 strcpy (rfm
, "rfm = var");
4463 strcpy (rat
, "rat = ");
4464 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4466 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4467 strcat (rat
, "ftn");
4468 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4469 strcat (rat
, "prn");
4470 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4471 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4472 strcat (rat
, ", blk");
4474 strcat (rat
, "blk");
4478 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
4479 strcpy (rat
, "rat=cr");
4481 /* Until the VAX C RTL fixes the many bugs with modes, always use
4482 mode 0 to get the user's default protection. */
4483 fd
= creat (name
, 0, rfm
, rat
);
4484 if (fd
< 0 && errno
== EEXIST
)
4486 if (unlink (name
) < 0)
4487 report_file_error ("delete", build_string (name
));
4488 fd
= creat (name
, 0, rfm
, rat
);
4494 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4496 sys_fwrite (ptr
, size
, num
, fp
)
4497 register char * ptr
;
4500 register int tot
= num
* size
;
4508 * The VMS C library routine creat actually creates a new version of an
4509 * existing file rather than truncating the old version. There are times
4510 * when this is not the desired behavior, for instance, when writing an
4511 * auto save file (you only want one version), or when you don't have
4512 * write permission in the directory containing the file (but the file
4513 * itself is writable). Hence this routine, which is equivalent to
4514 * "close (creat (fn, 0));" on Unix if fn already exists.
4520 struct FAB xfab
= cc$rms_fab
;
4521 struct RAB xrab
= cc$rms_rab
;
4524 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
4525 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
4526 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
4527 xfab
.fab$l_fna
= fn
;
4528 xfab
.fab$b_fns
= strlen (fn
);
4529 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
4531 xrab
.rab$l_fab
= &xfab
;
4533 /* This gibberish opens the file, positions to the first record, and
4534 deletes all records from there until the end of file. */
4535 if ((SYS$
OPEN (&xfab
) & 01) == 01)
4537 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
4538 (SYS$
FIND (&xrab
) & 01) == 01 &&
4539 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
4550 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4551 SYSPRV or a readable SYSUAF.DAT. */
4557 * Routine to read the VMS User Authorization File and return
4558 * a specific user's record.
4561 static struct UAF retuaf
;
4564 get_uaf_name (uname
)
4571 uaf_fab
= cc$rms_fab
;
4572 uaf_rab
= cc$rms_rab
;
4573 /* initialize fab fields */
4574 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4575 uaf_fab
.fab$b_fns
= 21;
4576 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4577 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4578 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4579 /* initialize rab fields */
4580 uaf_rab
.rab$l_fab
= &uaf_fab
;
4581 /* open the User Authorization File */
4582 status
= SYS$
OPEN (&uaf_fab
);
4586 vaxc$errno
= status
;
4589 status
= SYS$
CONNECT (&uaf_rab
);
4593 vaxc$errno
= status
;
4596 /* read the requested record - index is in uname */
4597 uaf_rab
.rab$l_kbf
= uname
;
4598 uaf_rab
.rab$b_ksz
= strlen (uname
);
4599 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4600 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4601 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4602 status
= SYS$
GET (&uaf_rab
);
4606 vaxc$errno
= status
;
4609 /* close the User Authorization File */
4610 status
= SYS$
DISCONNECT (&uaf_rab
);
4614 vaxc$errno
= status
;
4617 status
= SYS$
CLOSE (&uaf_fab
);
4621 vaxc$errno
= status
;
4635 uaf_fab
= cc$rms_fab
;
4636 uaf_rab
= cc$rms_rab
;
4637 /* initialize fab fields */
4638 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4639 uaf_fab
.fab$b_fns
= 21;
4640 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4641 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4642 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4643 /* initialize rab fields */
4644 uaf_rab
.rab$l_fab
= &uaf_fab
;
4645 /* open the User Authorization File */
4646 status
= SYS$
OPEN (&uaf_fab
);
4650 vaxc$errno
= status
;
4653 status
= SYS$
CONNECT (&uaf_rab
);
4657 vaxc$errno
= status
;
4660 /* read the requested record - index is in uic */
4661 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
4662 uaf_rab
.rab$l_kbf
= (char *) &uic
;
4663 uaf_rab
.rab$b_ksz
= sizeof uic
;
4664 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4665 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4666 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4667 status
= SYS$
GET (&uaf_rab
);
4671 vaxc$errno
= status
;
4674 /* close the User Authorization File */
4675 status
= SYS$
DISCONNECT (&uaf_rab
);
4679 vaxc$errno
= status
;
4682 status
= SYS$
CLOSE (&uaf_fab
);
4686 vaxc$errno
= status
;
4692 static struct passwd retpw
;
4700 /* copy these out first because if the username is 32 chars, the next
4701 section will overwrite the first byte of the UIC */
4702 retpw
.pw_uid
= up
->uaf$w_mem
;
4703 retpw
.pw_gid
= up
->uaf$w_grp
;
4705 /* I suppose this is not the best style, to possibly overwrite one
4706 byte beyond the end of the field, but what the heck... */
4707 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
4708 while (ptr
[-1] == ' ')
4711 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
4713 /* the rest of these are counted ascii strings */
4714 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
4715 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
4716 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
4717 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
4718 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
4719 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
4720 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
4721 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
4725 #else /* not READ_SYSUAF */
4726 static struct passwd retpw
;
4727 #endif /* not READ_SYSUAF */
4738 unsigned char * full
;
4739 #endif /* READ_SYSUAF */
4744 if ('a' <= *ptr
&& *ptr
<= 'z')
4749 if (!(up
= get_uaf_name (name
)))
4751 return cnv_uaf_pw (up
);
4753 if (strcmp (name
, getenv ("USER")) == 0)
4755 retpw
.pw_uid
= getuid ();
4756 retpw
.pw_gid
= getgid ();
4757 strcpy (retpw
.pw_name
, name
);
4758 if (full
= egetenv ("FULLNAME"))
4759 strcpy (retpw
.pw_gecos
, full
);
4761 *retpw
.pw_gecos
= '\0';
4762 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
4763 *retpw
.pw_shell
= '\0';
4768 #endif /* not READ_SYSUAF */
4778 if (!(up
= get_uaf_uic (uid
)))
4780 return cnv_uaf_pw (up
);
4782 if (uid
== sys_getuid ())
4783 return getpwnam (egetenv ("USER"));
4786 #endif /* not READ_SYSUAF */
4789 /* return total address space available to the current process. This is
4790 the sum of the current p0 size, p1 size and free page table entries
4796 unsigned long free_pages
;
4797 unsigned long frep0va
;
4798 unsigned long frep1va
;
4801 item_code
= JPI$_FREPTECNT
;
4802 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
4805 vaxc$errno
= status
;
4810 item_code
= JPI$_FREP0VA
;
4811 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
4814 vaxc$errno
= status
;
4817 item_code
= JPI$_FREP1VA
;
4818 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
4821 vaxc$errno
= status
;
4825 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
4829 define_logical_name (varname
, string
)
4833 struct dsc$descriptor_s strdsc
=
4834 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
4835 struct dsc$descriptor_s envdsc
=
4836 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4837 struct dsc$descriptor_s lnmdsc
=
4838 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4840 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
4844 delete_logical_name (varname
)
4847 struct dsc$descriptor_s envdsc
=
4848 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4849 struct dsc$descriptor_s lnmdsc
=
4850 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4852 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
4870 error ("execvp system call not implemented");
4879 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
4880 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
4881 char from_esn
[NAM$C_MAXRSS
];
4882 char to_esn
[NAM$C_MAXRSS
];
4884 from_fab
.fab$l_fna
= from
;
4885 from_fab
.fab$b_fns
= strlen (from
);
4886 from_fab
.fab$l_nam
= &from_nam
;
4887 from_fab
.fab$l_fop
= FAB$M_NAM
;
4889 from_nam
.nam$l_esa
= from_esn
;
4890 from_nam
.nam$b_ess
= sizeof from_esn
;
4892 to_fab
.fab$l_fna
= to
;
4893 to_fab
.fab$b_fns
= strlen (to
);
4894 to_fab
.fab$l_nam
= &to_nam
;
4895 to_fab
.fab$l_fop
= FAB$M_NAM
;
4897 to_nam
.nam$l_esa
= to_esn
;
4898 to_nam
.nam$b_ess
= sizeof to_esn
;
4900 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
4906 if (status
== RMS$_DEV
)
4910 vaxc$errno
= status
;
4915 /* This function renames a file like `rename', but it strips
4916 the version number from the "to" filename, such that the "to" file is
4917 will always be a new version. It also sets the file protection once it is
4918 finished. The protection that we will use is stored in fab_final_pro,
4919 and was set when we did a creat_copy_attrs to create the file that we
4922 We could use the chmod function, but Eunichs uses 3 bits per user category
4923 to describe the protection, and VMS uses 4 (write and delete are separate
4924 bits). To maintain portability, the VMS implementation of `chmod' wires
4925 the W and D bits together. */
4928 static struct fibdef fib
; /* We need this initialized to zero */
4929 char vms_file_written
[NAM$C_MAXRSS
];
4932 rename_sans_version (from
,to
)
4939 struct FAB to_fab
= cc$rms_fab
;
4940 struct NAM to_nam
= cc$rms_nam
;
4941 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
4942 struct dsc$descriptor fib_attr
[2]
4943 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
4944 char to_esn
[NAM$C_MAXRSS
];
4946 $
DESCRIPTOR (disk
,to_esn
);
4948 to_fab
.fab$l_fna
= to
;
4949 to_fab
.fab$b_fns
= strlen (to
);
4950 to_fab
.fab$l_nam
= &to_nam
;
4951 to_fab
.fab$l_fop
= FAB$M_NAM
;
4953 to_nam
.nam$l_esa
= to_esn
;
4954 to_nam
.nam$b_ess
= sizeof to_esn
;
4956 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
4958 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
4959 *(to_nam
.nam$l_ver
) = '\0';
4961 stat
= rename (from
, to_esn
);
4965 strcpy (vms_file_written
, to_esn
);
4967 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
4968 to_fab
.fab$b_fns
= strlen (vms_file_written
);
4970 /* Now set the file protection to the correct value */
4971 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
4973 /* Copy these fields into the fib */
4974 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
4975 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
4976 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
4978 SYS$
CLOSE (&to_fab
, 0, 0);
4980 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
4983 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
4984 0, 0, 0, &fib_attr
, 0);
4987 stat
= SYS$
DASSGN (chan
);
4990 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
5001 unsigned short fid
[3];
5002 char esa
[NAM$C_MAXRSS
];
5005 fab
.fab$l_fop
= FAB$M_OFP
;
5006 fab
.fab$l_fna
= file
;
5007 fab
.fab$b_fns
= strlen (file
);
5008 fab
.fab$l_nam
= &nam
;
5011 nam
.nam$l_esa
= esa
;
5012 nam
.nam$b_ess
= NAM$C_MAXRSS
;
5014 status
= SYS$
PARSE (&fab
);
5015 if ((status
& 1) == 0)
5018 vaxc$errno
= status
;
5021 status
= SYS$
SEARCH (&fab
);
5022 if ((status
& 1) == 0)
5025 vaxc$errno
= status
;
5029 fid
[0] = nam
.nam$w_fid
[0];
5030 fid
[1] = nam
.nam$w_fid
[1];
5031 fid
[2] = nam
.nam$w_fid
[2];
5033 fab
.fab$l_fna
= new;
5034 fab
.fab$b_fns
= strlen (new);
5036 status
= SYS$
PARSE (&fab
);
5037 if ((status
& 1) == 0)
5040 vaxc$errno
= status
;
5044 nam
.nam$w_fid
[0] = fid
[0];
5045 nam
.nam$w_fid
[1] = fid
[1];
5046 nam
.nam$w_fid
[2] = fid
[2];
5048 nam
.nam$l_esa
= nam
.nam$l_name
;
5049 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
5051 status
= SYS$
ENTER (&fab
);
5052 if ((status
& 1) == 0)
5055 vaxc$errno
= status
;
5066 printf ("%s not yet implemented\r\n", badfunc
);
5074 /* Arrange to return a range centered on zero. */
5075 return rand () - (1 << 30);
5087 /* Called from init_sys_modes. */
5093 /* If we're not on an HFT we shouldn't do any of this. We determine
5094 if we are on an HFT by trying to get an HFT error code. If this
5095 call fails, we're not on an HFT. */
5097 if (ioctl (0, HFQERROR
, &junk
) < 0)
5099 #else /* not IBMR2AIX */
5100 if (ioctl (0, HFQEIO
, 0) < 0)
5102 #endif /* not IBMR2AIX */
5104 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5105 as the rubout key's ASCII code. Here this is changed. The bug is that
5106 there's no way to determine the old mapping, so in reset_sys_modes
5107 we need to assume that the normal map had been present. Of course, this
5108 code also doesn't help if on a terminal emulator which doesn't understand
5112 struct hfkeymap keymap
;
5114 buf
.hf_bufp
= (char *)&keymap
;
5115 buf
.hf_buflen
= sizeof (keymap
);
5116 keymap
.hf_nkeys
= 2;
5117 keymap
.hfkey
[0].hf_kpos
= 15;
5118 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5120 keymap
.hfkey
[0].hf_keyidh
= '<';
5121 #else /* not IBMR2AIX */
5122 keymap
.hfkey
[0].hf_page
= '<';
5123 #endif /* not IBMR2AIX */
5124 keymap
.hfkey
[0].hf_char
= 127;
5125 keymap
.hfkey
[1].hf_kpos
= 15;
5126 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5128 keymap
.hfkey
[1].hf_keyidh
= '<';
5129 #else /* not IBMR2AIX */
5130 keymap
.hfkey
[1].hf_page
= '<';
5131 #endif /* not IBMR2AIX */
5132 keymap
.hfkey
[1].hf_char
= 127;
5133 hftctl (0, HFSKBD
, &buf
);
5135 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5137 line_ins_del_ok
= char_ins_del_ok
= 0;
5140 /* Reset the rubout key to backspace. */
5146 struct hfkeymap keymap
;
5150 if (ioctl (0, HFQERROR
, &junk
) < 0)
5152 #else /* not IBMR2AIX */
5153 if (ioctl (0, HFQEIO
, 0) < 0)
5155 #endif /* not IBMR2AIX */
5157 buf
.hf_bufp
= (char *)&keymap
;
5158 buf
.hf_buflen
= sizeof (keymap
);
5159 keymap
.hf_nkeys
= 2;
5160 keymap
.hfkey
[0].hf_kpos
= 15;
5161 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5163 keymap
.hfkey
[0].hf_keyidh
= '<';
5164 #else /* not IBMR2AIX */
5165 keymap
.hfkey
[0].hf_page
= '<';
5166 #endif /* not IBMR2AIX */
5167 keymap
.hfkey
[0].hf_char
= 8;
5168 keymap
.hfkey
[1].hf_kpos
= 15;
5169 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5171 keymap
.hfkey
[1].hf_keyidh
= '<';
5172 #else /* not IBMR2AIX */
5173 keymap
.hfkey
[1].hf_page
= '<';
5174 #endif /* not IBMR2AIX */
5175 keymap
.hfkey
[1].hf_char
= 8;
5176 hftctl (0, HFSKBD
, &buf
);
5183 /* These are included on Sunos 4.1 when we do not use shared libraries.
5184 X11 libraries may refer to these functions but (we hope) do not
5185 actually call them. */
5205 #endif /* USE_DL_STUBS */
5214 register int length
;
5218 long max_str
= 65535;
5220 while (length
> max_str
) {
5221 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5226 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5228 while (length
-- > 0)
5230 #endif /* not VMS */
5233 #endif /* no bzero */
5234 #endif /* BSTRING */
5236 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5239 /* Saying `void' requires a declaration, above, where bcopy is used
5240 and that declaration causes pain for systems where bcopy is a macro. */
5241 bcopy (b1
, b2
, length
)
5244 register int length
;
5247 long max_str
= 65535;
5249 while (length
> max_str
) {
5250 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
5256 (void) LIB$
MOVC3 (&length
, b1
, b2
);
5258 while (length
-- > 0)
5260 #endif /* not VMS */
5262 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5267 bcmp (b1
, b2
, length
) /* This could be a macro! */
5270 register int length
;
5273 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
5274 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
5276 return STR$
COMPARE (&src1
, &src2
);
5278 while (length
-- > 0)
5283 #endif /* not VMS */
5285 #endif /* no bcmp */
5286 #endif /* not BSTRING */
5288 #ifndef HAVE_STRSIGNAL
5295 if (0 <= code
&& code
< NSIG
)
5298 signame
= sys_errlist
[code
];
5300 /* Cast to suppress warning if the table has const char *. */
5301 signame
= (char *) sys_siglist
[code
];
5307 #endif /* HAVE_STRSIGNAL */
5309 /* All the Macintosh stuffs go here */
5314 #include <MacTypes.h>
5315 #include <TextUtils.h>
5316 #include <Folders.h>
5319 #include <sys/stat.h>
5322 #include <sys/param.h>
5324 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5325 that does not begin with a ':' and contains at least one ':'. A Mac
5326 full pathname causes an '/' to be prepended to the Unix pathname.
5327 The algorithm for the rest of the pathname is as follows:
5328 For each segment between two ':',
5329 if it is non-null, copy as is and then add a '/' at the end,
5330 otherwise, insert a "../" into the Unix pathname.
5331 Returns 1 if successful; 0 if fails. */
5334 Mac2UnixPathname (const char *mfn
, char *ufn
, int ufnbuflen
)
5336 const char *p
, *q
, *pe
;
5343 p
= strchr (mfn
, ':');
5344 if (p
!= 0 && p
!= mfn
) /* full pathname */
5351 pe
= mfn
+ strlen (mfn
);
5354 q
= strchr (p
, ':');
5358 { /* two consecutive ':' */
5359 if (strlen (ufn
) + 3 >= ufnbuflen
)
5361 strcat (ufn
, "../");
5365 if (strlen (ufn
) + (q
- p
) + 1 >= ufnbuflen
)
5367 strncat (ufn
, p
, q
- p
);
5374 if (strlen (ufn
) + (pe
- p
) >= ufnbuflen
)
5376 strncat (ufn
, p
, pe
- p
); /* no separator for last one */
5384 extern char *GetTempDirName ();
5386 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5387 above in algorithm. */
5389 Unix2MacPathname (const char *ufn
, char *mfn
, int mfnbuflen
)
5391 const char *p
, *q
, *pe
;
5392 char expandedPathname
[MAXPATHLEN
+1];
5401 /* Check for and handle volume names. Last comparison: strangely
5402 somewhere `/.emacs' is passed. A temporary fix for now. */
5403 if (*p
== '/' && strchr (p
+1, '/') == NULL
&& strcmp (p
, "/.emacs") != 0)
5405 if (strlen (p
) + 1 > mfnbuflen
)
5412 if (strncmp (p
, "~emacs/", 7) == 0)
5413 { /* expand to emacs dir found by InitEmacsPasswdDir */
5414 struct passwd
*pw
= getpwnam ("emacs");
5416 if (strlen (pw
->pw_dir
) + strlen (p
) > MAXPATHLEN
)
5418 strcpy (expandedPathname
, pw
->pw_dir
);
5419 strcat (expandedPathname
, p
);
5420 p
= expandedPathname
;
5421 /* Now p points to the pathname with emacs dir prefix. */
5423 else if (strncmp (p
, "/tmp/", 5) == 0)
5425 char *t
= GetTempDirName ();
5427 if (strlen (t
) + strlen (p
) > MAXPATHLEN
)
5429 strcpy (expandedPathname
, t
);
5430 strcat (expandedPathname
, p
);
5431 p
= expandedPathname
;
5432 /* Now p points to the pathname with emacs dir prefix. */
5434 else if (*p
!= '/') /* relative pathname */
5440 pe
= p
+ strlen (p
);
5443 q
= strchr (p
, '/');
5446 if (q
- p
== 2 && *p
== '.' && *(p
+1) == '.')
5448 if (strlen (mfn
) + 1 >= mfnbuflen
)
5454 if (strlen (mfn
) + (q
- p
) + 1 >= mfnbuflen
)
5456 strncat (mfn
, p
, q
- p
);
5463 if (strlen (mfn
) + (pe
- p
) >= mfnbuflen
)
5465 strncat (mfn
, p
, pe
- p
);
5473 /* The following functions with "sys_" prefix are stubs to Unix
5474 functions that have already been implemented by CW or MPW. The
5475 calls to them in Emacs source course are #define'd to call the sys_
5476 versions by the header files s-mac.h. In these stubs pathnames are
5477 converted between their Unix and Mac forms. */
5478 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5480 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5482 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5484 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5486 /* Define our own stat function for both MrC and CW. The reason for
5487 doing this: "stat" is both the name of a struct and function name:
5488 we can't #define stat to something else to
5489 redirect Emacs's calls to our own version that converts Unix style
5490 filenames to Mac style filename because all sorts of compilation
5491 errors will be generated if stat is #define'd to be something else. */
5494 stat (const char *path
, struct stat
*buf
)
5496 char MacPathname
[MAXPATHLEN
+1];
5499 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5502 c2pstr (MacPathname
);
5503 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5504 cipb
.hFileInfo
.ioVRefNum
= 0;
5505 cipb
.hFileInfo
.ioDirID
= 0;
5506 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5508 errno
= PBGetCatInfo (&cipb
, false);
5509 if (errno
== -43) /* -43: fnfErr defined in Errors.h */
5514 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5515 { /* bit 4 = 1 for directories */
5516 buf
->st_mode
= S_IFDIR
| S_IREAD
| S_IEXEC
;
5517 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5518 buf
->st_mode
|= S_IWRITE
;
5519 buf
->st_ino
= cipb
.dirInfo
.ioDrDirID
;
5520 buf
->st_dev
= cipb
.dirInfo
.ioVRefNum
;
5521 buf
->st_size
= cipb
.dirInfo
.ioDrNmFls
; /* size of dir = number of files and dirs */
5522 buf
->st_atime
= buf
->st_mtime
= cipb
.dirInfo
.ioDrMdDat
- MAC_UNIX_EPOCH_DIFF
;
5523 buf
->st_ctime
= cipb
.dirInfo
.ioDrCrDat
- MAC_UNIX_EPOCH_DIFF
;
5527 buf
->st_mode
= S_IFREG
| S_IREAD
;
5528 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5529 buf
->st_mode
|= S_IWRITE
;
5530 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5531 buf
->st_mode
|= S_IEXEC
;
5532 buf
->st_ino
= cipb
.hFileInfo
.ioDirID
;
5533 buf
->st_dev
= cipb
.hFileInfo
.ioVRefNum
;
5534 buf
->st_size
= cipb
.hFileInfo
.ioFlLgLen
;
5535 buf
->st_atime
= buf
->st_mtime
= cipb
.hFileInfo
.ioFlMdDat
- MAC_UNIX_EPOCH_DIFF
;
5536 buf
->st_ctime
= cipb
.hFileInfo
.ioFlCrDat
- MAC_UNIX_EPOCH_DIFF
;
5539 buf
->st_uid
= getuid ();
5540 buf
->st_gid
= getgid ();
5548 /* CW defines fstat in stat.mac.c while MPW does not provide this
5549 function. Without the information of how to get from a file
5550 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5551 to implement this function. Fortunately, there is only one place
5552 where this function is called in our configuration: in fileio.c,
5553 where only the st_dev and st_ino fields are used to determine
5554 whether two fildes point to different i-nodes to prevent copying
5555 a file onto itself equal. What we have here probably needs
5558 fstat (int fildes
, struct stat
*buf
)
5561 buf
->st_ino
= fildes
;
5562 return 0; /* success */
5565 #endif /* __MRC__ */
5567 /* From Think Reference code example */
5569 mkdir (const char *dirname
, int mode
)
5571 #pragma unused (mode)
5574 char MacPathname
[MAXPATHLEN
+1];
5576 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5579 c2pstr (MacPathname
);
5580 hfpb
.ioNamePtr
= MacPathname
;
5581 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5582 hfpb
.ioDirID
= 0; /*parent is the root */
5584 /* Just return the Mac OSErr code for now. */
5585 errno
= PBDirCreate ((HParmBlkPtr
) &hfpb
, false);
5586 return errno
== noErr
? 0 : -1;
5590 rmdir (const char *dirname
)
5593 char MacPathname
[MAXPATHLEN
+1];
5595 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5598 c2pstr (MacPathname
);
5599 hfpb
.ioNamePtr
= MacPathname
;
5600 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5601 hfpb
.ioDirID
= 0; /*parent is the root */
5603 errno
= PBHDelete ((HParmBlkPtr
) &hfpb
, false);
5604 return errno
== noErr
? 0 : -1;
5609 /* No implementation yet. */
5611 execvp (const char *path
, ...)
5616 #endif /* __MRC__ */
5619 utime (const char *path
, const struct utimbuf
*times
)
5621 char MacPathname
[MAXPATHLEN
+1];
5624 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5627 c2pstr (MacPathname
);
5628 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5629 cipb
.hFileInfo
.ioVRefNum
= 0;
5630 cipb
.hFileInfo
.ioDirID
= 0;
5631 /* Set to 0 to get information about specific dir or file. */
5632 cipb
.hFileInfo
.ioFDirIndex
= 0;
5634 errno
= PBGetCatInfo (&cipb
, false);
5638 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5639 { /* bit 4 = 1 for directories */
5641 cipb
.dirInfo
.ioDrMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5643 GetDateTime (&cipb
.dirInfo
.ioDrMdDat
);
5648 cipb
.hFileInfo
.ioFlMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5650 GetDateTime (&cipb
.hFileInfo
.ioFlMdDat
);
5653 errno
= PBSetCatInfo (&cipb
, false);
5654 return errno
== noErr
? 0 : -1;
5661 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5663 access (const char *path
, int mode
)
5665 char MacPathname
[MAXPATHLEN
+1];
5668 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5671 c2pstr (MacPathname
);
5672 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5673 cipb
.hFileInfo
.ioVRefNum
= 0;
5674 cipb
.hFileInfo
.ioDirID
= 0;
5675 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5677 errno
= PBGetCatInfo (&cipb
, false);
5681 if (mode
== F_OK
) /* got this far, file exists */
5685 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* path refers to a directory */
5689 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5696 return (cipb
.hFileInfo
.ioFlAttrib
& 0x1) ? -1 : 0; /* don't allow if lock bit on */
5701 #define DEV_NULL_FD 0x10000
5705 sys_open (const char *path
, int oflag
)
5707 char MacPathname
[MAXPATHLEN
+1];
5709 if (strcmp (path
, "/dev/null") == 0)
5710 return DEV_NULL_FD
; /* some bogus fd to be ignored in write */
5712 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5715 return open (MacPathname
, oflag
);
5720 sys_creat (const char *path
, mode_t mode
)
5722 char MacPathname
[MAXPATHLEN
+1];
5724 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5727 return creat (MacPathname
, mode
);
5732 sys_unlink (const char *path
)
5734 char MacPathname
[MAXPATHLEN
+1];
5736 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5739 return unlink (MacPathname
);
5744 sys_read (int fildes
, char *buf
, int count
)
5747 { /* if stdin, call (non-echoing) "getch" in console.h */
5748 if (MacKeyPending ())
5749 { /* don't wait for a key if none has been pressed */
5750 *buf
= MacGetChar ();
5757 return read (fildes
, buf
, count
);
5762 sys_write (int fildes
, char *buf
, int count
)
5764 if (fildes
== DEV_NULL_FD
)
5767 return write (fildes
, buf
, count
);
5772 sys_rename (const char * old_name
, const char * new_name
)
5774 char MacOldName
[MAXPATHLEN
+1], MacNewName
[MAXPATHLEN
+1];
5776 if (strcmp (old_name
, new_name
) == 0)
5779 if (Unix2MacPathname (old_name
, MacOldName
, MAXPATHLEN
+1) == 0)
5782 if (Unix2MacPathname (new_name
, MacNewName
, MAXPATHLEN
+1) == 0)
5785 return rename (MacOldName
, MacNewName
);
5789 extern FILE *fopen (const char *name
, const char *mode
);
5791 sys_fopen (const char *name
, const char *mode
)
5793 char MacPathname
[MAXPATHLEN
+1];
5795 if (Unix2MacPathname (name
, MacPathname
, MAXPATHLEN
+1) == 0)
5798 return fopen (MacPathname
, mode
);
5803 long targetTicks
= 0;
5806 __sigfun alarm_signal_func
= (__sigfun
) 0;
5808 __signal_func_ptr alarm_signal_func
= (__signal_func_ptr
) 0;
5813 /* These functions simulate SIG_ALRM. The stub for function signal
5814 stores the signal handler function in alarm_signal_func if a
5815 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5816 which emacs calls periodically. A pending alarm is represented by
5817 a non-zero targetTicks value. CheckAlarm calls the handler
5818 function pointed to by alarm_signal_func if one has been set up and
5819 an alarm is pending. */
5823 if (targetTicks
&& TickCount () > targetTicks
)
5826 if (alarm_signal_func
)
5827 (*alarm_signal_func
)(SIGALRM
);
5831 /* Called in sys_select to wait for an alarm signal to arrive. */
5835 unsigned long finalTick
;
5837 if (!targetTicks
) /* no alarm pending */
5840 while (TickCount () <= targetTicks
)
5841 Delay (1UL, &finalTick
); /* wait for 1/60 second before trying again */
5844 if (alarm_signal_func
)
5845 (*alarm_signal_func
)(SIGALRM
);
5853 long remaining
= targetTicks
? (TickCount () - targetTicks
) / 60 : 0;
5855 targetTicks
= seconds
? TickCount () + 60 * seconds
: 0;
5857 return (remaining
< 0) ? 0 : (unsigned int) remaining
;
5862 extern __sigfun
signal (int signal
, __sigfun signal_func
);
5864 sys_signal (int signal_num
, __sigfun signal_func
)
5866 extern __signal_func_ptr
signal (int signal
, __signal_func_ptr signal_func
);
5868 sys_signal (int signal_num
, __signal_func_ptr signal_func
)
5873 if (signal_num
!= SIGALRM
)
5874 return signal (signal_num
, signal_func
);
5878 __sigfun old_signal_func
;
5880 __signal_func_ptr old_signal_func
;
5884 old_signal_func
= alarm_signal_func
;
5885 alarm_signal_func
= signal_func
;
5886 return old_signal_func
;
5890 /* The time functions adjust time values according to the difference
5891 between the Unix and CW epoches. */
5894 extern struct tm
*gmtime (const time_t *);
5896 sys_gmtime (const time_t *timer
)
5898 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5900 return gmtime (&unixTime
);
5904 extern struct tm
*localtime (const time_t *);
5906 sys_localtime (const time_t *timer
)
5908 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5910 return localtime (&unixTime
);
5914 extern char *ctime (const time_t *);
5916 sys_ctime (const time_t *timer
)
5918 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5920 return ctime (&unixTime
);
5924 extern time_t time (time_t *);
5926 sys_time (time_t *timer
)
5928 time_t macTime
= time (NULL
) - CW_UNIX_EPOCH_DIFF
;
5936 /* no subprocesses, empty wait */
5944 croak (char *badfunc
)
5946 printf ("%s not yet implemented\r\n", badfunc
);
5951 index (const char * str
, int chr
)
5953 return strchr (str
, chr
);
5957 char **environ
= &e
[0];
5960 mktemp (char *template)
5965 len
= strlen (template);
5967 while (k
>= 0 && template[k
] == 'X')
5970 k
++; /* make k index of first 'X' */
5974 /* Zero filled, number of digits equal to the number of X's. */
5975 sprintf (&template[k
], "%0*d", len
-k
, seqnum
++);
5983 /* Emulate getpwuid, getpwnam and others. */
5985 #define PASSWD_FIELD_SIZE 256
5987 static char myPasswdName
[PASSWD_FIELD_SIZE
];
5988 static char myPasswdDir
[MAXPATHLEN
+1];
5990 static struct passwd myPasswd
=
5996 /* Initialized by main () in macterm.c to pathname of emacs directory. */
5997 char emacsPasswdDir
[MAXPATHLEN
+1];
6000 InitEmacsPasswdDir ()
6004 if (getwd (emacsPasswdDir
) && getwd (myPasswdDir
))
6006 /* Need pathname of first ancestor that begins with `emacs' since
6007 Mac emacs application is somewhere in the emacs-20.3 tree. */
6008 int len
= strlen (emacsPasswdDir
);
6009 /* J points to the "/" following the directory name being compared. */
6012 while (i
>= 0 && !found
)
6014 while (i
>= 0 && emacsPasswdDir
[i
] != '/')
6016 if (emacsPasswdDir
[i
] == '/' && i
+5 < len
)
6017 found
= (strncmp (&(emacsPasswdDir
[i
+1]), "emacs", 5) == 0);
6019 emacsPasswdDir
[j
+1] = '\0';
6029 { /* setting to "/" probably won't work,
6030 but set it to something anyway. */
6031 strcpy (emacsPasswdDir
, "/");
6032 strcpy (myPasswdDir
, "/");
6036 static struct passwd emacsPasswd
=
6042 static int myPasswdInited
= 0;
6049 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6050 where Emacs was started. */
6052 ownerName
= (char **) GetResource ('STR ',-16096);
6056 BlockMove ((unsigned char *) *ownerName
,
6057 (unsigned char *) myPasswdName
, *ownerName
[0] + 1);
6058 HUnlock (ownerName
);
6059 p2cstr ((unsigned char *) myPasswdName
);
6062 myPasswdName
[0] = 0;
6066 getpwuid (uid_t uid
)
6068 if (!myPasswdInited
)
6078 getpwnam (const char *name
)
6080 if (strcmp (name
, "emacs") == 0)
6081 return &emacsPasswd
;
6083 if (!myPasswdInited
)
6092 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6093 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6121 request_sigio (void)
6132 unrequest_sigio (void)
6136 /* djgpp does not implement pipe either. */
6138 pipe (int _fildes
[2])
6144 /* Hard and symbolic links. */
6146 symlink (const char *name1
, const char *name2
)
6153 link (const char *name1
, const char *name2
)
6160 lstat (const char *path
, struct stat
*sb
)
6162 return stat (path
, sb
);
6166 readlink (const char *path
, char *buf
, int bufsiz
)
6173 umask (mode_t numask
)
6175 static mode_t mask
= 022;
6176 mode_t oldmask
= mask
;
6182 chmod (const char *path
, mode_t mode
)
6184 /* say it always succeed for now */
6192 return fcntl (oldd
, F_DUPFD
, 0);
6194 /* current implementation of fcntl in fcntl.mac.c simply returns old
6196 return fcntl (oldd
, F_DUPFD
);
6202 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6203 newd if it already exists. Then, attempt to dup oldd. If not
6204 successful, call dup2 recursively until we are, then close the
6205 unsuccessful ones. */
6207 dup2 (int oldd
, int newd
)
6218 ret
= dup2 (oldd
, newd
);
6223 /* let it fail for now */
6237 ioctl (int d
, int request
, void *argp
)
6246 if (fildes
>=0 && fildes
<= 2)
6277 sleep (unsigned int seconds
)
6279 unsigned long finalTick
;
6281 Delay (seconds
* 60UL, &finalTick
);
6284 #endif /* __MRC__ */
6293 #endif /* __MWERKS__ */
6295 /* Return the path to the directory in which Emacs can create
6296 temporary files. The MacOS "temporary items" directory cannot be
6297 used because it removes the file written by a process when it
6298 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6299 again not exactly). And of course Emacs needs to read back the
6300 files written by its subprocesses. So here we write the files to a
6301 directory "Emacs" in the Preferences Folder. This directory is
6302 created if it does not exist. */
6306 static char *TempDirName
= NULL
;
6310 Str255 dirName
, fullPath
;
6312 char unixDirName
[MAXPATHLEN
+1];
6315 /* Cache directory name with pointer TempDirName.
6316 Look for it only the first time. */
6319 err
= FindFolder (kOnSystemDisk
, kPreferencesFolderType
,
6320 kCreateFolder
, &vRefNum
, &dirID
);
6325 cpb
.dirInfo
.ioNamePtr
= dirName
;
6326 cpb
.dirInfo
.ioDrParID
= dirID
;
6328 /* Standard ref num to full path name loop */
6330 cpb
.dirInfo
.ioVRefNum
= vRefNum
;
6331 cpb
.dirInfo
.ioFDirIndex
= -1;
6332 cpb
.dirInfo
.ioDrDirID
= cpb
.dirInfo
.ioDrParID
;
6334 err
= PBGetCatInfo (&cpb
, false);
6337 strcat (dirName
, ":");
6338 if (strlen (fullPath
) + strlen (dirName
) <= MAXPATHLEN
)
6340 strcat (dirName
, fullPath
);
6341 strcpy (fullPath
, dirName
);
6346 while (cpb
.dirInfo
.ioDrDirID
!= fsRtDirID
&& err
== noErr
);
6348 if (strlen (fullPath
) + 6 <= MAXPATHLEN
)
6349 strcat (fullPath
, "Emacs:");
6353 if (Mac2UnixPathname (fullPath
, unixDirName
, MAXPATHLEN
+1) == 0)
6356 dir
= opendir (unixDirName
); /* check whether temp directory exists */
6359 else if (mkdir (unixDirName
, 0700) != 0) /* create it if not */
6362 TempDirName
= (char *) xmalloc (strlen (unixDirName
) + 1);
6363 strcpy (TempDirName
, unixDirName
);
6370 getenv (const char * name
)
6372 if (strcmp (name
, "TERM") == 0)
6374 else if (strcmp (name
, "TERMCAP") == 0)
6375 /* for debugging purpose when code was still outputting to dumb terminal */
6376 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6377 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6378 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6379 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6380 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6381 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6382 else if (strcmp (name
, "TMPDIR") == 0)
6383 return GetTempDirName ();
6389 #include <utsname.h>
6392 uname (struct utsname
*name
)
6395 systemName
= GetString (-16413); /* IM - Resource Manager Reference */
6398 BlockMove (*systemName
, name
->nodename
, (*systemName
)[0]+1);
6399 p2cstr (name
->nodename
);
6406 #include <Processes.h>
6409 /* Event class of HLE sent to subprocess. */
6410 const OSType kEmacsSubprocessSend
= 'ESND';
6411 /* Event class of HLE sent back from subprocess. */
6412 const OSType kEmacsSubprocessReply
= 'ERPY';
6415 mystrchr (char *s
, char c
)
6417 while (*s
&& *s
!= c
)
6443 mystrcpy (char *to
, char *from
)
6454 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6455 terminated). The process should run with the default directory
6456 "workdir", read input from "infn", and write output and error to
6457 "outfn" and "errfn", resp. The Process Manager call
6458 LaunchApplication is used to start the subprocess. We use high
6459 level events as the mechanism to pass arguments to the subprocess
6460 and to make Emacs wait for the subprocess to terminate and pass
6461 back a result code. The bulk of the code here packs the arguments
6462 into one message to be passed together with the high level event.
6463 Emacs also sometimes starts a subprocess using a shell to perform
6464 wildcard filename expansion. Since we don't really have a shell on
6465 the Mac, this case is detected and the starting of the shell is
6466 by-passed. We really need to add code here to do filename
6467 expansion to support such functionality. */
6469 run_mac_command (argv
, workdir
, infn
, outfn
, errfn
)
6470 unsigned char **argv
;
6471 const char *workdir
;
6472 const char *infn
, *outfn
, errfn
;
6474 char macappname
[MAXPATHLEN
+1], macworkdir
[MAXPATHLEN
+1];
6475 char macinfn
[MAXPATHLEN
+1], macoutfn
[MAXPATHLEN
+1], macerrfn
[MAXPATHLEN
+1];
6476 int paramlen
, argc
, newargc
, j
, retries
;
6477 char **newargv
, *param
, *p
;
6480 LaunchParamBlockRec lpbr
;
6481 EventRecord sendEvent
, replyEvent
;
6482 RgnHandle cursorRegionHdl
;
6484 unsigned long refCon
, len
;
6486 if (Unix2MacPathname (workdir
, macworkdir
, MAXPATHLEN
+1) == 0)
6488 if (Unix2MacPathname (infn
, macinfn
, MAXPATHLEN
+1) == 0)
6490 if (Unix2MacPathname (outfn
, macoutfn
, MAXPATHLEN
+1) == 0)
6492 if (Unix2MacPathname (errfn
, macerrfn
, MAXPATHLEN
+1) == 0)
6495 paramlen
= strlen (macworkdir
) + strlen (macinfn
) + strlen (macoutfn
) + strlen (macerrfn
) + 4;
6496 /* count nulls at end of strings */
6505 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6506 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6507 j
= strlen (argv
[0]);
6508 if (j
>= 3 && strcmp (argv
[0]+j
-3, "/sh") == 0 && argc
== 3 && strcmp (argv
[1], "-c") == 0)
6510 char *command
, *t
, tempmacpathname
[MAXPATHLEN
+1];
6512 /* The arguments for the command in argv[2] are separated by
6513 spaces. Count them and put the count in newargc. */
6514 command
= (char *) alloca (strlen (argv
[2])+2);
6515 strcpy (command
, argv
[2]);
6516 if (command
[strlen (command
) - 1] != ' ')
6517 strcat (command
, " ");
6521 t
= mystrchr (t
, ' ');
6525 t
= mystrchr (t
+1, ' ');
6528 newargv
= (char **) alloca (sizeof (char *) * newargc
);
6531 for (j
= 0; j
< newargc
; j
++)
6533 newargv
[j
] = (char *) alloca (strlen (t
) + 1);
6534 mystrcpy (newargv
[j
], t
);
6537 paramlen
+= strlen (newargv
[j
]) + 1;
6540 if (strncmp (newargv
[0], "~emacs/", 7) == 0)
6542 if (Unix2MacPathname (newargv
[0], tempmacpathname
, MAXPATHLEN
+1) == 0)
6546 { /* sometimes Emacs call "sh" without a path for the command */
6548 char *t
= (char *) alloca (strlen (newargv
[0]) + 7 + 1);
6549 strcpy (t
, "~emacs/");
6550 strcat (t
, newargv
[0]);
6553 openp (Vexec_path
, build_string (newargv
[0]), EXEC_SUFFIXES
, &path
, 1);
6557 if (Unix2MacPathname (XSTRING (path
)->data
, tempmacpathname
, MAXPATHLEN
+1) == 0)
6560 strcpy (macappname
, tempmacpathname
);
6564 if (Unix2MacPathname (argv
[0], macappname
, MAXPATHLEN
+1) == 0)
6567 newargv
= (char **) alloca (sizeof (char *) * argc
);
6569 for (j
= 1; j
< argc
; j
++)
6571 if (strncmp (argv
[j
], "~emacs/", 7) == 0)
6573 char *t
= strchr (argv
[j
], ' ');
6576 char tempcmdname
[MAXPATHLEN
+1], tempmaccmdname
[MAXPATHLEN
+1];
6577 strncpy (tempcmdname
, argv
[j
], t
-argv
[j
]);
6578 tempcmdname
[t
-argv
[j
]] = '\0';
6579 if (Unix2MacPathname (tempcmdname
, tempmaccmdname
, MAXPATHLEN
+1) == 0)
6581 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
) + strlen (t
) + 1);
6582 strcpy (newargv
[j
], tempmaccmdname
);
6583 strcat (newargv
[j
], t
);
6587 char tempmaccmdname
[MAXPATHLEN
+1];
6588 if (Unix2MacPathname (argv
[j
], tempmaccmdname
, MAXPATHLEN
+1) == 0)
6590 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
)+1);
6591 strcpy (newargv
[j
], tempmaccmdname
);
6595 newargv
[j
] = argv
[j
];
6596 paramlen
+= strlen (newargv
[j
]) + 1;
6600 /* After expanding all the arguments, we now know the length of the parameter block to be
6601 sent to the subprocess as a message attached to the HLE. */
6602 param
= (char *) xmalloc (paramlen
+ 1);
6607 *p
++ = newargc
; /* first byte of message contains number of arguments for command */
6608 strcpy (p
, macworkdir
);
6609 p
+= strlen (macworkdir
);
6610 *p
++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6611 strcpy (p
, macinfn
);
6612 p
+= strlen (macinfn
);
6614 strcpy (p
, macoutfn
);
6615 p
+= strlen (macoutfn
);
6617 strcpy (p
, macerrfn
);
6618 p
+= strlen (macerrfn
);
6620 for (j
= 1; j
< newargc
; j
++) {
6621 strcpy (p
, newargv
[j
]);
6622 p
+= strlen (newargv
[j
]);
6626 c2pstr (macappname
);
6628 iErr
= FSMakeFSSpec (0, 0, macappname
, &spec
);
6630 if (iErr
!= noErr
) {
6635 lpbr
.launchBlockID
= extendedBlock
;
6636 lpbr
.launchEPBLength
= extendedBlockLen
;
6637 lpbr
.launchControlFlags
= launchContinue
+ launchNoFileFlags
;
6638 lpbr
.launchAppSpec
= &spec
;
6639 lpbr
.launchAppParameters
= NULL
;
6641 iErr
= LaunchApplication (&lpbr
); /* call the subprocess */
6648 sendEvent
.what
= kHighLevelEvent
;
6649 sendEvent
.message
= kEmacsSubprocessSend
; /* Event ID stored in "where" unused */
6652 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6653 iErr
= PostHighLevelEvent (&sendEvent
, &lpbr
.launchProcessSN
, 0, param
, paramlen
+ 1, receiverIDisPSN
);
6655 while (iErr
== sessClosedErr
&& retries
-- > 0);
6657 if (iErr
!= noErr
) {
6662 cursorRegionHdl
= NewRgn ();
6664 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6666 if (WaitNextEvent (highLevelEventMask
, &replyEvent
, 180, cursorRegionHdl
) && replyEvent
.message
== kEmacsSubprocessReply
)
6669 /* The return code is sent through the refCon */
6670 iErr
= AcceptHighLevelEvent (&targ
, &refCon
, NULL
, &len
);
6671 if (iErr
!= noErr
) {
6672 DisposeHandle ((Handle
) cursorRegionHdl
);
6677 DisposeHandle ((Handle
) cursorRegionHdl
);
6684 opendir (const char *dirname
)
6686 char MacPathname
[MAXPATHLEN
+1];
6691 dirp
= (DIR *) xmalloc (sizeof (DIR));
6695 /* Handle special case when dirname is "/": sets up for readir to
6696 get all mount volumes. */
6697 if (strcmp (dirname
, "/") == 0) {
6698 dirp
->getting_volumes
= 1; /* special all mounted volumes DIR struct */
6699 dirp
->current_index
= 1; /* index for first volume */
6703 /* Handle typical cases: not accessing all mounted volumes. */
6704 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
6707 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6708 len
= strlen (MacPathname
);
6709 if (MacPathname
[len
- 1] != ':' && len
< MAXPATHLEN
)
6710 strcat (MacPathname
, ":");
6712 c2pstr (MacPathname
);
6713 cipb
.hFileInfo
.ioNamePtr
= MacPathname
; /* using full pathname so vRefNum and dirID ignored */
6714 cipb
.hFileInfo
.ioVRefNum
= 0;
6715 cipb
.hFileInfo
.ioDirID
= 0;
6716 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
6718 errno
= PBGetCatInfo (&cipb
, false);
6719 if (errno
!= noErr
) {
6724 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x10)) /* bit 4 = 1 for directories */
6725 return 0; /* not a directory */
6727 dirp
->dir_id
= cipb
.dirInfo
.ioDrDirID
; /* used later in readdir */
6728 dirp
->getting_volumes
= 0;
6729 dirp
->current_index
= 1; /* index for first file/directory */
6744 HParamBlockRec HPBlock
;
6746 static struct dirent s_dirent
;
6747 static Str255 s_name
;
6750 /* Handle the root directory containing the mounted volumes. Call
6751 PBHGetVInfo specifying an index to obtain the info for a volume.
6752 PBHGetVInfo returns an error when it receives an index beyond the
6753 last volume, at which time we should return a nil dirent struct
6755 if (dp
->getting_volumes
) {
6756 HPBlock
.volumeParam
.ioNamePtr
= s_name
;
6757 HPBlock
.volumeParam
.ioVRefNum
= 0;
6758 HPBlock
.volumeParam
.ioVolIndex
= dp
->current_index
;
6760 errno
= PBHGetVInfo (&HPBlock
, false);
6761 if (errno
!= noErr
) {
6767 strcat (s_name
, "/"); /* need "/" for stat to work correctly */
6769 dp
->current_index
++;
6771 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
;
6772 s_dirent
.d_name
= s_name
;
6777 cipb
.hFileInfo
.ioVRefNum
= 0;
6778 cipb
.hFileInfo
.ioNamePtr
= s_name
; /* location to receive filename returned */
6780 /* return only visible files */
6783 cipb
.hFileInfo
.ioDirID
= dp
->dir_id
; /* directory ID found by opendir */
6784 cipb
.hFileInfo
.ioFDirIndex
= dp
->current_index
;
6786 errno
= PBGetCatInfo (&cipb
, false);
6787 if (errno
!= noErr
) {
6792 /* insist on an visibile entry */
6793 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* directory? */
6794 done
= !(cipb
.dirInfo
.ioDrUsrWds
.frFlags
& fInvisible
);
6796 done
= !(cipb
.hFileInfo
.ioFlFndrInfo
.fdFlags
& fInvisible
);
6798 dp
->current_index
++;
6803 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
; /* value unimportant: non-zero for valid file */
6804 s_dirent
.d_name
= s_name
;
6813 char MacPathname
[MAXPATHLEN
+1];
6814 Str255 directoryName
;
6818 MacPathname
[0] = '\0';
6819 directoryName
[0] = '\0';
6820 cipb
.dirInfo
.ioDrParID
= 0;
6821 cipb
.dirInfo
.ioNamePtr
= directoryName
; /* empty string = default directory */
6824 cipb
.dirInfo
.ioVRefNum
= 0;
6825 cipb
.dirInfo
.ioFDirIndex
= -1;
6826 cipb
.dirInfo
.ioDrDirID
= cipb
.dirInfo
.ioDrParID
; /* go up to parent each time */
6828 errno
= PBGetCatInfo (&cipb
, false);
6829 if (errno
!= noErr
) {
6834 p2cstr (directoryName
);
6835 strcat (directoryName
, ":");
6836 strcat (directoryName
, MacPathname
); /* attach to front since going up directory tree */
6837 strcpy (MacPathname
, directoryName
);
6838 } while (cipb
.dirInfo
.ioDrDirID
!= fsRtDirID
); /* until volume's root directory */
6840 if (Mac2UnixPathname (MacPathname
, path
, MAXPATHLEN
+1) == 0)
6846 #endif /* macintosh */