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. */
27 #include "blockinput.h"
32 __sigfun
sys_signal (int signal
, __sigfun signal_func
);
34 __signal_func_ptr
sys_signal (int signal
, __signal_func_ptr signal_func
);
39 /* Nonzero means delete a process right away if it exits (process.c). */
40 static int delete_exited_processes
;
42 #ifndef HAVE_X_WINDOWS
43 /* Search path for bitmap files (xfns.c). */
44 Lisp_Object Vx_bitmap_file_path
;
46 #endif /* macintosh */
48 #define min(x,y) ((x) > (y) ? (y) : (x))
52 #define write sys_write
55 #endif /* not WINDOWSNT */
57 /* Does anyone other than VMS need this? */
59 #define sys_fwrite fwrite
69 #include <sys/types.h>
73 /* Get _POSIX_VDISABLE, if it is available. */
78 /* Get SI_SRPC_DOMAIN, if it is available. */
79 #ifdef HAVE_SYS_SYSTEMINFO_H
80 #include <sys/systeminfo.h>
83 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
87 #include <sys/param.h>
91 extern unsigned start
__asm__ ("start");
111 #include <sys/file.h>
119 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
123 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
124 because the vms compiler doesn't grok `defined' */
132 #endif /* not 4.1 bsd */
135 #include <sys/ioctl.h>
141 #ifdef BROKEN_TIOCGWINSZ
146 #if defined (USG) || defined (DGUX)
147 #include <sys/utsname.h>
149 #ifndef MEMORY_IN_STRING_H
152 #if defined (TIOCGWINSZ) || defined (ISC4_0)
154 #include <sys/sioctl.h>
157 #include <sys/stream.h>
158 #include <sys/ptem.h>
160 #endif /* TIOCGWINSZ or ISC4_0 */
161 #endif /* USG or DGUX */
163 extern int quit_char
;
167 #include "termhooks.h"
168 #include "termchar.h"
169 #include "termopts.h"
170 #include "dispextern.h"
175 /* In process.h which conflicts with the local copy. */
177 int _CRTAPI1
_spawnlp (int, const char *, const char *, ...);
178 int _CRTAPI1
_getpid (void);
181 #ifdef NONSYSTEM_DIR_LIBRARY
183 #endif /* NONSYSTEM_DIR_LIBRARY */
185 #include "syssignal.h"
192 #ifndef HAVE_STRUCT_UTIMBUF
193 /* We want to use utime rather than utimes, but we couldn't find the
194 structure declaration. We'll use the traditional one. */
202 #ifndef VFORK_RETURN_TYPE
203 #define VFORK_RETURN_TYPE int
206 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
212 #define LNOFLSH 0100000
215 static int baud_convert
[] =
220 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
221 1800, 2400, 4800, 9600, 19200, 38400
225 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
228 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
230 /* HJL's version of libc is said to need this on the Alpha.
231 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
232 extern speed_t ospeed
;
238 /* The file descriptor for Emacs's input terminal.
239 Under Unix, this is normally zero except when using X;
240 under VMS, we place the input channel number here. */
243 void croak
P_ ((char *));
251 /* Specify a different file descriptor for further input operations. */
260 /* Discard pending input on descriptor input_fd. */
266 struct emacs_tty buf
;
271 /* Discarding input is not safe when the input could contain
272 replies from the X server. So don't do it. */
273 if (read_socket_hook
)
278 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
279 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
285 ioctl (input_fd
, TIOCFLUSH
, &zero
);
287 #else /* not Apollo */
288 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
289 while (dos_keyread () != -1)
291 #else /* not MSDOS */
292 EMACS_GET_TTY (input_fd
, &buf
);
293 EMACS_SET_TTY (input_fd
, &buf
, 0);
294 #endif /* not MSDOS */
295 #endif /* not Apollo */
297 #endif /* not WINDOWSNT */
302 /* Arrange for character C to be read as the next input from
309 if (read_socket_hook
)
312 /* Should perhaps error if in batch mode */
314 ioctl (input_fd
, TIOCSTI
, &c
);
315 #else /* no TIOCSTI */
316 error ("Cannot stuff terminal input characters in this version of Unix");
317 #endif /* no TIOCSTI */
329 #ifdef INIT_BAUD_RATE
334 #else /* not DOS_NT */
338 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
339 &sg
.class, 12, 0, 0, 0, 0 );
340 ospeed
= sg
.xmit_baud
;
346 tcgetattr (input_fd
, &sg
);
347 ospeed
= cfgetospeed (&sg
);
348 #if defined (USE_GETOBAUD) && defined (getobaud)
349 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
351 ospeed
= getobaud (sg
.c_cflag
);
353 #else /* neither VMS nor TERMIOS */
359 tcgetattr (input_fd
, &sg
);
361 ioctl (input_fd
, TCGETA
, &sg
);
363 ospeed
= sg
.c_cflag
& CBAUD
;
364 #else /* neither VMS nor TERMIOS nor TERMIO */
367 sg
.sg_ospeed
= B9600
;
368 if (ioctl (input_fd
, TIOCGETP
, &sg
) < 0)
370 ospeed
= sg
.sg_ospeed
;
371 #endif /* not HAVE_TERMIO */
372 #endif /* not HAVE_TERMIOS */
374 #endif /* not DOS_NT */
375 #endif /* not INIT_BAUD_RATE */
378 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
379 ? baud_convert
[ospeed
] : 9600);
386 set_exclusive_use (fd
)
390 ioctl (fd
, FIOCLEX
, 0);
392 /* Ok to do nothing if this feature does not exist */
397 wait_without_blocking ()
400 wait3 (0, WNOHANG
| WUNTRACED
, 0);
402 croak ("wait_without_blocking");
404 synch_process_alive
= 0;
407 #endif /* not subprocesses */
409 int wait_debugging
; /* Set nonzero to make following function work under dbx
410 (at least for bsd). */
413 wait_for_termination_signal ()
416 /* Wait for subprocess with process id `pid' to terminate and
417 make sure it will get eliminated (not remain forever as a zombie) */
420 wait_for_termination (pid
)
429 status
= SYS$
FORCEX (&pid
, 0, 0);
432 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
433 /* Note that kill returns -1 even if the process is just a zombie now.
434 But inevitably a SIGCHLD interrupt should be generated
435 and child_sig will do wait3 and make the process go away. */
436 /* There is some indication that there is a bug involved with
437 termination of subprocesses, perhaps involving a kernel bug too,
438 but no idea what it is. Just as a hunch we signal SIGCHLD to see
439 if that causes the problem to go away or get worse. */
440 sigsetmask (sigmask (SIGCHLD
));
441 if (0 > kill (pid
, 0))
443 sigsetmask (SIGEMPTYMASK
);
444 kill (getpid (), SIGCHLD
);
450 sigpause (SIGEMPTYMASK
);
451 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
452 #if defined (UNIPLUS)
453 if (0 > kill (pid
, 0))
456 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
457 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
458 sigblock (sigmask (SIGCHLD
));
459 if (0 > kill (pid
, 0))
461 sigunblock (sigmask (SIGCHLD
));
464 sigpause (SIGEMPTYMASK
);
465 #else /* not POSIX_SIGNALS */
466 #ifdef HAVE_SYSV_SIGPAUSE
468 if (0 > kill (pid
, 0))
474 #else /* not HAVE_SYSV_SIGPAUSE */
478 #else /* not WINDOWSNT */
479 if (0 > kill (pid
, 0))
481 /* Using sleep instead of pause avoids timing error.
482 If the inferior dies just before the sleep,
483 we lose just one second. */
485 #endif /* not WINDOWSNT */
486 #endif /* not HAVE_SYSV_SIGPAUSE */
487 #endif /* not POSIX_SIGNALS */
488 #endif /* not UNIPLUS */
489 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
491 #else /* not subprocesses */
494 #else /* not __DJGPP__ > 1 */
496 if (kill (pid
, 0) < 0)
502 if (status
== pid
|| status
== -1)
505 #endif /* not __DJGPP__ > 1*/
506 #endif /* not subprocesses */
513 * flush any pending output
514 * (may flush input as well; it does not matter the way we use it)
518 flush_pending_output (channel
)
522 /* If we try this, we get hit with SIGTTIN, because
523 the child's tty belongs to the child's pgrp. */
526 ioctl (channel
, TCFLSH
, 1);
530 /* 3rd arg should be ignored
531 but some 4.2 kernels actually want the address of an int
532 and nonzero means something different. */
533 ioctl (channel
, TIOCFLUSH
, &zero
);
540 /* Set up the terminal at the other end of a pseudo-terminal that
541 we will be controlling an inferior through.
542 It should not echo or do line-editing, since that is done
543 in Emacs. No padding needed for insertion into an Emacs buffer. */
546 child_setup_tty (out
)
552 EMACS_GET_TTY (out
, &s
);
554 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
555 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
556 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
558 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
559 /* No output delays */
561 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
562 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
564 s
.main
.c_iflag
&= ~IUCLC
; /* Disable downcasing on input. */
567 s
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
570 s
.main
.c_oflag
&= ~OLCUC
; /* Disable upcasing on output. */
572 s
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
573 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CSIZE
) | CS8
; /* Don't strip 8th bit */
575 /* Said to be unnecessary: */
576 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
577 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
580 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
581 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
582 s
.main
.c_cc
[VERASE
] = CDISABLE
; /* disable erase processing */
583 s
.main
.c_cc
[VKILL
] = CDISABLE
; /* disable kill processing */
586 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
590 /* AIX enhanced edit loses NULs, so disable it */
593 s
.main
.c_iflag
&= ~ASCEDIT
;
595 /* Also, PTY overloads NUL and BREAK.
596 don't ignore break, but don't signal either, so it looks like NUL. */
597 s
.main
.c_iflag
&= ~IGNBRK
;
598 s
.main
.c_iflag
&= ~BRKINT
;
599 /* QUIT and INTR work better as signals, so disable character forms */
600 s
.main
.c_cc
[VINTR
] = 0377;
601 #ifdef SIGNALS_VIA_CHARACTERS
602 /* the QUIT and INTR character are used in process_send_signal
603 so set them here to something useful. */
604 if (s
.main
.c_cc
[VQUIT
] == 0377)
605 s
.main
.c_cc
[VQUIT
] = '\\'&037; /* Control-\ */
606 if (s
.main
.c_cc
[VINTR
] == 0377)
607 s
.main
.c_cc
[VINTR
] = 'C'&037; /* Control-C */
608 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
609 /* QUIT and INTR work better as signals, so disable character forms */
610 s
.main
.c_cc
[VQUIT
] = 0377;
611 s
.main
.c_cc
[VINTR
] = 0377;
612 s
.main
.c_lflag
&= ~ISIG
;
613 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
614 s
.main
.c_cc
[VEOL
] = 0377;
615 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
618 #else /* not HAVE_TERMIO */
620 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
622 s
.main
.sg_flags
|= LPASS8
;
623 s
.main
.sg_erase
= 0377;
624 s
.main
.sg_kill
= 0377;
625 s
.lmode
= LLITOUT
| s
.lmode
; /* Don't strip 8th bit */
627 #endif /* not HAVE_TERMIO */
629 EMACS_SET_TTY (out
, &s
, 0);
638 ioctl (out
, FIOASYNC
, &zero
);
641 #endif /* not DOS_NT */
645 #endif /* subprocesses */
647 /* Record a signal code and the handler for it. */
651 SIGTYPE (*handler
) P_ ((int));
654 static void save_signal_handlers
P_ ((struct save_signal
*));
655 static void restore_signal_handlers
P_ ((struct save_signal
*));
657 /* Suspend the Emacs process; give terminal to its superior. */
663 /* "Foster" parentage allows emacs to return to a subprocess that attached
664 to the current emacs as a cheaper than starting a whole new process. This
665 is set up by KEPTEDITOR.COM. */
666 unsigned long parent_id
, foster_parent_id
;
669 fpid_string
= getenv ("EMACS_PARENT_PID");
670 if (fpid_string
!= NULL
)
672 sscanf (fpid_string
, "%x", &foster_parent_id
);
673 if (foster_parent_id
!= 0)
674 parent_id
= foster_parent_id
;
676 parent_id
= getppid ();
679 parent_id
= getppid ();
681 xfree (fpid_string
); /* On VMS, this was malloc'd */
683 if (parent_id
&& parent_id
!= 0xffffffff)
685 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
686 int status
= LIB$
ATTACH (&parent_id
) & 1;
687 signal (SIGINT
, oldsig
);
696 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
697 d_prompt
.a
= "Emacs: "; /* Just a reminder */
698 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
703 #if defined (SIGTSTP) && !defined (MSDOS)
706 int pgrp
= EMACS_GETPGRP (0);
707 EMACS_KILLPG (pgrp
, SIGTSTP
);
710 #else /* No SIGTSTP */
711 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
712 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
713 kill (getpid (), SIGQUIT
);
715 #else /* No SIGTSTP or USG_JOBCTRL */
717 /* On a system where suspending is not implemented,
718 instead fork a subshell and let it talk directly to the terminal
722 #endif /* no USG_JOBCTRL */
723 #endif /* no SIGTSTP */
727 /* Fork a subshell. */
733 error ("Can't spawn subshell");
736 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
738 char oldwd
[MAXPATHLEN
+1]; /* Fixed length is safe on MSDOS. */
741 struct save_signal saved_handlers
[5];
743 unsigned char *str
= 0;
746 saved_handlers
[0].code
= SIGINT
;
747 saved_handlers
[1].code
= SIGQUIT
;
748 saved_handlers
[2].code
= SIGTERM
;
750 saved_handlers
[3].code
= SIGIO
;
751 saved_handlers
[4].code
= 0;
753 saved_handlers
[3].code
= 0;
756 /* Mentioning current_buffer->buffer would mean including buffer.h,
757 which somehow wedges the hp compiler. So instead... */
759 dir
= intern ("default-directory");
760 if (NILP (Fboundp (dir
)))
762 dir
= Fsymbol_value (dir
);
766 dir
= expand_and_dir_to_file (Funhandled_file_name_directory (dir
), Qnil
);
767 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
768 len
= XSTRING (dir
)->size
;
769 bcopy (XSTRING (dir
)->data
, str
, len
);
770 if (str
[len
- 1] != '/') str
[len
++] = '/';
777 save_signal_handlers (saved_handlers
);
778 synch_process_alive
= 1;
779 #endif /* __DJGPP__ > 1 */
783 error ("Can't spawn subshell");
790 #ifdef DOS_NT /* MW, Aug 1993 */
793 sh
= (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
796 sh
= (char *) egetenv ("SHELL");
800 /* Use our buffer's default directory for the subshell. */
802 chdir ((char *) str
);
805 close_process_descs (); /* Close Emacs's pipes/ptys */
808 #ifdef SET_EMACS_PRIORITY
810 extern int emacs_priority
;
812 if (emacs_priority
< 0)
813 nice (-emacs_priority
);
817 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
820 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
822 report_file_error ("Can't execute subshell", Fcons (build_string (sh
), Qnil
));
824 #else /* not MSDOS */
826 /* Waits for process completion */
827 pid
= _spawnlp (_P_WAIT
, sh
, sh
, NULL
);
830 write (1, "Can't execute subshell", 22);
831 #else /* not WINDOWSNT */
833 write (1, "Can't execute subshell", 22);
835 #endif /* not WINDOWSNT */
836 #endif /* not MSDOS */
839 /* Do this now if we did not do it before. */
840 #if !defined (MSDOS) || __DJGPP__ == 1
841 save_signal_handlers (saved_handlers
);
842 synch_process_alive
= 1;
846 wait_for_termination (pid
);
848 restore_signal_handlers (saved_handlers
);
849 synch_process_alive
= 0;
851 #endif /* !macintosh */
855 save_signal_handlers (saved_handlers
)
856 struct save_signal
*saved_handlers
;
858 while (saved_handlers
->code
)
860 saved_handlers
->handler
861 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers
->code
, SIG_IGN
);
867 restore_signal_handlers (saved_handlers
)
868 struct save_signal
*saved_handlers
;
870 while (saved_handlers
->code
)
872 signal (saved_handlers
->code
, saved_handlers
->handler
);
886 old_fcntl_flags
= fcntl (fd
, F_GETFL
, 0) & ~FASYNC
;
887 fcntl (fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
889 interrupts_deferred
= 0;
898 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
903 if (read_socket_hook
)
907 sigunblock (sigmask (SIGWINCH
));
909 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
911 interrupts_deferred
= 0;
917 if (read_socket_hook
)
921 sigblock (sigmask (SIGWINCH
));
923 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
);
924 interrupts_deferred
= 1;
927 #else /* no FASYNC */
928 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
935 if (read_socket_hook
)
938 ioctl (input_fd
, FIOASYNC
, &on
);
939 interrupts_deferred
= 0;
947 if (read_socket_hook
)
950 ioctl (input_fd
, FIOASYNC
, &off
);
951 interrupts_deferred
= 1;
954 #else /* not FASYNC, not STRIDE */
966 if (read_socket_hook
)
970 sigaddset (&st
, SIGIO
);
971 ioctl (input_fd
, FIOASYNC
, &on
);
972 interrupts_deferred
= 0;
973 sigprocmask (SIG_UNBLOCK
, &st
, (sigset_t
*)0);
981 if (read_socket_hook
)
984 ioctl (input_fd
, FIOASYNC
, &off
);
985 interrupts_deferred
= 1;
993 if (read_socket_hook
)
996 croak ("request_sigio");
1002 if (read_socket_hook
)
1005 croak ("unrequest_sigio");
1011 #endif /* F_SETFL */
1013 /* Saving and restoring the process group of Emacs's terminal. */
1017 /* The process group of which Emacs was a member when it initially
1020 If Emacs was in its own process group (i.e. inherited_pgroup ==
1021 getpid ()), then we know we're running under a shell with job
1022 control (Emacs would never be run as part of a pipeline).
1025 If Emacs was not in its own process group, then we know we're
1026 running under a shell (or a caller) that doesn't know how to
1027 separate itself from Emacs (like sh). Emacs must be in its own
1028 process group in order to receive SIGIO correctly. In this
1029 situation, we put ourselves in our own pgroup, forcibly set the
1030 tty's pgroup to our pgroup, and make sure to restore and reinstate
1031 the tty's pgroup just like any other terminal setting. If
1032 inherited_group was not the tty's pgroup, then we'll get a
1033 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1034 it goes foreground in the future, which is what should happen. */
1035 int inherited_pgroup
;
1037 /* Split off the foreground process group to Emacs alone.
1038 When we are in the foreground, but not started in our own process
1039 group, redirect the TTY to point to our own process group. We need
1040 to be in our own process group to receive SIGIO properly. */
1042 narrow_foreground_group ()
1046 setpgrp (0, inherited_pgroup
);
1047 if (inherited_pgroup
!= me
)
1048 EMACS_SET_TTY_PGRP (input_fd
, &me
);
1052 /* Set the tty to our original foreground group. */
1054 widen_foreground_group ()
1056 if (inherited_pgroup
!= getpid ())
1057 EMACS_SET_TTY_PGRP (input_fd
, &inherited_pgroup
);
1058 setpgrp (0, inherited_pgroup
);
1061 #endif /* BSD_PGRPS */
1063 /* Getting and setting emacs_tty structures. */
1065 /* Set *TC to the parameters associated with the terminal FD.
1066 Return zero if all's well, or -1 if we ran into an error we
1067 couldn't deal with. */
1069 emacs_get_tty (fd
, settings
)
1071 struct emacs_tty
*settings
;
1073 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1075 /* We have those nifty POSIX tcmumbleattr functions. */
1076 bzero (&settings
->main
, sizeof (settings
->main
));
1077 if (tcgetattr (fd
, &settings
->main
) < 0)
1082 /* The SYSV-style interface? */
1083 if (ioctl (fd
, TCGETA
, &settings
->main
) < 0)
1088 /* Vehemently Monstrous System? :-) */
1089 if (! (SYS$
QIOW (0, fd
, IO$_SENSEMODE
, settings
, 0, 0,
1090 &settings
->main
.class, 12, 0, 0, 0, 0)
1096 /* I give up - I hope you have the BSD ioctls. */
1097 if (ioctl (fd
, TIOCGETP
, &settings
->main
) < 0)
1099 #endif /* not DOS_NT */
1104 /* Suivant - Do we have to get struct ltchars data? */
1106 if (ioctl (fd
, TIOCGLTC
, &settings
->ltchars
) < 0)
1110 /* How about a struct tchars and a wordful of lmode bits? */
1112 if (ioctl (fd
, TIOCGETC
, &settings
->tchars
) < 0
1113 || ioctl (fd
, TIOCLGET
, &settings
->lmode
) < 0)
1117 /* We have survived the tempest. */
1122 /* Set the parameters of the tty on FD according to the contents of
1123 *SETTINGS. If FLUSHP is non-zero, we discard input.
1124 Return 0 if all went well, and -1 if anything failed. */
1127 emacs_set_tty (fd
, settings
, flushp
)
1129 struct emacs_tty
*settings
;
1132 /* Set the primary parameters - baud rate, character size, etcetera. */
1135 /* We have those nifty POSIX tcmumbleattr functions.
1136 William J. Smith <wjs@wiis.wang.com> writes:
1137 "POSIX 1003.1 defines tcsetattr to return success if it was
1138 able to perform any of the requested actions, even if some
1139 of the requested actions could not be performed.
1140 We must read settings back to ensure tty setup properly.
1141 AIX requires this to keep tty from hanging occasionally." */
1142 /* This make sure that we don't loop indefinitely in here. */
1143 for (i
= 0 ; i
< 10 ; i
++)
1144 if (tcsetattr (fd
, flushp
? TCSAFLUSH
: TCSADRAIN
, &settings
->main
) < 0)
1155 bzero (&new, sizeof (new));
1156 /* Get the current settings, and see if they're what we asked for. */
1157 tcgetattr (fd
, &new);
1158 /* We cannot use memcmp on the whole structure here because under
1159 * aix386 the termios structure has some reserved field that may
1162 if ( new.c_iflag
== settings
->main
.c_iflag
1163 && new.c_oflag
== settings
->main
.c_oflag
1164 && new.c_cflag
== settings
->main
.c_cflag
1165 && new.c_lflag
== settings
->main
.c_lflag
1166 && memcmp (new.c_cc
, settings
->main
.c_cc
, NCCS
) == 0)
1174 /* The SYSV-style interface? */
1175 if (ioctl (fd
, flushp
? TCSETAF
: TCSETAW
, &settings
->main
) < 0)
1180 /* Vehemently Monstrous System? :-) */
1181 if (! (SYS$
QIOW (0, fd
, IO$_SETMODE
, &input_iosb
, 0, 0,
1182 &settings
->main
.class, 12, 0, 0, 0, 0)
1188 /* I give up - I hope you have the BSD ioctls. */
1189 if (ioctl (fd
, (flushp
) ? TIOCSETP
: TIOCSETN
, &settings
->main
) < 0)
1191 #endif /* not DOS_NT */
1197 /* Suivant - Do we have to get struct ltchars data? */
1199 if (ioctl (fd
, TIOCSLTC
, &settings
->ltchars
) < 0)
1203 /* How about a struct tchars and a wordful of lmode bits? */
1205 if (ioctl (fd
, TIOCSETC
, &settings
->tchars
) < 0
1206 || ioctl (fd
, TIOCLSET
, &settings
->lmode
) < 0)
1210 /* We have survived the tempest. */
1215 /* The initial tty mode bits */
1216 struct emacs_tty old_tty
;
1218 /* 1 if we have been through init_sys_modes. */
1221 /* 1 if outer tty status has been recorded. */
1225 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1230 #ifndef F_SETOWN_BUG
1232 int old_fcntl_owner
;
1233 #endif /* F_SETOWN */
1234 #endif /* F_SETOWN_BUG */
1236 /* This may also be defined in stdio,
1237 but if so, this does no harm,
1238 and using the same name avoids wasting the other one's space. */
1241 extern char *_sobuf
;
1243 #if defined (USG) || defined (DGUX)
1244 unsigned char _sobuf
[BUFSIZ
+8];
1246 char _sobuf
[BUFSIZ
];
1251 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
1254 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
1260 struct emacs_tty tty
;
1263 Vwindow_system
= intern ("mac");
1264 Vwindow_system_version
= make_number (1);
1266 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1267 #ifndef subprocesses
1268 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
1269 "*Non-nil means delete processes immediately when they exit.\n\
1270 nil means don't delete them until `list-processes' is run.");
1271 delete_exited_processes
= 0;
1274 #ifndef HAVE_X_WINDOWS
1275 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
1276 "List of directories to search for bitmap files for X.");
1277 Vx_bitmap_file_path
= decode_env_path ((char *) 0, ".");
1280 #endif /* not macintosh */
1284 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
1285 extern int (*interrupt_signal
) ();
1289 Vtty_erase_char
= Qnil
;
1296 input_ef
= get_kbd_event_flag ();
1297 /* LIB$GET_EF (&input_ef); */
1298 SYS$
CLREF (input_ef
);
1299 waiting_for_ast
= 0;
1301 timer_ef
= get_timer_event_flag ();
1302 /* LIB$GET_EF (&timer_ef); */
1303 SYS$
CLREF (timer_ef
);
1307 LIB$
GET_EF (&process_ef
);
1308 SYS$
CLREF (process_ef
);
1310 if (input_ef
/ 32 != process_ef
/ 32)
1311 croak ("Input and process event flags in different clusters.");
1313 if (input_ef
/ 32 != timer_ef
/ 32)
1314 croak ("Input and timer event flags in different clusters.");
1316 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1317 ((unsigned) 1 << (process_ef
% 32));
1319 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1320 ((unsigned) 1 << (timer_ef
% 32));
1322 sys_access_reinit ();
1324 #endif /* not VMS */
1327 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1328 narrow_foreground_group ();
1331 #ifdef HAVE_WINDOW_SYSTEM
1332 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1333 needs the initialization code below. */
1334 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1337 EMACS_GET_TTY (input_fd
, &old_tty
);
1343 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1344 XSETINT (Vtty_erase_char
, old_tty
.main
.c_cc
[VERASE
]);
1347 /* This allows meta to be sent on 8th bit. */
1348 tty
.main
.c_iflag
&= ~INPCK
; /* don't check input for parity */
1350 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
1351 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
1352 #ifdef INLCR /* I'm just being cautious,
1353 since I can't check how widespread INLCR is--rms. */
1354 tty
.main
.c_iflag
&= ~INLCR
; /* Disable map of NL to CR on input */
1357 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
1359 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
1360 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
1362 tty
.main
.c_lflag
&= ~IEXTEN
; /* Disable other editing characters. */
1364 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
1367 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
1369 tty
.main
.c_iflag
&= ~IXANY
;
1373 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
1374 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
1376 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
1380 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
1381 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
1384 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
1385 /* Set up C-g for both SIGQUIT and SIGINT.
1386 We don't know which we will get, but we handle both alike
1387 so which one it really gives us does not matter. */
1388 tty
.main
.c_cc
[VQUIT
] = quit_char
;
1389 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
1390 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
1392 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
1396 #if defined (mips) || defined (HAVE_TCATTR)
1398 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
1401 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
1402 #endif /* V_DSUSP */
1403 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1404 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
1407 tty
.main
.c_cc
[VLNEXT
] = CDISABLE
;
1410 tty
.main
.c_cc
[VREPRINT
] = CDISABLE
;
1411 #endif /* VREPRINT */
1413 tty
.main
.c_cc
[VWERASE
] = CDISABLE
;
1414 #endif /* VWERASE */
1416 tty
.main
.c_cc
[VDISCARD
] = CDISABLE
;
1417 #endif /* VDISCARD */
1422 tty
.main
.c_cc
[VSTART
] = '\021';
1425 tty
.main
.c_cc
[VSTOP
] = '\023';
1431 tty
.main
.c_cc
[VSTART
] = CDISABLE
;
1434 tty
.main
.c_cc
[VSTOP
] = CDISABLE
;
1437 #endif /* mips or HAVE_TCATTR */
1439 #ifdef SET_LINE_DISCIPLINE
1440 /* Need to explicitly request TERMIODISC line discipline or
1441 Ultrix's termios does not work correctly. */
1442 tty
.main
.c_line
= SET_LINE_DISCIPLINE
;
1446 /* AIX enhanced edit loses NULs, so disable it. */
1447 tty
.main
.c_line
= 0;
1448 tty
.main
.c_iflag
&= ~ASCEDIT
;
1450 tty
.main
.c_cc
[VSTRT
] = 255;
1451 tty
.main
.c_cc
[VSTOP
] = 255;
1452 tty
.main
.c_cc
[VSUSP
] = 255;
1453 tty
.main
.c_cc
[VDSUSP
] = 255;
1454 #endif /* IBMR2AIX */
1458 tty
.main
.c_cc
[VSTART
] = '\021';
1461 tty
.main
.c_cc
[VSTOP
] = '\023';
1464 /* Also, PTY overloads NUL and BREAK.
1465 don't ignore break, but don't signal either, so it looks like NUL.
1466 This really serves a purpose only if running in an XTERM window
1467 or via TELNET or the like, but does no harm elsewhere. */
1468 tty
.main
.c_iflag
&= ~IGNBRK
;
1469 tty
.main
.c_iflag
&= ~BRKINT
;
1471 #else /* if not HAVE_TERMIO */
1473 tty
.main
.tt_char
|= TT$M_NOECHO
;
1475 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
1477 tty
.main
.tt_char
|= TT$M_TTSYNC
;
1479 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
1480 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
1481 #else /* not VMS (BSD, that is) */
1483 XSETINT (Vtty_erase_char
, tty
.main
.sg_erase
);
1484 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
1486 tty
.main
.sg_flags
|= ANYP
;
1487 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
1488 #endif /* not DOS_NT */
1489 #endif /* not VMS (BSD, that is) */
1490 #endif /* not HAVE_TERMIO */
1492 /* If going to use CBREAK mode, we must request C-g to interrupt
1493 and turn off start and stop chars, etc. If not going to use
1494 CBREAK mode, do this anyway so as to turn off local flow
1495 control for user coming over network on 4.2; in this case,
1496 only t_stopc and t_startc really matter. */
1499 /* Note: if not using CBREAK mode, it makes no difference how we
1501 tty
.tchars
= new_tchars
;
1502 tty
.tchars
.t_intrc
= quit_char
;
1505 tty
.tchars
.t_startc
= '\021';
1506 tty
.tchars
.t_stopc
= '\023';
1509 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
1511 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1512 anything, and leaving it in breaks the meta key. Go figure. */
1513 tty
.lmode
&= ~LLITOUT
;
1520 #endif /* HAVE_TCHARS */
1521 #endif /* not HAVE_TERMIO */
1524 tty
.ltchars
= new_ltchars
;
1525 #endif /* HAVE_LTCHARS */
1526 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1528 internal_terminal_init ();
1532 EMACS_SET_TTY (input_fd
, &tty
, 0);
1534 /* This code added to insure that, if flow-control is not to be used,
1535 we have an unlocked terminal at the start. */
1538 if (!flow_control
) ioctl (input_fd
, TCXONC
, 1);
1542 if (!flow_control
) ioctl (input_fd
, TIOCSTART
, 0);
1546 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1548 if (!flow_control
) tcflow (input_fd
, TCOON
);
1556 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1557 to be only LF. This is the way that is done. */
1560 if (ioctl (1, HFTGETID
, &tty
) != -1)
1561 write (1, "\033[20l", 5);
1567 /* Appears to do nothing when in PASTHRU mode.
1568 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1569 interrupt_signal, oob_chars, 0, 0, 0, 0);
1571 queue_kbd_input (0);
1576 #ifndef F_SETOWN_BUG
1577 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1579 && ! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1581 old_fcntl_owner
= fcntl (input_fd
, F_GETOWN
, 0);
1582 fcntl (input_fd
, F_SETOWN
, getpid ());
1583 init_sigio (input_fd
);
1585 #endif /* F_GETOWN */
1586 #endif /* F_SETOWN_BUG */
1587 #endif /* F_SETFL */
1590 if (interrupt_input
)
1591 init_sigio (input_fd
);
1594 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1598 /* This symbol is defined on recent USG systems.
1599 Someone says without this call USG won't really buffer the file
1600 even with a call to setbuf. */
1601 setvbuf (stdout
, (char *) _sobuf
, _IOFBF
, sizeof _sobuf
);
1603 setbuf (stdout
, (char *) _sobuf
);
1605 #ifdef HAVE_WINDOW_SYSTEM
1606 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1607 needs the initialization code below. */
1608 if (EQ (Vwindow_system
, Qnil
)
1610 /* When running in tty mode on NT/Win95, we have a read_socket
1611 hook, but still need the rest of the initialization code below. */
1612 && (! read_socket_hook
)
1616 set_terminal_modes ();
1619 && FRAMEP (Vterminal_frame
)
1620 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame
)))
1621 init_frame_faces (XFRAME (Vterminal_frame
));
1623 if (term_initted
&& no_redraw_on_reenter
)
1625 if (display_completed
)
1626 direct_output_forward_char (0);
1631 if (FRAMEP (Vterminal_frame
))
1632 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
1638 /* Return nonzero if safe to use tabs in output.
1639 At the time this is called, init_sys_modes has not been done yet. */
1644 struct emacs_tty tty
;
1646 EMACS_GET_TTY (input_fd
, &tty
);
1647 return EMACS_TTY_TABS_OK (&tty
);
1650 /* Get terminal size from system.
1651 Store number of lines into *HEIGHTP and width into *WIDTHP.
1652 We store 0 if there's no valid information. */
1655 get_frame_size (widthp
, heightp
)
1656 int *widthp
, *heightp
;
1662 struct winsize size
;
1664 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1665 *widthp
= *heightp
= 0;
1668 *widthp
= size
.ws_col
;
1669 *heightp
= size
.ws_row
;
1675 /* SunOS - style. */
1676 struct ttysize size
;
1678 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1679 *widthp
= *heightp
= 0;
1682 *widthp
= size
.ts_cols
;
1683 *heightp
= size
.ts_lines
;
1689 struct sensemode tty
;
1691 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1692 &tty
.class, 12, 0, 0, 0, 0);
1693 *widthp
= tty
.scr_wid
;
1694 *heightp
= tty
.scr_len
;
1698 *widthp
= ScreenCols ();
1699 *heightp
= ScreenRows ();
1700 #else /* system doesn't know size */
1705 #endif /* not VMS */
1706 #endif /* not SunOS-style */
1707 #endif /* not BSD-style */
1710 /* Set the logical window size associated with descriptor FD
1711 to HEIGHT and WIDTH. This is used mainly with ptys. */
1714 set_window_size (fd
, height
, width
)
1715 int fd
, height
, width
;
1720 struct winsize size
;
1721 size
.ws_row
= height
;
1722 size
.ws_col
= width
;
1724 if (ioctl (fd
, TIOCSWINSZ
, &size
) == -1)
1725 return 0; /* error */
1732 /* SunOS - style. */
1733 struct ttysize size
;
1734 size
.ts_lines
= height
;
1735 size
.ts_cols
= width
;
1737 if (ioctl (fd
, TIOCGSIZE
, &size
) == -1)
1743 #endif /* not SunOS-style */
1744 #endif /* not BSD-style */
1748 /* Prepare the terminal for exiting Emacs; move the cursor to the
1749 bottom of the frame, turn off interrupt-driven I/O, etc. */
1762 #ifdef HAVE_WINDOW_SYSTEM
1763 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1764 needs the clean-up code below. */
1765 if (!EQ (Vwindow_system
, Qnil
)
1767 /* When running in tty mode on NT/Win95, we have a read_socket
1768 hook, but still need the rest of the clean-up code below. */
1774 sf
= SELECTED_FRAME ();
1775 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1776 clear_end_of_line (FRAME_WIDTH (sf
));
1777 /* clear_end_of_line may move the cursor */
1778 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1779 #if defined (IBMR2AIX) && defined (AIXHFT)
1781 /* HFT devices normally use ^J as a LF/CR. We forced it to
1782 do the LF only. Now, we need to reset it. */
1785 if (ioctl (1, HFTGETID
, &tty
) != -1)
1786 write (1, "\033[20h", 5);
1790 reset_terminal_modes ();
1794 /* Avoid possible loss of output when changing terminal modes. */
1795 fsync (fileno (stdout
));
1800 #ifndef F_SETOWN_BUG
1801 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1802 if (interrupt_input
)
1805 fcntl (input_fd
, F_SETOWN
, old_fcntl_owner
);
1807 #endif /* F_SETOWN */
1808 #endif /* F_SETOWN_BUG */
1810 fcntl (input_fd
, F_SETFL
, fcntl (input_fd
, F_GETFL
, 0) & ~O_NDELAY
);
1812 #endif /* F_SETFL */
1814 if (interrupt_input
)
1819 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1822 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1826 #ifdef SET_LINE_DISCIPLINE
1827 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1828 A different old line discipline is therefore not restored, yet.
1829 Restore the old line discipline by hand. */
1830 ioctl (0, TIOCSETD
, &old_tty
.main
.c_line
);
1838 widen_foreground_group ();
1844 /* Set up the proper status flags for use of a pty. */
1850 /* I'm told that TOICREMOTE does not mean control chars
1851 "can't be sent" but rather that they don't have
1852 input-editing or signaling effects.
1853 That should be good, because we have other ways
1854 to do those things in Emacs.
1855 However, telnet mode seems not to work on 4.2.
1856 So TIOCREMOTE is turned off now. */
1858 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1859 will hang. In particular, the "timeout" feature (which
1860 causes a read to return if there is no data available)
1861 does this. Also it is known that telnet mode will hang
1862 in such a way that Emacs must be stopped (perhaps this
1863 is the same problem).
1865 If TIOCREMOTE is turned off, then there is a bug in
1866 hp-ux which sometimes loses data. Apparently the
1867 code which blocks the master process when the internal
1868 buffer fills up does not work. Other than this,
1869 though, everything else seems to work fine.
1871 Since the latter lossage is more benign, we may as well
1872 lose that way. -- cph */
1877 ioctl (fd
, FIONBIO
, &on
);
1882 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1883 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1884 /* cause EMACS not to die when it should, i.e., when its own controlling */
1885 /* tty goes away. I've complained to the AIX developers, and they may */
1886 /* change this behavior, but I'm not going to hold my breath. */
1887 signal (SIGHUP
, SIG_IGN
);
1890 #endif /* HAVE_PTYS */
1894 /* Assigning an input channel is done at the start of Emacs execution.
1895 This is called each time Emacs is resumed, also, but does nothing
1896 because input_chain is no longer zero. */
1905 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1911 /* Deassigning the input channel is done before exiting. */
1916 return SYS$
DASSGN (input_fd
);
1921 /* Request reading one character into the keyboard buffer.
1922 This is done as soon as the buffer becomes empty. */
1928 extern kbd_input_ast ();
1930 waiting_for_ast
= 0;
1932 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1933 &input_iosb
, kbd_input_ast
, 1,
1934 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1939 /* Ast routine that is called when keyboard input comes in
1940 in accord with the SYS$QIO above. */
1945 register int c
= -1;
1946 int old_errno
= errno
;
1947 extern EMACS_TIME
*input_available_clear_time
;
1949 if (waiting_for_ast
)
1950 SYS$
SETEF (input_ef
);
1951 waiting_for_ast
= 0;
1954 if (input_count
== 25)
1956 printf ("Ast # %d,", input_count
);
1957 printf (" iosb = %x, %x, %x, %x",
1958 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1961 if (input_iosb
.offset
)
1965 printf (", char = 0%o", c
);
1977 struct input_event e
;
1978 e
.kind
= ascii_keystroke
;
1979 XSETINT (e
.code
, c
);
1980 e
.frame_or_window
= selected_frame
;
1981 kbd_buffer_store_event (&e
);
1983 if (input_available_clear_time
)
1984 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
1988 /* Wait until there is something in kbd_buffer. */
1991 wait_for_kbd_input ()
1993 extern int have_process_input
, process_exited
;
1995 /* If already something, avoid doing system calls. */
1996 if (detect_input_pending ())
2000 /* Clear a flag, and tell ast routine above to set it. */
2001 SYS$
CLREF (input_ef
);
2002 waiting_for_ast
= 1;
2003 /* Check for timing error: ast happened while we were doing that. */
2004 if (!detect_input_pending ())
2006 /* No timing error: wait for flag to be set. */
2007 set_waiting_for_input (0);
2008 SYS$
WFLOR (input_ef
, input_eflist
);
2009 clear_waiting_for_input (0);
2010 if (!detect_input_pending ())
2011 /* Check for subprocess input availability */
2013 int dsp
= have_process_input
|| process_exited
;
2015 SYS$
CLREF (process_ef
);
2016 if (have_process_input
)
2017 process_command_input ();
2022 update_mode_lines
++;
2023 prepare_menu_bars ();
2024 redisplay_preserve_echo_area ();
2028 waiting_for_ast
= 0;
2031 /* Get rid of any pending QIO, when we are about to suspend
2032 or when we want to throw away pending input.
2033 We wait for a positive sign that the AST routine has run
2034 and therefore there is no I/O request queued when we return.
2035 SYS$SETAST is used to avoid a timing error. */
2041 printf ("At end_kbd_input.\n");
2045 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2047 SYS$
CANCEL (input_fd
);
2052 /* Clear a flag, and tell ast routine above to set it. */
2053 SYS$
CLREF (input_ef
);
2054 waiting_for_ast
= 1;
2056 SYS$
CANCEL (input_fd
);
2058 SYS$
WAITFR (input_ef
);
2059 waiting_for_ast
= 0;
2062 /* Wait for either input available or time interval expiry. */
2065 input_wait_timeout (timeval
)
2066 int timeval
; /* Time to wait, in seconds */
2069 static int zero
= 0;
2070 static int large
= -10000000;
2072 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2074 /* If already something, avoid doing system calls. */
2075 if (detect_input_pending ())
2079 /* Clear a flag, and tell ast routine above to set it. */
2080 SYS$
CLREF (input_ef
);
2081 waiting_for_ast
= 1;
2082 /* Check for timing error: ast happened while we were doing that. */
2083 if (!detect_input_pending ())
2085 /* No timing error: wait for flag to be set. */
2087 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2088 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
2090 waiting_for_ast
= 0;
2093 /* The standard `sleep' routine works some other way
2094 and it stops working if you have ever quit out of it.
2095 This one continues to work. */
2101 static int zero
= 0;
2102 static int large
= -10000000;
2104 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2107 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2108 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
2126 croak ("request sigio");
2132 croak ("unrequest sigio");
2137 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2142 #ifndef SYSTEM_MALLOC
2149 /* Some systems that cannot dump also cannot implement these. */
2152 * Return the address of the start of the text segment prior to
2153 * doing an unexec. After unexec the return value is undefined.
2154 * See crt0.c for further explanation and _start.
2158 #if !(defined (__NetBSD__) && defined (__ELF__))
2159 #ifndef HAVE_TEXT_START
2164 return ((char *) TEXT_START
);
2168 return ((char *) csrt
);
2169 #else /* not GOULD */
2170 extern int _start ();
2171 return ((char *) _start
);
2173 #endif /* TEXT_START */
2175 #endif /* not HAVE_TEXT_START */
2179 * Return the address of the start of the data segment prior to
2180 * doing an unexec. After unexec the return value is undefined.
2181 * See crt0.c for further information and definition of data_start.
2183 * Apparently, on BSD systems this is etext at startup. On
2184 * USG systems (swapping) this is highly mmu dependent and
2185 * is also dependent on whether or not the program is running
2186 * with shared text. Generally there is a (possibly large)
2187 * gap between end of text and start of data with shared text.
2189 * On Uniplus+ systems with shared text, data starts at a
2190 * fixed address. Each port (from a given oem) is generally
2191 * different, and the specific value of the start of data can
2192 * be obtained via the UniPlus+ specific "uvar" system call,
2193 * however the method outlined in crt0.c seems to be more portable.
2195 * Probably what will have to happen when a USG unexec is available,
2196 * at least on UniPlus, is temacs will have to be made unshared so
2197 * that text and data are contiguous. Then once loadup is complete,
2198 * unexec will produce a shared executable where the data can be
2199 * at the normal shared text boundary and the startofdata variable
2200 * will be patched by unexec to the correct value.
2208 return ((char *) DATA_START
);
2210 #ifdef ORDINARY_LINK
2212 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2213 * data_start isn't defined. We take the address of environ, which
2214 * is known to live at or near the start of the system crt0.c, and
2215 * we don't sweat the handful of bytes that might lose.
2217 extern char **environ
;
2219 return ((char *) &environ
);
2221 extern int data_start
;
2222 return ((char *) &data_start
);
2223 #endif /* ORDINARY_LINK */
2224 #endif /* DATA_START */
2226 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2229 /* Some systems that cannot dump also cannot implement these. */
2232 * Return the address of the end of the text segment prior to
2233 * doing an unexec. After unexec the return value is undefined.
2240 return ((char *) TEXT_END
);
2243 return ((char *) &etext
);
2248 * Return the address of the end of the data segment prior to
2249 * doing an unexec. After unexec the return value is undefined.
2256 return ((char *) DATA_END
);
2259 return ((char *) &edata
);
2263 #endif /* not CANNOT_DUMP */
2265 /* init_system_name sets up the string for the Lisp function
2266 system-name to return. */
2272 extern Lisp_Object Vsystem_name
;
2277 #include <sys/socket.h>
2279 #endif /* HAVE_SOCKETS */
2280 #endif /* not VMS */
2281 #endif /* not BSD4_1 */
2287 Vsystem_name
= build_string (sysname
);
2291 if ((sp
= egetenv ("SYS$NODE")) == 0)
2292 Vsystem_name
= build_string ("vax-vms");
2293 else if ((end
= index (sp
, ':')) == 0)
2294 Vsystem_name
= build_string (sp
);
2296 Vsystem_name
= make_string (sp
, end
- sp
);
2298 #ifndef HAVE_GETHOSTNAME
2301 Vsystem_name
= build_string (uts
.nodename
);
2302 #else /* HAVE_GETHOSTNAME */
2303 unsigned int hostname_size
= 256;
2304 char *hostname
= (char *) alloca (hostname_size
);
2306 /* Try to get the host name; if the buffer is too short, try
2307 again. Apparently, the only indication gethostname gives of
2308 whether the buffer was large enough is the presence or absence
2309 of a '\0' in the string. Eech. */
2312 gethostname (hostname
, hostname_size
- 1);
2313 hostname
[hostname_size
- 1] = '\0';
2315 /* Was the buffer large enough for the '\0'? */
2316 if (strlen (hostname
) < hostname_size
- 1)
2319 hostname_size
<<= 1;
2320 hostname
= (char *) alloca (hostname_size
);
2323 /* Turn the hostname into the official, fully-qualified hostname.
2324 Don't do this if we're going to dump; this can confuse system
2325 libraries on some machines and make the dumped emacs core dump. */
2328 #endif /* not CANNOT_DUMP */
2329 if (! index (hostname
, '.'))
2333 for (count
= 0;; count
++)
2338 hp
= gethostbyname (hostname
);
2340 if (! (hp
== 0 && h_errno
== TRY_AGAIN
))
2345 Fsleep_for (make_number (1), Qnil
);
2349 char *fqdn
= (char *) hp
->h_name
;
2352 if (!index (fqdn
, '.'))
2354 /* We still don't have a fully qualified domain name.
2355 Try to find one in the list of alternate names */
2356 char **alias
= hp
->h_aliases
;
2357 while (*alias
&& !index (*alias
, '.'))
2364 /* Convert the host name to lower case. */
2365 /* Using ctype.h here would introduce a possible locale
2366 dependence that is probably wrong for hostnames. */
2370 if (*p
>= 'A' && *p
<= 'Z')
2377 #endif /* HAVE_SOCKETS */
2378 /* We used to try using getdomainname here,
2379 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2380 getdomainname gets the NIS/YP domain which often is not the same
2381 as in Internet domain name. */
2382 #if 0 /* Turned off because sysinfo is not really likely to return the
2383 correct Internet domain. */
2384 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2385 if (! index (hostname
, '.'))
2387 /* The hostname is not fully qualified. Append the domain name. */
2389 int hostlen
= strlen (hostname
);
2390 int domain_size
= 256;
2394 char *domain
= (char *) alloca (domain_size
+ 1);
2395 char *fqdn
= (char *) alloca (hostlen
+ 1 + domain_size
+ 1);
2396 int sys_domain_size
= sysinfo (SI_SRPC_DOMAIN
, domain
, domain_size
);
2397 if (sys_domain_size
<= 0)
2399 if (domain_size
< sys_domain_size
)
2401 domain_size
= sys_domain_size
;
2404 strcpy (fqdn
, hostname
);
2405 if (domain
[0] == '.')
2406 strcpy (fqdn
+ hostlen
, domain
);
2407 else if (domain
[0] != 0)
2409 fqdn
[hostlen
] = '.';
2410 strcpy (fqdn
+ hostlen
+ 1, domain
);
2416 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2418 Vsystem_name
= build_string (hostname
);
2419 #endif /* HAVE_GETHOSTNAME */
2424 for (p
= XSTRING (Vsystem_name
)->data
; *p
; p
++)
2425 if (*p
== ' ' || *p
== '\t')
2432 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2434 #include "sysselect.h"
2437 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2438 /* Cause explanatory error message at compile time,
2439 since the select emulation is not good enough for X. */
2440 int *x
= &x_windows_lose_if_no_select_system_call
;
2443 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2444 * Only checks read descriptors.
2446 /* How long to wait between checking fds in select */
2447 #define SELECT_PAUSE 1
2450 /* For longjmp'ing back to read_input_waiting. */
2452 jmp_buf read_alarm_throw
;
2454 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2455 The read_socket_hook function sets this to 1 while it is waiting. */
2457 int read_alarm_should_throw
;
2465 #else /* not BSD4_1 */
2466 signal (SIGALRM
, SIG_IGN
);
2467 #endif /* not BSD4_1 */
2468 if (read_alarm_should_throw
)
2469 longjmp (read_alarm_throw
, 1);
2473 /* Only rfds are checked. */
2475 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2477 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2478 EMACS_TIME
*timeout
;
2484 extern int proc_buffered_char
[];
2485 #ifndef subprocesses
2486 int process_tick
= 0, update_tick
= 0;
2488 extern int process_tick
, update_tick
;
2492 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2493 /* If we're using X, then the native select will work; we only need the
2494 emulation for non-X usage. */
2495 if (!NILP (Vwindow_system
))
2496 return select (nfds
, rfds
, wfds
, efds
, timeout
);
2498 timeoutval
= timeout
? EMACS_SECS (*timeout
) : 100000;
2499 local_timeout
= &timeoutval
;
2511 /* If we are looking only for the terminal, with no timeout,
2512 just read it and wait -- that's more efficient. */
2513 if (*local_timeout
== 100000 && process_tick
== update_tick
2514 && FD_ISSET (0, &orfds
))
2517 for (fd
= 1; fd
< nfds
; ++fd
)
2518 if (FD_ISSET (fd
, &orfds
))
2520 if (! detect_input_pending ())
2521 read_input_waiting ();
2527 /* Once a second, till the timer expires, check all the flagged read
2528 * descriptors to see if any input is available. If there is some then
2529 * set the corresponding bit in the return copy of rfds.
2533 register int to_check
, fd
;
2537 for (to_check
= nfds
, fd
= 0; --to_check
>= 0; fd
++)
2539 if (FD_ISSET (fd
, &orfds
))
2541 int avail
= 0, status
= 0;
2544 avail
= detect_input_pending (); /* Special keyboard handler */
2548 status
= ioctl (fd
, FIONREAD
, &avail
);
2549 #else /* no FIONREAD */
2550 /* Hoping it will return -1 if nothing available
2551 or 0 if all 0 chars requested are read. */
2552 if (proc_buffered_char
[fd
] >= 0)
2556 avail
= read (fd
, &buf
, 1);
2558 proc_buffered_char
[fd
] = buf
;
2560 #endif /* no FIONREAD */
2562 if (status
>= 0 && avail
> 0)
2570 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
2573 turn_on_atimers (0);
2574 signal (SIGALRM
, select_alarm
);
2576 alarm (SELECT_PAUSE
);
2578 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2579 while (select_alarmed
== 0 && *local_timeout
!= 0
2580 && process_tick
== update_tick
)
2582 /* If we are interested in terminal input,
2583 wait by reading the terminal.
2584 That makes instant wakeup for terminal input at least. */
2585 if (FD_ISSET (0, &orfds
))
2587 read_input_waiting ();
2588 if (detect_input_pending ())
2594 (*local_timeout
) -= SELECT_PAUSE
;
2596 /* Reset the old alarm if there was one. */
2597 turn_on_atimers (1);
2599 if (*local_timeout
== 0) /* Stop on timer being cleared */
2604 #endif /* not WINDOWSNT */
2606 /* Read keyboard input into the standard buffer,
2607 waiting for at least one character. */
2609 /* Make all keyboard buffers much bigger when using a window system. */
2610 #ifdef HAVE_WINDOW_SYSTEM
2611 #define BUFFER_SIZE_FACTOR 16
2613 #define BUFFER_SIZE_FACTOR 1
2617 read_input_waiting ()
2619 struct input_event e
;
2621 extern int quit_char
;
2623 if (read_socket_hook
)
2625 struct input_event buf
[256];
2627 read_alarm_should_throw
= 0;
2628 if (! setjmp (read_alarm_throw
))
2629 nread
= (*read_socket_hook
) (0, buf
, 256, 1);
2633 /* Scan the chars for C-g and store them in kbd_buffer. */
2634 for (i
= 0; i
< nread
; i
++)
2636 kbd_buffer_store_event (&buf
[i
]);
2637 /* Don't look at input that follows a C-g too closely.
2638 This reduces lossage due to autorepeat on C-g. */
2639 if (buf
[i
].kind
== ascii_keystroke
2640 && buf
[i
].code
== quit_char
)
2647 nread
= read (fileno (stdin
), buf
, 1);
2649 /* Scan the chars for C-g and store them in kbd_buffer. */
2650 e
.kind
= ascii_keystroke
;
2651 e
.frame_or_window
= selected_frame
;
2653 for (i
= 0; i
< nread
; i
++)
2655 /* Convert chars > 0177 to meta events if desired.
2656 We do this under the same conditions that read_avail_input does. */
2657 if (read_socket_hook
== 0)
2659 /* If the user says she has a meta key, then believe her. */
2660 if (meta_key
== 1 && (buf
[i
] & 0x80))
2661 e
.modifiers
= meta_modifier
;
2666 XSETINT (e
.code
, buf
[i
]);
2667 kbd_buffer_store_event (&e
);
2668 /* Don't look at input that follows a C-g too closely.
2669 This reduces lossage due to autorepeat on C-g. */
2670 if (buf
[i
] == quit_char
)
2676 #endif /* not HAVE_SELECT */
2677 #endif /* not VMS */
2678 #endif /* not MSDOS */
2687 lmode
= LINTRUP
| lmode
;
2688 ioctl (fd
, TIOCLSET
, &lmode
);
2696 lmode
= ~LINTRUP
& lmode
;
2697 ioctl (0, TIOCLSET
, &lmode
);
2705 interrupts_deferred
= 0;
2713 interrupts_deferred
= 1;
2716 /* still inside #ifdef BSD4_1 */
2719 int sigheld
; /* Mask of held signals */
2725 sigheld
|= sigbit (signum
);
2733 sigheld
|= sigbit (signum
);
2740 sigheld
&= ~sigbit (signum
);
2745 sigfree () /* Free all held signals */
2748 for (i
= 0; i
< NSIG
; i
++)
2749 if (sigheld
& sigbit (i
))
2757 return 1 << (i
- 1);
2759 #endif /* subprocesses */
2762 /* POSIX signals support - DJB */
2763 /* Anyone with POSIX signals should have ANSI C declarations */
2765 #ifdef POSIX_SIGNALS
2767 sigset_t empty_mask
, full_mask
;
2770 sys_signal (int signal_number
, signal_handler_t action
)
2772 struct sigaction new_action
, old_action
;
2773 sigemptyset (&new_action
.sa_mask
);
2774 new_action
.sa_handler
= action
;
2776 /* Emacs mostly works better with restartable system services. If this
2777 * flag exists, we probably want to turn it on here.
2779 new_action
.sa_flags
= SA_RESTART
;
2781 new_action
.sa_flags
= 0;
2783 sigaction (signal_number
, &new_action
, &old_action
);
2784 return (old_action
.sa_handler
);
2788 /* If we're compiling with GCC, we don't need this function, since it
2789 can be written as a macro. */
2791 sys_sigmask (int sig
)
2794 sigemptyset (&mask
);
2795 sigaddset (&mask
, sig
);
2800 /* I'd like to have these guys return pointers to the mask storage in here,
2801 but there'd be trouble if the code was saving multiple masks. I'll be
2802 safe and pass the structure. It normally won't be more than 2 bytes
2806 sys_sigblock (sigset_t new_mask
)
2809 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
2814 sys_sigunblock (sigset_t new_mask
)
2817 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
2822 sys_sigsetmask (sigset_t new_mask
)
2825 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
2829 #endif /* POSIX_SIGNALS */
2831 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2832 static char *my_sys_siglist
[NSIG
];
2836 # define sys_siglist my_sys_siglist
2842 #ifdef POSIX_SIGNALS
2843 sigemptyset (&empty_mask
);
2844 sigfillset (&full_mask
);
2847 #if !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED
2851 sys_siglist
[SIGABRT
] = "Aborted";
2854 sys_siglist
[SIGAIO
] = "LAN I/O interrupt";
2857 sys_siglist
[SIGALRM
] = "Alarm clock";
2860 sys_siglist
[SIGBUS
] = "Bus error";
2863 sys_siglist
[SIGCLD
] = "Child status changed";
2866 sys_siglist
[SIGCHLD
] = "Child status changed";
2869 sys_siglist
[SIGCONT
] = "Continued";
2872 sys_siglist
[SIGDANGER
] = "Swap space dangerously low";
2875 sys_siglist
[SIGDGNOTIFY
] = "Notification message in queue";
2878 sys_siglist
[SIGEMT
] = "Emulation trap";
2881 sys_siglist
[SIGFPE
] = "Arithmetic exception";
2884 sys_siglist
[SIGFREEZE
] = "SIGFREEZE";
2887 sys_siglist
[SIGGRANT
] = "Monitor mode granted";
2890 sys_siglist
[SIGHUP
] = "Hangup";
2893 sys_siglist
[SIGILL
] = "Illegal instruction";
2896 sys_siglist
[SIGINT
] = "Interrupt";
2899 sys_siglist
[SIGIO
] = "I/O possible";
2902 sys_siglist
[SIGIOINT
] = "I/O intervention required";
2905 sys_siglist
[SIGIOT
] = "IOT trap";
2908 sys_siglist
[SIGKILL
] = "Killed";
2911 sys_siglist
[SIGLOST
] = "Resource lost";
2914 sys_siglist
[SIGLWP
] = "SIGLWP";
2917 sys_siglist
[SIGMSG
] = "Monitor mode data available";
2920 sys_siglist
[SIGWIND
] = "SIGPHONE";
2923 sys_siglist
[SIGPIPE
] = "Broken pipe";
2926 sys_siglist
[SIGPOLL
] = "Pollable event occurred";
2929 sys_siglist
[SIGPROF
] = "Profiling timer expired";
2932 sys_siglist
[SIGPTY
] = "PTY I/O interrupt";
2935 sys_siglist
[SIGPWR
] = "Power-fail restart";
2938 sys_siglist
[SIGQUIT
] = "Quit";
2941 sys_siglist
[SIGRETRACT
] = "Need to relinguish monitor mode";
2944 sys_siglist
[SIGSAK
] = "Secure attention";
2947 sys_siglist
[SIGSEGV
] = "Segmentation violation";
2950 sys_siglist
[SIGSOUND
] = "Sound completed";
2953 sys_siglist
[SIGSTOP
] = "Stopped (signal)";
2956 sys_siglist
[SIGSTP
] = "Stopped (user)";
2959 sys_siglist
[SIGSYS
] = "Bad argument to system call";
2962 sys_siglist
[SIGTERM
] = "Terminated";
2965 sys_siglist
[SIGTHAW
] = "SIGTHAW";
2968 sys_siglist
[SIGTRAP
] = "Trace/breakpoint trap";
2971 sys_siglist
[SIGTSTP
] = "Stopped (user)";
2974 sys_siglist
[SIGTTIN
] = "Stopped (tty input)";
2977 sys_siglist
[SIGTTOU
] = "Stopped (tty output)";
2980 sys_siglist
[SIGURG
] = "Urgent I/O condition";
2983 sys_siglist
[SIGUSR1
] = "User defined signal 1";
2986 sys_siglist
[SIGUSR2
] = "User defined signal 2";
2989 sys_siglist
[SIGVTALRM
] = "Virtual timer expired";
2992 sys_siglist
[SIGWAITING
] = "Process's LWPs are blocked";
2995 sys_siglist
[SIGWINCH
] = "Window size changed";
2998 sys_siglist
[SIGWIND
] = "SIGWIND";
3001 sys_siglist
[SIGXCPU
] = "CPU time limit exceeded";
3004 sys_siglist
[SIGXFSZ
] = "File size limit exceeded";
3007 #endif /* !defined HAVE_STRSIGNAL && !defined SYS_SIGLIST_DECLARED */
3016 /* Figure out how many bits the system's random number generator uses.
3017 `random' and `lrand48' are assumed to return 31 usable bits.
3018 BSD `rand' returns a 31 bit value but the low order bits are unusable;
3019 so we'll shift it and treat it like the 15-bit USG `rand'. */
3023 # define RAND_BITS 31
3024 # else /* !HAVE_RANDOM */
3025 # ifdef HAVE_LRAND48
3026 # define RAND_BITS 31
3027 # define random lrand48
3028 # else /* !HAVE_LRAND48 */
3029 # define RAND_BITS 15
3030 # if RAND_MAX == 32767
3031 # define random rand
3032 # else /* RAND_MAX != 32767 */
3033 # if RAND_MAX == 2147483647
3034 # define random() (rand () >> 16)
3035 # else /* RAND_MAX != 2147483647 */
3037 # define random rand
3039 # define random() (rand () >> 16)
3041 # endif /* RAND_MAX != 2147483647 */
3042 # endif /* RAND_MAX != 32767 */
3043 # endif /* !HAVE_LRAND48 */
3044 # endif /* !HAVE_RANDOM */
3045 #endif /* !RAND_BITS */
3052 srandom ((unsigned int)arg
);
3054 # ifdef HAVE_LRAND48
3057 srand ((unsigned int)arg
);
3063 * Build a full Emacs-sized word out of whatever we've got.
3064 * This suffices even for a 64-bit architecture with a 15-bit rand.
3069 long val
= random ();
3070 #if VALBITS > RAND_BITS
3071 val
= (val
<< RAND_BITS
) ^ random ();
3072 #if VALBITS > 2*RAND_BITS
3073 val
= (val
<< RAND_BITS
) ^ random ();
3074 #if VALBITS > 3*RAND_BITS
3075 val
= (val
<< RAND_BITS
) ^ random ();
3076 #if VALBITS > 4*RAND_BITS
3077 val
= (val
<< RAND_BITS
) ^ random ();
3078 #endif /* need at least 5 */
3079 #endif /* need at least 4 */
3080 #endif /* need at least 3 */
3081 #endif /* need at least 2 */
3082 return val
& ((1L << VALBITS
) - 1);
3085 #ifdef WRONG_NAME_INSQUE
3098 /* If any place else asks for the TERM variable,
3099 allow it to be overridden with the EMACS_TERM variable
3100 before attempting to translate the logical name TERM. As a last
3101 resort, ask for VAX C's special idea of the TERM variable. */
3108 static char buf
[256];
3109 static struct dsc$descriptor_s equiv
3110 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
3111 static struct dsc$descriptor_s d_name
3112 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
3115 if (!strcmp (name
, "TERM"))
3117 val
= (char *) getenv ("EMACS_TERM");
3122 d_name
.dsc$w_length
= strlen (name
);
3123 d_name
.dsc$a_pointer
= name
;
3124 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
3126 char *str
= (char *) xmalloc (eqlen
+ 1);
3127 bcopy (buf
, str
, eqlen
);
3129 /* This is a storage leak, but a pain to fix. With luck,
3130 no one will ever notice. */
3133 return (char *) getenv (name
);
3138 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3139 to force a call on the debugger from within the image. */
3144 LIB$
SIGNAL (SS$_DEBUG
);
3150 #ifdef LINK_CRTL_SHARE
3151 #ifdef SHARABLE_LIB_BUG
3152 /* Variables declared noshare and initialized in sharable libraries
3153 cannot be shared. The VMS linker incorrectly forces you to use a private
3154 version which is uninitialized... If not for this "feature", we
3155 could use the C library definition of sys_nerr and sys_errlist. */
3157 char *sys_errlist
[] =
3161 "no such file or directory",
3163 "interrupted system call",
3165 "no such device or address",
3166 "argument list too long",
3167 "exec format error",
3170 "no more processes",
3171 "not enough memory",
3172 "permission denied",
3174 "block device required",
3175 "mount devices busy",
3177 "cross-device link",
3182 "file table overflow",
3183 "too many open files",
3187 "no space left on device",
3189 "read-only file system",
3195 "vax/vms specific error code nontranslatable error"
3197 #endif /* SHARABLE_LIB_BUG */
3198 #endif /* LINK_CRTL_SHARE */
3201 #ifndef HAVE_STRERROR
3207 extern char *sys_errlist
[];
3208 extern int sys_nerr
;
3210 if (errnum
>= 0 && errnum
< sys_nerr
)
3211 return sys_errlist
[errnum
];
3212 return (char *) "Unknown error";
3214 #endif /* not WINDOWSNT */
3215 #endif /* ! HAVE_STRERROR */
3218 emacs_open (path
, oflag
, mode
)
3222 register int rtnval
;
3225 if (oflag
& O_CREAT
)
3226 return creat (path
, mode
);
3229 while ((rtnval
= open (path
, oflag
, mode
)) == -1
3230 && (errno
== EINTR
));
3239 register int rtnval
;
3241 while ((rtnval
= close (fd
)) == -1
3242 && (errno
== EINTR
))
3245 /* If close is interrupted SunOS 4.1 may or may not have closed the
3246 file descriptor. If it did the second close will fail with
3247 errno = EBADF. That means we have succeeded. */
3248 if (rtnval
== -1 && did_retry
&& errno
== EBADF
)
3255 emacs_read (fildes
, buf
, nbyte
)
3260 register int rtnval
;
3262 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
3263 && (errno
== EINTR
));
3268 emacs_write (fildes
, buf
, nbyte
)
3273 register int rtnval
, bytes_written
;
3279 rtnval
= write (fildes
, buf
, nbyte
);
3286 return (bytes_written
? bytes_written
: -1);
3291 bytes_written
+= rtnval
;
3293 return (bytes_written
);
3298 * All of the following are for USG.
3300 * On USG systems the system calls are INTERRUPTIBLE by signals
3301 * that the user program has elected to catch. Thus the system call
3302 * must be retried in these cases. To handle this without massive
3303 * changes in the source code, we remap the standard system call names
3304 * to names for our own functions in sysdep.c that do the system call
3305 * with retries. Actually, for portability reasons, it is good
3306 * programming practice, as this example shows, to limit all actual
3307 * system calls to a single occurrence in the source. Sure, this
3308 * adds an extra level of function call overhead but it is almost
3309 * always negligible. Fred Fish, Unisoft Systems Inc.
3313 * Warning, this function may not duplicate 4.2 action properly
3314 * under error conditions.
3318 /* In 4.1, param.h fails to define this. */
3319 #define MAXPATHLEN 1024
3328 char *npath
, *spath
;
3329 extern char *getcwd ();
3331 BLOCK_INPUT
; /* getcwd uses malloc */
3332 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
3335 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3336 up to first slash. Should be harmless on other systems. */
3337 while (*npath
&& *npath
!= '/')
3339 strcpy (pathname
, npath
);
3340 free (spath
); /* getcwd uses malloc */
3345 #endif /* HAVE_GETWD */
3348 * Emulate rename using unlink/link. Note that this is
3349 * only partially correct. Also, doesn't enforce restriction
3350 * that files be of same type (regular->regular, dir->dir, etc).
3359 if (access (from
, 0) == 0)
3362 if (link (from
, to
) == 0)
3363 if (unlink (from
) == 0)
3375 /* HPUX curses library references perror, but as far as we know
3376 it won't be called. Anyway this definition will do for now. */
3382 #endif /* not HAVE_PERROR */
3388 * Emulate BSD dup2. First close newd if it already exists.
3389 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3390 * until we are, then close the unsuccessful ones.
3397 register int fd
, ret
;
3402 return fcntl (oldd
, F_DUPFD
, newd
);
3409 ret
= dup2 (old
,new);
3415 #endif /* not HAVE_DUP2 */
3418 * Gettimeofday. Simulate as much as possible. Only accurate
3419 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3420 * Only needed when subprocesses are defined.
3425 #ifndef HAVE_GETTIMEOFDAY
3430 gettimeofday (tp
, tzp
)
3432 struct timezone
*tzp
;
3434 extern long time ();
3436 tp
->tv_sec
= time ((long *)0);
3439 tzp
->tz_minuteswest
= -1;
3446 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3449 * This function will go away as soon as all the stubs fixed. (fnf)
3456 printf ("%s not yet implemented\r\n", badfunc
);
3463 /* Directory routines for systems that don't have them. */
3465 #ifdef SYSV_SYSTEM_DIR
3469 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3473 register DIR *dirp
; /* stream from opendir */
3477 rtnval
= emacs_close (dirp
->dd_fd
);
3479 /* Some systems (like Solaris) allocate the buffer and the DIR all
3480 in one block. Why in the world are we freeing this ourselves
3482 #if ! (defined (sun) && defined (USG5_4))
3483 xfree ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
3485 xfree ((char *) dirp
);
3489 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3490 #endif /* SYSV_SYSTEM_DIR */
3492 #ifdef NONSYSTEM_DIR_LIBRARY
3496 char *filename
; /* name of directory */
3498 register DIR *dirp
; /* -> malloc'ed storage */
3499 register int fd
; /* file descriptor for read */
3500 struct stat sbuf
; /* result of fstat */
3502 fd
= emacs_open (filename
, O_RDONLY
, 0);
3507 if (fstat (fd
, &sbuf
) < 0
3508 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
3509 || (dirp
= (DIR *) malloc (sizeof (DIR))) == 0)
3513 return 0; /* bad luck today */
3518 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
3525 register DIR *dirp
; /* stream from opendir */
3527 emacs_close (dirp
->dd_fd
);
3528 xfree ((char *) dirp
);
3536 ino_t od_ino
; /* inode */
3537 char od_name
[DIRSIZ
]; /* filename */
3539 #endif /* not VMS */
3541 struct direct dir_static
; /* simulated directory contents */
3546 register DIR *dirp
; /* stream from opendir */
3549 register struct olddir
*dp
; /* -> directory data */
3551 register struct dir$_name
*dp
; /* -> directory data */
3552 register struct dir$_version
*dv
; /* -> version data */
3557 if (dirp
->dd_loc
>= dirp
->dd_size
)
3558 dirp
->dd_loc
= dirp
->dd_size
= 0;
3560 if (dirp
->dd_size
== 0 /* refill buffer */
3561 && (dirp
->dd_size
= emacs_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3565 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
3566 dirp
->dd_loc
+= sizeof (struct olddir
);
3568 if (dp
->od_ino
!= 0) /* not deleted entry */
3570 dir_static
.d_ino
= dp
->od_ino
;
3571 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
3572 dir_static
.d_name
[DIRSIZ
] = '\0';
3573 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3574 dir_static
.d_reclen
= sizeof (struct direct
)
3576 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3577 return &dir_static
; /* -> simulated structure */
3580 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3581 if (dirp
->dd_loc
== 0)
3582 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
3583 : dp
->dir$b_namecount
;
3584 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
3585 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3586 dir_static
.d_namlen
= dp
->dir$b_namecount
;
3587 dir_static
.d_reclen
= sizeof (struct direct
)
3589 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3590 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3591 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
3592 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
3599 /* readdirver is just like readdir except it returns all versions of a file
3600 as separate entries. */
3605 register DIR *dirp
; /* stream from opendir */
3607 register struct dir$_name
*dp
; /* -> directory data */
3608 register struct dir$_version
*dv
; /* -> version data */
3610 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
3611 dirp
->dd_loc
= dirp
->dd_size
= 0;
3613 if (dirp
->dd_size
== 0 /* refill buffer */
3614 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3617 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3618 if (dirp
->dd_loc
== 0)
3619 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
3620 : dp
->dir$b_namecount
;
3621 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
3622 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3623 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
3624 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3625 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3626 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
3627 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3628 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
3634 #endif /* NONSYSTEM_DIR_LIBRARY */
3638 set_file_times (filename
, atime
, mtime
)
3640 EMACS_TIME atime
, mtime
;
3643 struct timeval tv
[2];
3646 return utimes (filename
, tv
);
3647 #else /* not HAVE_UTIMES */
3649 utb
.actime
= EMACS_SECS (atime
);
3650 utb
.modtime
= EMACS_SECS (mtime
);
3651 return utime (filename
, &utb
);
3652 #endif /* not HAVE_UTIMES */
3655 /* mkdir and rmdir functions, for systems which don't have them. */
3659 * Written by Robert Rother, Mariah Corporation, August 1985.
3661 * If you want it, it's yours. All I ask in return is that if you
3662 * figure out how to do this in a Bourne Shell script you send me
3664 * sdcsvax!rmr or rmr@uscd
3666 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3667 * subroutine. 11Mar86; hoptoad!gnu
3669 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3670 * subroutine didn't return EEXIST. It does now.
3676 #ifdef MKDIR_PROTOTYPE
3680 mkdir (dpath
, dmode
)
3685 int cpid
, status
, fd
;
3686 struct stat statbuf
;
3688 if (stat (dpath
, &statbuf
) == 0)
3690 errno
= EEXIST
; /* Stat worked, so it already exists */
3694 /* If stat fails for a reason other than non-existence, return error */
3695 if (errno
!= ENOENT
)
3698 synch_process_alive
= 1;
3699 switch (cpid
= fork ())
3702 case -1: /* Error in fork */
3703 return (-1); /* Errno is set already */
3705 case 0: /* Child process */
3707 * Cheap hack to set mode of new directory. Since this
3708 * child process is going away anyway, we zap its umask.
3709 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3710 * directory. Does anybody care?
3712 status
= umask (0); /* Get current umask */
3713 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
3714 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3721 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
3722 _exit (-1); /* Can't exec /bin/mkdir */
3724 default: /* Parent process */
3725 wait_for_termination (cpid
);
3728 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3730 errno
= EIO
; /* We don't know why, but */
3731 return -1; /* /bin/mkdir failed */
3736 #endif /* not HAVE_MKDIR */
3743 int cpid
, status
, fd
;
3744 struct stat statbuf
;
3746 if (stat (dpath
, &statbuf
) != 0)
3748 /* Stat just set errno. We don't have to */
3752 synch_process_alive
= 1;
3753 switch (cpid
= fork ())
3756 case -1: /* Error in fork */
3757 return (-1); /* Errno is set already */
3759 case 0: /* Child process */
3760 fd
= emacs_open ("/dev/null", O_RDWR
, 0);
3767 execl ("/bin/rmdir", "rmdir", dpath
, (char *) 0);
3768 _exit (-1); /* Can't exec /bin/rmdir */
3770 default: /* Parent process */
3771 wait_for_termination (cpid
);
3774 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3776 errno
= EIO
; /* We don't know why, but */
3777 return -1; /* /bin/rmdir failed */
3782 #endif /* !HAVE_RMDIR */
3786 /* Functions for VMS */
3788 #include "vms-pwd.h"
3793 /* Return as a string the VMS error string pertaining to STATUS.
3794 Reuses the same static buffer each time it is called. */
3798 int status
; /* VMS status code */
3802 static char buf
[257];
3804 bufadr
[0] = sizeof buf
- 1;
3805 bufadr
[1] = (int) buf
;
3806 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
3807 return "untranslatable VMS error status";
3815 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3816 * not work correctly. (It also doesn't work well in version 2.3.)
3821 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3822 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3826 unsigned short s_buflen
;
3827 unsigned short s_code
;
3829 unsigned short *s_retlenadr
;
3833 #define buflen s.s_buflen
3834 #define code s.s_code
3835 #define bufadr s.s_bufadr
3836 #define retlenadr s.s_retlenadr
3838 #define R_OK 4 /* test for read permission */
3839 #define W_OK 2 /* test for write permission */
3840 #define X_OK 1 /* test for execute (search) permission */
3841 #define F_OK 0 /* test for presence of file */
3844 sys_access (path
, mode
)
3848 static char *user
= NULL
;
3851 /* translate possible directory spec into .DIR file name, so brain-dead
3852 * access can treat the directory like a file. */
3853 if (directory_file_name (path
, dir_fn
))
3857 return access (path
, mode
);
3858 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
3864 unsigned short int dummy
;
3866 static int constant
= ACL$C_FILE
;
3867 DESCRIPTOR (path_desc
, path
);
3868 DESCRIPTOR (user_desc
, user
);
3872 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
3875 acces
|= CHP$M_READ
;
3877 acces
|= CHP$M_WRITE
;
3878 itemlst
[0].buflen
= sizeof (int);
3879 itemlst
[0].code
= CHP$_FLAGS
;
3880 itemlst
[0].bufadr
= (char *) &flags
;
3881 itemlst
[0].retlenadr
= &dummy
;
3882 itemlst
[1].buflen
= sizeof (int);
3883 itemlst
[1].code
= CHP$_ACCESS
;
3884 itemlst
[1].bufadr
= (char *) &acces
;
3885 itemlst
[1].retlenadr
= &dummy
;
3886 itemlst
[2].end
= CHP$_END
;
3887 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
3888 return stat
== SS$_NORMAL
? 0 : -1;
3892 #else /* not VMS4_4 */
3895 #define ACE$M_WRITE 2
3896 #define ACE$C_KEYID 1
3898 static unsigned short memid
, grpid
;
3899 static unsigned int uic
;
3901 /* Called from init_sys_modes, so it happens not very often
3902 but at least each time Emacs is loaded. */
3904 sys_access_reinit ()
3910 sys_access (filename
, type
)
3916 int status
, size
, i
, typecode
, acl_controlled
;
3917 unsigned int *aclptr
, *aclend
, aclbuf
[60];
3918 union prvdef prvmask
;
3920 /* Get UIC and GRP values for protection checking. */
3923 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
3926 memid
= uic
& 0xFFFF;
3930 if (type
!= 2) /* not checking write access */
3931 return access (filename
, type
);
3933 /* Check write protection. */
3935 #define CHECKPRIV(bit) (prvmask.bit)
3936 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3938 /* Find privilege bits */
3939 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
3941 error ("Unable to find privileges: %s", vmserrstr (status
));
3942 if (CHECKPRIV (PRV$V_BYPASS
))
3943 return 0; /* BYPASS enabled */
3945 fab
.fab$b_fac
= FAB$M_GET
;
3946 fab
.fab$l_fna
= filename
;
3947 fab
.fab$b_fns
= strlen (filename
);
3948 fab
.fab$l_xab
= &xab
;
3949 xab
= cc$rms_xabpro
;
3950 xab
.xab$l_aclbuf
= aclbuf
;
3951 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
3952 status
= SYS$
OPEN (&fab
, 0, 0);
3955 SYS$
CLOSE (&fab
, 0, 0);
3956 /* Check system access */
3957 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITABLE (XAB$V_SYS
))
3959 /* Check ACL entries, if any */
3961 if (xab
.xab$w_acllen
> 0)
3964 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
3965 while (*aclptr
&& aclptr
< aclend
)
3967 size
= (*aclptr
& 0xff) / 4;
3968 typecode
= (*aclptr
>> 8) & 0xff;
3969 if (typecode
== ACE$C_KEYID
)
3970 for (i
= size
- 1; i
> 1; i
--)
3971 if (aclptr
[i
] == uic
)
3974 if (aclptr
[1] & ACE$M_WRITE
)
3975 return 0; /* Write access through ACL */
3977 aclptr
= &aclptr
[size
];
3979 if (acl_controlled
) /* ACL specified, prohibits write access */
3982 /* No ACL entries specified, check normal protection */
3983 if (WRITABLE (XAB$V_WLD
)) /* World writable */
3985 if (WRITABLE (XAB$V_GRP
) &&
3986 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
3987 return 0; /* Group writable */
3988 if (WRITABLE (XAB$V_OWN
) &&
3989 (xab
.xab$l_uic
& 0xFFFF) == memid
)
3990 return 0; /* Owner writable */
3992 return -1; /* Not writable */
3994 #endif /* not VMS4_4 */
3997 static char vtbuf
[NAM$C_MAXRSS
+1];
3999 /* translate a vms file spec to a unix path */
4001 sys_translate_vms (vfile
)
4012 /* leading device or logical name is a root directory */
4013 if (p
= strchr (vfile
, ':'))
4022 if (*p
== '[' || *p
== '<')
4024 while (*++vfile
!= *p
+ 2)
4028 if (vfile
[-1] == *p
)
4051 static char utbuf
[NAM$C_MAXRSS
+1];
4053 /* translate a unix path to a VMS file spec */
4055 sys_translate_unix (ufile
)
4078 if (index (&ufile
[1], '/'))
4085 if (index (&ufile
[1], '/'))
4092 if (strncmp (ufile
, "./", 2) == 0)
4099 ufile
++; /* skip the dot */
4100 if (index (&ufile
[1], '/'))
4105 else if (strncmp (ufile
, "../", 3) == 0)
4113 ufile
+= 2; /* skip the dots */
4114 if (index (&ufile
[1], '/'))
4139 extern char *getcwd ();
4141 #define MAXPATHLEN 1024
4143 ptr
= xmalloc (MAXPATHLEN
);
4144 val
= getcwd (ptr
, MAXPATHLEN
);
4150 strcpy (pathname
, ptr
);
4159 long item_code
= JPI$_OWNER
;
4160 unsigned long parent_id
;
4163 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
4166 vaxc$errno
= status
;
4176 return (getgid () << 16) | getuid ();
4181 sys_read (fildes
, buf
, nbyte
)
4186 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
4191 sys_write (fildes
, buf
, nbyte
)
4196 register int nwrote
, rtnval
= 0;
4198 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
4204 return rtnval
? rtnval
: -1;
4205 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
4206 return rtnval
? rtnval
: -1;
4207 return (rtnval
+ nwrote
);
4212 * VAX/VMS VAX C RTL really loses. It insists that records
4213 * end with a newline (carriage return) character, and if they
4214 * don't it adds one (nice of it isn't it!)
4216 * Thus we do this stupidity below.
4221 sys_write (fildes
, buf
, nbytes
)
4224 unsigned int nbytes
;
4231 fstat (fildes
, &st
);
4237 /* Handle fixed-length files with carriage control. */
4238 if (st
.st_fab_rfm
== FAB$C_FIX
4239 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
4241 len
= st
.st_fab_mrs
;
4242 retval
= write (fildes
, p
, min (len
, nbytes
));
4245 retval
++; /* This skips the implied carriage control */
4249 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4250 while (*e
!= '\n' && e
> p
) e
--;
4251 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
4252 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4254 retval
= write (fildes
, p
, len
);
4265 /* Create file NEW copying its attributes from file OLD. If
4266 OLD is 0 or does not exist, create based on the value of
4269 /* Protection value the file should ultimately have.
4270 Set by create_copy_attrs, and use by rename_sansversions. */
4271 static unsigned short int fab_final_pro
;
4274 creat_copy_attrs (old
, new)
4277 struct FAB fab
= cc$rms_fab
;
4278 struct XABPRO xabpro
;
4279 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
4280 extern int vms_stmlf_recfm
;
4284 fab
.fab$b_fac
= FAB$M_GET
;
4285 fab
.fab$l_fna
= old
;
4286 fab
.fab$b_fns
= strlen (old
);
4287 fab
.fab$l_xab
= (char *) &xabpro
;
4288 xabpro
= cc$rms_xabpro
;
4289 xabpro
.xab$l_aclbuf
= aclbuf
;
4290 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
4291 /* Call $OPEN to fill in the fab & xabpro fields. */
4292 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4294 SYS$
CLOSE (&fab
, 0, 0);
4295 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
4296 if (xabpro
.xab$w_acllen
> 0)
4298 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
4299 /* If the acl buffer was too short, redo open with longer one.
4300 Wouldn't need to do this if there were some system imposed
4301 limit on the size of an ACL, but I can't find any such. */
4303 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
4304 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
4305 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4306 SYS$
CLOSE (&fab
, 0, 0);
4312 xabpro
.xab$l_aclbuf
= 0;
4317 fab
.fab$l_fna
= new;
4318 fab
.fab$b_fns
= strlen (new);
4322 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
4323 fab
.fab$b_rat
= FAB$M_CR
;
4326 /* Set the file protections such that we will be able to manipulate
4327 this file. Once we are done writing and renaming it, we will set
4328 the protections back. */
4330 fab_final_pro
= xabpro
.xab$w_pro
;
4332 SYS$
SETDFPROT (0, &fab_final_pro
);
4333 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
4335 /* Create the new file with either default attrs or attrs copied
4337 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
4339 SYS$
CLOSE (&fab
, 0, 0);
4340 /* As this is a "replacement" for creat, return a file descriptor
4341 opened for writing. */
4342 return open (new, O_WRONLY
);
4347 #include <varargs.h>
4350 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4355 sys_creat (va_alist
)
4358 va_list list_incrementer
;
4361 int rfd
; /* related file descriptor */
4362 int fd
; /* Our new file descriptor */
4369 extern int vms_stmlf_recfm
;
4372 va_start (list_incrementer
);
4373 name
= va_arg (list_incrementer
, char *);
4374 mode
= va_arg (list_incrementer
, int);
4376 rfd
= va_arg (list_incrementer
, int);
4377 va_end (list_incrementer
);
4380 /* Use information from the related file descriptor to set record
4381 format of the newly created file. */
4382 fstat (rfd
, &st_buf
);
4383 switch (st_buf
.st_fab_rfm
)
4386 strcpy (rfm
, "rfm = fix");
4387 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
4388 strcpy (rat
, "rat = ");
4389 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4391 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4392 strcat (rat
, "ftn");
4393 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4394 strcat (rat
, "prn");
4395 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4396 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4397 strcat (rat
, ", blk");
4399 strcat (rat
, "blk");
4400 return creat (name
, 0, rfm
, rat
, mrs
);
4403 strcpy (rfm
, "rfm = vfc");
4404 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
4405 strcpy (rat
, "rat = ");
4406 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4408 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4409 strcat (rat
, "ftn");
4410 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4411 strcat (rat
, "prn");
4412 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4413 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4414 strcat (rat
, ", blk");
4416 strcat (rat
, "blk");
4417 return creat (name
, 0, rfm
, rat
, fsz
);
4420 strcpy (rfm
, "rfm = stm");
4424 strcpy (rfm
, "rfm = stmcr");
4428 strcpy (rfm
, "rfm = stmlf");
4432 strcpy (rfm
, "rfm = udf");
4436 strcpy (rfm
, "rfm = var");
4439 strcpy (rat
, "rat = ");
4440 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4442 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4443 strcat (rat
, "ftn");
4444 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4445 strcat (rat
, "prn");
4446 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4447 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4448 strcat (rat
, ", blk");
4450 strcat (rat
, "blk");
4454 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
4455 strcpy (rat
, "rat=cr");
4457 /* Until the VAX C RTL fixes the many bugs with modes, always use
4458 mode 0 to get the user's default protection. */
4459 fd
= creat (name
, 0, rfm
, rat
);
4460 if (fd
< 0 && errno
== EEXIST
)
4462 if (unlink (name
) < 0)
4463 report_file_error ("delete", build_string (name
));
4464 fd
= creat (name
, 0, rfm
, rat
);
4470 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4472 sys_fwrite (ptr
, size
, num
, fp
)
4473 register char * ptr
;
4476 register int tot
= num
* size
;
4484 * The VMS C library routine creat actually creates a new version of an
4485 * existing file rather than truncating the old version. There are times
4486 * when this is not the desired behavior, for instance, when writing an
4487 * auto save file (you only want one version), or when you don't have
4488 * write permission in the directory containing the file (but the file
4489 * itself is writable). Hence this routine, which is equivalent to
4490 * "close (creat (fn, 0));" on Unix if fn already exists.
4496 struct FAB xfab
= cc$rms_fab
;
4497 struct RAB xrab
= cc$rms_rab
;
4500 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
4501 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
4502 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
4503 xfab
.fab$l_fna
= fn
;
4504 xfab
.fab$b_fns
= strlen (fn
);
4505 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
4507 xrab
.rab$l_fab
= &xfab
;
4509 /* This gibberish opens the file, positions to the first record, and
4510 deletes all records from there until the end of file. */
4511 if ((SYS$
OPEN (&xfab
) & 01) == 01)
4513 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
4514 (SYS$
FIND (&xrab
) & 01) == 01 &&
4515 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
4526 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4527 SYSPRV or a readable SYSUAF.DAT. */
4533 * Routine to read the VMS User Authorization File and return
4534 * a specific user's record.
4537 static struct UAF retuaf
;
4540 get_uaf_name (uname
)
4547 uaf_fab
= cc$rms_fab
;
4548 uaf_rab
= cc$rms_rab
;
4549 /* initialize fab fields */
4550 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4551 uaf_fab
.fab$b_fns
= 21;
4552 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4553 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4554 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4555 /* initialize rab fields */
4556 uaf_rab
.rab$l_fab
= &uaf_fab
;
4557 /* open the User Authorization File */
4558 status
= SYS$
OPEN (&uaf_fab
);
4562 vaxc$errno
= status
;
4565 status
= SYS$
CONNECT (&uaf_rab
);
4569 vaxc$errno
= status
;
4572 /* read the requested record - index is in uname */
4573 uaf_rab
.rab$l_kbf
= uname
;
4574 uaf_rab
.rab$b_ksz
= strlen (uname
);
4575 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4576 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4577 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4578 status
= SYS$
GET (&uaf_rab
);
4582 vaxc$errno
= status
;
4585 /* close the User Authorization File */
4586 status
= SYS$
DISCONNECT (&uaf_rab
);
4590 vaxc$errno
= status
;
4593 status
= SYS$
CLOSE (&uaf_fab
);
4597 vaxc$errno
= status
;
4611 uaf_fab
= cc$rms_fab
;
4612 uaf_rab
= cc$rms_rab
;
4613 /* initialize fab fields */
4614 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4615 uaf_fab
.fab$b_fns
= 21;
4616 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4617 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4618 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4619 /* initialize rab fields */
4620 uaf_rab
.rab$l_fab
= &uaf_fab
;
4621 /* open the User Authorization File */
4622 status
= SYS$
OPEN (&uaf_fab
);
4626 vaxc$errno
= status
;
4629 status
= SYS$
CONNECT (&uaf_rab
);
4633 vaxc$errno
= status
;
4636 /* read the requested record - index is in uic */
4637 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
4638 uaf_rab
.rab$l_kbf
= (char *) &uic
;
4639 uaf_rab
.rab$b_ksz
= sizeof uic
;
4640 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4641 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4642 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4643 status
= SYS$
GET (&uaf_rab
);
4647 vaxc$errno
= status
;
4650 /* close the User Authorization File */
4651 status
= SYS$
DISCONNECT (&uaf_rab
);
4655 vaxc$errno
= status
;
4658 status
= SYS$
CLOSE (&uaf_fab
);
4662 vaxc$errno
= status
;
4668 static struct passwd retpw
;
4676 /* copy these out first because if the username is 32 chars, the next
4677 section will overwrite the first byte of the UIC */
4678 retpw
.pw_uid
= up
->uaf$w_mem
;
4679 retpw
.pw_gid
= up
->uaf$w_grp
;
4681 /* I suppose this is not the best style, to possibly overwrite one
4682 byte beyond the end of the field, but what the heck... */
4683 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
4684 while (ptr
[-1] == ' ')
4687 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
4689 /* the rest of these are counted ascii strings */
4690 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
4691 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
4692 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
4693 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
4694 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
4695 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
4696 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
4697 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
4701 #else /* not READ_SYSUAF */
4702 static struct passwd retpw
;
4703 #endif /* not READ_SYSUAF */
4714 unsigned char * full
;
4715 #endif /* READ_SYSUAF */
4720 if ('a' <= *ptr
&& *ptr
<= 'z')
4725 if (!(up
= get_uaf_name (name
)))
4727 return cnv_uaf_pw (up
);
4729 if (strcmp (name
, getenv ("USER")) == 0)
4731 retpw
.pw_uid
= getuid ();
4732 retpw
.pw_gid
= getgid ();
4733 strcpy (retpw
.pw_name
, name
);
4734 if (full
= egetenv ("FULLNAME"))
4735 strcpy (retpw
.pw_gecos
, full
);
4737 *retpw
.pw_gecos
= '\0';
4738 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
4739 *retpw
.pw_shell
= '\0';
4744 #endif /* not READ_SYSUAF */
4754 if (!(up
= get_uaf_uic (uid
)))
4756 return cnv_uaf_pw (up
);
4758 if (uid
== sys_getuid ())
4759 return getpwnam (egetenv ("USER"));
4762 #endif /* not READ_SYSUAF */
4765 /* return total address space available to the current process. This is
4766 the sum of the current p0 size, p1 size and free page table entries
4772 unsigned long free_pages
;
4773 unsigned long frep0va
;
4774 unsigned long frep1va
;
4777 item_code
= JPI$_FREPTECNT
;
4778 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
4781 vaxc$errno
= status
;
4786 item_code
= JPI$_FREP0VA
;
4787 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
4790 vaxc$errno
= status
;
4793 item_code
= JPI$_FREP1VA
;
4794 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
4797 vaxc$errno
= status
;
4801 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
4805 define_logical_name (varname
, string
)
4809 struct dsc$descriptor_s strdsc
=
4810 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
4811 struct dsc$descriptor_s envdsc
=
4812 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4813 struct dsc$descriptor_s lnmdsc
=
4814 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4816 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
4820 delete_logical_name (varname
)
4823 struct dsc$descriptor_s envdsc
=
4824 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4825 struct dsc$descriptor_s lnmdsc
=
4826 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4828 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
4846 error ("execvp system call not implemented");
4855 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
4856 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
4857 char from_esn
[NAM$C_MAXRSS
];
4858 char to_esn
[NAM$C_MAXRSS
];
4860 from_fab
.fab$l_fna
= from
;
4861 from_fab
.fab$b_fns
= strlen (from
);
4862 from_fab
.fab$l_nam
= &from_nam
;
4863 from_fab
.fab$l_fop
= FAB$M_NAM
;
4865 from_nam
.nam$l_esa
= from_esn
;
4866 from_nam
.nam$b_ess
= sizeof from_esn
;
4868 to_fab
.fab$l_fna
= to
;
4869 to_fab
.fab$b_fns
= strlen (to
);
4870 to_fab
.fab$l_nam
= &to_nam
;
4871 to_fab
.fab$l_fop
= FAB$M_NAM
;
4873 to_nam
.nam$l_esa
= to_esn
;
4874 to_nam
.nam$b_ess
= sizeof to_esn
;
4876 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
4882 if (status
== RMS$_DEV
)
4886 vaxc$errno
= status
;
4891 /* This function renames a file like `rename', but it strips
4892 the version number from the "to" filename, such that the "to" file is
4893 will always be a new version. It also sets the file protection once it is
4894 finished. The protection that we will use is stored in fab_final_pro,
4895 and was set when we did a creat_copy_attrs to create the file that we
4898 We could use the chmod function, but Eunichs uses 3 bits per user category
4899 to describe the protection, and VMS uses 4 (write and delete are separate
4900 bits). To maintain portability, the VMS implementation of `chmod' wires
4901 the W and D bits together. */
4904 static struct fibdef fib
; /* We need this initialized to zero */
4905 char vms_file_written
[NAM$C_MAXRSS
];
4908 rename_sans_version (from
,to
)
4915 struct FAB to_fab
= cc$rms_fab
;
4916 struct NAM to_nam
= cc$rms_nam
;
4917 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
4918 struct dsc$descriptor fib_attr
[2]
4919 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
4920 char to_esn
[NAM$C_MAXRSS
];
4922 $
DESCRIPTOR (disk
,to_esn
);
4924 to_fab
.fab$l_fna
= to
;
4925 to_fab
.fab$b_fns
= strlen (to
);
4926 to_fab
.fab$l_nam
= &to_nam
;
4927 to_fab
.fab$l_fop
= FAB$M_NAM
;
4929 to_nam
.nam$l_esa
= to_esn
;
4930 to_nam
.nam$b_ess
= sizeof to_esn
;
4932 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
4934 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
4935 *(to_nam
.nam$l_ver
) = '\0';
4937 stat
= rename (from
, to_esn
);
4941 strcpy (vms_file_written
, to_esn
);
4943 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
4944 to_fab
.fab$b_fns
= strlen (vms_file_written
);
4946 /* Now set the file protection to the correct value */
4947 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
4949 /* Copy these fields into the fib */
4950 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
4951 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
4952 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
4954 SYS$
CLOSE (&to_fab
, 0, 0);
4956 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
4959 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
4960 0, 0, 0, &fib_attr
, 0);
4963 stat
= SYS$
DASSGN (chan
);
4966 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
4977 unsigned short fid
[3];
4978 char esa
[NAM$C_MAXRSS
];
4981 fab
.fab$l_fop
= FAB$M_OFP
;
4982 fab
.fab$l_fna
= file
;
4983 fab
.fab$b_fns
= strlen (file
);
4984 fab
.fab$l_nam
= &nam
;
4987 nam
.nam$l_esa
= esa
;
4988 nam
.nam$b_ess
= NAM$C_MAXRSS
;
4990 status
= SYS$
PARSE (&fab
);
4991 if ((status
& 1) == 0)
4994 vaxc$errno
= status
;
4997 status
= SYS$
SEARCH (&fab
);
4998 if ((status
& 1) == 0)
5001 vaxc$errno
= status
;
5005 fid
[0] = nam
.nam$w_fid
[0];
5006 fid
[1] = nam
.nam$w_fid
[1];
5007 fid
[2] = nam
.nam$w_fid
[2];
5009 fab
.fab$l_fna
= new;
5010 fab
.fab$b_fns
= strlen (new);
5012 status
= SYS$
PARSE (&fab
);
5013 if ((status
& 1) == 0)
5016 vaxc$errno
= status
;
5020 nam
.nam$w_fid
[0] = fid
[0];
5021 nam
.nam$w_fid
[1] = fid
[1];
5022 nam
.nam$w_fid
[2] = fid
[2];
5024 nam
.nam$l_esa
= nam
.nam$l_name
;
5025 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
5027 status
= SYS$
ENTER (&fab
);
5028 if ((status
& 1) == 0)
5031 vaxc$errno
= status
;
5042 printf ("%s not yet implemented\r\n", badfunc
);
5050 /* Arrange to return a range centered on zero. */
5051 return rand () - (1 << 30);
5063 /* Called from init_sys_modes. */
5069 /* If we're not on an HFT we shouldn't do any of this. We determine
5070 if we are on an HFT by trying to get an HFT error code. If this
5071 call fails, we're not on an HFT. */
5073 if (ioctl (0, HFQERROR
, &junk
) < 0)
5075 #else /* not IBMR2AIX */
5076 if (ioctl (0, HFQEIO
, 0) < 0)
5078 #endif /* not IBMR2AIX */
5080 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5081 as the rubout key's ASCII code. Here this is changed. The bug is that
5082 there's no way to determine the old mapping, so in reset_sys_modes
5083 we need to assume that the normal map had been present. Of course, this
5084 code also doesn't help if on a terminal emulator which doesn't understand
5088 struct hfkeymap keymap
;
5090 buf
.hf_bufp
= (char *)&keymap
;
5091 buf
.hf_buflen
= sizeof (keymap
);
5092 keymap
.hf_nkeys
= 2;
5093 keymap
.hfkey
[0].hf_kpos
= 15;
5094 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5096 keymap
.hfkey
[0].hf_keyidh
= '<';
5097 #else /* not IBMR2AIX */
5098 keymap
.hfkey
[0].hf_page
= '<';
5099 #endif /* not IBMR2AIX */
5100 keymap
.hfkey
[0].hf_char
= 127;
5101 keymap
.hfkey
[1].hf_kpos
= 15;
5102 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5104 keymap
.hfkey
[1].hf_keyidh
= '<';
5105 #else /* not IBMR2AIX */
5106 keymap
.hfkey
[1].hf_page
= '<';
5107 #endif /* not IBMR2AIX */
5108 keymap
.hfkey
[1].hf_char
= 127;
5109 hftctl (0, HFSKBD
, &buf
);
5111 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5113 line_ins_del_ok
= char_ins_del_ok
= 0;
5116 /* Reset the rubout key to backspace. */
5122 struct hfkeymap keymap
;
5126 if (ioctl (0, HFQERROR
, &junk
) < 0)
5128 #else /* not IBMR2AIX */
5129 if (ioctl (0, HFQEIO
, 0) < 0)
5131 #endif /* not IBMR2AIX */
5133 buf
.hf_bufp
= (char *)&keymap
;
5134 buf
.hf_buflen
= sizeof (keymap
);
5135 keymap
.hf_nkeys
= 2;
5136 keymap
.hfkey
[0].hf_kpos
= 15;
5137 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5139 keymap
.hfkey
[0].hf_keyidh
= '<';
5140 #else /* not IBMR2AIX */
5141 keymap
.hfkey
[0].hf_page
= '<';
5142 #endif /* not IBMR2AIX */
5143 keymap
.hfkey
[0].hf_char
= 8;
5144 keymap
.hfkey
[1].hf_kpos
= 15;
5145 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5147 keymap
.hfkey
[1].hf_keyidh
= '<';
5148 #else /* not IBMR2AIX */
5149 keymap
.hfkey
[1].hf_page
= '<';
5150 #endif /* not IBMR2AIX */
5151 keymap
.hfkey
[1].hf_char
= 8;
5152 hftctl (0, HFSKBD
, &buf
);
5159 /* These are included on Sunos 4.1 when we do not use shared libraries.
5160 X11 libraries may refer to these functions but (we hope) do not
5161 actually call them. */
5181 #endif /* USE_DL_STUBS */
5190 register int length
;
5194 long max_str
= 65535;
5196 while (length
> max_str
) {
5197 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5202 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5204 while (length
-- > 0)
5206 #endif /* not VMS */
5209 #endif /* no bzero */
5210 #endif /* BSTRING */
5212 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5215 /* Saying `void' requires a declaration, above, where bcopy is used
5216 and that declaration causes pain for systems where bcopy is a macro. */
5217 bcopy (b1
, b2
, length
)
5220 register int length
;
5223 long max_str
= 65535;
5225 while (length
> max_str
) {
5226 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
5232 (void) LIB$
MOVC3 (&length
, b1
, b2
);
5234 while (length
-- > 0)
5236 #endif /* not VMS */
5238 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5243 bcmp (b1
, b2
, length
) /* This could be a macro! */
5246 register int length
;
5249 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
5250 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
5252 return STR$
COMPARE (&src1
, &src2
);
5254 while (length
-- > 0)
5259 #endif /* not VMS */
5261 #endif /* no bcmp */
5262 #endif /* not BSTRING */
5264 #ifndef HAVE_STRSIGNAL
5271 if (0 <= code
&& code
< NSIG
)
5274 signame
= sys_errlist
[code
];
5276 /* Cast to suppress warning if the table has const char *. */
5277 signame
= (char *) sys_siglist
[code
];
5283 #endif /* HAVE_STRSIGNAL */
5285 /* All the Macintosh stuffs go here */
5290 #include <MacTypes.h>
5291 #include <TextUtils.h>
5292 #include <Folders.h>
5295 #include <sys/stat.h>
5298 #include <sys/param.h>
5300 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5301 that does not begin with a ':' and contains at least one ':'. A Mac
5302 full pathname causes an '/' to be prepended to the Unix pathname.
5303 The algorithm for the rest of the pathname is as follows:
5304 For each segment between two ':',
5305 if it is non-null, copy as is and then add a '/' at the end,
5306 otherwise, insert a "../" into the Unix pathname.
5307 Returns 1 if successful; 0 if fails. */
5310 Mac2UnixPathname (const char *mfn
, char *ufn
, int ufnbuflen
)
5312 const char *p
, *q
, *pe
;
5319 p
= strchr (mfn
, ':');
5320 if (p
!= 0 && p
!= mfn
) /* full pathname */
5327 pe
= mfn
+ strlen (mfn
);
5330 q
= strchr (p
, ':');
5334 { /* two consecutive ':' */
5335 if (strlen (ufn
) + 3 >= ufnbuflen
)
5337 strcat (ufn
, "../");
5341 if (strlen (ufn
) + (q
- p
) + 1 >= ufnbuflen
)
5343 strncat (ufn
, p
, q
- p
);
5350 if (strlen (ufn
) + (pe
- p
) >= ufnbuflen
)
5352 strncat (ufn
, p
, pe
- p
); /* no separator for last one */
5360 extern char *GetTempDirName ();
5362 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5363 above in algorithm. */
5365 Unix2MacPathname (const char *ufn
, char *mfn
, int mfnbuflen
)
5367 const char *p
, *q
, *pe
;
5368 char expandedPathname
[MAXPATHLEN
+1];
5377 /* Check for and handle volume names. Last comparison: strangely
5378 somewhere `/.emacs' is passed. A temporary fix for now. */
5379 if (*p
== '/' && strchr (p
+1, '/') == NULL
&& strcmp (p
, "/.emacs") != 0)
5381 if (strlen (p
) + 1 > mfnbuflen
)
5388 if (strncmp (p
, "~emacs/", 7) == 0)
5389 { /* expand to emacs dir found by InitEmacsPasswdDir */
5390 struct passwd
*pw
= getpwnam ("emacs");
5392 if (strlen (pw
->pw_dir
) + strlen (p
) > MAXPATHLEN
)
5394 strcpy (expandedPathname
, pw
->pw_dir
);
5395 strcat (expandedPathname
, p
);
5396 p
= expandedPathname
;
5397 /* Now p points to the pathname with emacs dir prefix. */
5399 else if (strncmp (p
, "/tmp/", 5) == 0)
5401 char *t
= GetTempDirName ();
5403 if (strlen (t
) + strlen (p
) > MAXPATHLEN
)
5405 strcpy (expandedPathname
, t
);
5406 strcat (expandedPathname
, p
);
5407 p
= expandedPathname
;
5408 /* Now p points to the pathname with emacs dir prefix. */
5410 else if (*p
!= '/') /* relative pathname */
5416 pe
= p
+ strlen (p
);
5419 q
= strchr (p
, '/');
5422 if (q
- p
== 2 && *p
== '.' && *(p
+1) == '.')
5424 if (strlen (mfn
) + 1 >= mfnbuflen
)
5430 if (strlen (mfn
) + (q
- p
) + 1 >= mfnbuflen
)
5432 strncat (mfn
, p
, q
- p
);
5439 if (strlen (mfn
) + (pe
- p
) >= mfnbuflen
)
5441 strncat (mfn
, p
, pe
- p
);
5449 /* The following functions with "sys_" prefix are stubs to Unix
5450 functions that have already been implemented by CW or MPW. The
5451 calls to them in Emacs source course are #define'd to call the sys_
5452 versions by the header files s-mac.h. In these stubs pathnames are
5453 converted between their Unix and Mac forms. */
5454 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5456 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5458 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5460 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5462 /* Define our own stat function for both MrC and CW. The reason for
5463 doing this: "stat" is both the name of a struct and function name:
5464 we can't #define stat to something else to
5465 redirect Emacs's calls to our own version that converts Unix style
5466 filenames to Mac style filename because all sorts of compilation
5467 errors will be generated if stat is #define'd to be something else. */
5470 stat (const char *path
, struct stat
*buf
)
5472 char MacPathname
[MAXPATHLEN
+1];
5475 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5478 c2pstr (MacPathname
);
5479 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5480 cipb
.hFileInfo
.ioVRefNum
= 0;
5481 cipb
.hFileInfo
.ioDirID
= 0;
5482 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5484 errno
= PBGetCatInfo (&cipb
, false);
5485 if (errno
== -43) /* -43: fnfErr defined in Errors.h */
5490 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5491 { /* bit 4 = 1 for directories */
5492 buf
->st_mode
= S_IFDIR
| S_IREAD
| S_IEXEC
;
5493 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5494 buf
->st_mode
|= S_IWRITE
;
5495 buf
->st_ino
= cipb
.dirInfo
.ioDrDirID
;
5496 buf
->st_dev
= cipb
.dirInfo
.ioVRefNum
;
5497 buf
->st_size
= cipb
.dirInfo
.ioDrNmFls
; /* size of dir = number of files and dirs */
5498 buf
->st_atime
= buf
->st_mtime
= cipb
.dirInfo
.ioDrMdDat
- MAC_UNIX_EPOCH_DIFF
;
5499 buf
->st_ctime
= cipb
.dirInfo
.ioDrCrDat
- MAC_UNIX_EPOCH_DIFF
;
5503 buf
->st_mode
= S_IFREG
| S_IREAD
;
5504 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5505 buf
->st_mode
|= S_IWRITE
;
5506 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5507 buf
->st_mode
|= S_IEXEC
;
5508 buf
->st_ino
= cipb
.hFileInfo
.ioDirID
;
5509 buf
->st_dev
= cipb
.hFileInfo
.ioVRefNum
;
5510 buf
->st_size
= cipb
.hFileInfo
.ioFlLgLen
;
5511 buf
->st_atime
= buf
->st_mtime
= cipb
.hFileInfo
.ioFlMdDat
- MAC_UNIX_EPOCH_DIFF
;
5512 buf
->st_ctime
= cipb
.hFileInfo
.ioFlCrDat
- MAC_UNIX_EPOCH_DIFF
;
5515 buf
->st_uid
= getuid ();
5516 buf
->st_gid
= getgid ();
5524 /* CW defines fstat in stat.mac.c while MPW does not provide this
5525 function. Without the information of how to get from a file
5526 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5527 to implement this function. Fortunately, there is only one place
5528 where this function is called in our configuration: in fileio.c,
5529 where only the st_dev and st_ino fields are used to determine
5530 whether two fildes point to different i-nodes to prevent copying
5531 a file onto itself equal. What we have here probably needs
5534 fstat (int fildes
, struct stat
*buf
)
5537 buf
->st_ino
= fildes
;
5538 return 0; /* success */
5541 #endif /* __MRC__ */
5543 /* From Think Reference code example */
5545 mkdir (const char *dirname
, int mode
)
5547 #pragma unused (mode)
5550 char MacPathname
[MAXPATHLEN
+1];
5552 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5555 c2pstr (MacPathname
);
5556 hfpb
.ioNamePtr
= MacPathname
;
5557 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5558 hfpb
.ioDirID
= 0; /*parent is the root */
5560 /* Just return the Mac OSErr code for now. */
5561 errno
= PBDirCreate ((HParmBlkPtr
) &hfpb
, false);
5562 return errno
== noErr
? 0 : -1;
5566 rmdir (const char *dirname
)
5569 char MacPathname
[MAXPATHLEN
+1];
5571 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5574 c2pstr (MacPathname
);
5575 hfpb
.ioNamePtr
= MacPathname
;
5576 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5577 hfpb
.ioDirID
= 0; /*parent is the root */
5579 errno
= PBHDelete ((HParmBlkPtr
) &hfpb
, false);
5580 return errno
== noErr
? 0 : -1;
5585 /* No implementation yet. */
5587 execvp (const char *path
, ...)
5592 #endif /* __MRC__ */
5595 utime (const char *path
, const struct utimbuf
*times
)
5597 char MacPathname
[MAXPATHLEN
+1];
5600 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5603 c2pstr (MacPathname
);
5604 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5605 cipb
.hFileInfo
.ioVRefNum
= 0;
5606 cipb
.hFileInfo
.ioDirID
= 0;
5607 /* Set to 0 to get information about specific dir or file. */
5608 cipb
.hFileInfo
.ioFDirIndex
= 0;
5610 errno
= PBGetCatInfo (&cipb
, false);
5614 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5615 { /* bit 4 = 1 for directories */
5617 cipb
.dirInfo
.ioDrMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5619 GetDateTime (&cipb
.dirInfo
.ioDrMdDat
);
5624 cipb
.hFileInfo
.ioFlMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5626 GetDateTime (&cipb
.hFileInfo
.ioFlMdDat
);
5629 errno
= PBSetCatInfo (&cipb
, false);
5630 return errno
== noErr
? 0 : -1;
5637 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5639 access (const char *path
, int mode
)
5641 char MacPathname
[MAXPATHLEN
+1];
5644 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5647 c2pstr (MacPathname
);
5648 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5649 cipb
.hFileInfo
.ioVRefNum
= 0;
5650 cipb
.hFileInfo
.ioDirID
= 0;
5651 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5653 errno
= PBGetCatInfo (&cipb
, false);
5657 if (mode
== F_OK
) /* got this far, file exists */
5661 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* path refers to a directory */
5665 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5672 return (cipb
.hFileInfo
.ioFlAttrib
& 0x1) ? -1 : 0; /* don't allow if lock bit on */
5677 #define DEV_NULL_FD 0x10000
5681 sys_open (const char *path
, int oflag
)
5683 char MacPathname
[MAXPATHLEN
+1];
5685 if (strcmp (path
, "/dev/null") == 0)
5686 return DEV_NULL_FD
; /* some bogus fd to be ignored in write */
5688 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5691 return open (MacPathname
, oflag
);
5696 sys_creat (const char *path
, mode_t mode
)
5698 char MacPathname
[MAXPATHLEN
+1];
5700 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5703 return creat (MacPathname
, mode
);
5708 sys_unlink (const char *path
)
5710 char MacPathname
[MAXPATHLEN
+1];
5712 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5715 return unlink (MacPathname
);
5720 sys_read (int fildes
, char *buf
, int count
)
5723 { /* if stdin, call (non-echoing) "getch" in console.h */
5724 if (MacKeyPending ())
5725 { /* don't wait for a key if none has been pressed */
5726 *buf
= MacGetChar ();
5733 return read (fildes
, buf
, count
);
5738 sys_write (int fildes
, char *buf
, int count
)
5740 if (fildes
== DEV_NULL_FD
)
5743 return write (fildes
, buf
, count
);
5748 sys_rename (const char * old_name
, const char * new_name
)
5750 char MacOldName
[MAXPATHLEN
+1], MacNewName
[MAXPATHLEN
+1];
5752 if (strcmp (old_name
, new_name
) == 0)
5755 if (Unix2MacPathname (old_name
, MacOldName
, MAXPATHLEN
+1) == 0)
5758 if (Unix2MacPathname (new_name
, MacNewName
, MAXPATHLEN
+1) == 0)
5761 return rename (MacOldName
, MacNewName
);
5765 extern FILE *fopen (const char *name
, const char *mode
);
5767 sys_fopen (const char *name
, const char *mode
)
5769 char MacPathname
[MAXPATHLEN
+1];
5771 if (Unix2MacPathname (name
, MacPathname
, MAXPATHLEN
+1) == 0)
5774 return fopen (MacPathname
, mode
);
5779 long targetTicks
= 0;
5782 __sigfun alarm_signal_func
= (__sigfun
) 0;
5784 __signal_func_ptr alarm_signal_func
= (__signal_func_ptr
) 0;
5789 /* These functions simulate SIG_ALRM. The stub for function signal
5790 stores the signal handler function in alarm_signal_func if a
5791 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5792 which emacs calls periodically. A pending alarm is represented by
5793 a non-zero targetTicks value. CheckAlarm calls the handler
5794 function pointed to by alarm_signal_func if one has been set up and
5795 an alarm is pending. */
5799 if (targetTicks
&& TickCount () > targetTicks
)
5802 if (alarm_signal_func
)
5803 (*alarm_signal_func
)(SIGALRM
);
5807 /* Called in sys_select to wait for an alarm signal to arrive. */
5811 unsigned long finalTick
;
5813 if (!targetTicks
) /* no alarm pending */
5816 while (TickCount () <= targetTicks
)
5817 Delay (1UL, &finalTick
); /* wait for 1/60 second before trying again */
5820 if (alarm_signal_func
)
5821 (*alarm_signal_func
)(SIGALRM
);
5829 long remaining
= targetTicks
? (TickCount () - targetTicks
) / 60 : 0;
5831 targetTicks
= seconds
? TickCount () + 60 * seconds
: 0;
5833 return (remaining
< 0) ? 0 : (unsigned int) remaining
;
5838 extern __sigfun
signal (int signal
, __sigfun signal_func
);
5840 sys_signal (int signal_num
, __sigfun signal_func
)
5842 extern __signal_func_ptr
signal (int signal
, __signal_func_ptr signal_func
);
5844 sys_signal (int signal_num
, __signal_func_ptr signal_func
)
5849 if (signal_num
!= SIGALRM
)
5850 return signal (signal_num
, signal_func
);
5854 __sigfun old_signal_func
;
5856 __signal_func_ptr old_signal_func
;
5860 old_signal_func
= alarm_signal_func
;
5861 alarm_signal_func
= signal_func
;
5862 return old_signal_func
;
5866 /* The time functions adjust time values according to the difference
5867 between the Unix and CW epoches. */
5870 extern struct tm
*gmtime (const time_t *);
5872 sys_gmtime (const time_t *timer
)
5874 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5876 return gmtime (&unixTime
);
5880 extern struct tm
*localtime (const time_t *);
5882 sys_localtime (const time_t *timer
)
5884 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5886 return localtime (&unixTime
);
5890 extern char *ctime (const time_t *);
5892 sys_ctime (const time_t *timer
)
5894 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5896 return ctime (&unixTime
);
5900 extern time_t time (time_t *);
5902 sys_time (time_t *timer
)
5904 time_t macTime
= time (NULL
) - CW_UNIX_EPOCH_DIFF
;
5912 /* no subprocesses, empty wait */
5920 croak (char *badfunc
)
5922 printf ("%s not yet implemented\r\n", badfunc
);
5927 index (const char * str
, int chr
)
5929 return strchr (str
, chr
);
5933 char **environ
= &e
[0];
5936 mktemp (char *template)
5941 len
= strlen (template);
5943 while (k
>= 0 && template[k
] == 'X')
5946 k
++; /* make k index of first 'X' */
5950 /* Zero filled, number of digits equal to the number of X's. */
5951 sprintf (&template[k
], "%0*d", len
-k
, seqnum
++);
5959 /* Emulate getpwuid, getpwnam and others. */
5961 #define PASSWD_FIELD_SIZE 256
5963 static char myPasswdName
[PASSWD_FIELD_SIZE
];
5964 static char myPasswdDir
[MAXPATHLEN
+1];
5966 static struct passwd myPasswd
=
5972 /* Initialized by main () in macterm.c to pathname of emacs directory. */
5973 char emacsPasswdDir
[MAXPATHLEN
+1];
5976 InitEmacsPasswdDir ()
5980 if (getwd (emacsPasswdDir
) && getwd (myPasswdDir
))
5982 /* Need pathname of first ancestor that begins with `emacs' since
5983 Mac emacs application is somewhere in the emacs-20.3 tree. */
5984 int len
= strlen (emacsPasswdDir
);
5985 /* J points to the "/" following the directory name being compared. */
5988 while (i
>= 0 && !found
)
5990 while (i
>= 0 && emacsPasswdDir
[i
] != '/')
5992 if (emacsPasswdDir
[i
] == '/' && i
+5 < len
)
5993 found
= (strncmp (&(emacsPasswdDir
[i
+1]), "emacs", 5) == 0);
5995 emacsPasswdDir
[j
+1] = '\0';
6005 { /* setting to "/" probably won't work,
6006 but set it to something anyway. */
6007 strcpy (emacsPasswdDir
, "/");
6008 strcpy (myPasswdDir
, "/");
6012 static struct passwd emacsPasswd
=
6018 static int myPasswdInited
= 0;
6025 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6026 where Emacs was started. */
6028 ownerName
= (char **) GetResource ('STR ',-16096);
6032 BlockMove ((unsigned char *) *ownerName
,
6033 (unsigned char *) myPasswdName
, *ownerName
[0] + 1);
6034 HUnlock (ownerName
);
6035 p2cstr ((unsigned char *) myPasswdName
);
6038 myPasswdName
[0] = 0;
6042 getpwuid (uid_t uid
)
6044 if (!myPasswdInited
)
6054 getpwnam (const char *name
)
6056 if (strcmp (name
, "emacs") == 0)
6057 return &emacsPasswd
;
6059 if (!myPasswdInited
)
6068 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6069 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6097 request_sigio (void)
6108 unrequest_sigio (void)
6112 /* djgpp does not implement pipe either. */
6114 pipe (int _fildes
[2])
6120 /* Hard and symbolic links. */
6122 symlink (const char *name1
, const char *name2
)
6129 link (const char *name1
, const char *name2
)
6136 lstat (const char *path
, struct stat
*sb
)
6138 return stat (path
, sb
);
6142 readlink (const char *path
, char *buf
, int bufsiz
)
6149 umask (mode_t numask
)
6151 static mode_t mask
= 022;
6152 mode_t oldmask
= mask
;
6158 chmod (const char *path
, mode_t mode
)
6160 /* say it always succeed for now */
6168 return fcntl (oldd
, F_DUPFD
, 0);
6170 /* current implementation of fcntl in fcntl.mac.c simply returns old
6172 return fcntl (oldd
, F_DUPFD
);
6178 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6179 newd if it already exists. Then, attempt to dup oldd. If not
6180 successful, call dup2 recursively until we are, then close the
6181 unsuccessful ones. */
6183 dup2 (int oldd
, int newd
)
6194 ret
= dup2 (oldd
, newd
);
6199 /* let it fail for now */
6213 ioctl (int d
, int request
, void *argp
)
6222 if (fildes
>=0 && fildes
<= 2)
6253 sleep (unsigned int seconds
)
6255 unsigned long finalTick
;
6257 Delay (seconds
* 60UL, &finalTick
);
6260 #endif /* __MRC__ */
6269 #endif /* __MWERKS__ */
6271 /* Return the path to the directory in which Emacs can create
6272 temporary files. The MacOS "temporary items" directory cannot be
6273 used because it removes the file written by a process when it
6274 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6275 again not exactly). And of course Emacs needs to read back the
6276 files written by its subprocesses. So here we write the files to a
6277 directory "Emacs" in the Preferences Folder. This directory is
6278 created if it does not exist. */
6282 static char *TempDirName
= NULL
;
6286 Str255 dirName
, fullPath
;
6288 char unixDirName
[MAXPATHLEN
+1];
6291 /* Cache directory name with pointer TempDirName.
6292 Look for it only the first time. */
6295 err
= FindFolder (kOnSystemDisk
, kPreferencesFolderType
,
6296 kCreateFolder
, &vRefNum
, &dirID
);
6301 cpb
.dirInfo
.ioNamePtr
= dirName
;
6302 cpb
.dirInfo
.ioDrParID
= dirID
;
6304 /* Standard ref num to full path name loop */
6306 cpb
.dirInfo
.ioVRefNum
= vRefNum
;
6307 cpb
.dirInfo
.ioFDirIndex
= -1;
6308 cpb
.dirInfo
.ioDrDirID
= cpb
.dirInfo
.ioDrParID
;
6310 err
= PBGetCatInfo (&cpb
, false);
6313 strcat (dirName
, ":");
6314 if (strlen (fullPath
) + strlen (dirName
) <= MAXPATHLEN
)
6316 strcat (dirName
, fullPath
);
6317 strcpy (fullPath
, dirName
);
6322 while (cpb
.dirInfo
.ioDrDirID
!= fsRtDirID
&& err
== noErr
);
6324 if (strlen (fullPath
) + 6 <= MAXPATHLEN
)
6325 strcat (fullPath
, "Emacs:");
6329 if (Mac2UnixPathname (fullPath
, unixDirName
, MAXPATHLEN
+1) == 0)
6332 dir
= opendir (unixDirName
); /* check whether temp directory exists */
6335 else if (mkdir (unixDirName
, 0700) != 0) /* create it if not */
6338 TempDirName
= (char *) malloc (strlen (unixDirName
) + 1);
6339 strcpy (TempDirName
, unixDirName
);
6346 getenv (const char * name
)
6348 if (strcmp (name
, "TERM") == 0)
6350 else if (strcmp (name
, "TERMCAP") == 0)
6351 /* for debugging purpose when code was still outputting to dumb terminal */
6352 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6353 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6354 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6355 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6356 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6357 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6358 else if (strcmp (name
, "TMPDIR") == 0)
6359 return GetTempDirName ();
6365 #include <utsname.h>
6368 uname (struct utsname
*name
)
6371 systemName
= GetString (-16413); /* IM - Resource Manager Reference */
6374 BlockMove (*systemName
, name
->nodename
, (*systemName
)[0]+1);
6375 p2cstr (name
->nodename
);
6382 #include <Processes.h>
6385 /* Event class of HLE sent to subprocess. */
6386 const OSType kEmacsSubprocessSend
= 'ESND';
6387 /* Event class of HLE sent back from subprocess. */
6388 const OSType kEmacsSubprocessReply
= 'ERPY';
6391 mystrchr (char *s
, char c
)
6393 while (*s
&& *s
!= c
)
6419 mystrcpy (char *to
, char *from
)
6430 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6431 terminated). The process should run with the default directory
6432 "workdir", read input from "infn", and write output and error to
6433 "outfn" and "errfn", resp. The Process Manager call
6434 LaunchApplication is used to start the subprocess. We use high
6435 level events as the mechanism to pass arguments to the subprocess
6436 and to make Emacs wait for the subprocess to terminate and pass
6437 back a result code. The bulk of the code here packs the arguments
6438 into one message to be passed together with the high level event.
6439 Emacs also sometimes starts a subprocess using a shell to perform
6440 wildcard filename expansion. Since we don't really have a shell on
6441 the Mac, this case is detected and the starting of the shell is
6442 by-passed. We really need to add code here to do filename
6443 expansion to support such functionality. */
6445 run_mac_command (argv
, workdir
, infn
, outfn
, errfn
)
6446 unsigned char **argv
;
6447 const char *workdir
;
6448 const char *infn
, *outfn
, errfn
;
6450 char macappname
[MAXPATHLEN
+1], macworkdir
[MAXPATHLEN
+1];
6451 char macinfn
[MAXPATHLEN
+1], macoutfn
[MAXPATHLEN
+1], macerrfn
[MAXPATHLEN
+1];
6452 int paramlen
, argc
, newargc
, j
, retries
;
6453 char **newargv
, *param
, *p
;
6456 LaunchParamBlockRec lpbr
;
6457 EventRecord sendEvent
, replyEvent
;
6458 RgnHandle cursorRegionHdl
;
6460 unsigned long refCon
, len
;
6462 if (Unix2MacPathname (workdir
, macworkdir
, MAXPATHLEN
+1) == 0)
6464 if (Unix2MacPathname (infn
, macinfn
, MAXPATHLEN
+1) == 0)
6466 if (Unix2MacPathname (outfn
, macoutfn
, MAXPATHLEN
+1) == 0)
6468 if (Unix2MacPathname (errfn
, macerrfn
, MAXPATHLEN
+1) == 0)
6471 paramlen
= strlen (macworkdir
) + strlen (macinfn
) + strlen (macoutfn
) + strlen (macerrfn
) + 4;
6472 /* count nulls at end of strings */
6481 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6482 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6483 j
= strlen (argv
[0]);
6484 if (j
>= 3 && strcmp (argv
[0]+j
-3, "/sh") == 0 && argc
== 3 && strcmp (argv
[1], "-c") == 0)
6486 char *command
, *t
, tempmacpathname
[MAXPATHLEN
+1];
6488 /* The arguments for the command in argv[2] are separated by spaces. Count them and put
6489 the count in newargc. */
6490 command
= (char *) alloca (strlen (argv
[2])+2);
6491 strcpy (command
, argv
[2]);
6492 if (command
[strlen (command
) - 1] != ' ')
6493 strcat (command
, " ");
6497 t
= mystrchr (t
, ' ');
6501 t
= mystrchr (t
+1, ' ');
6504 newargv
= (char **) alloca (sizeof (char *) * newargc
);
6507 for (j
= 0; j
< newargc
; j
++)
6509 newargv
[j
] = (char *) alloca (strlen (t
) + 1);
6510 mystrcpy (newargv
[j
], t
);
6513 paramlen
+= strlen (newargv
[j
]) + 1;
6516 if (strncmp (newargv
[0], "~emacs/", 7) == 0)
6518 if (Unix2MacPathname (newargv
[0], tempmacpathname
, MAXPATHLEN
+1) == 0)
6522 { /* sometimes Emacs call "sh" without a path for the command */
6524 char *t
= (char *) alloca (strlen (newargv
[0]) + 7 + 1);
6525 strcpy (t
, "~emacs/");
6526 strcat (t
, newargv
[0]);
6529 openp (Vexec_path
, build_string (newargv
[0]), EXEC_SUFFIXES
, &path
, 1);
6533 if (Unix2MacPathname (XSTRING (path
)->data
, tempmacpathname
, MAXPATHLEN
+1) == 0)
6536 strcpy (macappname
, tempmacpathname
);
6540 if (Unix2MacPathname (argv
[0], macappname
, MAXPATHLEN
+1) == 0)
6543 newargv
= (char **) alloca (sizeof (char *) * argc
);
6545 for (j
= 1; j
< argc
; j
++)
6547 if (strncmp (argv
[j
], "~emacs/", 7) == 0)
6549 char *t
= strchr (argv
[j
], ' ');
6552 char tempcmdname
[MAXPATHLEN
+1], tempmaccmdname
[MAXPATHLEN
+1];
6553 strncpy (tempcmdname
, argv
[j
], t
-argv
[j
]);
6554 tempcmdname
[t
-argv
[j
]] = '\0';
6555 if (Unix2MacPathname (tempcmdname
, tempmaccmdname
, MAXPATHLEN
+1) == 0)
6557 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
) + strlen (t
) + 1);
6558 strcpy (newargv
[j
], tempmaccmdname
);
6559 strcat (newargv
[j
], t
);
6563 char tempmaccmdname
[MAXPATHLEN
+1];
6564 if (Unix2MacPathname (argv
[j
], tempmaccmdname
, MAXPATHLEN
+1) == 0)
6566 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
)+1);
6567 strcpy (newargv
[j
], tempmaccmdname
);
6571 newargv
[j
] = argv
[j
];
6572 paramlen
+= strlen (newargv
[j
]) + 1;
6576 /* After expanding all the arguments, we now know the length of the parameter block to be
6577 sent to the subprocess as a message attached to the HLE. */
6578 param
= (char *) malloc (paramlen
+ 1);
6583 *p
++ = newargc
; /* first byte of message contains number of arguments for command */
6584 strcpy (p
, macworkdir
);
6585 p
+= strlen (macworkdir
);
6586 *p
++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6587 strcpy (p
, macinfn
);
6588 p
+= strlen (macinfn
);
6590 strcpy (p
, macoutfn
);
6591 p
+= strlen (macoutfn
);
6593 strcpy (p
, macerrfn
);
6594 p
+= strlen (macerrfn
);
6596 for (j
= 1; j
< newargc
; j
++) {
6597 strcpy (p
, newargv
[j
]);
6598 p
+= strlen (newargv
[j
]);
6602 c2pstr (macappname
);
6604 iErr
= FSMakeFSSpec (0, 0, macappname
, &spec
);
6606 if (iErr
!= noErr
) {
6611 lpbr
.launchBlockID
= extendedBlock
;
6612 lpbr
.launchEPBLength
= extendedBlockLen
;
6613 lpbr
.launchControlFlags
= launchContinue
+ launchNoFileFlags
;
6614 lpbr
.launchAppSpec
= &spec
;
6615 lpbr
.launchAppParameters
= NULL
;
6617 iErr
= LaunchApplication (&lpbr
); /* call the subprocess */
6618 if (iErr
!= noErr
) {
6623 sendEvent
.what
= kHighLevelEvent
;
6624 sendEvent
.message
= kEmacsSubprocessSend
; /* Event ID stored in "where" unused */
6627 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6628 iErr
= PostHighLevelEvent (&sendEvent
, &lpbr
.launchProcessSN
, 0, param
, paramlen
+ 1, receiverIDisPSN
);
6630 while (iErr
== sessClosedErr
&& retries
-- > 0);
6632 if (iErr
!= noErr
) {
6637 cursorRegionHdl
= NewRgn ();
6639 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6641 if (WaitNextEvent (highLevelEventMask
, &replyEvent
, 180, cursorRegionHdl
) && replyEvent
.message
== kEmacsSubprocessReply
)
6644 /* The return code is sent through the refCon */
6645 iErr
= AcceptHighLevelEvent (&targ
, &refCon
, NULL
, &len
);
6646 if (iErr
!= noErr
) {
6647 DisposeHandle ((Handle
) cursorRegionHdl
);
6652 DisposeHandle ((Handle
) cursorRegionHdl
);
6659 opendir (const char *dirname
)
6661 char MacPathname
[MAXPATHLEN
+1];
6666 dirp
= (DIR *) malloc (sizeof (DIR));
6670 /* Handle special case when dirname is "/": sets up for readir to
6671 get all mount volumes. */
6672 if (strcmp (dirname
, "/") == 0) {
6673 dirp
->getting_volumes
= 1; /* special all mounted volumes DIR struct */
6674 dirp
->current_index
= 1; /* index for first volume */
6678 /* Handle typical cases: not accessing all mounted volumes. */
6679 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
6682 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6683 len
= strlen (MacPathname
);
6684 if (MacPathname
[len
- 1] != ':' && len
< MAXPATHLEN
)
6685 strcat (MacPathname
, ":");
6687 c2pstr (MacPathname
);
6688 cipb
.hFileInfo
.ioNamePtr
= MacPathname
; /* using full pathname so vRefNum and dirID ignored */
6689 cipb
.hFileInfo
.ioVRefNum
= 0;
6690 cipb
.hFileInfo
.ioDirID
= 0;
6691 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
6693 errno
= PBGetCatInfo (&cipb
, false);
6694 if (errno
!= noErr
) {
6699 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x10)) /* bit 4 = 1 for directories */
6700 return 0; /* not a directory */
6702 dirp
->dir_id
= cipb
.dirInfo
.ioDrDirID
; /* used later in readdir */
6703 dirp
->getting_volumes
= 0;
6704 dirp
->current_index
= 1; /* index for first file/directory */
6720 HParamBlockRec HPBlock
;
6722 static struct dirent s_dirent
;
6723 static Str255 s_name
;
6726 /* Handle the root directory containing the mounted volumes. Call
6727 PBHGetVInfo specifying an index to obtain the info for a volume.
6728 PBHGetVInfo returns an error when it receives an index beyond the
6729 last volume, at which time we should return a nil dirent struct
6731 if (dp
->getting_volumes
) {
6732 HPBlock
.volumeParam
.ioNamePtr
= s_name
;
6733 HPBlock
.volumeParam
.ioVRefNum
= 0;
6734 HPBlock
.volumeParam
.ioVolIndex
= dp
->current_index
;
6736 errno
= PBHGetVInfo (&HPBlock
, false);
6737 if (errno
!= noErr
) {
6743 strcat (s_name
, "/"); /* need "/" for stat to work correctly */
6745 dp
->current_index
++;
6747 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
;
6748 s_dirent
.d_name
= s_name
;
6753 cipb
.hFileInfo
.ioVRefNum
= 0;
6754 cipb
.hFileInfo
.ioNamePtr
= s_name
; /* location to receive filename returned */
6756 /* return only visible files */
6759 cipb
.hFileInfo
.ioDirID
= dp
->dir_id
; /* directory ID found by opendir */
6760 cipb
.hFileInfo
.ioFDirIndex
= dp
->current_index
;
6762 errno
= PBGetCatInfo (&cipb
, false);
6763 if (errno
!= noErr
) {
6768 /* insist on an visibile entry */
6769 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* directory? */
6770 done
= !(cipb
.dirInfo
.ioDrUsrWds
.frFlags
& fInvisible
);
6772 done
= !(cipb
.hFileInfo
.ioFlFndrInfo
.fdFlags
& fInvisible
);
6774 dp
->current_index
++;
6779 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
; /* value unimportant: non-zero for valid file */
6780 s_dirent
.d_name
= s_name
;
6789 char MacPathname
[MAXPATHLEN
+1];
6790 Str255 directoryName
;
6794 MacPathname
[0] = '\0';
6795 directoryName
[0] = '\0';
6796 cipb
.dirInfo
.ioDrParID
= 0;
6797 cipb
.dirInfo
.ioNamePtr
= directoryName
; /* empty string = default directory */
6800 cipb
.dirInfo
.ioVRefNum
= 0;
6801 cipb
.dirInfo
.ioFDirIndex
= -1;
6802 cipb
.dirInfo
.ioDrDirID
= cipb
.dirInfo
.ioDrParID
; /* go up to parent each time */
6804 errno
= PBGetCatInfo (&cipb
, false);
6805 if (errno
!= noErr
) {
6810 p2cstr (directoryName
);
6811 strcat (directoryName
, ":");
6812 strcat (directoryName
, MacPathname
); /* attach to front since going up directory tree */
6813 strcpy (MacPathname
, directoryName
);
6814 } while (cipb
.dirInfo
.ioDrDirID
!= fsRtDirID
); /* until volume's root directory */
6816 if (Mac2UnixPathname (MacPathname
, path
, MAXPATHLEN
+1) == 0)
6822 #endif /* macintosh */