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
73 #endif /* TRY_AGAIN */
76 #include <sys/types.h>
80 /* Get _POSIX_VDISABLE, if it is available. */
90 #if !defined (USG) || defined (BSD_PGRPS)
92 #define setpgrp setpgid
96 /* Get SI_SRPC_DOMAIN, if it is available. */
97 #ifdef HAVE_SYS_SYSTEMINFO_H
98 #include <sys/systeminfo.h>
101 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
105 #include <sys/param.h>
109 extern unsigned start
__asm__ ("start");
131 #include <sys/file.h>
139 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
143 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
144 because the vms compiler doesn't grok `defined' */
152 #endif /* not 4.1 bsd */
155 #include <sys/ioctl.h>
161 #ifdef BROKEN_TIOCGWINSZ
166 #if defined (USG) || defined (DGUX)
167 #include <sys/utsname.h>
168 #ifndef MEMORY_IN_STRING_H
171 #if defined (TIOCGWINSZ) || defined (ISC4_0)
173 #include <sys/sioctl.h>
176 #include <sys/stream.h>
177 #include <sys/ptem.h>
179 #endif /* TIOCGWINSZ or ISC4_0 */
180 #endif /* USG or DGUX */
182 extern int quit_char
;
184 #include "keyboard.h"
187 #include "termhooks.h"
188 #include "termchar.h"
189 #include "termopts.h"
190 #include "dispextern.h"
195 /* In process.h which conflicts with the local copy. */
197 int _CRTAPI1
_spawnlp (int, const char *, const char *, ...);
198 int _CRTAPI1
_getpid (void);
201 #ifdef NONSYSTEM_DIR_LIBRARY
203 #endif /* NONSYSTEM_DIR_LIBRARY */
205 #include "syssignal.h"
212 #ifndef HAVE_STRUCT_UTIMBUF
213 /* We want to use utime rather than utimes, but we couldn't find the
214 structure declaration. We'll use the traditional one. */
222 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
228 #define LNOFLSH 0100000
231 static int baud_convert
[] =
236 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
237 1800, 2400, 4800, 9600, 19200, 38400
243 extern speed_t ospeed
;
245 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
248 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
250 /* HJL's version of libc is said to need this on the Alpha.
251 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
252 extern speed_t ospeed
;
259 /* The file descriptor for Emacs's input terminal.
260 Under Unix, this is normally zero except when using X;
261 under VMS, we place the input channel number here. */
264 void croak
P_ ((char *));
271 /* Temporary used by `sigblock' when defined in terms of signprocmask. */
273 SIGMASKTYPE sigprocmask_set
;
276 /* Specify a different file descriptor for further input operations. */
285 /* Discard pending input on descriptor input_fd. */
291 struct emacs_tty buf
;
296 /* Discarding input is not safe when the input could contain
297 replies from the X server. So don't do it. */
298 if (read_socket_hook
)
303 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
304 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
310 ioctl (input_fd
, TIOCFLUSH
, &zero
);
312 #else /* not Apollo */
313 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
314 while (dos_keyread () != -1)
316 #else /* not MSDOS */
317 EMACS_GET_TTY (input_fd
, &buf
);
318 EMACS_SET_TTY (input_fd
, &buf
, 0);
319 #endif /* not MSDOS */
320 #endif /* not Apollo */
322 #endif /* not WINDOWSNT */
327 /* Arrange for character C to be read as the next input from
334 if (read_socket_hook
)
337 /* Should perhaps error if in batch mode */
339 ioctl (input_fd
, TIOCSTI
, &c
);
340 #else /* no TIOCSTI */
341 error ("Cannot stuff terminal input characters in this version of Unix");
342 #endif /* no TIOCSTI */
354 #ifdef INIT_BAUD_RATE
359 #else /* not DOS_NT */
363 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
364 &sg
.class, 12, 0, 0, 0, 0 );
365 ospeed
= sg
.xmit_baud
;
371 tcgetattr (input_fd
, &sg
);
372 ospeed
= cfgetospeed (&sg
);
373 #if defined (USE_GETOBAUD) && defined (getobaud)
374 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
376 ospeed
= getobaud (sg
.c_cflag
);
378 #else /* neither VMS nor TERMIOS */
384 tcgetattr (input_fd
, &sg
);
386 ioctl (input_fd
, TCGETA
, &sg
);
388 ospeed
= sg
.c_cflag
& CBAUD
;
389 #else /* neither VMS nor TERMIOS nor TERMIO */
392 sg
.sg_ospeed
= B9600
;
393 if (ioctl (input_fd
, TIOCGETP
, &sg
) < 0)
395 ospeed
= sg
.sg_ospeed
;
396 #endif /* not HAVE_TERMIO */
397 #endif /* not HAVE_TERMIOS */
399 #endif /* not DOS_NT */
400 #endif /* not INIT_BAUD_RATE */
403 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
404 ? baud_convert
[ospeed
] : 9600);
411 set_exclusive_use (fd
)
415 ioctl (fd
, FIOCLEX
, 0);
417 /* Ok to do nothing if this feature does not exist */
422 wait_without_blocking ()
425 wait3 (0, WNOHANG
| WUNTRACED
, 0);
427 croak ("wait_without_blocking");
429 synch_process_alive
= 0;
432 #endif /* not subprocesses */
434 int wait_debugging
; /* Set nonzero to make following function work under dbx
435 (at least for bsd). */
438 wait_for_termination_signal ()
441 /* Wait for subprocess with process id `pid' to terminate and
442 make sure it will get eliminated (not remain forever as a zombie) */
445 wait_for_termination (pid
)
454 status
= SYS$
FORCEX (&pid
, 0, 0);
457 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
458 /* Note that kill returns -1 even if the process is just a zombie now.
459 But inevitably a SIGCHLD interrupt should be generated
460 and child_sig will do wait3 and make the process go away. */
461 /* There is some indication that there is a bug involved with
462 termination of subprocesses, perhaps involving a kernel bug too,
463 but no idea what it is. Just as a hunch we signal SIGCHLD to see
464 if that causes the problem to go away or get worse. */
465 sigsetmask (sigmask (SIGCHLD
));
466 if (0 > kill (pid
, 0))
468 sigsetmask (SIGEMPTYMASK
);
469 kill (getpid (), SIGCHLD
);
475 sigpause (SIGEMPTYMASK
);
476 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
477 #if defined (UNIPLUS)
478 if (0 > kill (pid
, 0))
481 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
482 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
483 sigblock (sigmask (SIGCHLD
));
484 if (0 > kill (pid
, 0))
486 sigunblock (sigmask (SIGCHLD
));
489 sigpause (SIGEMPTYMASK
);
490 #else /* not POSIX_SIGNALS */
491 #ifdef HAVE_SYSV_SIGPAUSE
493 if (0 > kill (pid
, 0))
499 #else /* not HAVE_SYSV_SIGPAUSE */
503 #else /* not WINDOWSNT */
504 if (0 > kill (pid
, 0))
506 /* Using sleep instead of pause avoids timing error.
507 If the inferior dies just before the sleep,
508 we lose just one second. */
510 #endif /* not WINDOWSNT */
511 #endif /* not HAVE_SYSV_SIGPAUSE */
512 #endif /* not POSIX_SIGNALS */
513 #endif /* not UNIPLUS */
514 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
516 #else /* not subprocesses */
519 #else /* not __DJGPP__ > 1 */
521 if (kill (pid
, 0) < 0)
527 if (status
== pid
|| status
== -1)
530 #endif /* not __DJGPP__ > 1*/
531 #endif /* not subprocesses */
538 * flush any pending output
539 * (may flush input as well; it does not matter the way we use it)
543 flush_pending_output (channel
)
547 /* If we try this, we get hit with SIGTTIN, because
548 the child's tty belongs to the child's pgrp. */
551 ioctl (channel
, TCFLSH
, 1);
555 /* 3rd arg should be ignored
556 but some 4.2 kernels actually want the address of an int
557 and nonzero means something different. */
558 ioctl (channel
, TIOCFLUSH
, &zero
);
565 /* Set up the terminal at the other end of a pseudo-terminal that
566 we will be controlling an inferior through.
567 It should not echo or do line-editing, since that is done
568 in Emacs. No padding needed for insertion into an Emacs buffer. */
571 child_setup_tty (out
)
577 EMACS_GET_TTY (out
, &s
);
579 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
580 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
581 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
583 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
584 /* No output delays */
586 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
587 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
589 s
.main
.c_iflag
&= ~IUCLC
; /* Disable downcasing on input. */
592 s
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
595 s
.main
.c_oflag
&= ~OLCUC
; /* Disable upcasing on output. */
597 s
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
598 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CSIZE
) | CS8
; /* Don't strip 8th bit */
600 /* Said to be unnecessary: */
601 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
602 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
605 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
606 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
607 s
.main
.c_cc
[VERASE
] = CDISABLE
; /* disable erase processing */
608 s
.main
.c_cc
[VKILL
] = CDISABLE
; /* disable kill processing */
611 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
615 /* AIX enhanced edit loses NULs, so disable it */
618 s
.main
.c_iflag
&= ~ASCEDIT
;
620 /* Also, PTY overloads NUL and BREAK.
621 don't ignore break, but don't signal either, so it looks like NUL. */
622 s
.main
.c_iflag
&= ~IGNBRK
;
623 s
.main
.c_iflag
&= ~BRKINT
;
624 /* QUIT and INTR work better as signals, so disable character forms */
625 s
.main
.c_cc
[VINTR
] = 0377;
626 #ifdef SIGNALS_VIA_CHARACTERS
627 /* the QUIT and INTR character are used in process_send_signal
628 so set them here to something useful. */
629 if (s
.main
.c_cc
[VQUIT
] == 0377)
630 s
.main
.c_cc
[VQUIT
] = '\\'&037; /* Control-\ */
631 if (s
.main
.c_cc
[VINTR
] == 0377)
632 s
.main
.c_cc
[VINTR
] = 'C'&037; /* Control-C */
633 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
634 /* QUIT and INTR work better as signals, so disable character forms */
635 s
.main
.c_cc
[VQUIT
] = 0377;
636 s
.main
.c_cc
[VINTR
] = 0377;
637 s
.main
.c_lflag
&= ~ISIG
;
638 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
639 s
.main
.c_cc
[VEOL
] = 0377;
640 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
643 #else /* not HAVE_TERMIO */
645 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
647 s
.main
.sg_flags
|= LPASS8
;
648 s
.main
.sg_erase
= 0377;
649 s
.main
.sg_kill
= 0377;
650 s
.lmode
= LLITOUT
| s
.lmode
; /* Don't strip 8th bit */
652 #endif /* not HAVE_TERMIO */
654 EMACS_SET_TTY (out
, &s
, 0);
663 ioctl (out
, FIOASYNC
, &zero
);
666 #endif /* not DOS_NT */
670 #endif /* subprocesses */
672 /* Record a signal code and the handler for it. */
676 SIGTYPE (*handler
) P_ ((int));
679 static void save_signal_handlers
P_ ((struct save_signal
*));
680 static void restore_signal_handlers
P_ ((struct save_signal
*));
682 /* Suspend the Emacs process; give terminal to its superior. */
688 /* "Foster" parentage allows emacs to return to a subprocess that attached
689 to the current emacs as a cheaper than starting a whole new process. This
690 is set up by KEPTEDITOR.COM. */
691 unsigned long parent_id
, foster_parent_id
;
694 fpid_string
= getenv ("EMACS_PARENT_PID");
695 if (fpid_string
!= NULL
)
697 sscanf (fpid_string
, "%x", &foster_parent_id
);
698 if (foster_parent_id
!= 0)
699 parent_id
= foster_parent_id
;
701 parent_id
= getppid ();
704 parent_id
= getppid ();
706 xfree (fpid_string
); /* On VMS, this was malloc'd */
708 if (parent_id
&& parent_id
!= 0xffffffff)
710 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
711 int status
= LIB$
ATTACH (&parent_id
) & 1;
712 signal (SIGINT
, oldsig
);
721 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
722 d_prompt
.a
= "Emacs: "; /* Just a reminder */
723 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
728 #if defined (SIGTSTP) && !defined (MSDOS)
731 int pgrp
= EMACS_GETPGRP (0);
732 EMACS_KILLPG (pgrp
, SIGTSTP
);
735 #else /* No SIGTSTP */
736 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
737 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
738 kill (getpid (), SIGQUIT
);
740 #else /* No SIGTSTP or USG_JOBCTRL */
742 /* On a system where suspending is not implemented,
743 instead fork a subshell and let it talk directly to the terminal
747 #endif /* no USG_JOBCTRL */
748 #endif /* no SIGTSTP */
752 /* Fork a subshell. */
758 error ("Can't spawn subshell");
761 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
763 char oldwd
[MAXPATHLEN
+1]; /* Fixed length is safe on MSDOS. */
766 struct save_signal saved_handlers
[5];
768 unsigned char *str
= 0;
771 saved_handlers
[0].code
= SIGINT
;
772 saved_handlers
[1].code
= SIGQUIT
;
773 saved_handlers
[2].code
= SIGTERM
;
775 saved_handlers
[3].code
= SIGIO
;
776 saved_handlers
[4].code
= 0;
778 saved_handlers
[3].code
= 0;
781 /* Mentioning current_buffer->buffer would mean including buffer.h,
782 which somehow wedges the hp compiler. So instead... */
784 dir
= intern ("default-directory");
785 if (NILP (Fboundp (dir
)))
787 dir
= Fsymbol_value (dir
);
791 dir
= expand_and_dir_to_file (Funhandled_file_name_directory (dir
), Qnil
);
792 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
793 len
= XSTRING (dir
)->size
;
794 bcopy (XSTRING (dir
)->data
, str
, len
);
795 if (str
[len
- 1] != '/') str
[len
++] = '/';
802 save_signal_handlers (saved_handlers
);
803 synch_process_alive
= 1;
804 #endif /* __DJGPP__ > 1 */
808 error ("Can't spawn subshell");
815 #ifdef DOS_NT /* MW, Aug 1993 */
818 sh
= (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
821 sh
= (char *) egetenv ("SHELL");
825 /* Use our buffer's default directory for the subshell. */
827 chdir ((char *) str
);
830 close_process_descs (); /* Close Emacs's pipes/ptys */
833 #ifdef SET_EMACS_PRIORITY
835 extern int emacs_priority
;
837 if (emacs_priority
< 0)
838 nice (-emacs_priority
);
842 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
845 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
847 report_file_error ("Can't execute subshell", Fcons (build_string (sh
), Qnil
));
849 #else /* not MSDOS */
851 /* Waits for process completion */
852 pid
= _spawnlp (_P_WAIT
, sh
, sh
, NULL
);
855 write (1, "Can't execute subshell", 22);
856 #else /* not WINDOWSNT */
858 write (1, "Can't execute subshell", 22);
860 #endif /* not WINDOWSNT */
861 #endif /* not MSDOS */
864 /* Do this now if we did not do it before. */
865 #if !defined (MSDOS) || __DJGPP__ == 1
866 save_signal_handlers (saved_handlers
);
867 synch_process_alive
= 1;
871 wait_for_termination (pid
);
873 restore_signal_handlers (saved_handlers
);
874 synch_process_alive
= 0;
876 #endif /* !macintosh */
880 save_signal_handlers (saved_handlers
)
881 struct save_signal
*saved_handlers
;
883 while (saved_handlers
->code
)
885 saved_handlers
->handler
886 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers
->code
, SIG_IGN
);
892 restore_signal_handlers (saved_handlers
)
893 struct save_signal
*saved_handlers
;
895 while (saved_handlers
->code
)
897 signal (saved_handlers
->code
, saved_handlers
->handler
);
911 old_fcntl_flags
= fcntl (fd
, F_GETFL
, 0) & ~FASYNC
;
912 fcntl (fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
914 interrupts_deferred
= 0;
923 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
928 if (read_socket_hook
)
932 sigunblock (sigmask (SIGWINCH
));
934 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
936 interrupts_deferred
= 0;
942 if (read_socket_hook
)
946 sigblock (sigmask (SIGWINCH
));
948 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
);
949 interrupts_deferred
= 1;
952 #else /* no FASYNC */
953 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
960 if (read_socket_hook
)
963 ioctl (input_fd
, FIOASYNC
, &on
);
964 interrupts_deferred
= 0;
972 if (read_socket_hook
)
975 ioctl (input_fd
, FIOASYNC
, &off
);
976 interrupts_deferred
= 1;
979 #else /* not FASYNC, not STRIDE */
991 if (read_socket_hook
)
995 sigaddset (&st
, SIGIO
);
996 ioctl (input_fd
, FIOASYNC
, &on
);
997 interrupts_deferred
= 0;
998 sigprocmask (SIG_UNBLOCK
, &st
, (sigset_t
*)0);
1006 if (read_socket_hook
)
1009 ioctl (input_fd
, FIOASYNC
, &off
);
1010 interrupts_deferred
= 1;
1013 #else /* ! _CX_UX */
1018 if (read_socket_hook
)
1021 croak ("request_sigio");
1027 if (read_socket_hook
)
1030 croak ("unrequest_sigio");
1036 #endif /* F_SETFL */
1038 /* Saving and restoring the process group of Emacs's terminal. */
1042 /* The process group of which Emacs was a member when it initially
1045 If Emacs was in its own process group (i.e. inherited_pgroup ==
1046 getpid ()), then we know we're running under a shell with job
1047 control (Emacs would never be run as part of a pipeline).
1050 If Emacs was not in its own process group, then we know we're
1051 running under a shell (or a caller) that doesn't know how to
1052 separate itself from Emacs (like sh). Emacs must be in its own
1053 process group in order to receive SIGIO correctly. In this
1054 situation, we put ourselves in our own pgroup, forcibly set the
1055 tty's pgroup to our pgroup, and make sure to restore and reinstate
1056 the tty's pgroup just like any other terminal setting. If
1057 inherited_group was not the tty's pgroup, then we'll get a
1058 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1059 it goes foreground in the future, which is what should happen. */
1060 int inherited_pgroup
;
1062 /* Split off the foreground process group to Emacs alone.
1063 When we are in the foreground, but not started in our own process
1064 group, redirect the TTY to point to our own process group. We need
1065 to be in our own process group to receive SIGIO properly. */
1067 narrow_foreground_group ()
1071 setpgrp (0, inherited_pgroup
);
1072 if (inherited_pgroup
!= me
)
1073 EMACS_SET_TTY_PGRP (input_fd
, &me
);
1077 /* Set the tty to our original foreground group. */
1079 widen_foreground_group ()
1081 if (inherited_pgroup
!= getpid ())
1082 EMACS_SET_TTY_PGRP (input_fd
, &inherited_pgroup
);
1083 setpgrp (0, inherited_pgroup
);
1086 #endif /* BSD_PGRPS */
1088 /* Getting and setting emacs_tty structures. */
1090 /* Set *TC to the parameters associated with the terminal FD.
1091 Return zero if all's well, or -1 if we ran into an error we
1092 couldn't deal with. */
1094 emacs_get_tty (fd
, settings
)
1096 struct emacs_tty
*settings
;
1098 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1100 /* We have those nifty POSIX tcmumbleattr functions. */
1101 bzero (&settings
->main
, sizeof (settings
->main
));
1102 if (tcgetattr (fd
, &settings
->main
) < 0)
1107 /* The SYSV-style interface? */
1108 if (ioctl (fd
, TCGETA
, &settings
->main
) < 0)
1113 /* Vehemently Monstrous System? :-) */
1114 if (! (SYS$
QIOW (0, fd
, IO$_SENSEMODE
, settings
, 0, 0,
1115 &settings
->main
.class, 12, 0, 0, 0, 0)
1121 /* I give up - I hope you have the BSD ioctls. */
1122 if (ioctl (fd
, TIOCGETP
, &settings
->main
) < 0)
1124 #endif /* not DOS_NT */
1129 /* Suivant - Do we have to get struct ltchars data? */
1131 if (ioctl (fd
, TIOCGLTC
, &settings
->ltchars
) < 0)
1135 /* How about a struct tchars and a wordful of lmode bits? */
1137 if (ioctl (fd
, TIOCGETC
, &settings
->tchars
) < 0
1138 || ioctl (fd
, TIOCLGET
, &settings
->lmode
) < 0)
1142 /* We have survived the tempest. */
1147 /* Set the parameters of the tty on FD according to the contents of
1148 *SETTINGS. If FLUSHP is non-zero, we discard input.
1149 Return 0 if all went well, and -1 if anything failed. */
1152 emacs_set_tty (fd
, settings
, flushp
)
1154 struct emacs_tty
*settings
;
1157 /* Set the primary parameters - baud rate, character size, etcetera. */
1160 /* We have those nifty POSIX tcmumbleattr functions.
1161 William J. Smith <wjs@wiis.wang.com> writes:
1162 "POSIX 1003.1 defines tcsetattr to return success if it was
1163 able to perform any of the requested actions, even if some
1164 of the requested actions could not be performed.
1165 We must read settings back to ensure tty setup properly.
1166 AIX requires this to keep tty from hanging occasionally." */
1167 /* This make sure that we don't loop indefinitely in here. */
1168 for (i
= 0 ; i
< 10 ; i
++)
1169 if (tcsetattr (fd
, flushp
? TCSAFLUSH
: TCSADRAIN
, &settings
->main
) < 0)
1180 bzero (&new, sizeof (new));
1181 /* Get the current settings, and see if they're what we asked for. */
1182 tcgetattr (fd
, &new);
1183 /* We cannot use memcmp on the whole structure here because under
1184 * aix386 the termios structure has some reserved field that may
1187 if ( new.c_iflag
== settings
->main
.c_iflag
1188 && new.c_oflag
== settings
->main
.c_oflag
1189 && new.c_cflag
== settings
->main
.c_cflag
1190 && new.c_lflag
== settings
->main
.c_lflag
1191 && memcmp (new.c_cc
, settings
->main
.c_cc
, NCCS
) == 0)
1199 /* The SYSV-style interface? */
1200 if (ioctl (fd
, flushp
? TCSETAF
: TCSETAW
, &settings
->main
) < 0)
1205 /* Vehemently Monstrous System? :-) */
1206 if (! (SYS$
QIOW (0, fd
, IO$_SETMODE
, &input_iosb
, 0, 0,
1207 &settings
->main
.class, 12, 0, 0, 0, 0)
1213 /* I give up - I hope you have the BSD ioctls. */
1214 if (ioctl (fd
, (flushp
) ? TIOCSETP
: TIOCSETN
, &settings
->main
) < 0)
1216 #endif /* not DOS_NT */
1222 /* Suivant - Do we have to get struct ltchars data? */
1224 if (ioctl (fd
, TIOCSLTC
, &settings
->ltchars
) < 0)
1228 /* How about a struct tchars and a wordful of lmode bits? */
1230 if (ioctl (fd
, TIOCSETC
, &settings
->tchars
) < 0
1231 || ioctl (fd
, TIOCLSET
, &settings
->lmode
) < 0)
1235 /* We have survived the tempest. */
1240 /* The initial tty mode bits */
1241 struct emacs_tty old_tty
;
1243 /* 1 if we have been through init_sys_modes. */
1246 /* 1 if outer tty status has been recorded. */
1250 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1255 #ifndef F_SETOWN_BUG
1257 int old_fcntl_owner
;
1258 #endif /* F_SETOWN */
1259 #endif /* F_SETOWN_BUG */
1261 /* This may also be defined in stdio,
1262 but if so, this does no harm,
1263 and using the same name avoids wasting the other one's space. */
1266 extern char *_sobuf
;
1268 #if defined (USG) || defined (DGUX)
1269 unsigned char _sobuf
[BUFSIZ
+8];
1271 char _sobuf
[BUFSIZ
];
1276 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
1279 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
1285 struct emacs_tty tty
;
1288 Vwindow_system
= intern ("mac");
1289 Vwindow_system_version
= make_number (1);
1291 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1292 #ifndef subprocesses
1293 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
1294 "*Non-nil means delete processes immediately when they exit.\n\
1295 nil means don't delete them until `list-processes' is run.");
1296 delete_exited_processes
= 0;
1299 #ifndef HAVE_X_WINDOWS
1300 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
1301 "List of directories to search for bitmap files for X.");
1302 Vx_bitmap_file_path
= decode_env_path ((char *) 0, ".");
1305 #endif /* not macintosh */
1309 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
1310 extern int (*interrupt_signal
) ();
1314 Vtty_erase_char
= Qnil
;
1321 input_ef
= get_kbd_event_flag ();
1322 /* LIB$GET_EF (&input_ef); */
1323 SYS$
CLREF (input_ef
);
1324 waiting_for_ast
= 0;
1326 timer_ef
= get_timer_event_flag ();
1327 /* LIB$GET_EF (&timer_ef); */
1328 SYS$
CLREF (timer_ef
);
1332 LIB$
GET_EF (&process_ef
);
1333 SYS$
CLREF (process_ef
);
1335 if (input_ef
/ 32 != process_ef
/ 32)
1336 croak ("Input and process event flags in different clusters.");
1338 if (input_ef
/ 32 != timer_ef
/ 32)
1339 croak ("Input and timer event flags in different clusters.");
1341 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1342 ((unsigned) 1 << (process_ef
% 32));
1344 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1345 ((unsigned) 1 << (timer_ef
% 32));
1347 sys_access_reinit ();
1349 #endif /* not VMS */
1352 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1353 narrow_foreground_group ();
1356 #ifdef HAVE_WINDOW_SYSTEM
1357 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1358 needs the initialization code below. */
1359 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1362 EMACS_GET_TTY (input_fd
, &old_tty
);
1368 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1369 XSETINT (Vtty_erase_char
, old_tty
.main
.c_cc
[VERASE
]);
1372 /* This allows meta to be sent on 8th bit. */
1373 tty
.main
.c_iflag
&= ~INPCK
; /* don't check input for parity */
1375 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
1376 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
1377 #ifdef INLCR /* I'm just being cautious,
1378 since I can't check how widespread INLCR is--rms. */
1379 tty
.main
.c_iflag
&= ~INLCR
; /* Disable map of NL to CR on input */
1382 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
1384 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
1385 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
1387 tty
.main
.c_lflag
&= ~IEXTEN
; /* Disable other editing characters. */
1389 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
1392 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
1394 tty
.main
.c_iflag
&= ~IXANY
;
1398 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
1399 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
1401 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
1405 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
1406 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
1409 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
1410 /* Set up C-g for both SIGQUIT and SIGINT.
1411 We don't know which we will get, but we handle both alike
1412 so which one it really gives us does not matter. */
1413 tty
.main
.c_cc
[VQUIT
] = quit_char
;
1414 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
1415 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
1417 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
1421 #if defined (mips) || defined (HAVE_TCATTR)
1423 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
1426 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
1427 #endif /* V_DSUSP */
1428 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1429 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
1432 tty
.main
.c_cc
[VLNEXT
] = CDISABLE
;
1435 tty
.main
.c_cc
[VREPRINT
] = CDISABLE
;
1436 #endif /* VREPRINT */
1438 tty
.main
.c_cc
[VWERASE
] = CDISABLE
;
1439 #endif /* VWERASE */
1441 tty
.main
.c_cc
[VDISCARD
] = CDISABLE
;
1442 #endif /* VDISCARD */
1447 tty
.main
.c_cc
[VSTART
] = '\021';
1450 tty
.main
.c_cc
[VSTOP
] = '\023';
1456 tty
.main
.c_cc
[VSTART
] = CDISABLE
;
1459 tty
.main
.c_cc
[VSTOP
] = CDISABLE
;
1462 #endif /* mips or HAVE_TCATTR */
1464 #ifdef SET_LINE_DISCIPLINE
1465 /* Need to explicitly request TERMIODISC line discipline or
1466 Ultrix's termios does not work correctly. */
1467 tty
.main
.c_line
= SET_LINE_DISCIPLINE
;
1471 /* AIX enhanced edit loses NULs, so disable it. */
1472 tty
.main
.c_line
= 0;
1473 tty
.main
.c_iflag
&= ~ASCEDIT
;
1475 tty
.main
.c_cc
[VSTRT
] = 255;
1476 tty
.main
.c_cc
[VSTOP
] = 255;
1477 tty
.main
.c_cc
[VSUSP
] = 255;
1478 tty
.main
.c_cc
[VDSUSP
] = 255;
1479 #endif /* IBMR2AIX */
1483 tty
.main
.c_cc
[VSTART
] = '\021';
1486 tty
.main
.c_cc
[VSTOP
] = '\023';
1489 /* Also, PTY overloads NUL and BREAK.
1490 don't ignore break, but don't signal either, so it looks like NUL.
1491 This really serves a purpose only if running in an XTERM window
1492 or via TELNET or the like, but does no harm elsewhere. */
1493 tty
.main
.c_iflag
&= ~IGNBRK
;
1494 tty
.main
.c_iflag
&= ~BRKINT
;
1496 #else /* if not HAVE_TERMIO */
1498 tty
.main
.tt_char
|= TT$M_NOECHO
;
1500 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
1502 tty
.main
.tt_char
|= TT$M_TTSYNC
;
1504 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
1505 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
1506 #else /* not VMS (BSD, that is) */
1508 XSETINT (Vtty_erase_char
, tty
.main
.sg_erase
);
1509 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
1511 tty
.main
.sg_flags
|= ANYP
;
1512 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
1513 #endif /* not DOS_NT */
1514 #endif /* not VMS (BSD, that is) */
1515 #endif /* not HAVE_TERMIO */
1517 /* If going to use CBREAK mode, we must request C-g to interrupt
1518 and turn off start and stop chars, etc. If not going to use
1519 CBREAK mode, do this anyway so as to turn off local flow
1520 control for user coming over network on 4.2; in this case,
1521 only t_stopc and t_startc really matter. */
1524 /* Note: if not using CBREAK mode, it makes no difference how we
1526 tty
.tchars
= new_tchars
;
1527 tty
.tchars
.t_intrc
= quit_char
;
1530 tty
.tchars
.t_startc
= '\021';
1531 tty
.tchars
.t_stopc
= '\023';
1534 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
1536 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1537 anything, and leaving it in breaks the meta key. Go figure. */
1538 tty
.lmode
&= ~LLITOUT
;
1545 #endif /* HAVE_TCHARS */
1546 #endif /* not HAVE_TERMIO */
1549 tty
.ltchars
= new_ltchars
;
1550 #endif /* HAVE_LTCHARS */
1551 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1553 internal_terminal_init ();
1557 EMACS_SET_TTY (input_fd
, &tty
, 0);
1559 /* This code added to insure that, if flow-control is not to be used,
1560 we have an unlocked terminal at the start. */
1563 if (!flow_control
) ioctl (input_fd
, TCXONC
, 1);
1567 if (!flow_control
) ioctl (input_fd
, TIOCSTART
, 0);
1571 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1573 if (!flow_control
) tcflow (input_fd
, TCOON
);
1581 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1582 to be only LF. This is the way that is done. */
1585 if (ioctl (1, HFTGETID
, &tty
) != -1)
1586 write (1, "\033[20l", 5);
1592 /* Appears to do nothing when in PASTHRU mode.
1593 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1594 interrupt_signal, oob_chars, 0, 0, 0, 0);
1596 queue_kbd_input (0);
1601 #ifndef F_SETOWN_BUG
1602 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1604 && ! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1606 old_fcntl_owner
= fcntl (input_fd
, F_GETOWN
, 0);
1607 fcntl (input_fd
, F_SETOWN
, getpid ());
1608 init_sigio (input_fd
);
1610 #endif /* F_GETOWN */
1611 #endif /* F_SETOWN_BUG */
1612 #endif /* F_SETFL */
1615 if (interrupt_input
)
1616 init_sigio (input_fd
);
1619 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1623 /* This symbol is defined on recent USG systems.
1624 Someone says without this call USG won't really buffer the file
1625 even with a call to setbuf. */
1626 setvbuf (stdout
, (char *) _sobuf
, _IOFBF
, sizeof _sobuf
);
1628 setbuf (stdout
, (char *) _sobuf
);
1630 #ifdef HAVE_WINDOW_SYSTEM
1631 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1632 needs the initialization code below. */
1633 if (EQ (Vwindow_system
, Qnil
)
1635 /* When running in tty mode on NT/Win95, we have a read_socket
1636 hook, but still need the rest of the initialization code below. */
1637 && (! read_socket_hook
)
1641 set_terminal_modes ();
1644 && FRAMEP (Vterminal_frame
)
1645 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame
)))
1646 init_frame_faces (XFRAME (Vterminal_frame
));
1648 if (term_initted
&& no_redraw_on_reenter
)
1650 if (display_completed
)
1651 direct_output_forward_char (0);
1656 if (FRAMEP (Vterminal_frame
))
1657 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
1663 /* Return nonzero if safe to use tabs in output.
1664 At the time this is called, init_sys_modes has not been done yet. */
1669 struct emacs_tty tty
;
1671 EMACS_GET_TTY (input_fd
, &tty
);
1672 return EMACS_TTY_TABS_OK (&tty
);
1675 /* Get terminal size from system.
1676 Store number of lines into *HEIGHTP and width into *WIDTHP.
1677 We store 0 if there's no valid information. */
1680 get_frame_size (widthp
, heightp
)
1681 int *widthp
, *heightp
;
1687 struct winsize size
;
1689 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1690 *widthp
= *heightp
= 0;
1693 *widthp
= size
.ws_col
;
1694 *heightp
= size
.ws_row
;
1700 /* SunOS - style. */
1701 struct ttysize size
;
1703 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1704 *widthp
= *heightp
= 0;
1707 *widthp
= size
.ts_cols
;
1708 *heightp
= size
.ts_lines
;
1714 struct sensemode tty
;
1716 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1717 &tty
.class, 12, 0, 0, 0, 0);
1718 *widthp
= tty
.scr_wid
;
1719 *heightp
= tty
.scr_len
;
1723 *widthp
= ScreenCols ();
1724 *heightp
= ScreenRows ();
1725 #else /* system doesn't know size */
1730 #endif /* not VMS */
1731 #endif /* not SunOS-style */
1732 #endif /* not BSD-style */
1735 /* Set the logical window size associated with descriptor FD
1736 to HEIGHT and WIDTH. This is used mainly with ptys. */
1739 set_window_size (fd
, height
, width
)
1740 int fd
, height
, width
;
1745 struct winsize size
;
1746 size
.ws_row
= height
;
1747 size
.ws_col
= width
;
1749 if (ioctl (fd
, TIOCSWINSZ
, &size
) == -1)
1750 return 0; /* error */
1757 /* SunOS - style. */
1758 struct ttysize size
;
1759 size
.ts_lines
= height
;
1760 size
.ts_cols
= width
;
1762 if (ioctl (fd
, TIOCGSIZE
, &size
) == -1)
1768 #endif /* not SunOS-style */
1769 #endif /* not BSD-style */
1773 /* Prepare the terminal for exiting Emacs; move the cursor to the
1774 bottom of the frame, turn off interrupt-driven I/O, etc. */
1787 #ifdef HAVE_WINDOW_SYSTEM
1788 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1789 needs the clean-up code below. */
1790 if (!EQ (Vwindow_system
, Qnil
)
1792 /* When running in tty mode on NT/Win95, we have a read_socket
1793 hook, but still need the rest of the clean-up code below. */
1799 sf
= SELECTED_FRAME ();
1800 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1801 clear_end_of_line (FRAME_WIDTH (sf
));
1802 /* clear_end_of_line may move the cursor */
1803 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1804 #if defined (IBMR2AIX) && defined (AIXHFT)
1806 /* HFT devices normally use ^J as a LF/CR. We forced it to
1807 do the LF only. Now, we need to reset it. */
1810 if (ioctl (1, HFTGETID
, &tty
) != -1)
1811 write (1, "\033[20h", 5);
1815 reset_terminal_modes ();
1819 /* Avoid possible loss of output when changing terminal modes. */
1820 fsync (fileno (stdout
));
1825 #ifndef F_SETOWN_BUG
1826 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1827 if (interrupt_input
)
1830 fcntl (input_fd
, F_SETOWN
, old_fcntl_owner
);
1832 #endif /* F_SETOWN */
1833 #endif /* F_SETOWN_BUG */
1835 fcntl (input_fd
, F_SETFL
, fcntl (input_fd
, F_GETFL
, 0) & ~O_NDELAY
);
1837 #endif /* F_SETFL */
1839 if (interrupt_input
)
1844 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1847 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1851 #ifdef SET_LINE_DISCIPLINE
1852 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1853 A different old line discipline is therefore not restored, yet.
1854 Restore the old line discipline by hand. */
1855 ioctl (0, TIOCSETD
, &old_tty
.main
.c_line
);
1863 widen_foreground_group ();
1869 /* Set up the proper status flags for use of a pty. */
1875 /* I'm told that TOICREMOTE does not mean control chars
1876 "can't be sent" but rather that they don't have
1877 input-editing or signaling effects.
1878 That should be good, because we have other ways
1879 to do those things in Emacs.
1880 However, telnet mode seems not to work on 4.2.
1881 So TIOCREMOTE is turned off now. */
1883 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1884 will hang. In particular, the "timeout" feature (which
1885 causes a read to return if there is no data available)
1886 does this. Also it is known that telnet mode will hang
1887 in such a way that Emacs must be stopped (perhaps this
1888 is the same problem).
1890 If TIOCREMOTE is turned off, then there is a bug in
1891 hp-ux which sometimes loses data. Apparently the
1892 code which blocks the master process when the internal
1893 buffer fills up does not work. Other than this,
1894 though, everything else seems to work fine.
1896 Since the latter lossage is more benign, we may as well
1897 lose that way. -- cph */
1899 #if defined(SYSV_PTYS) || defined(UNIX98_PTYS)
1902 ioctl (fd
, FIONBIO
, &on
);
1907 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1908 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1909 /* cause EMACS not to die when it should, i.e., when its own controlling */
1910 /* tty goes away. I've complained to the AIX developers, and they may */
1911 /* change this behavior, but I'm not going to hold my breath. */
1912 signal (SIGHUP
, SIG_IGN
);
1915 #endif /* HAVE_PTYS */
1919 /* Assigning an input channel is done at the start of Emacs execution.
1920 This is called each time Emacs is resumed, also, but does nothing
1921 because input_chain is no longer zero. */
1930 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1936 /* Deassigning the input channel is done before exiting. */
1941 return SYS$
DASSGN (input_fd
);
1946 /* Request reading one character into the keyboard buffer.
1947 This is done as soon as the buffer becomes empty. */
1953 extern kbd_input_ast ();
1955 waiting_for_ast
= 0;
1957 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1958 &input_iosb
, kbd_input_ast
, 1,
1959 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1964 /* Ast routine that is called when keyboard input comes in
1965 in accord with the SYS$QIO above. */
1970 register int c
= -1;
1971 int old_errno
= errno
;
1972 extern EMACS_TIME
*input_available_clear_time
;
1974 if (waiting_for_ast
)
1975 SYS$
SETEF (input_ef
);
1976 waiting_for_ast
= 0;
1979 if (input_count
== 25)
1981 printf ("Ast # %d,", input_count
);
1982 printf (" iosb = %x, %x, %x, %x",
1983 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1986 if (input_iosb
.offset
)
1990 printf (", char = 0%o", c
);
2002 struct input_event e
;
2003 e
.kind
= ascii_keystroke
;
2004 XSETINT (e
.code
, c
);
2005 e
.frame_or_window
= selected_frame
;
2006 kbd_buffer_store_event (&e
);
2008 if (input_available_clear_time
)
2009 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
2013 /* Wait until there is something in kbd_buffer. */
2016 wait_for_kbd_input ()
2018 extern int have_process_input
, process_exited
;
2020 /* If already something, avoid doing system calls. */
2021 if (detect_input_pending ())
2025 /* Clear a flag, and tell ast routine above to set it. */
2026 SYS$
CLREF (input_ef
);
2027 waiting_for_ast
= 1;
2028 /* Check for timing error: ast happened while we were doing that. */
2029 if (!detect_input_pending ())
2031 /* No timing error: wait for flag to be set. */
2032 set_waiting_for_input (0);
2033 SYS$
WFLOR (input_ef
, input_eflist
);
2034 clear_waiting_for_input (0);
2035 if (!detect_input_pending ())
2036 /* Check for subprocess input availability */
2038 int dsp
= have_process_input
|| process_exited
;
2040 SYS$
CLREF (process_ef
);
2041 if (have_process_input
)
2042 process_command_input ();
2047 update_mode_lines
++;
2048 prepare_menu_bars ();
2049 redisplay_preserve_echo_area ();
2053 waiting_for_ast
= 0;
2056 /* Get rid of any pending QIO, when we are about to suspend
2057 or when we want to throw away pending input.
2058 We wait for a positive sign that the AST routine has run
2059 and therefore there is no I/O request queued when we return.
2060 SYS$SETAST is used to avoid a timing error. */
2066 printf ("At end_kbd_input.\n");
2070 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2072 SYS$
CANCEL (input_fd
);
2077 /* Clear a flag, and tell ast routine above to set it. */
2078 SYS$
CLREF (input_ef
);
2079 waiting_for_ast
= 1;
2081 SYS$
CANCEL (input_fd
);
2083 SYS$
WAITFR (input_ef
);
2084 waiting_for_ast
= 0;
2087 /* Wait for either input available or time interval expiry. */
2090 input_wait_timeout (timeval
)
2091 int timeval
; /* Time to wait, in seconds */
2094 static int zero
= 0;
2095 static int large
= -10000000;
2097 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2099 /* If already something, avoid doing system calls. */
2100 if (detect_input_pending ())
2104 /* Clear a flag, and tell ast routine above to set it. */
2105 SYS$
CLREF (input_ef
);
2106 waiting_for_ast
= 1;
2107 /* Check for timing error: ast happened while we were doing that. */
2108 if (!detect_input_pending ())
2110 /* No timing error: wait for flag to be set. */
2112 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2113 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
2115 waiting_for_ast
= 0;
2118 /* The standard `sleep' routine works some other way
2119 and it stops working if you have ever quit out of it.
2120 This one continues to work. */
2126 static int zero
= 0;
2127 static int large
= -10000000;
2129 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2132 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2133 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
2151 croak ("request sigio");
2157 croak ("unrequest sigio");
2162 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2167 #ifndef SYSTEM_MALLOC
2174 /* Some systems that cannot dump also cannot implement these. */
2177 * Return the address of the start of the text segment prior to
2178 * doing an unexec. After unexec the return value is undefined.
2179 * See crt0.c for further explanation and _start.
2183 #if !(defined (__NetBSD__) && defined (__ELF__))
2184 #ifndef HAVE_TEXT_START
2189 return ((char *) TEXT_START
);
2193 return ((char *) csrt
);
2194 #else /* not GOULD */
2195 extern int _start ();
2196 return ((char *) _start
);
2198 #endif /* TEXT_START */
2200 #endif /* not HAVE_TEXT_START */
2204 * Return the address of the start of the data segment prior to
2205 * doing an unexec. After unexec the return value is undefined.
2206 * See crt0.c for further information and definition of data_start.
2208 * Apparently, on BSD systems this is etext at startup. On
2209 * USG systems (swapping) this is highly mmu dependent and
2210 * is also dependent on whether or not the program is running
2211 * with shared text. Generally there is a (possibly large)
2212 * gap between end of text and start of data with shared text.
2214 * On Uniplus+ systems with shared text, data starts at a
2215 * fixed address. Each port (from a given oem) is generally
2216 * different, and the specific value of the start of data can
2217 * be obtained via the UniPlus+ specific "uvar" system call,
2218 * however the method outlined in crt0.c seems to be more portable.
2220 * Probably what will have to happen when a USG unexec is available,
2221 * at least on UniPlus, is temacs will have to be made unshared so
2222 * that text and data are contiguous. Then once loadup is complete,
2223 * unexec will produce a shared executable where the data can be
2224 * at the normal shared text boundary and the startofdata variable
2225 * will be patched by unexec to the correct value.
2233 return ((char *) DATA_START
);
2235 #ifdef ORDINARY_LINK
2237 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2238 * data_start isn't defined. We take the address of environ, which
2239 * is known to live at or near the start of the system crt0.c, and
2240 * we don't sweat the handful of bytes that might lose.
2242 extern char **environ
;
2244 return ((char *) &environ
);
2246 extern int data_start
;
2247 return ((char *) &data_start
);
2248 #endif /* ORDINARY_LINK */
2249 #endif /* DATA_START */
2251 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2254 /* Some systems that cannot dump also cannot implement these. */
2257 * Return the address of the end of the text segment prior to
2258 * doing an unexec. After unexec the return value is undefined.
2265 return ((char *) TEXT_END
);
2268 return ((char *) &etext
);
2273 * Return the address of the end of the data segment prior to
2274 * doing an unexec. After unexec the return value is undefined.
2281 return ((char *) DATA_END
);
2284 return ((char *) &edata
);
2288 #endif /* not CANNOT_DUMP */
2290 /* init_system_name sets up the string for the Lisp function
2291 system-name to return. */
2297 extern Lisp_Object Vsystem_name
;
2302 #include <sys/socket.h>
2304 #endif /* HAVE_SOCKETS */
2305 #endif /* not VMS */
2306 #endif /* not BSD4_1 */
2312 Vsystem_name
= build_string (sysname
);
2316 if ((sp
= egetenv ("SYS$NODE")) == 0)
2317 Vsystem_name
= build_string ("vax-vms");
2318 else if ((end
= index (sp
, ':')) == 0)
2319 Vsystem_name
= build_string (sp
);
2321 Vsystem_name
= make_string (sp
, end
- sp
);
2323 #ifndef HAVE_GETHOSTNAME
2326 Vsystem_name
= build_string (uts
.nodename
);
2327 #else /* HAVE_GETHOSTNAME */
2328 unsigned int hostname_size
= 256;
2329 char *hostname
= (char *) alloca (hostname_size
);
2331 /* Try to get the host name; if the buffer is too short, try
2332 again. Apparently, the only indication gethostname gives of
2333 whether the buffer was large enough is the presence or absence
2334 of a '\0' in the string. Eech. */
2337 gethostname (hostname
, hostname_size
- 1);
2338 hostname
[hostname_size
- 1] = '\0';
2340 /* Was the buffer large enough for the '\0'? */
2341 if (strlen (hostname
) < hostname_size
- 1)
2344 hostname_size
<<= 1;
2345 hostname
= (char *) alloca (hostname_size
);
2348 /* Turn the hostname into the official, fully-qualified hostname.
2349 Don't do this if we're going to dump; this can confuse system
2350 libraries on some machines and make the dumped emacs core dump. */
2353 #endif /* not CANNOT_DUMP */
2354 if (! index (hostname
, '.'))
2358 for (count
= 0;; count
++)
2363 hp
= gethostbyname (hostname
);
2365 if (! (hp
== 0 && h_errno
== TRY_AGAIN
))
2370 Fsleep_for (make_number (1), Qnil
);
2374 char *fqdn
= (char *) hp
->h_name
;
2377 if (!index (fqdn
, '.'))
2379 /* We still don't have a fully qualified domain name.
2380 Try to find one in the list of alternate names */
2381 char **alias
= hp
->h_aliases
;
2382 while (*alias
&& !index (*alias
, '.'))
2389 /* Convert the host name to lower case. */
2390 /* Using ctype.h here would introduce a possible locale
2391 dependence that is probably wrong for hostnames. */
2395 if (*p
>= 'A' && *p
<= 'Z')
2402 #endif /* HAVE_SOCKETS */
2403 /* We used to try using getdomainname here,
2404 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2405 getdomainname gets the NIS/YP domain which often is not the same
2406 as in Internet domain name. */
2407 #if 0 /* Turned off because sysinfo is not really likely to return the
2408 correct Internet domain. */
2409 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2410 if (! index (hostname
, '.'))
2412 /* The hostname is not fully qualified. Append the domain name. */
2414 int hostlen
= strlen (hostname
);
2415 int domain_size
= 256;
2419 char *domain
= (char *) alloca (domain_size
+ 1);
2420 char *fqdn
= (char *) alloca (hostlen
+ 1 + domain_size
+ 1);
2421 int sys_domain_size
= sysinfo (SI_SRPC_DOMAIN
, domain
, domain_size
);
2422 if (sys_domain_size
<= 0)
2424 if (domain_size
< sys_domain_size
)
2426 domain_size
= sys_domain_size
;
2429 strcpy (fqdn
, hostname
);
2430 if (domain
[0] == '.')
2431 strcpy (fqdn
+ hostlen
, domain
);
2432 else if (domain
[0] != 0)
2434 fqdn
[hostlen
] = '.';
2435 strcpy (fqdn
+ hostlen
+ 1, domain
);
2441 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2443 Vsystem_name
= build_string (hostname
);
2444 #endif /* HAVE_GETHOSTNAME */
2449 for (p
= XSTRING (Vsystem_name
)->data
; *p
; p
++)
2450 if (*p
== ' ' || *p
== '\t')
2457 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2459 #include "sysselect.h"
2462 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2463 /* Cause explanatory error message at compile time,
2464 since the select emulation is not good enough for X. */
2465 int *x
= &x_windows_lose_if_no_select_system_call
;
2468 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2469 * Only checks read descriptors.
2471 /* How long to wait between checking fds in select */
2472 #define SELECT_PAUSE 1
2475 /* For longjmp'ing back to read_input_waiting. */
2477 jmp_buf read_alarm_throw
;
2479 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2480 The read_socket_hook function sets this to 1 while it is waiting. */
2482 int read_alarm_should_throw
;
2490 #else /* not BSD4_1 */
2491 signal (SIGALRM
, SIG_IGN
);
2492 #endif /* not BSD4_1 */
2493 if (read_alarm_should_throw
)
2494 longjmp (read_alarm_throw
, 1);
2498 /* Only rfds are checked. */
2500 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2502 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2503 EMACS_TIME
*timeout
;
2509 extern int proc_buffered_char
[];
2510 #ifndef subprocesses
2511 int process_tick
= 0, update_tick
= 0;
2513 extern int process_tick
, update_tick
;
2517 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2518 /* If we're using X, then the native select will work; we only need the
2519 emulation for non-X usage. */
2520 if (!NILP (Vwindow_system
))
2521 return select (nfds
, rfds
, wfds
, efds
, timeout
);
2523 timeoutval
= timeout
? EMACS_SECS (*timeout
) : 100000;
2524 local_timeout
= &timeoutval
;
2536 /* If we are looking only for the terminal, with no timeout,
2537 just read it and wait -- that's more efficient. */
2538 if (*local_timeout
== 100000 && process_tick
== update_tick
2539 && FD_ISSET (0, &orfds
))
2542 for (fd
= 1; fd
< nfds
; ++fd
)
2543 if (FD_ISSET (fd
, &orfds
))
2545 if (! detect_input_pending ())
2546 read_input_waiting ();
2552 /* Once a second, till the timer expires, check all the flagged read
2553 * descriptors to see if any input is available. If there is some then
2554 * set the corresponding bit in the return copy of rfds.
2558 register int to_check
, fd
;
2562 for (to_check
= nfds
, fd
= 0; --to_check
>= 0; fd
++)
2564 if (FD_ISSET (fd
, &orfds
))
2566 int avail
= 0, status
= 0;
2569 avail
= detect_input_pending (); /* Special keyboard handler */
2573 status
= ioctl (fd
, FIONREAD
, &avail
);
2574 #else /* no FIONREAD */
2575 /* Hoping it will return -1 if nothing available
2576 or 0 if all 0 chars requested are read. */
2577 if (proc_buffered_char
[fd
] >= 0)
2581 avail
= read (fd
, &buf
, 1);
2583 proc_buffered_char
[fd
] = buf
;
2585 #endif /* no FIONREAD */
2587 if (status
>= 0 && avail
> 0)
2595 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
2598 turn_on_atimers (0);
2599 signal (SIGALRM
, select_alarm
);
2601 alarm (SELECT_PAUSE
);
2603 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2604 while (select_alarmed
== 0 && *local_timeout
!= 0
2605 && process_tick
== update_tick
)
2607 /* If we are interested in terminal input,
2608 wait by reading the terminal.
2609 That makes instant wakeup for terminal input at least. */
2610 if (FD_ISSET (0, &orfds
))
2612 read_input_waiting ();
2613 if (detect_input_pending ())
2619 (*local_timeout
) -= SELECT_PAUSE
;
2621 /* Reset the old alarm if there was one. */
2622 turn_on_atimers (1);
2624 if (*local_timeout
== 0) /* Stop on timer being cleared */
2629 #endif /* not WINDOWSNT */
2631 /* Read keyboard input into the standard buffer,
2632 waiting for at least one character. */
2634 /* Make all keyboard buffers much bigger when using a window system. */
2635 #ifdef HAVE_WINDOW_SYSTEM
2636 #define BUFFER_SIZE_FACTOR 16
2638 #define BUFFER_SIZE_FACTOR 1
2642 read_input_waiting ()
2644 struct input_event e
;
2646 extern int quit_char
;
2648 if (read_socket_hook
)
2650 struct input_event buf
[256];
2652 read_alarm_should_throw
= 0;
2653 if (! setjmp (read_alarm_throw
))
2654 nread
= (*read_socket_hook
) (0, buf
, 256, 1);
2658 /* Scan the chars for C-g and store them in kbd_buffer. */
2659 for (i
= 0; i
< nread
; i
++)
2661 kbd_buffer_store_event (&buf
[i
]);
2662 /* Don't look at input that follows a C-g too closely.
2663 This reduces lossage due to autorepeat on C-g. */
2664 if (buf
[i
].kind
== ascii_keystroke
2665 && buf
[i
].code
== quit_char
)
2672 nread
= read (fileno (stdin
), buf
, 1);
2674 /* Scan the chars for C-g and store them in kbd_buffer. */
2675 e
.kind
= ascii_keystroke
;
2676 e
.frame_or_window
= selected_frame
;
2678 for (i
= 0; i
< nread
; i
++)
2680 /* Convert chars > 0177 to meta events if desired.
2681 We do this under the same conditions that read_avail_input does. */
2682 if (read_socket_hook
== 0)
2684 /* If the user says she has a meta key, then believe her. */
2685 if (meta_key
== 1 && (buf
[i
] & 0x80))
2686 e
.modifiers
= meta_modifier
;
2691 XSETINT (e
.code
, buf
[i
]);
2692 kbd_buffer_store_event (&e
);
2693 /* Don't look at input that follows a C-g too closely.
2694 This reduces lossage due to autorepeat on C-g. */
2695 if (buf
[i
] == quit_char
)
2701 #endif /* not HAVE_SELECT */
2702 #endif /* not VMS */
2703 #endif /* not MSDOS */
2712 lmode
= LINTRUP
| lmode
;
2713 ioctl (fd
, TIOCLSET
, &lmode
);
2721 lmode
= ~LINTRUP
& lmode
;
2722 ioctl (0, TIOCLSET
, &lmode
);
2730 interrupts_deferred
= 0;
2738 interrupts_deferred
= 1;
2741 /* still inside #ifdef BSD4_1 */
2744 int sigheld
; /* Mask of held signals */
2750 sigheld
|= sigbit (signum
);
2758 sigheld
|= sigbit (signum
);
2765 sigheld
&= ~sigbit (signum
);
2770 sigfree () /* Free all held signals */
2773 for (i
= 0; i
< NSIG
; i
++)
2774 if (sigheld
& sigbit (i
))
2782 return 1 << (i
- 1);
2784 #endif /* subprocesses */
2787 /* POSIX signals support - DJB */
2788 /* Anyone with POSIX signals should have ANSI C declarations */
2790 #ifdef POSIX_SIGNALS
2792 sigset_t empty_mask
, full_mask
;
2795 sys_signal (int signal_number
, signal_handler_t action
)
2797 struct sigaction new_action
, old_action
;
2798 sigemptyset (&new_action
.sa_mask
);
2799 new_action
.sa_handler
= action
;
2801 /* Emacs mostly works better with restartable system services. If this
2802 * flag exists, we probably want to turn it on here.
2804 new_action
.sa_flags
= SA_RESTART
;
2806 new_action
.sa_flags
= 0;
2808 sigaction (signal_number
, &new_action
, &old_action
);
2809 return (old_action
.sa_handler
);
2813 /* If we're compiling with GCC, we don't need this function, since it
2814 can be written as a macro. */
2816 sys_sigmask (int sig
)
2819 sigemptyset (&mask
);
2820 sigaddset (&mask
, sig
);
2825 /* I'd like to have these guys return pointers to the mask storage in here,
2826 but there'd be trouble if the code was saving multiple masks. I'll be
2827 safe and pass the structure. It normally won't be more than 2 bytes
2831 sys_sigblock (sigset_t new_mask
)
2834 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
2839 sys_sigunblock (sigset_t new_mask
)
2842 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
2847 sys_sigsetmask (sigset_t new_mask
)
2850 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
2854 #endif /* POSIX_SIGNALS */
2856 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2857 static char *my_sys_siglist
[NSIG
];
2861 # define sys_siglist my_sys_siglist
2867 #ifdef POSIX_SIGNALS
2868 sigemptyset (&empty_mask
);
2869 sigfillset (&full_mask
);
2872 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2876 sys_siglist
[SIGABRT
] = "Aborted";
2879 sys_siglist
[SIGAIO
] = "LAN I/O interrupt";
2882 sys_siglist
[SIGALRM
] = "Alarm clock";
2885 sys_siglist
[SIGBUS
] = "Bus error";
2888 sys_siglist
[SIGCLD
] = "Child status changed";
2891 sys_siglist
[SIGCHLD
] = "Child status changed";
2894 sys_siglist
[SIGCONT
] = "Continued";
2897 sys_siglist
[SIGDANGER
] = "Swap space dangerously low";
2900 sys_siglist
[SIGDGNOTIFY
] = "Notification message in queue";
2903 sys_siglist
[SIGEMT
] = "Emulation trap";
2906 sys_siglist
[SIGFPE
] = "Arithmetic exception";
2909 sys_siglist
[SIGFREEZE
] = "SIGFREEZE";
2912 sys_siglist
[SIGGRANT
] = "Monitor mode granted";
2915 sys_siglist
[SIGHUP
] = "Hangup";
2918 sys_siglist
[SIGILL
] = "Illegal instruction";
2921 sys_siglist
[SIGINT
] = "Interrupt";
2924 sys_siglist
[SIGIO
] = "I/O possible";
2927 sys_siglist
[SIGIOINT
] = "I/O intervention required";
2930 sys_siglist
[SIGIOT
] = "IOT trap";
2933 sys_siglist
[SIGKILL
] = "Killed";
2936 sys_siglist
[SIGLOST
] = "Resource lost";
2939 sys_siglist
[SIGLWP
] = "SIGLWP";
2942 sys_siglist
[SIGMSG
] = "Monitor mode data available";
2945 sys_siglist
[SIGWIND
] = "SIGPHONE";
2948 sys_siglist
[SIGPIPE
] = "Broken pipe";
2951 sys_siglist
[SIGPOLL
] = "Pollable event occurred";
2954 sys_siglist
[SIGPROF
] = "Profiling timer expired";
2957 sys_siglist
[SIGPTY
] = "PTY I/O interrupt";
2960 sys_siglist
[SIGPWR
] = "Power-fail restart";
2963 sys_siglist
[SIGQUIT
] = "Quit";
2966 sys_siglist
[SIGRETRACT
] = "Need to relinguish monitor mode";
2969 sys_siglist
[SIGSAK
] = "Secure attention";
2972 sys_siglist
[SIGSEGV
] = "Segmentation violation";
2975 sys_siglist
[SIGSOUND
] = "Sound completed";
2978 sys_siglist
[SIGSTOP
] = "Stopped (signal)";
2981 sys_siglist
[SIGSTP
] = "Stopped (user)";
2984 sys_siglist
[SIGSYS
] = "Bad argument to system call";
2987 sys_siglist
[SIGTERM
] = "Terminated";
2990 sys_siglist
[SIGTHAW
] = "SIGTHAW";
2993 sys_siglist
[SIGTRAP
] = "Trace/breakpoint trap";
2996 sys_siglist
[SIGTSTP
] = "Stopped (user)";
2999 sys_siglist
[SIGTTIN
] = "Stopped (tty input)";
3002 sys_siglist
[SIGTTOU
] = "Stopped (tty output)";
3005 sys_siglist
[SIGURG
] = "Urgent I/O condition";
3008 sys_siglist
[SIGUSR1
] = "User defined signal 1";
3011 sys_siglist
[SIGUSR2
] = "User defined signal 2";
3014 sys_siglist
[SIGVTALRM
] = "Virtual timer expired";
3017 sys_siglist
[SIGWAITING
] = "Process's LWPs are blocked";
3020 sys_siglist
[SIGWINCH
] = "Window size changed";
3023 sys_siglist
[SIGWIND
] = "SIGWIND";
3026 sys_siglist
[SIGXCPU
] = "CPU time limit exceeded";
3029 sys_siglist
[SIGXFSZ
] = "File size limit exceeded";
3032 #endif /* !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED */
3041 /* Figure out how many bits the system's random number generator uses.
3042 `random' and `lrand48' are assumed to return 31 usable bits.
3043 BSD `rand' returns a 31 bit value but the low order bits are unusable;
3044 so we'll shift it and treat it like the 15-bit USG `rand'. */
3048 # define RAND_BITS 31
3049 # else /* !HAVE_RANDOM */
3050 # ifdef HAVE_LRAND48
3051 # define RAND_BITS 31
3052 # define random lrand48
3053 # else /* !HAVE_LRAND48 */
3054 # define RAND_BITS 15
3055 # if RAND_MAX == 32767
3056 # define random rand
3057 # else /* RAND_MAX != 32767 */
3058 # if RAND_MAX == 2147483647
3059 # define random() (rand () >> 16)
3060 # else /* RAND_MAX != 2147483647 */
3062 # define random rand
3064 # define random() (rand () >> 16)
3066 # endif /* RAND_MAX != 2147483647 */
3067 # endif /* RAND_MAX != 32767 */
3068 # endif /* !HAVE_LRAND48 */
3069 # endif /* !HAVE_RANDOM */
3070 #endif /* !RAND_BITS */
3077 srandom ((unsigned int)arg
);
3079 # ifdef HAVE_LRAND48
3082 srand ((unsigned int)arg
);
3088 * Build a full Emacs-sized word out of whatever we've got.
3089 * This suffices even for a 64-bit architecture with a 15-bit rand.
3094 long val
= random ();
3095 #if VALBITS > RAND_BITS
3096 val
= (val
<< RAND_BITS
) ^ random ();
3097 #if VALBITS > 2*RAND_BITS
3098 val
= (val
<< RAND_BITS
) ^ random ();
3099 #if VALBITS > 3*RAND_BITS
3100 val
= (val
<< RAND_BITS
) ^ random ();
3101 #if VALBITS > 4*RAND_BITS
3102 val
= (val
<< RAND_BITS
) ^ random ();
3103 #endif /* need at least 5 */
3104 #endif /* need at least 4 */
3105 #endif /* need at least 3 */
3106 #endif /* need at least 2 */
3107 return val
& ((1L << VALBITS
) - 1);
3110 #ifdef WRONG_NAME_INSQUE
3123 /* If any place else asks for the TERM variable,
3124 allow it to be overridden with the EMACS_TERM variable
3125 before attempting to translate the logical name TERM. As a last
3126 resort, ask for VAX C's special idea of the TERM variable. */
3133 static char buf
[256];
3134 static struct dsc$descriptor_s equiv
3135 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
3136 static struct dsc$descriptor_s d_name
3137 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
3140 if (!strcmp (name
, "TERM"))
3142 val
= (char *) getenv ("EMACS_TERM");
3147 d_name
.dsc$w_length
= strlen (name
);
3148 d_name
.dsc$a_pointer
= name
;
3149 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
3151 char *str
= (char *) xmalloc (eqlen
+ 1);
3152 bcopy (buf
, str
, eqlen
);
3154 /* This is a storage leak, but a pain to fix. With luck,
3155 no one will ever notice. */
3158 return (char *) getenv (name
);
3163 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3164 to force a call on the debugger from within the image. */
3169 LIB$
SIGNAL (SS$_DEBUG
);
3175 #ifdef LINK_CRTL_SHARE
3176 #ifdef SHARABLE_LIB_BUG
3177 /* Variables declared noshare and initialized in sharable libraries
3178 cannot be shared. The VMS linker incorrectly forces you to use a private
3179 version which is uninitialized... If not for this "feature", we
3180 could use the C library definition of sys_nerr and sys_errlist. */
3182 char *sys_errlist
[] =
3186 "no such file or directory",
3188 "interrupted system call",
3190 "no such device or address",
3191 "argument list too long",
3192 "exec format error",
3195 "no more processes",
3196 "not enough memory",
3197 "permission denied",
3199 "block device required",
3200 "mount devices busy",
3202 "cross-device link",
3207 "file table overflow",
3208 "too many open files",
3212 "no space left on device",
3214 "read-only file system",
3220 "vax/vms specific error code nontranslatable error"
3222 #endif /* SHARABLE_LIB_BUG */
3223 #endif /* LINK_CRTL_SHARE */
3226 #ifndef HAVE_STRERROR
3232 extern char *sys_errlist
[];
3233 extern int sys_nerr
;
3235 if (errnum
>= 0 && errnum
< sys_nerr
)
3236 return sys_errlist
[errnum
];
3237 return (char *) "Unknown error";
3239 #endif /* not WINDOWSNT */
3240 #endif /* ! HAVE_STRERROR */
3243 emacs_open (path
, oflag
, mode
)
3247 register int rtnval
;
3250 if (oflag
& O_CREAT
)
3251 return creat (path
, mode
);
3254 while ((rtnval
= open (path
, oflag
, mode
)) == -1
3255 && (errno
== EINTR
));
3264 register int rtnval
;
3266 while ((rtnval
= close (fd
)) == -1
3267 && (errno
== EINTR
))
3270 /* If close is interrupted SunOS 4.1 may or may not have closed the
3271 file descriptor. If it did the second close will fail with
3272 errno = EBADF. That means we have succeeded. */
3273 if (rtnval
== -1 && did_retry
&& errno
== EBADF
)
3280 emacs_read (fildes
, buf
, nbyte
)
3285 register int rtnval
;
3287 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
3288 && (errno
== EINTR
));
3293 emacs_write (fildes
, buf
, nbyte
)
3298 register int rtnval
, bytes_written
;
3304 rtnval
= write (fildes
, buf
, nbyte
);
3311 return (bytes_written
? bytes_written
: -1);
3316 bytes_written
+= rtnval
;
3318 return (bytes_written
);
3323 * All of the following are for USG.
3325 * On USG systems the system calls are INTERRUPTIBLE by signals
3326 * that the user program has elected to catch. Thus the system call
3327 * must be retried in these cases. To handle this without massive
3328 * changes in the source code, we remap the standard system call names
3329 * to names for our own functions in sysdep.c that do the system call
3330 * with retries. Actually, for portability reasons, it is good
3331 * programming practice, as this example shows, to limit all actual
3332 * system calls to a single occurrence in the source. Sure, this
3333 * adds an extra level of function call overhead but it is almost
3334 * always negligible. Fred Fish, Unisoft Systems Inc.
3338 * Warning, this function may not duplicate 4.2 action properly
3339 * under error conditions.
3343 /* In 4.1, param.h fails to define this. */
3344 #define MAXPATHLEN 1024
3353 char *npath
, *spath
;
3354 extern char *getcwd ();
3356 BLOCK_INPUT
; /* getcwd uses malloc */
3357 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
3360 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3361 up to first slash. Should be harmless on other systems. */
3362 while (*npath
&& *npath
!= '/')
3364 strcpy (pathname
, npath
);
3365 free (spath
); /* getcwd uses malloc */
3370 #endif /* HAVE_GETWD */
3373 * Emulate rename using unlink/link. Note that this is
3374 * only partially correct. Also, doesn't enforce restriction
3375 * that files be of same type (regular->regular, dir->dir, etc).
3384 if (access (from
, 0) == 0)
3387 if (link (from
, to
) == 0)
3388 if (unlink (from
) == 0)
3400 /* HPUX curses library references perror, but as far as we know
3401 it won't be called. Anyway this definition will do for now. */
3407 #endif /* not HAVE_PERROR */
3413 * Emulate BSD dup2. First close newd if it already exists.
3414 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3415 * until we are, then close the unsuccessful ones.
3422 register int fd
, ret
;
3427 return fcntl (oldd
, F_DUPFD
, newd
);
3434 ret
= dup2 (old
,new);
3440 #endif /* not HAVE_DUP2 */
3443 * Gettimeofday. Simulate as much as possible. Only accurate
3444 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3445 * Only needed when subprocesses are defined.
3450 #ifndef HAVE_GETTIMEOFDAY
3455 gettimeofday (tp
, tzp
)
3457 struct timezone
*tzp
;
3459 extern long time ();
3461 tp
->tv_sec
= time ((long *)0);
3464 tzp
->tz_minuteswest
= -1;
3471 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3474 * This function will go away as soon as all the stubs fixed. (fnf)
3481 printf ("%s not yet implemented\r\n", badfunc
);
3488 /* Directory routines for systems that don't have them. */
3490 #ifdef SYSV_SYSTEM_DIR
3494 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3498 register DIR *dirp
; /* stream from opendir */
3502 rtnval
= emacs_close (dirp
->dd_fd
);
3504 /* Some systems (like Solaris) allocate the buffer and the DIR all
3505 in one block. Why in the world are we freeing this ourselves
3507 #if ! (defined (sun) && defined (USG5_4))
3508 xfree ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
3510 xfree ((char *) dirp
);
3514 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3515 #endif /* SYSV_SYSTEM_DIR */
3517 #ifdef NONSYSTEM_DIR_LIBRARY
3521 char *filename
; /* name of directory */
3523 register DIR *dirp
; /* -> malloc'ed storage */
3524 register int fd
; /* file descriptor for read */
3525 struct stat sbuf
; /* result of fstat */
3527 fd
= emacs_open (filename
, O_RDONLY
, 0);
3532 if (fstat (fd
, &sbuf
) < 0
3533 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
3534 || (dirp
= (DIR *) xmalloc (sizeof (DIR))) == 0)
3538 return 0; /* bad luck today */
3543 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
3550 register DIR *dirp
; /* stream from opendir */
3552 emacs_close (dirp
->dd_fd
);
3553 xfree ((char *) dirp
);
3561 ino_t od_ino
; /* inode */
3562 char od_name
[DIRSIZ
]; /* filename */
3564 #endif /* not VMS */
3566 struct direct dir_static
; /* simulated directory contents */
3571 register DIR *dirp
; /* stream from opendir */
3574 register struct olddir
*dp
; /* -> directory data */
3576 register struct dir$_name
*dp
; /* -> directory data */
3577 register struct dir$_version
*dv
; /* -> version data */
3582 if (dirp
->dd_loc
>= dirp
->dd_size
)
3583 dirp
->dd_loc
= dirp
->dd_size
= 0;
3585 if (dirp
->dd_size
== 0 /* refill buffer */
3586 && (dirp
->dd_size
= emacs_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3590 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
3591 dirp
->dd_loc
+= sizeof (struct olddir
);
3593 if (dp
->od_ino
!= 0) /* not deleted entry */
3595 dir_static
.d_ino
= dp
->od_ino
;
3596 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
3597 dir_static
.d_name
[DIRSIZ
] = '\0';
3598 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3599 dir_static
.d_reclen
= sizeof (struct direct
)
3601 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3602 return &dir_static
; /* -> simulated structure */
3605 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3606 if (dirp
->dd_loc
== 0)
3607 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
3608 : dp
->dir$b_namecount
;
3609 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
3610 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3611 dir_static
.d_namlen
= dp
->dir$b_namecount
;
3612 dir_static
.d_reclen
= sizeof (struct direct
)
3614 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3615 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3616 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
3617 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
3624 /* readdirver is just like readdir except it returns all versions of a file
3625 as separate entries. */
3630 register DIR *dirp
; /* stream from opendir */
3632 register struct dir$_name
*dp
; /* -> directory data */
3633 register struct dir$_version
*dv
; /* -> version data */
3635 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
3636 dirp
->dd_loc
= dirp
->dd_size
= 0;
3638 if (dirp
->dd_size
== 0 /* refill buffer */
3639 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3642 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3643 if (dirp
->dd_loc
== 0)
3644 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
3645 : dp
->dir$b_namecount
;
3646 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
3647 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3648 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
3649 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3650 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3651 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
3652 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3653 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
3659 #endif /* NONSYSTEM_DIR_LIBRARY */
3663 set_file_times (filename
, atime
, mtime
)
3665 EMACS_TIME atime
, mtime
;
3668 struct timeval tv
[2];
3671 return utimes (filename
, tv
);
3672 #else /* not HAVE_UTIMES */
3674 utb
.actime
= EMACS_SECS (atime
);
3675 utb
.modtime
= EMACS_SECS (mtime
);
3676 return utime (filename
, &utb
);
3677 #endif /* not HAVE_UTIMES */
3680 /* mkdir and rmdir functions, for systems which don't have them. */
3684 * Written by Robert Rother, Mariah Corporation, August 1985.
3686 * If you want it, it's yours. All I ask in return is that if you
3687 * figure out how to do this in a Bourne Shell script you send me
3689 * sdcsvax!rmr or rmr@uscd
3691 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3692 * subroutine. 11Mar86; hoptoad!gnu
3694 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3695 * subroutine didn't return EEXIST. It does now.
3701 #ifdef MKDIR_PROTOTYPE
3705 mkdir (dpath
, dmode
)
3710 int cpid
, status
, fd
;
3711 struct stat statbuf
;
3713 if (stat (dpath
, &statbuf
) == 0)
3715 errno
= EEXIST
; /* Stat worked, so it already exists */
3719 /* If stat fails for a reason other than non-existence, return error */
3720 if (errno
!= ENOENT
)
3723 synch_process_alive
= 1;
3724 switch (cpid
= fork ())
3727 case -1: /* Error in fork */
3728 return (-1); /* Errno is set already */
3730 case 0: /* Child process */
3732 * Cheap hack to set mode of new directory. Since this
3733 * child process is going away anyway, we zap its umask.
3734 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3735 * directory. Does anybody care?
3737 status
= umask (0); /* Get current umask */
3738 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
3739 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3746 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
3747 _exit (-1); /* Can't exec /bin/mkdir */
3749 default: /* Parent process */
3750 wait_for_termination (cpid
);
3753 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3755 errno
= EIO
; /* We don't know why, but */
3756 return -1; /* /bin/mkdir failed */
3761 #endif /* not HAVE_MKDIR */
3768 int cpid
, status
, fd
;
3769 struct stat statbuf
;
3771 if (stat (dpath
, &statbuf
) != 0)
3773 /* Stat just set errno. We don't have to */
3777 synch_process_alive
= 1;
3778 switch (cpid
= fork ())
3781 case -1: /* Error in fork */
3782 return (-1); /* Errno is set already */
3784 case 0: /* Child process */
3785 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3792 execl ("/bin/rmdir", "rmdir", dpath
, (char *) 0);
3793 _exit (-1); /* Can't exec /bin/rmdir */
3795 default: /* Parent process */
3796 wait_for_termination (cpid
);
3799 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3801 errno
= EIO
; /* We don't know why, but */
3802 return -1; /* /bin/rmdir failed */
3807 #endif /* !HAVE_RMDIR */
3811 /* Functions for VMS */
3813 #include "vms-pwd.h"
3818 /* Return as a string the VMS error string pertaining to STATUS.
3819 Reuses the same static buffer each time it is called. */
3823 int status
; /* VMS status code */
3827 static char buf
[257];
3829 bufadr
[0] = sizeof buf
- 1;
3830 bufadr
[1] = (int) buf
;
3831 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
3832 return "untranslatable VMS error status";
3840 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3841 * not work correctly. (It also doesn't work well in version 2.3.)
3846 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3847 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3851 unsigned short s_buflen
;
3852 unsigned short s_code
;
3854 unsigned short *s_retlenadr
;
3858 #define buflen s.s_buflen
3859 #define code s.s_code
3860 #define bufadr s.s_bufadr
3861 #define retlenadr s.s_retlenadr
3863 #define R_OK 4 /* test for read permission */
3864 #define W_OK 2 /* test for write permission */
3865 #define X_OK 1 /* test for execute (search) permission */
3866 #define F_OK 0 /* test for presence of file */
3869 sys_access (path
, mode
)
3873 static char *user
= NULL
;
3876 /* translate possible directory spec into .DIR file name, so brain-dead
3877 * access can treat the directory like a file. */
3878 if (directory_file_name (path
, dir_fn
))
3882 return access (path
, mode
);
3883 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
3889 unsigned short int dummy
;
3891 static int constant
= ACL$C_FILE
;
3892 DESCRIPTOR (path_desc
, path
);
3893 DESCRIPTOR (user_desc
, user
);
3897 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
3900 acces
|= CHP$M_READ
;
3902 acces
|= CHP$M_WRITE
;
3903 itemlst
[0].buflen
= sizeof (int);
3904 itemlst
[0].code
= CHP$_FLAGS
;
3905 itemlst
[0].bufadr
= (char *) &flags
;
3906 itemlst
[0].retlenadr
= &dummy
;
3907 itemlst
[1].buflen
= sizeof (int);
3908 itemlst
[1].code
= CHP$_ACCESS
;
3909 itemlst
[1].bufadr
= (char *) &acces
;
3910 itemlst
[1].retlenadr
= &dummy
;
3911 itemlst
[2].end
= CHP$_END
;
3912 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
3913 return stat
== SS$_NORMAL
? 0 : -1;
3917 #else /* not VMS4_4 */
3920 #define ACE$M_WRITE 2
3921 #define ACE$C_KEYID 1
3923 static unsigned short memid
, grpid
;
3924 static unsigned int uic
;
3926 /* Called from init_sys_modes, so it happens not very often
3927 but at least each time Emacs is loaded. */
3929 sys_access_reinit ()
3935 sys_access (filename
, type
)
3941 int status
, size
, i
, typecode
, acl_controlled
;
3942 unsigned int *aclptr
, *aclend
, aclbuf
[60];
3943 union prvdef prvmask
;
3945 /* Get UIC and GRP values for protection checking. */
3948 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
3951 memid
= uic
& 0xFFFF;
3955 if (type
!= 2) /* not checking write access */
3956 return access (filename
, type
);
3958 /* Check write protection. */
3960 #define CHECKPRIV(bit) (prvmask.bit)
3961 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3963 /* Find privilege bits */
3964 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
3966 error ("Unable to find privileges: %s", vmserrstr (status
));
3967 if (CHECKPRIV (PRV$V_BYPASS
))
3968 return 0; /* BYPASS enabled */
3970 fab
.fab$b_fac
= FAB$M_GET
;
3971 fab
.fab$l_fna
= filename
;
3972 fab
.fab$b_fns
= strlen (filename
);
3973 fab
.fab$l_xab
= &xab
;
3974 xab
= cc$rms_xabpro
;
3975 xab
.xab$l_aclbuf
= aclbuf
;
3976 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
3977 status
= SYS$
OPEN (&fab
, 0, 0);
3980 SYS$
CLOSE (&fab
, 0, 0);
3981 /* Check system access */
3982 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITABLE (XAB$V_SYS
))
3984 /* Check ACL entries, if any */
3986 if (xab
.xab$w_acllen
> 0)
3989 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
3990 while (*aclptr
&& aclptr
< aclend
)
3992 size
= (*aclptr
& 0xff) / 4;
3993 typecode
= (*aclptr
>> 8) & 0xff;
3994 if (typecode
== ACE$C_KEYID
)
3995 for (i
= size
- 1; i
> 1; i
--)
3996 if (aclptr
[i
] == uic
)
3999 if (aclptr
[1] & ACE$M_WRITE
)
4000 return 0; /* Write access through ACL */
4002 aclptr
= &aclptr
[size
];
4004 if (acl_controlled
) /* ACL specified, prohibits write access */
4007 /* No ACL entries specified, check normal protection */
4008 if (WRITABLE (XAB$V_WLD
)) /* World writable */
4010 if (WRITABLE (XAB$V_GRP
) &&
4011 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
4012 return 0; /* Group writable */
4013 if (WRITABLE (XAB$V_OWN
) &&
4014 (xab
.xab$l_uic
& 0xFFFF) == memid
)
4015 return 0; /* Owner writable */
4017 return -1; /* Not writable */
4019 #endif /* not VMS4_4 */
4022 static char vtbuf
[NAM$C_MAXRSS
+1];
4024 /* translate a vms file spec to a unix path */
4026 sys_translate_vms (vfile
)
4037 /* leading device or logical name is a root directory */
4038 if (p
= strchr (vfile
, ':'))
4047 if (*p
== '[' || *p
== '<')
4049 while (*++vfile
!= *p
+ 2)
4053 if (vfile
[-1] == *p
)
4076 static char utbuf
[NAM$C_MAXRSS
+1];
4078 /* translate a unix path to a VMS file spec */
4080 sys_translate_unix (ufile
)
4103 if (index (&ufile
[1], '/'))
4110 if (index (&ufile
[1], '/'))
4117 if (strncmp (ufile
, "./", 2) == 0)
4124 ufile
++; /* skip the dot */
4125 if (index (&ufile
[1], '/'))
4130 else if (strncmp (ufile
, "../", 3) == 0)
4138 ufile
+= 2; /* skip the dots */
4139 if (index (&ufile
[1], '/'))
4164 extern char *getcwd ();
4166 #define MAXPATHLEN 1024
4168 ptr
= xmalloc (MAXPATHLEN
);
4169 val
= getcwd (ptr
, MAXPATHLEN
);
4175 strcpy (pathname
, ptr
);
4184 long item_code
= JPI$_OWNER
;
4185 unsigned long parent_id
;
4188 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
4191 vaxc$errno
= status
;
4201 return (getgid () << 16) | getuid ();
4206 sys_read (fildes
, buf
, nbyte
)
4211 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
4216 sys_write (fildes
, buf
, nbyte
)
4221 register int nwrote
, rtnval
= 0;
4223 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
4229 return rtnval
? rtnval
: -1;
4230 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
4231 return rtnval
? rtnval
: -1;
4232 return (rtnval
+ nwrote
);
4237 * VAX/VMS VAX C RTL really loses. It insists that records
4238 * end with a newline (carriage return) character, and if they
4239 * don't it adds one (nice of it isn't it!)
4241 * Thus we do this stupidity below.
4246 sys_write (fildes
, buf
, nbytes
)
4249 unsigned int nbytes
;
4256 fstat (fildes
, &st
);
4262 /* Handle fixed-length files with carriage control. */
4263 if (st
.st_fab_rfm
== FAB$C_FIX
4264 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
4266 len
= st
.st_fab_mrs
;
4267 retval
= write (fildes
, p
, min (len
, nbytes
));
4270 retval
++; /* This skips the implied carriage control */
4274 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4275 while (*e
!= '\n' && e
> p
) e
--;
4276 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
4277 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4279 retval
= write (fildes
, p
, len
);
4290 /* Create file NEW copying its attributes from file OLD. If
4291 OLD is 0 or does not exist, create based on the value of
4294 /* Protection value the file should ultimately have.
4295 Set by create_copy_attrs, and use by rename_sansversions. */
4296 static unsigned short int fab_final_pro
;
4299 creat_copy_attrs (old
, new)
4302 struct FAB fab
= cc$rms_fab
;
4303 struct XABPRO xabpro
;
4304 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
4305 extern int vms_stmlf_recfm
;
4309 fab
.fab$b_fac
= FAB$M_GET
;
4310 fab
.fab$l_fna
= old
;
4311 fab
.fab$b_fns
= strlen (old
);
4312 fab
.fab$l_xab
= (char *) &xabpro
;
4313 xabpro
= cc$rms_xabpro
;
4314 xabpro
.xab$l_aclbuf
= aclbuf
;
4315 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
4316 /* Call $OPEN to fill in the fab & xabpro fields. */
4317 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4319 SYS$
CLOSE (&fab
, 0, 0);
4320 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
4321 if (xabpro
.xab$w_acllen
> 0)
4323 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
4324 /* If the acl buffer was too short, redo open with longer one.
4325 Wouldn't need to do this if there were some system imposed
4326 limit on the size of an ACL, but I can't find any such. */
4328 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
4329 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
4330 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4331 SYS$
CLOSE (&fab
, 0, 0);
4337 xabpro
.xab$l_aclbuf
= 0;
4342 fab
.fab$l_fna
= new;
4343 fab
.fab$b_fns
= strlen (new);
4347 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
4348 fab
.fab$b_rat
= FAB$M_CR
;
4351 /* Set the file protections such that we will be able to manipulate
4352 this file. Once we are done writing and renaming it, we will set
4353 the protections back. */
4355 fab_final_pro
= xabpro
.xab$w_pro
;
4357 SYS$
SETDFPROT (0, &fab_final_pro
);
4358 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
4360 /* Create the new file with either default attrs or attrs copied
4362 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
4364 SYS$
CLOSE (&fab
, 0, 0);
4365 /* As this is a "replacement" for creat, return a file descriptor
4366 opened for writing. */
4367 return open (new, O_WRONLY
);
4372 #include <varargs.h>
4375 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4380 sys_creat (va_alist
)
4383 va_list list_incrementer
;
4386 int rfd
; /* related file descriptor */
4387 int fd
; /* Our new file descriptor */
4394 extern int vms_stmlf_recfm
;
4397 va_start (list_incrementer
);
4398 name
= va_arg (list_incrementer
, char *);
4399 mode
= va_arg (list_incrementer
, int);
4401 rfd
= va_arg (list_incrementer
, int);
4402 va_end (list_incrementer
);
4405 /* Use information from the related file descriptor to set record
4406 format of the newly created file. */
4407 fstat (rfd
, &st_buf
);
4408 switch (st_buf
.st_fab_rfm
)
4411 strcpy (rfm
, "rfm = fix");
4412 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
4413 strcpy (rat
, "rat = ");
4414 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4416 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4417 strcat (rat
, "ftn");
4418 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4419 strcat (rat
, "prn");
4420 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4421 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4422 strcat (rat
, ", blk");
4424 strcat (rat
, "blk");
4425 return creat (name
, 0, rfm
, rat
, mrs
);
4428 strcpy (rfm
, "rfm = vfc");
4429 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
4430 strcpy (rat
, "rat = ");
4431 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4433 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4434 strcat (rat
, "ftn");
4435 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4436 strcat (rat
, "prn");
4437 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4438 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4439 strcat (rat
, ", blk");
4441 strcat (rat
, "blk");
4442 return creat (name
, 0, rfm
, rat
, fsz
);
4445 strcpy (rfm
, "rfm = stm");
4449 strcpy (rfm
, "rfm = stmcr");
4453 strcpy (rfm
, "rfm = stmlf");
4457 strcpy (rfm
, "rfm = udf");
4461 strcpy (rfm
, "rfm = var");
4464 strcpy (rat
, "rat = ");
4465 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4467 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4468 strcat (rat
, "ftn");
4469 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4470 strcat (rat
, "prn");
4471 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4472 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4473 strcat (rat
, ", blk");
4475 strcat (rat
, "blk");
4479 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
4480 strcpy (rat
, "rat=cr");
4482 /* Until the VAX C RTL fixes the many bugs with modes, always use
4483 mode 0 to get the user's default protection. */
4484 fd
= creat (name
, 0, rfm
, rat
);
4485 if (fd
< 0 && errno
== EEXIST
)
4487 if (unlink (name
) < 0)
4488 report_file_error ("delete", build_string (name
));
4489 fd
= creat (name
, 0, rfm
, rat
);
4495 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4497 sys_fwrite (ptr
, size
, num
, fp
)
4498 register char * ptr
;
4501 register int tot
= num
* size
;
4509 * The VMS C library routine creat actually creates a new version of an
4510 * existing file rather than truncating the old version. There are times
4511 * when this is not the desired behavior, for instance, when writing an
4512 * auto save file (you only want one version), or when you don't have
4513 * write permission in the directory containing the file (but the file
4514 * itself is writable). Hence this routine, which is equivalent to
4515 * "close (creat (fn, 0));" on Unix if fn already exists.
4521 struct FAB xfab
= cc$rms_fab
;
4522 struct RAB xrab
= cc$rms_rab
;
4525 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
4526 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
4527 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
4528 xfab
.fab$l_fna
= fn
;
4529 xfab
.fab$b_fns
= strlen (fn
);
4530 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
4532 xrab
.rab$l_fab
= &xfab
;
4534 /* This gibberish opens the file, positions to the first record, and
4535 deletes all records from there until the end of file. */
4536 if ((SYS$
OPEN (&xfab
) & 01) == 01)
4538 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
4539 (SYS$
FIND (&xrab
) & 01) == 01 &&
4540 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
4551 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4552 SYSPRV or a readable SYSUAF.DAT. */
4558 * Routine to read the VMS User Authorization File and return
4559 * a specific user's record.
4562 static struct UAF retuaf
;
4565 get_uaf_name (uname
)
4572 uaf_fab
= cc$rms_fab
;
4573 uaf_rab
= cc$rms_rab
;
4574 /* initialize fab fields */
4575 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4576 uaf_fab
.fab$b_fns
= 21;
4577 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4578 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4579 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4580 /* initialize rab fields */
4581 uaf_rab
.rab$l_fab
= &uaf_fab
;
4582 /* open the User Authorization File */
4583 status
= SYS$
OPEN (&uaf_fab
);
4587 vaxc$errno
= status
;
4590 status
= SYS$
CONNECT (&uaf_rab
);
4594 vaxc$errno
= status
;
4597 /* read the requested record - index is in uname */
4598 uaf_rab
.rab$l_kbf
= uname
;
4599 uaf_rab
.rab$b_ksz
= strlen (uname
);
4600 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4601 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4602 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4603 status
= SYS$
GET (&uaf_rab
);
4607 vaxc$errno
= status
;
4610 /* close the User Authorization File */
4611 status
= SYS$
DISCONNECT (&uaf_rab
);
4615 vaxc$errno
= status
;
4618 status
= SYS$
CLOSE (&uaf_fab
);
4622 vaxc$errno
= status
;
4636 uaf_fab
= cc$rms_fab
;
4637 uaf_rab
= cc$rms_rab
;
4638 /* initialize fab fields */
4639 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4640 uaf_fab
.fab$b_fns
= 21;
4641 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4642 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4643 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4644 /* initialize rab fields */
4645 uaf_rab
.rab$l_fab
= &uaf_fab
;
4646 /* open the User Authorization File */
4647 status
= SYS$
OPEN (&uaf_fab
);
4651 vaxc$errno
= status
;
4654 status
= SYS$
CONNECT (&uaf_rab
);
4658 vaxc$errno
= status
;
4661 /* read the requested record - index is in uic */
4662 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
4663 uaf_rab
.rab$l_kbf
= (char *) &uic
;
4664 uaf_rab
.rab$b_ksz
= sizeof uic
;
4665 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4666 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4667 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4668 status
= SYS$
GET (&uaf_rab
);
4672 vaxc$errno
= status
;
4675 /* close the User Authorization File */
4676 status
= SYS$
DISCONNECT (&uaf_rab
);
4680 vaxc$errno
= status
;
4683 status
= SYS$
CLOSE (&uaf_fab
);
4687 vaxc$errno
= status
;
4693 static struct passwd retpw
;
4701 /* copy these out first because if the username is 32 chars, the next
4702 section will overwrite the first byte of the UIC */
4703 retpw
.pw_uid
= up
->uaf$w_mem
;
4704 retpw
.pw_gid
= up
->uaf$w_grp
;
4706 /* I suppose this is not the best style, to possibly overwrite one
4707 byte beyond the end of the field, but what the heck... */
4708 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
4709 while (ptr
[-1] == ' ')
4712 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
4714 /* the rest of these are counted ascii strings */
4715 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
4716 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
4717 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
4718 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
4719 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
4720 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
4721 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
4722 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
4726 #else /* not READ_SYSUAF */
4727 static struct passwd retpw
;
4728 #endif /* not READ_SYSUAF */
4739 unsigned char * full
;
4740 #endif /* READ_SYSUAF */
4745 if ('a' <= *ptr
&& *ptr
<= 'z')
4750 if (!(up
= get_uaf_name (name
)))
4752 return cnv_uaf_pw (up
);
4754 if (strcmp (name
, getenv ("USER")) == 0)
4756 retpw
.pw_uid
= getuid ();
4757 retpw
.pw_gid
= getgid ();
4758 strcpy (retpw
.pw_name
, name
);
4759 if (full
= egetenv ("FULLNAME"))
4760 strcpy (retpw
.pw_gecos
, full
);
4762 *retpw
.pw_gecos
= '\0';
4763 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
4764 *retpw
.pw_shell
= '\0';
4769 #endif /* not READ_SYSUAF */
4779 if (!(up
= get_uaf_uic (uid
)))
4781 return cnv_uaf_pw (up
);
4783 if (uid
== sys_getuid ())
4784 return getpwnam (egetenv ("USER"));
4787 #endif /* not READ_SYSUAF */
4790 /* return total address space available to the current process. This is
4791 the sum of the current p0 size, p1 size and free page table entries
4797 unsigned long free_pages
;
4798 unsigned long frep0va
;
4799 unsigned long frep1va
;
4802 item_code
= JPI$_FREPTECNT
;
4803 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
4806 vaxc$errno
= status
;
4811 item_code
= JPI$_FREP0VA
;
4812 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
4815 vaxc$errno
= status
;
4818 item_code
= JPI$_FREP1VA
;
4819 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
4822 vaxc$errno
= status
;
4826 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
4830 define_logical_name (varname
, string
)
4834 struct dsc$descriptor_s strdsc
=
4835 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
4836 struct dsc$descriptor_s envdsc
=
4837 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4838 struct dsc$descriptor_s lnmdsc
=
4839 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4841 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
4845 delete_logical_name (varname
)
4848 struct dsc$descriptor_s envdsc
=
4849 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4850 struct dsc$descriptor_s lnmdsc
=
4851 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4853 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
4871 error ("execvp system call not implemented");
4880 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
4881 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
4882 char from_esn
[NAM$C_MAXRSS
];
4883 char to_esn
[NAM$C_MAXRSS
];
4885 from_fab
.fab$l_fna
= from
;
4886 from_fab
.fab$b_fns
= strlen (from
);
4887 from_fab
.fab$l_nam
= &from_nam
;
4888 from_fab
.fab$l_fop
= FAB$M_NAM
;
4890 from_nam
.nam$l_esa
= from_esn
;
4891 from_nam
.nam$b_ess
= sizeof from_esn
;
4893 to_fab
.fab$l_fna
= to
;
4894 to_fab
.fab$b_fns
= strlen (to
);
4895 to_fab
.fab$l_nam
= &to_nam
;
4896 to_fab
.fab$l_fop
= FAB$M_NAM
;
4898 to_nam
.nam$l_esa
= to_esn
;
4899 to_nam
.nam$b_ess
= sizeof to_esn
;
4901 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
4907 if (status
== RMS$_DEV
)
4911 vaxc$errno
= status
;
4916 /* This function renames a file like `rename', but it strips
4917 the version number from the "to" filename, such that the "to" file is
4918 will always be a new version. It also sets the file protection once it is
4919 finished. The protection that we will use is stored in fab_final_pro,
4920 and was set when we did a creat_copy_attrs to create the file that we
4923 We could use the chmod function, but Eunichs uses 3 bits per user category
4924 to describe the protection, and VMS uses 4 (write and delete are separate
4925 bits). To maintain portability, the VMS implementation of `chmod' wires
4926 the W and D bits together. */
4929 static struct fibdef fib
; /* We need this initialized to zero */
4930 char vms_file_written
[NAM$C_MAXRSS
];
4933 rename_sans_version (from
,to
)
4940 struct FAB to_fab
= cc$rms_fab
;
4941 struct NAM to_nam
= cc$rms_nam
;
4942 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
4943 struct dsc$descriptor fib_attr
[2]
4944 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
4945 char to_esn
[NAM$C_MAXRSS
];
4947 $
DESCRIPTOR (disk
,to_esn
);
4949 to_fab
.fab$l_fna
= to
;
4950 to_fab
.fab$b_fns
= strlen (to
);
4951 to_fab
.fab$l_nam
= &to_nam
;
4952 to_fab
.fab$l_fop
= FAB$M_NAM
;
4954 to_nam
.nam$l_esa
= to_esn
;
4955 to_nam
.nam$b_ess
= sizeof to_esn
;
4957 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
4959 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
4960 *(to_nam
.nam$l_ver
) = '\0';
4962 stat
= rename (from
, to_esn
);
4966 strcpy (vms_file_written
, to_esn
);
4968 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
4969 to_fab
.fab$b_fns
= strlen (vms_file_written
);
4971 /* Now set the file protection to the correct value */
4972 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
4974 /* Copy these fields into the fib */
4975 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
4976 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
4977 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
4979 SYS$
CLOSE (&to_fab
, 0, 0);
4981 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
4984 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
4985 0, 0, 0, &fib_attr
, 0);
4988 stat
= SYS$
DASSGN (chan
);
4991 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
5002 unsigned short fid
[3];
5003 char esa
[NAM$C_MAXRSS
];
5006 fab
.fab$l_fop
= FAB$M_OFP
;
5007 fab
.fab$l_fna
= file
;
5008 fab
.fab$b_fns
= strlen (file
);
5009 fab
.fab$l_nam
= &nam
;
5012 nam
.nam$l_esa
= esa
;
5013 nam
.nam$b_ess
= NAM$C_MAXRSS
;
5015 status
= SYS$
PARSE (&fab
);
5016 if ((status
& 1) == 0)
5019 vaxc$errno
= status
;
5022 status
= SYS$
SEARCH (&fab
);
5023 if ((status
& 1) == 0)
5026 vaxc$errno
= status
;
5030 fid
[0] = nam
.nam$w_fid
[0];
5031 fid
[1] = nam
.nam$w_fid
[1];
5032 fid
[2] = nam
.nam$w_fid
[2];
5034 fab
.fab$l_fna
= new;
5035 fab
.fab$b_fns
= strlen (new);
5037 status
= SYS$
PARSE (&fab
);
5038 if ((status
& 1) == 0)
5041 vaxc$errno
= status
;
5045 nam
.nam$w_fid
[0] = fid
[0];
5046 nam
.nam$w_fid
[1] = fid
[1];
5047 nam
.nam$w_fid
[2] = fid
[2];
5049 nam
.nam$l_esa
= nam
.nam$l_name
;
5050 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
5052 status
= SYS$
ENTER (&fab
);
5053 if ((status
& 1) == 0)
5056 vaxc$errno
= status
;
5067 printf ("%s not yet implemented\r\n", badfunc
);
5075 /* Arrange to return a range centered on zero. */
5076 return rand () - (1 << 30);
5088 /* Called from init_sys_modes. */
5094 /* If we're not on an HFT we shouldn't do any of this. We determine
5095 if we are on an HFT by trying to get an HFT error code. If this
5096 call fails, we're not on an HFT. */
5098 if (ioctl (0, HFQERROR
, &junk
) < 0)
5100 #else /* not IBMR2AIX */
5101 if (ioctl (0, HFQEIO
, 0) < 0)
5103 #endif /* not IBMR2AIX */
5105 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5106 as the rubout key's ASCII code. Here this is changed. The bug is that
5107 there's no way to determine the old mapping, so in reset_sys_modes
5108 we need to assume that the normal map had been present. Of course, this
5109 code also doesn't help if on a terminal emulator which doesn't understand
5113 struct hfkeymap keymap
;
5115 buf
.hf_bufp
= (char *)&keymap
;
5116 buf
.hf_buflen
= sizeof (keymap
);
5117 keymap
.hf_nkeys
= 2;
5118 keymap
.hfkey
[0].hf_kpos
= 15;
5119 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5121 keymap
.hfkey
[0].hf_keyidh
= '<';
5122 #else /* not IBMR2AIX */
5123 keymap
.hfkey
[0].hf_page
= '<';
5124 #endif /* not IBMR2AIX */
5125 keymap
.hfkey
[0].hf_char
= 127;
5126 keymap
.hfkey
[1].hf_kpos
= 15;
5127 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5129 keymap
.hfkey
[1].hf_keyidh
= '<';
5130 #else /* not IBMR2AIX */
5131 keymap
.hfkey
[1].hf_page
= '<';
5132 #endif /* not IBMR2AIX */
5133 keymap
.hfkey
[1].hf_char
= 127;
5134 hftctl (0, HFSKBD
, &buf
);
5136 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5138 line_ins_del_ok
= char_ins_del_ok
= 0;
5141 /* Reset the rubout key to backspace. */
5147 struct hfkeymap keymap
;
5151 if (ioctl (0, HFQERROR
, &junk
) < 0)
5153 #else /* not IBMR2AIX */
5154 if (ioctl (0, HFQEIO
, 0) < 0)
5156 #endif /* not IBMR2AIX */
5158 buf
.hf_bufp
= (char *)&keymap
;
5159 buf
.hf_buflen
= sizeof (keymap
);
5160 keymap
.hf_nkeys
= 2;
5161 keymap
.hfkey
[0].hf_kpos
= 15;
5162 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5164 keymap
.hfkey
[0].hf_keyidh
= '<';
5165 #else /* not IBMR2AIX */
5166 keymap
.hfkey
[0].hf_page
= '<';
5167 #endif /* not IBMR2AIX */
5168 keymap
.hfkey
[0].hf_char
= 8;
5169 keymap
.hfkey
[1].hf_kpos
= 15;
5170 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5172 keymap
.hfkey
[1].hf_keyidh
= '<';
5173 #else /* not IBMR2AIX */
5174 keymap
.hfkey
[1].hf_page
= '<';
5175 #endif /* not IBMR2AIX */
5176 keymap
.hfkey
[1].hf_char
= 8;
5177 hftctl (0, HFSKBD
, &buf
);
5184 /* These are included on Sunos 4.1 when we do not use shared libraries.
5185 X11 libraries may refer to these functions but (we hope) do not
5186 actually call them. */
5206 #endif /* USE_DL_STUBS */
5215 register int length
;
5219 long max_str
= 65535;
5221 while (length
> max_str
) {
5222 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5227 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5229 while (length
-- > 0)
5231 #endif /* not VMS */
5234 #endif /* no bzero */
5235 #endif /* BSTRING */
5237 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5240 /* Saying `void' requires a declaration, above, where bcopy is used
5241 and that declaration causes pain for systems where bcopy is a macro. */
5242 bcopy (b1
, b2
, length
)
5245 register int length
;
5248 long max_str
= 65535;
5250 while (length
> max_str
) {
5251 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
5257 (void) LIB$
MOVC3 (&length
, b1
, b2
);
5259 while (length
-- > 0)
5261 #endif /* not VMS */
5263 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5268 bcmp (b1
, b2
, length
) /* This could be a macro! */
5271 register int length
;
5274 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
5275 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
5277 return STR$
COMPARE (&src1
, &src2
);
5279 while (length
-- > 0)
5284 #endif /* not VMS */
5286 #endif /* no bcmp */
5287 #endif /* not BSTRING */
5289 #ifndef HAVE_STRSIGNAL
5296 if (0 <= code
&& code
< NSIG
)
5299 signame
= sys_errlist
[code
];
5301 /* Cast to suppress warning if the table has const char *. */
5302 signame
= (char *) sys_siglist
[code
];
5308 #endif /* HAVE_STRSIGNAL */
5310 /* All the Macintosh stuffs go here */
5315 #include <MacTypes.h>
5316 #include <TextUtils.h>
5317 #include <Folders.h>
5320 #include <sys/stat.h>
5323 #include <sys/param.h>
5325 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5326 that does not begin with a ':' and contains at least one ':'. A Mac
5327 full pathname causes an '/' to be prepended to the Unix pathname.
5328 The algorithm for the rest of the pathname is as follows:
5329 For each segment between two ':',
5330 if it is non-null, copy as is and then add a '/' at the end,
5331 otherwise, insert a "../" into the Unix pathname.
5332 Returns 1 if successful; 0 if fails. */
5335 Mac2UnixPathname (const char *mfn
, char *ufn
, int ufnbuflen
)
5337 const char *p
, *q
, *pe
;
5344 p
= strchr (mfn
, ':');
5345 if (p
!= 0 && p
!= mfn
) /* full pathname */
5352 pe
= mfn
+ strlen (mfn
);
5355 q
= strchr (p
, ':');
5359 { /* two consecutive ':' */
5360 if (strlen (ufn
) + 3 >= ufnbuflen
)
5362 strcat (ufn
, "../");
5366 if (strlen (ufn
) + (q
- p
) + 1 >= ufnbuflen
)
5368 strncat (ufn
, p
, q
- p
);
5375 if (strlen (ufn
) + (pe
- p
) >= ufnbuflen
)
5377 strncat (ufn
, p
, pe
- p
); /* no separator for last one */
5385 extern char *GetTempDirName ();
5387 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5388 above in algorithm. */
5390 Unix2MacPathname (const char *ufn
, char *mfn
, int mfnbuflen
)
5392 const char *p
, *q
, *pe
;
5393 char expandedPathname
[MAXPATHLEN
+1];
5402 /* Check for and handle volume names. Last comparison: strangely
5403 somewhere `/.emacs' is passed. A temporary fix for now. */
5404 if (*p
== '/' && strchr (p
+1, '/') == NULL
&& strcmp (p
, "/.emacs") != 0)
5406 if (strlen (p
) + 1 > mfnbuflen
)
5413 if (strncmp (p
, "~emacs/", 7) == 0)
5414 { /* expand to emacs dir found by InitEmacsPasswdDir */
5415 struct passwd
*pw
= getpwnam ("emacs");
5417 if (strlen (pw
->pw_dir
) + strlen (p
) > MAXPATHLEN
)
5419 strcpy (expandedPathname
, pw
->pw_dir
);
5420 strcat (expandedPathname
, p
);
5421 p
= expandedPathname
;
5422 /* Now p points to the pathname with emacs dir prefix. */
5424 else if (strncmp (p
, "/tmp/", 5) == 0)
5426 char *t
= GetTempDirName ();
5428 if (strlen (t
) + strlen (p
) > MAXPATHLEN
)
5430 strcpy (expandedPathname
, t
);
5431 strcat (expandedPathname
, p
);
5432 p
= expandedPathname
;
5433 /* Now p points to the pathname with emacs dir prefix. */
5435 else if (*p
!= '/') /* relative pathname */
5441 pe
= p
+ strlen (p
);
5444 q
= strchr (p
, '/');
5447 if (q
- p
== 2 && *p
== '.' && *(p
+1) == '.')
5449 if (strlen (mfn
) + 1 >= mfnbuflen
)
5455 if (strlen (mfn
) + (q
- p
) + 1 >= mfnbuflen
)
5457 strncat (mfn
, p
, q
- p
);
5464 if (strlen (mfn
) + (pe
- p
) >= mfnbuflen
)
5466 strncat (mfn
, p
, pe
- p
);
5474 /* The following functions with "sys_" prefix are stubs to Unix
5475 functions that have already been implemented by CW or MPW. The
5476 calls to them in Emacs source course are #define'd to call the sys_
5477 versions by the header files s-mac.h. In these stubs pathnames are
5478 converted between their Unix and Mac forms. */
5479 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5481 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5483 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5485 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5487 /* Define our own stat function for both MrC and CW. The reason for
5488 doing this: "stat" is both the name of a struct and function name:
5489 we can't #define stat to something else to
5490 redirect Emacs's calls to our own version that converts Unix style
5491 filenames to Mac style filename because all sorts of compilation
5492 errors will be generated if stat is #define'd to be something else. */
5495 stat (const char *path
, struct stat
*buf
)
5497 char MacPathname
[MAXPATHLEN
+1];
5500 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5503 c2pstr (MacPathname
);
5504 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5505 cipb
.hFileInfo
.ioVRefNum
= 0;
5506 cipb
.hFileInfo
.ioDirID
= 0;
5507 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5509 errno
= PBGetCatInfo (&cipb
, false);
5510 if (errno
== -43) /* -43: fnfErr defined in Errors.h */
5515 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5516 { /* bit 4 = 1 for directories */
5517 buf
->st_mode
= S_IFDIR
| S_IREAD
| S_IEXEC
;
5518 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5519 buf
->st_mode
|= S_IWRITE
;
5520 buf
->st_ino
= cipb
.dirInfo
.ioDrDirID
;
5521 buf
->st_dev
= cipb
.dirInfo
.ioVRefNum
;
5522 buf
->st_size
= cipb
.dirInfo
.ioDrNmFls
; /* size of dir = number of files and dirs */
5523 buf
->st_atime
= buf
->st_mtime
= cipb
.dirInfo
.ioDrMdDat
- MAC_UNIX_EPOCH_DIFF
;
5524 buf
->st_ctime
= cipb
.dirInfo
.ioDrCrDat
- MAC_UNIX_EPOCH_DIFF
;
5528 buf
->st_mode
= S_IFREG
| S_IREAD
;
5529 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5530 buf
->st_mode
|= S_IWRITE
;
5531 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5532 buf
->st_mode
|= S_IEXEC
;
5533 buf
->st_ino
= cipb
.hFileInfo
.ioDirID
;
5534 buf
->st_dev
= cipb
.hFileInfo
.ioVRefNum
;
5535 buf
->st_size
= cipb
.hFileInfo
.ioFlLgLen
;
5536 buf
->st_atime
= buf
->st_mtime
= cipb
.hFileInfo
.ioFlMdDat
- MAC_UNIX_EPOCH_DIFF
;
5537 buf
->st_ctime
= cipb
.hFileInfo
.ioFlCrDat
- MAC_UNIX_EPOCH_DIFF
;
5540 buf
->st_uid
= getuid ();
5541 buf
->st_gid
= getgid ();
5549 /* CW defines fstat in stat.mac.c while MPW does not provide this
5550 function. Without the information of how to get from a file
5551 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5552 to implement this function. Fortunately, there is only one place
5553 where this function is called in our configuration: in fileio.c,
5554 where only the st_dev and st_ino fields are used to determine
5555 whether two fildes point to different i-nodes to prevent copying
5556 a file onto itself equal. What we have here probably needs
5559 fstat (int fildes
, struct stat
*buf
)
5562 buf
->st_ino
= fildes
;
5563 return 0; /* success */
5566 #endif /* __MRC__ */
5568 /* From Think Reference code example */
5570 mkdir (const char *dirname
, int mode
)
5572 #pragma unused (mode)
5575 char MacPathname
[MAXPATHLEN
+1];
5577 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5580 c2pstr (MacPathname
);
5581 hfpb
.ioNamePtr
= MacPathname
;
5582 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5583 hfpb
.ioDirID
= 0; /*parent is the root */
5585 /* Just return the Mac OSErr code for now. */
5586 errno
= PBDirCreate ((HParmBlkPtr
) &hfpb
, false);
5587 return errno
== noErr
? 0 : -1;
5591 rmdir (const char *dirname
)
5594 char MacPathname
[MAXPATHLEN
+1];
5596 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5599 c2pstr (MacPathname
);
5600 hfpb
.ioNamePtr
= MacPathname
;
5601 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5602 hfpb
.ioDirID
= 0; /*parent is the root */
5604 errno
= PBHDelete ((HParmBlkPtr
) &hfpb
, false);
5605 return errno
== noErr
? 0 : -1;
5610 /* No implementation yet. */
5612 execvp (const char *path
, ...)
5617 #endif /* __MRC__ */
5620 utime (const char *path
, const struct utimbuf
*times
)
5622 char MacPathname
[MAXPATHLEN
+1];
5625 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5628 c2pstr (MacPathname
);
5629 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5630 cipb
.hFileInfo
.ioVRefNum
= 0;
5631 cipb
.hFileInfo
.ioDirID
= 0;
5632 /* Set to 0 to get information about specific dir or file. */
5633 cipb
.hFileInfo
.ioFDirIndex
= 0;
5635 errno
= PBGetCatInfo (&cipb
, false);
5639 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5640 { /* bit 4 = 1 for directories */
5642 cipb
.dirInfo
.ioDrMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5644 GetDateTime (&cipb
.dirInfo
.ioDrMdDat
);
5649 cipb
.hFileInfo
.ioFlMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5651 GetDateTime (&cipb
.hFileInfo
.ioFlMdDat
);
5654 errno
= PBSetCatInfo (&cipb
, false);
5655 return errno
== noErr
? 0 : -1;
5662 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5664 access (const char *path
, int mode
)
5666 char MacPathname
[MAXPATHLEN
+1];
5669 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5672 c2pstr (MacPathname
);
5673 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5674 cipb
.hFileInfo
.ioVRefNum
= 0;
5675 cipb
.hFileInfo
.ioDirID
= 0;
5676 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5678 errno
= PBGetCatInfo (&cipb
, false);
5682 if (mode
== F_OK
) /* got this far, file exists */
5686 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* path refers to a directory */
5690 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5697 return (cipb
.hFileInfo
.ioFlAttrib
& 0x1) ? -1 : 0; /* don't allow if lock bit on */
5702 #define DEV_NULL_FD 0x10000
5706 sys_open (const char *path
, int oflag
)
5708 char MacPathname
[MAXPATHLEN
+1];
5710 if (strcmp (path
, "/dev/null") == 0)
5711 return DEV_NULL_FD
; /* some bogus fd to be ignored in write */
5713 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5716 return open (MacPathname
, oflag
);
5721 sys_creat (const char *path
, mode_t mode
)
5723 char MacPathname
[MAXPATHLEN
+1];
5725 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5728 return creat (MacPathname
, mode
);
5733 sys_unlink (const char *path
)
5735 char MacPathname
[MAXPATHLEN
+1];
5737 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5740 return unlink (MacPathname
);
5745 sys_read (int fildes
, char *buf
, int count
)
5748 { /* if stdin, call (non-echoing) "getch" in console.h */
5749 if (MacKeyPending ())
5750 { /* don't wait for a key if none has been pressed */
5751 *buf
= MacGetChar ();
5758 return read (fildes
, buf
, count
);
5763 sys_write (int fildes
, char *buf
, int count
)
5765 if (fildes
== DEV_NULL_FD
)
5768 return write (fildes
, buf
, count
);
5773 sys_rename (const char * old_name
, const char * new_name
)
5775 char MacOldName
[MAXPATHLEN
+1], MacNewName
[MAXPATHLEN
+1];
5777 if (strcmp (old_name
, new_name
) == 0)
5780 if (Unix2MacPathname (old_name
, MacOldName
, MAXPATHLEN
+1) == 0)
5783 if (Unix2MacPathname (new_name
, MacNewName
, MAXPATHLEN
+1) == 0)
5786 return rename (MacOldName
, MacNewName
);
5790 extern FILE *fopen (const char *name
, const char *mode
);
5792 sys_fopen (const char *name
, const char *mode
)
5794 char MacPathname
[MAXPATHLEN
+1];
5796 if (Unix2MacPathname (name
, MacPathname
, MAXPATHLEN
+1) == 0)
5799 return fopen (MacPathname
, mode
);
5804 long targetTicks
= 0;
5807 __sigfun alarm_signal_func
= (__sigfun
) 0;
5809 __signal_func_ptr alarm_signal_func
= (__signal_func_ptr
) 0;
5814 /* These functions simulate SIG_ALRM. The stub for function signal
5815 stores the signal handler function in alarm_signal_func if a
5816 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5817 which emacs calls periodically. A pending alarm is represented by
5818 a non-zero targetTicks value. CheckAlarm calls the handler
5819 function pointed to by alarm_signal_func if one has been set up and
5820 an alarm is pending. */
5824 if (targetTicks
&& TickCount () > targetTicks
)
5827 if (alarm_signal_func
)
5828 (*alarm_signal_func
)(SIGALRM
);
5832 /* Called in sys_select to wait for an alarm signal to arrive. */
5836 unsigned long finalTick
;
5838 if (!targetTicks
) /* no alarm pending */
5841 while (TickCount () <= targetTicks
)
5842 Delay (1UL, &finalTick
); /* wait for 1/60 second before trying again */
5845 if (alarm_signal_func
)
5846 (*alarm_signal_func
)(SIGALRM
);
5854 long remaining
= targetTicks
? (TickCount () - targetTicks
) / 60 : 0;
5856 targetTicks
= seconds
? TickCount () + 60 * seconds
: 0;
5858 return (remaining
< 0) ? 0 : (unsigned int) remaining
;
5863 extern __sigfun
signal (int signal
, __sigfun signal_func
);
5865 sys_signal (int signal_num
, __sigfun signal_func
)
5867 extern __signal_func_ptr
signal (int signal
, __signal_func_ptr signal_func
);
5869 sys_signal (int signal_num
, __signal_func_ptr signal_func
)
5874 if (signal_num
!= SIGALRM
)
5875 return signal (signal_num
, signal_func
);
5879 __sigfun old_signal_func
;
5881 __signal_func_ptr old_signal_func
;
5885 old_signal_func
= alarm_signal_func
;
5886 alarm_signal_func
= signal_func
;
5887 return old_signal_func
;
5891 /* The time functions adjust time values according to the difference
5892 between the Unix and CW epoches. */
5895 extern struct tm
*gmtime (const time_t *);
5897 sys_gmtime (const time_t *timer
)
5899 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5901 return gmtime (&unixTime
);
5905 extern struct tm
*localtime (const time_t *);
5907 sys_localtime (const time_t *timer
)
5909 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5911 return localtime (&unixTime
);
5915 extern char *ctime (const time_t *);
5917 sys_ctime (const time_t *timer
)
5919 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5921 return ctime (&unixTime
);
5925 extern time_t time (time_t *);
5927 sys_time (time_t *timer
)
5929 time_t macTime
= time (NULL
) - CW_UNIX_EPOCH_DIFF
;
5937 /* no subprocesses, empty wait */
5945 croak (char *badfunc
)
5947 printf ("%s not yet implemented\r\n", badfunc
);
5952 index (const char * str
, int chr
)
5954 return strchr (str
, chr
);
5958 char **environ
= &e
[0];
5961 mktemp (char *template)
5966 len
= strlen (template);
5968 while (k
>= 0 && template[k
] == 'X')
5971 k
++; /* make k index of first 'X' */
5975 /* Zero filled, number of digits equal to the number of X's. */
5976 sprintf (&template[k
], "%0*d", len
-k
, seqnum
++);
5984 /* Emulate getpwuid, getpwnam and others. */
5986 #define PASSWD_FIELD_SIZE 256
5988 static char myPasswdName
[PASSWD_FIELD_SIZE
];
5989 static char myPasswdDir
[MAXPATHLEN
+1];
5991 static struct passwd myPasswd
=
5997 /* Initialized by main () in macterm.c to pathname of emacs directory. */
5998 char emacsPasswdDir
[MAXPATHLEN
+1];
6001 InitEmacsPasswdDir ()
6005 if (getwd (emacsPasswdDir
) && getwd (myPasswdDir
))
6007 /* Need pathname of first ancestor that begins with `emacs' since
6008 Mac emacs application is somewhere in the emacs-20.3 tree. */
6009 int len
= strlen (emacsPasswdDir
);
6010 /* J points to the "/" following the directory name being compared. */
6013 while (i
>= 0 && !found
)
6015 while (i
>= 0 && emacsPasswdDir
[i
] != '/')
6017 if (emacsPasswdDir
[i
] == '/' && i
+5 < len
)
6018 found
= (strncmp (&(emacsPasswdDir
[i
+1]), "emacs", 5) == 0);
6020 emacsPasswdDir
[j
+1] = '\0';
6030 { /* setting to "/" probably won't work,
6031 but set it to something anyway. */
6032 strcpy (emacsPasswdDir
, "/");
6033 strcpy (myPasswdDir
, "/");
6037 static struct passwd emacsPasswd
=
6043 static int myPasswdInited
= 0;
6050 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6051 where Emacs was started. */
6053 ownerName
= (char **) GetResource ('STR ',-16096);
6057 BlockMove ((unsigned char *) *ownerName
,
6058 (unsigned char *) myPasswdName
, *ownerName
[0] + 1);
6059 HUnlock (ownerName
);
6060 p2cstr ((unsigned char *) myPasswdName
);
6063 myPasswdName
[0] = 0;
6067 getpwuid (uid_t uid
)
6069 if (!myPasswdInited
)
6079 getpwnam (const char *name
)
6081 if (strcmp (name
, "emacs") == 0)
6082 return &emacsPasswd
;
6084 if (!myPasswdInited
)
6093 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6094 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6122 request_sigio (void)
6133 unrequest_sigio (void)
6137 /* djgpp does not implement pipe either. */
6139 pipe (int _fildes
[2])
6145 /* Hard and symbolic links. */
6147 symlink (const char *name1
, const char *name2
)
6154 link (const char *name1
, const char *name2
)
6161 lstat (const char *path
, struct stat
*sb
)
6163 return stat (path
, sb
);
6167 readlink (const char *path
, char *buf
, int bufsiz
)
6174 umask (mode_t numask
)
6176 static mode_t mask
= 022;
6177 mode_t oldmask
= mask
;
6183 chmod (const char *path
, mode_t mode
)
6185 /* say it always succeed for now */
6193 return fcntl (oldd
, F_DUPFD
, 0);
6195 /* current implementation of fcntl in fcntl.mac.c simply returns old
6197 return fcntl (oldd
, F_DUPFD
);
6203 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6204 newd if it already exists. Then, attempt to dup oldd. If not
6205 successful, call dup2 recursively until we are, then close the
6206 unsuccessful ones. */
6208 dup2 (int oldd
, int newd
)
6219 ret
= dup2 (oldd
, newd
);
6224 /* let it fail for now */
6238 ioctl (int d
, int request
, void *argp
)
6247 if (fildes
>=0 && fildes
<= 2)
6278 sleep (unsigned int seconds
)
6280 unsigned long finalTick
;
6282 Delay (seconds
* 60UL, &finalTick
);
6285 #endif /* __MRC__ */
6294 #endif /* __MWERKS__ */
6296 /* Return the path to the directory in which Emacs can create
6297 temporary files. The MacOS "temporary items" directory cannot be
6298 used because it removes the file written by a process when it
6299 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6300 again not exactly). And of course Emacs needs to read back the
6301 files written by its subprocesses. So here we write the files to a
6302 directory "Emacs" in the Preferences Folder. This directory is
6303 created if it does not exist. */
6307 static char *TempDirName
= NULL
;
6311 Str255 dirName
, fullPath
;
6313 char unixDirName
[MAXPATHLEN
+1];
6316 /* Cache directory name with pointer TempDirName.
6317 Look for it only the first time. */
6320 err
= FindFolder (kOnSystemDisk
, kPreferencesFolderType
,
6321 kCreateFolder
, &vRefNum
, &dirID
);
6326 cpb
.dirInfo
.ioNamePtr
= dirName
;
6327 cpb
.dirInfo
.ioDrParID
= dirID
;
6329 /* Standard ref num to full path name loop */
6331 cpb
.dirInfo
.ioVRefNum
= vRefNum
;
6332 cpb
.dirInfo
.ioFDirIndex
= -1;
6333 cpb
.dirInfo
.ioDrDirID
= cpb
.dirInfo
.ioDrParID
;
6335 err
= PBGetCatInfo (&cpb
, false);
6338 strcat (dirName
, ":");
6339 if (strlen (fullPath
) + strlen (dirName
) <= MAXPATHLEN
)
6341 strcat (dirName
, fullPath
);
6342 strcpy (fullPath
, dirName
);
6347 while (cpb
.dirInfo
.ioDrDirID
!= fsRtDirID
&& err
== noErr
);
6349 if (strlen (fullPath
) + 6 <= MAXPATHLEN
)
6350 strcat (fullPath
, "Emacs:");
6354 if (Mac2UnixPathname (fullPath
, unixDirName
, MAXPATHLEN
+1) == 0)
6357 dir
= opendir (unixDirName
); /* check whether temp directory exists */
6360 else if (mkdir (unixDirName
, 0700) != 0) /* create it if not */
6363 TempDirName
= (char *) xmalloc (strlen (unixDirName
) + 1);
6364 strcpy (TempDirName
, unixDirName
);
6371 getenv (const char * name
)
6373 if (strcmp (name
, "TERM") == 0)
6375 else if (strcmp (name
, "TERMCAP") == 0)
6376 /* for debugging purpose when code was still outputting to dumb terminal */
6377 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6378 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6379 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6380 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6381 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6382 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6383 else if (strcmp (name
, "TMPDIR") == 0)
6384 return GetTempDirName ();
6390 #include <utsname.h>
6393 uname (struct utsname
*name
)
6396 systemName
= GetString (-16413); /* IM - Resource Manager Reference */
6399 BlockMove (*systemName
, name
->nodename
, (*systemName
)[0]+1);
6400 p2cstr (name
->nodename
);
6407 #include <Processes.h>
6410 /* Event class of HLE sent to subprocess. */
6411 const OSType kEmacsSubprocessSend
= 'ESND';
6412 /* Event class of HLE sent back from subprocess. */
6413 const OSType kEmacsSubprocessReply
= 'ERPY';
6416 mystrchr (char *s
, char c
)
6418 while (*s
&& *s
!= c
)
6444 mystrcpy (char *to
, char *from
)
6455 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6456 terminated). The process should run with the default directory
6457 "workdir", read input from "infn", and write output and error to
6458 "outfn" and "errfn", resp. The Process Manager call
6459 LaunchApplication is used to start the subprocess. We use high
6460 level events as the mechanism to pass arguments to the subprocess
6461 and to make Emacs wait for the subprocess to terminate and pass
6462 back a result code. The bulk of the code here packs the arguments
6463 into one message to be passed together with the high level event.
6464 Emacs also sometimes starts a subprocess using a shell to perform
6465 wildcard filename expansion. Since we don't really have a shell on
6466 the Mac, this case is detected and the starting of the shell is
6467 by-passed. We really need to add code here to do filename
6468 expansion to support such functionality. */
6470 run_mac_command (argv
, workdir
, infn
, outfn
, errfn
)
6471 unsigned char **argv
;
6472 const char *workdir
;
6473 const char *infn
, *outfn
, errfn
;
6475 char macappname
[MAXPATHLEN
+1], macworkdir
[MAXPATHLEN
+1];
6476 char macinfn
[MAXPATHLEN
+1], macoutfn
[MAXPATHLEN
+1], macerrfn
[MAXPATHLEN
+1];
6477 int paramlen
, argc
, newargc
, j
, retries
;
6478 char **newargv
, *param
, *p
;
6481 LaunchParamBlockRec lpbr
;
6482 EventRecord sendEvent
, replyEvent
;
6483 RgnHandle cursorRegionHdl
;
6485 unsigned long refCon
, len
;
6487 if (Unix2MacPathname (workdir
, macworkdir
, MAXPATHLEN
+1) == 0)
6489 if (Unix2MacPathname (infn
, macinfn
, MAXPATHLEN
+1) == 0)
6491 if (Unix2MacPathname (outfn
, macoutfn
, MAXPATHLEN
+1) == 0)
6493 if (Unix2MacPathname (errfn
, macerrfn
, MAXPATHLEN
+1) == 0)
6496 paramlen
= strlen (macworkdir
) + strlen (macinfn
) + strlen (macoutfn
) + strlen (macerrfn
) + 4;
6497 /* count nulls at end of strings */
6506 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6507 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6508 j
= strlen (argv
[0]);
6509 if (j
>= 3 && strcmp (argv
[0]+j
-3, "/sh") == 0 && argc
== 3 && strcmp (argv
[1], "-c") == 0)
6511 char *command
, *t
, tempmacpathname
[MAXPATHLEN
+1];
6513 /* The arguments for the command in argv[2] are separated by
6514 spaces. Count them and put the count in newargc. */
6515 command
= (char *) alloca (strlen (argv
[2])+2);
6516 strcpy (command
, argv
[2]);
6517 if (command
[strlen (command
) - 1] != ' ')
6518 strcat (command
, " ");
6522 t
= mystrchr (t
, ' ');
6526 t
= mystrchr (t
+1, ' ');
6529 newargv
= (char **) alloca (sizeof (char *) * newargc
);
6532 for (j
= 0; j
< newargc
; j
++)
6534 newargv
[j
] = (char *) alloca (strlen (t
) + 1);
6535 mystrcpy (newargv
[j
], t
);
6538 paramlen
+= strlen (newargv
[j
]) + 1;
6541 if (strncmp (newargv
[0], "~emacs/", 7) == 0)
6543 if (Unix2MacPathname (newargv
[0], tempmacpathname
, MAXPATHLEN
+1) == 0)
6547 { /* sometimes Emacs call "sh" without a path for the command */
6549 char *t
= (char *) alloca (strlen (newargv
[0]) + 7 + 1);
6550 strcpy (t
, "~emacs/");
6551 strcat (t
, newargv
[0]);
6554 openp (Vexec_path
, build_string (newargv
[0]), EXEC_SUFFIXES
, &path
, 1);
6558 if (Unix2MacPathname (XSTRING (path
)->data
, tempmacpathname
, MAXPATHLEN
+1) == 0)
6561 strcpy (macappname
, tempmacpathname
);
6565 if (Unix2MacPathname (argv
[0], macappname
, MAXPATHLEN
+1) == 0)
6568 newargv
= (char **) alloca (sizeof (char *) * argc
);
6570 for (j
= 1; j
< argc
; j
++)
6572 if (strncmp (argv
[j
], "~emacs/", 7) == 0)
6574 char *t
= strchr (argv
[j
], ' ');
6577 char tempcmdname
[MAXPATHLEN
+1], tempmaccmdname
[MAXPATHLEN
+1];
6578 strncpy (tempcmdname
, argv
[j
], t
-argv
[j
]);
6579 tempcmdname
[t
-argv
[j
]] = '\0';
6580 if (Unix2MacPathname (tempcmdname
, tempmaccmdname
, MAXPATHLEN
+1) == 0)
6582 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
) + strlen (t
) + 1);
6583 strcpy (newargv
[j
], tempmaccmdname
);
6584 strcat (newargv
[j
], t
);
6588 char tempmaccmdname
[MAXPATHLEN
+1];
6589 if (Unix2MacPathname (argv
[j
], tempmaccmdname
, MAXPATHLEN
+1) == 0)
6591 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
)+1);
6592 strcpy (newargv
[j
], tempmaccmdname
);
6596 newargv
[j
] = argv
[j
];
6597 paramlen
+= strlen (newargv
[j
]) + 1;
6601 /* After expanding all the arguments, we now know the length of the parameter block to be
6602 sent to the subprocess as a message attached to the HLE. */
6603 param
= (char *) xmalloc (paramlen
+ 1);
6608 *p
++ = newargc
; /* first byte of message contains number of arguments for command */
6609 strcpy (p
, macworkdir
);
6610 p
+= strlen (macworkdir
);
6611 *p
++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6612 strcpy (p
, macinfn
);
6613 p
+= strlen (macinfn
);
6615 strcpy (p
, macoutfn
);
6616 p
+= strlen (macoutfn
);
6618 strcpy (p
, macerrfn
);
6619 p
+= strlen (macerrfn
);
6621 for (j
= 1; j
< newargc
; j
++) {
6622 strcpy (p
, newargv
[j
]);
6623 p
+= strlen (newargv
[j
]);
6627 c2pstr (macappname
);
6629 iErr
= FSMakeFSSpec (0, 0, macappname
, &spec
);
6631 if (iErr
!= noErr
) {
6636 lpbr
.launchBlockID
= extendedBlock
;
6637 lpbr
.launchEPBLength
= extendedBlockLen
;
6638 lpbr
.launchControlFlags
= launchContinue
+ launchNoFileFlags
;
6639 lpbr
.launchAppSpec
= &spec
;
6640 lpbr
.launchAppParameters
= NULL
;
6642 iErr
= LaunchApplication (&lpbr
); /* call the subprocess */
6649 sendEvent
.what
= kHighLevelEvent
;
6650 sendEvent
.message
= kEmacsSubprocessSend
; /* Event ID stored in "where" unused */
6653 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6654 iErr
= PostHighLevelEvent (&sendEvent
, &lpbr
.launchProcessSN
, 0, param
, paramlen
+ 1, receiverIDisPSN
);
6656 while (iErr
== sessClosedErr
&& retries
-- > 0);
6658 if (iErr
!= noErr
) {
6663 cursorRegionHdl
= NewRgn ();
6665 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6667 if (WaitNextEvent (highLevelEventMask
, &replyEvent
, 180, cursorRegionHdl
) && replyEvent
.message
== kEmacsSubprocessReply
)
6670 /* The return code is sent through the refCon */
6671 iErr
= AcceptHighLevelEvent (&targ
, &refCon
, NULL
, &len
);
6672 if (iErr
!= noErr
) {
6673 DisposeHandle ((Handle
) cursorRegionHdl
);
6678 DisposeHandle ((Handle
) cursorRegionHdl
);
6685 opendir (const char *dirname
)
6687 char MacPathname
[MAXPATHLEN
+1];
6692 dirp
= (DIR *) xmalloc (sizeof (DIR));
6696 /* Handle special case when dirname is "/": sets up for readir to
6697 get all mount volumes. */
6698 if (strcmp (dirname
, "/") == 0) {
6699 dirp
->getting_volumes
= 1; /* special all mounted volumes DIR struct */
6700 dirp
->current_index
= 1; /* index for first volume */
6704 /* Handle typical cases: not accessing all mounted volumes. */
6705 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
6708 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6709 len
= strlen (MacPathname
);
6710 if (MacPathname
[len
- 1] != ':' && len
< MAXPATHLEN
)
6711 strcat (MacPathname
, ":");
6713 c2pstr (MacPathname
);
6714 cipb
.hFileInfo
.ioNamePtr
= MacPathname
; /* using full pathname so vRefNum and dirID ignored */
6715 cipb
.hFileInfo
.ioVRefNum
= 0;
6716 cipb
.hFileInfo
.ioDirID
= 0;
6717 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
6719 errno
= PBGetCatInfo (&cipb
, false);
6720 if (errno
!= noErr
) {
6725 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x10)) /* bit 4 = 1 for directories */
6726 return 0; /* not a directory */
6728 dirp
->dir_id
= cipb
.dirInfo
.ioDrDirID
; /* used later in readdir */
6729 dirp
->getting_volumes
= 0;
6730 dirp
->current_index
= 1; /* index for first file/directory */
6745 HParamBlockRec HPBlock
;
6747 static struct dirent s_dirent
;
6748 static Str255 s_name
;
6751 /* Handle the root directory containing the mounted volumes. Call
6752 PBHGetVInfo specifying an index to obtain the info for a volume.
6753 PBHGetVInfo returns an error when it receives an index beyond the
6754 last volume, at which time we should return a nil dirent struct
6756 if (dp
->getting_volumes
) {
6757 HPBlock
.volumeParam
.ioNamePtr
= s_name
;
6758 HPBlock
.volumeParam
.ioVRefNum
= 0;
6759 HPBlock
.volumeParam
.ioVolIndex
= dp
->current_index
;
6761 errno
= PBHGetVInfo (&HPBlock
, false);
6762 if (errno
!= noErr
) {
6768 strcat (s_name
, "/"); /* need "/" for stat to work correctly */
6770 dp
->current_index
++;
6772 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
;
6773 s_dirent
.d_name
= s_name
;
6778 cipb
.hFileInfo
.ioVRefNum
= 0;
6779 cipb
.hFileInfo
.ioNamePtr
= s_name
; /* location to receive filename returned */
6781 /* return only visible files */
6784 cipb
.hFileInfo
.ioDirID
= dp
->dir_id
; /* directory ID found by opendir */
6785 cipb
.hFileInfo
.ioFDirIndex
= dp
->current_index
;
6787 errno
= PBGetCatInfo (&cipb
, false);
6788 if (errno
!= noErr
) {
6793 /* insist on an visibile entry */
6794 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* directory? */
6795 done
= !(cipb
.dirInfo
.ioDrUsrWds
.frFlags
& fInvisible
);
6797 done
= !(cipb
.hFileInfo
.ioFlFndrInfo
.fdFlags
& fInvisible
);
6799 dp
->current_index
++;
6804 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
; /* value unimportant: non-zero for valid file */
6805 s_dirent
.d_name
= s_name
;
6814 char MacPathname
[MAXPATHLEN
+1];
6815 Str255 directoryName
;
6819 MacPathname
[0] = '\0';
6820 directoryName
[0] = '\0';
6821 cipb
.dirInfo
.ioDrParID
= 0;
6822 cipb
.dirInfo
.ioNamePtr
= directoryName
; /* empty string = default directory */
6825 cipb
.dirInfo
.ioVRefNum
= 0;
6826 cipb
.dirInfo
.ioFDirIndex
= -1;
6827 cipb
.dirInfo
.ioDrDirID
= cipb
.dirInfo
.ioDrParID
; /* go up to parent each time */
6829 errno
= PBGetCatInfo (&cipb
, false);
6830 if (errno
!= noErr
) {
6835 p2cstr (directoryName
);
6836 strcat (directoryName
, ":");
6837 strcat (directoryName
, MacPathname
); /* attach to front since going up directory tree */
6838 strcpy (MacPathname
, directoryName
);
6839 } while (cipb
.dirInfo
.ioDrDirID
!= fsRtDirID
); /* until volume's root directory */
6841 if (Mac2UnixPathname (MacPathname
, path
, MAXPATHLEN
+1) == 0)
6847 #endif /* macintosh */