1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
30 #include "blockinput.h"
35 __sigfun
sys_signal (int signal
, __sigfun signal_func
);
37 __signal_func_ptr
sys_signal (int signal
, __signal_func_ptr signal_func
);
42 /* Nonzero means delete a process right away if it exits (process.c). */
43 static int delete_exited_processes
;
45 #ifndef HAVE_X_WINDOWS
46 /* Search path for bitmap files (xfns.c). */
47 Lisp_Object Vx_bitmap_file_path
;
49 #endif /* macintosh */
51 #define min(x,y) ((x) > (y) ? (y) : (x))
53 /* In this file, open, read and write refer to the system calls,
54 not our sugared interfaces sys_open, sys_read and sys_write.
55 Contrariwise, for systems where we use the system calls directly,
56 define sys_read, etc. here as aliases for them. */
59 #define sys_write write
60 #endif /* `read' is not a macro */
70 #endif /* not WINDOWSNT */
73 #define sys_close close
80 #else /* `open' is a macro */
82 #endif /* `open' is a macro */
84 /* Does anyone other than VMS need this? */
86 #define sys_fwrite fwrite
96 #include <sys/types.h>
100 /* Get _POSIX_VDISABLE, if it is available. */
105 /* Get SI_SRPC_DOMAIN, if it is available. */
106 #ifdef HAVE_SYS_SYSTEMINFO_H
107 #include <sys/systeminfo.h>
110 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
114 #include <sys/param.h>
118 extern unsigned start
__asm__ ("start");
138 #include <sys/file.h>
146 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
150 #ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
151 because the vms compiler doesn't grok `defined' */
159 #endif /* not 4.1 bsd */
162 #include <sys/ioctl.h>
168 #ifdef BROKEN_TIOCGWINSZ
173 #if defined (USG) || defined (DGUX)
174 #include <sys/utsname.h>
176 #ifndef MEMORY_IN_STRING_H
179 #if defined (TIOCGWINSZ) || defined (ISC4_0)
181 #include <sys/sioctl.h>
184 #include <sys/stream.h>
185 #include <sys/ptem.h>
187 #endif /* TIOCGWINSZ or ISC4_0 */
188 #endif /* USG or DGUX */
190 extern int quit_char
;
194 #include "termhooks.h"
195 #include "termchar.h"
196 #include "termopts.h"
197 #include "dispextern.h"
202 /* In process.h which conflicts with the local copy. */
204 int _CRTAPI1
_spawnlp (int, const char *, const char *, ...);
205 int _CRTAPI1
_getpid (void);
208 #ifdef NONSYSTEM_DIR_LIBRARY
210 #endif /* NONSYSTEM_DIR_LIBRARY */
212 #include "syssignal.h"
219 #ifndef HAVE_STRUCT_UTIMBUF
220 /* We want to use utime rather than utimes, but we couldn't find the
221 structure declaration. We'll use the traditional one. */
229 #ifndef VFORK_RETURN_TYPE
230 #define VFORK_RETURN_TYPE int
233 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
239 #define LNOFLSH 0100000
242 static int baud_convert
[] =
247 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
248 1800, 2400, 4800, 9600, 19200, 38400
252 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
255 #if defined (HAVE_TERMIOS_H) && defined (LINUX)
257 /* HJL's version of libc is said to need this on the Alpha.
258 On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short. */
259 extern speed_t ospeed
;
265 /* The file descriptor for Emacs's input terminal.
266 Under Unix, this is normally zero except when using X;
267 under VMS, we place the input channel number here. */
270 void croak
P_ ((char *));
278 /* Specify a different file descriptor for further input operations. */
287 /* Discard pending input on descriptor input_fd. */
293 struct emacs_tty buf
;
298 /* Discarding input is not safe when the input could contain
299 replies from the X server. So don't do it. */
300 if (read_socket_hook
)
305 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
306 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
312 ioctl (input_fd
, TIOCFLUSH
, &zero
);
314 #else /* not Apollo */
315 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
316 while (dos_keyread () != -1)
318 #else /* not MSDOS */
319 EMACS_GET_TTY (input_fd
, &buf
);
320 EMACS_SET_TTY (input_fd
, &buf
, 0);
321 #endif /* not MSDOS */
322 #endif /* not Apollo */
324 #endif /* not WINDOWSNT */
329 /* Arrange for character C to be read as the next input from
336 if (read_socket_hook
)
339 /* Should perhaps error if in batch mode */
341 ioctl (input_fd
, TIOCSTI
, &c
);
342 #else /* no TIOCSTI */
343 error ("Cannot stuff terminal input characters in this version of Unix");
344 #endif /* no TIOCSTI */
356 #ifdef INIT_BAUD_RATE
361 #else /* not DOS_NT */
365 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
366 &sg
.class, 12, 0, 0, 0, 0 );
367 ospeed
= sg
.xmit_baud
;
373 tcgetattr (input_fd
, &sg
);
374 ospeed
= cfgetospeed (&sg
);
375 #if defined (USE_GETOBAUD) && defined (getobaud)
376 /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
378 ospeed
= getobaud (sg
.c_cflag
);
380 #else /* neither VMS nor TERMIOS */
386 tcgetattr (input_fd
, &sg
);
388 ioctl (input_fd
, TCGETA
, &sg
);
390 ospeed
= sg
.c_cflag
& CBAUD
;
391 #else /* neither VMS nor TERMIOS nor TERMIO */
394 sg
.sg_ospeed
= B9600
;
395 if (ioctl (input_fd
, TIOCGETP
, &sg
) < 0)
397 ospeed
= sg
.sg_ospeed
;
398 #endif /* not HAVE_TERMIO */
399 #endif /* not HAVE_TERMIOS */
401 #endif /* not DOS_NT */
402 #endif /* not INIT_BAUD_RATE */
405 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
406 ? baud_convert
[ospeed
] : 9600);
413 set_exclusive_use (fd
)
417 ioctl (fd
, FIOCLEX
, 0);
419 /* Ok to do nothing if this feature does not exist */
424 wait_without_blocking ()
427 wait3 (0, WNOHANG
| WUNTRACED
, 0);
429 croak ("wait_without_blocking");
431 synch_process_alive
= 0;
434 #endif /* not subprocesses */
436 int wait_debugging
; /* Set nonzero to make following function work under dbx
437 (at least for bsd). */
440 wait_for_termination_signal ()
443 /* Wait for subprocess with process id `pid' to terminate and
444 make sure it will get eliminated (not remain forever as a zombie) */
447 wait_for_termination (pid
)
456 status
= SYS$
FORCEX (&pid
, 0, 0);
459 #if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
460 /* Note that kill returns -1 even if the process is just a zombie now.
461 But inevitably a SIGCHLD interrupt should be generated
462 and child_sig will do wait3 and make the process go away. */
463 /* There is some indication that there is a bug involved with
464 termination of subprocesses, perhaps involving a kernel bug too,
465 but no idea what it is. Just as a hunch we signal SIGCHLD to see
466 if that causes the problem to go away or get worse. */
467 sigsetmask (sigmask (SIGCHLD
));
468 if (0 > kill (pid
, 0))
470 sigsetmask (SIGEMPTYMASK
);
471 kill (getpid (), SIGCHLD
);
477 sigpause (SIGEMPTYMASK
);
478 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
479 #if defined (UNIPLUS)
480 if (0 > kill (pid
, 0))
483 #else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
484 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
485 sigblock (sigmask (SIGCHLD
));
486 if (0 > kill (pid
, 0))
488 sigunblock (sigmask (SIGCHLD
));
491 sigpause (SIGEMPTYMASK
);
492 #else /* not POSIX_SIGNALS */
493 #ifdef HAVE_SYSV_SIGPAUSE
495 if (0 > kill (pid
, 0))
501 #else /* not HAVE_SYSV_SIGPAUSE */
505 #else /* not WINDOWSNT */
506 if (0 > kill (pid
, 0))
508 /* Using sleep instead of pause avoids timing error.
509 If the inferior dies just before the sleep,
510 we lose just one second. */
512 #endif /* not WINDOWSNT */
513 #endif /* not HAVE_SYSV_SIGPAUSE */
514 #endif /* not POSIX_SIGNALS */
515 #endif /* not UNIPLUS */
516 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
518 #else /* not subprocesses */
521 #else /* not __DJGPP__ > 1 */
523 if (kill (pid
, 0) < 0)
529 if (status
== pid
|| status
== -1)
532 #endif /* not __DJGPP__ > 1*/
533 #endif /* not subprocesses */
540 * flush any pending output
541 * (may flush input as well; it does not matter the way we use it)
545 flush_pending_output (channel
)
549 /* If we try this, we get hit with SIGTTIN, because
550 the child's tty belongs to the child's pgrp. */
553 ioctl (channel
, TCFLSH
, 1);
557 /* 3rd arg should be ignored
558 but some 4.2 kernels actually want the address of an int
559 and nonzero means something different. */
560 ioctl (channel
, TIOCFLUSH
, &zero
);
567 /* Set up the terminal at the other end of a pseudo-terminal that
568 we will be controlling an inferior through.
569 It should not echo or do line-editing, since that is done
570 in Emacs. No padding needed for insertion into an Emacs buffer. */
573 child_setup_tty (out
)
579 EMACS_GET_TTY (out
, &s
);
581 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
582 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
583 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
585 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
586 /* No output delays */
588 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
589 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
591 s
.main
.c_iflag
&= ~IUCLC
; /* Disable downcasing on input. */
594 s
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
597 s
.main
.c_oflag
&= ~OLCUC
; /* Disable upcasing on output. */
599 s
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
600 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CSIZE
) | CS8
; /* Don't strip 8th bit */
602 /* Said to be unnecessary: */
603 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
604 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
607 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
608 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
609 s
.main
.c_cc
[VERASE
] = CDISABLE
; /* disable erase processing */
610 s
.main
.c_cc
[VKILL
] = CDISABLE
; /* disable kill processing */
613 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
617 /* AIX enhanced edit loses NULs, so disable it */
620 s
.main
.c_iflag
&= ~ASCEDIT
;
622 /* Also, PTY overloads NUL and BREAK.
623 don't ignore break, but don't signal either, so it looks like NUL. */
624 s
.main
.c_iflag
&= ~IGNBRK
;
625 s
.main
.c_iflag
&= ~BRKINT
;
626 /* QUIT and INTR work better as signals, so disable character forms */
627 s
.main
.c_cc
[VINTR
] = 0377;
628 #ifdef SIGNALS_VIA_CHARACTERS
629 /* the QUIT and INTR character are used in process_send_signal
630 so set them here to something useful. */
631 if (s
.main
.c_cc
[VQUIT
] == 0377)
632 s
.main
.c_cc
[VQUIT
] = '\\'&037; /* Control-\ */
633 if (s
.main
.c_cc
[VINTR
] == 0377)
634 s
.main
.c_cc
[VINTR
] = 'C'&037; /* Control-C */
635 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
636 /* QUIT and INTR work better as signals, so disable character forms */
637 s
.main
.c_cc
[VQUIT
] = 0377;
638 s
.main
.c_cc
[VINTR
] = 0377;
639 s
.main
.c_lflag
&= ~ISIG
;
640 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
641 s
.main
.c_cc
[VEOL
] = 0377;
642 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
645 #else /* not HAVE_TERMIO */
647 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
649 s
.main
.sg_flags
|= LPASS8
;
650 s
.main
.sg_erase
= 0377;
651 s
.main
.sg_kill
= 0377;
652 s
.lmode
= LLITOUT
| s
.lmode
; /* Don't strip 8th bit */
654 #endif /* not HAVE_TERMIO */
656 EMACS_SET_TTY (out
, &s
, 0);
665 ioctl (out
, FIOASYNC
, &zero
);
668 #endif /* not DOS_NT */
672 #endif /* subprocesses */
674 /* Record a signal code and the handler for it. */
678 SIGTYPE (*handler
) P_ ((int));
681 static void save_signal_handlers
P_ ((struct save_signal
*));
682 static void restore_signal_handlers
P_ ((struct save_signal
*));
684 /* Suspend the Emacs process; give terminal to its superior. */
690 /* "Foster" parentage allows emacs to return to a subprocess that attached
691 to the current emacs as a cheaper than starting a whole new process. This
692 is set up by KEPTEDITOR.COM. */
693 unsigned long parent_id
, foster_parent_id
;
696 fpid_string
= getenv ("EMACS_PARENT_PID");
697 if (fpid_string
!= NULL
)
699 sscanf (fpid_string
, "%x", &foster_parent_id
);
700 if (foster_parent_id
!= 0)
701 parent_id
= foster_parent_id
;
703 parent_id
= getppid ();
706 parent_id
= getppid ();
708 xfree (fpid_string
); /* On VMS, this was malloc'd */
710 if (parent_id
&& parent_id
!= 0xffffffff)
712 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
713 int status
= LIB$
ATTACH (&parent_id
) & 1;
714 signal (SIGINT
, oldsig
);
723 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
724 d_prompt
.a
= "Emacs: "; /* Just a reminder */
725 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
730 #if defined (SIGTSTP) && !defined (MSDOS)
733 int pgrp
= EMACS_GETPGRP (0);
734 EMACS_KILLPG (pgrp
, SIGTSTP
);
737 #else /* No SIGTSTP */
738 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
739 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
740 kill (getpid (), SIGQUIT
);
742 #else /* No SIGTSTP or USG_JOBCTRL */
744 /* On a system where suspending is not implemented,
745 instead fork a subshell and let it talk directly to the terminal
749 #endif /* no USG_JOBCTRL */
750 #endif /* no SIGTSTP */
754 /* Fork a subshell. */
760 error ("Can't spawn subshell");
763 #ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
765 char oldwd
[MAXPATHLEN
+1]; /* Fixed length is safe on MSDOS. */
768 struct save_signal saved_handlers
[5];
770 unsigned char *str
= 0;
773 saved_handlers
[0].code
= SIGINT
;
774 saved_handlers
[1].code
= SIGQUIT
;
775 saved_handlers
[2].code
= SIGTERM
;
777 saved_handlers
[3].code
= SIGIO
;
778 saved_handlers
[4].code
= 0;
780 saved_handlers
[3].code
= 0;
783 /* Mentioning current_buffer->buffer would mean including buffer.h,
784 which somehow wedges the hp compiler. So instead... */
786 dir
= intern ("default-directory");
787 if (NILP (Fboundp (dir
)))
789 dir
= Fsymbol_value (dir
);
793 dir
= expand_and_dir_to_file (Funhandled_file_name_directory (dir
), Qnil
);
794 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
795 len
= XSTRING (dir
)->size
;
796 bcopy (XSTRING (dir
)->data
, str
, len
);
797 if (str
[len
- 1] != '/') str
[len
++] = '/';
804 save_signal_handlers (saved_handlers
);
805 synch_process_alive
= 1;
806 #endif /* __DJGPP__ > 1 */
810 error ("Can't spawn subshell");
817 #ifdef DOS_NT /* MW, Aug 1993 */
820 sh
= (char *) egetenv ("SUSPEND"); /* KFS, 1994-12-14 */
823 sh
= (char *) egetenv ("SHELL");
827 /* Use our buffer's default directory for the subshell. */
829 chdir ((char *) str
);
832 close_process_descs (); /* Close Emacs's pipes/ptys */
835 #ifdef SET_EMACS_PRIORITY
837 extern int emacs_priority
;
839 if (emacs_priority
< 0)
840 nice (-emacs_priority
);
844 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
847 #if 0 /* This is also reported if last command executed in subshell failed, KFS */
849 report_file_error ("Can't execute subshell", Fcons (build_string (sh
), Qnil
));
851 #else /* not MSDOS */
853 /* Waits for process completion */
854 pid
= _spawnlp (_P_WAIT
, sh
, sh
, NULL
);
857 write (1, "Can't execute subshell", 22);
858 #else /* not WINDOWSNT */
860 write (1, "Can't execute subshell", 22);
862 #endif /* not WINDOWSNT */
863 #endif /* not MSDOS */
866 /* Do this now if we did not do it before. */
867 #if !defined (MSDOS) || __DJGPP__ == 1
868 save_signal_handlers (saved_handlers
);
869 synch_process_alive
= 1;
873 wait_for_termination (pid
);
875 restore_signal_handlers (saved_handlers
);
876 synch_process_alive
= 0;
878 #endif /* !macintosh */
882 save_signal_handlers (saved_handlers
)
883 struct save_signal
*saved_handlers
;
885 while (saved_handlers
->code
)
887 saved_handlers
->handler
888 = (SIGTYPE (*) P_ ((int))) signal (saved_handlers
->code
, SIG_IGN
);
894 restore_signal_handlers (saved_handlers
)
895 struct save_signal
*saved_handlers
;
897 while (saved_handlers
->code
)
899 signal (saved_handlers
->code
, saved_handlers
->handler
);
913 old_fcntl_flags
= fcntl (fd
, F_GETFL
, 0) & ~FASYNC
;
914 fcntl (fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
916 interrupts_deferred
= 0;
925 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
930 if (read_socket_hook
)
934 sigunblock (sigmask (SIGWINCH
));
936 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
938 interrupts_deferred
= 0;
944 if (read_socket_hook
)
948 sigblock (sigmask (SIGWINCH
));
950 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
);
951 interrupts_deferred
= 1;
954 #else /* no FASYNC */
955 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
962 if (read_socket_hook
)
965 ioctl (input_fd
, FIOASYNC
, &on
);
966 interrupts_deferred
= 0;
974 if (read_socket_hook
)
977 ioctl (input_fd
, FIOASYNC
, &off
);
978 interrupts_deferred
= 1;
981 #else /* not FASYNC, not STRIDE */
993 if (read_socket_hook
)
997 sigaddset (&st
, SIGIO
);
998 ioctl (input_fd
, FIOASYNC
, &on
);
999 interrupts_deferred
= 0;
1000 sigprocmask (SIG_UNBLOCK
, &st
, (sigset_t
*)0);
1008 if (read_socket_hook
)
1011 ioctl (input_fd
, FIOASYNC
, &off
);
1012 interrupts_deferred
= 1;
1015 #else /* ! _CX_UX */
1020 if (read_socket_hook
)
1023 croak ("request_sigio");
1029 if (read_socket_hook
)
1032 croak ("unrequest_sigio");
1038 #endif /* F_SETFL */
1040 /* Saving and restoring the process group of Emacs's terminal. */
1044 /* The process group of which Emacs was a member when it initially
1047 If Emacs was in its own process group (i.e. inherited_pgroup ==
1048 getpid ()), then we know we're running under a shell with job
1049 control (Emacs would never be run as part of a pipeline).
1052 If Emacs was not in its own process group, then we know we're
1053 running under a shell (or a caller) that doesn't know how to
1054 separate itself from Emacs (like sh). Emacs must be in its own
1055 process group in order to receive SIGIO correctly. In this
1056 situation, we put ourselves in our own pgroup, forcibly set the
1057 tty's pgroup to our pgroup, and make sure to restore and reinstate
1058 the tty's pgroup just like any other terminal setting. If
1059 inherited_group was not the tty's pgroup, then we'll get a
1060 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
1061 it goes foreground in the future, which is what should happen. */
1062 int inherited_pgroup
;
1064 /* Split off the foreground process group to Emacs alone.
1065 When we are in the foreground, but not started in our own process
1066 group, redirect the TTY to point to our own process group. We need
1067 to be in our own process group to receive SIGIO properly. */
1069 narrow_foreground_group ()
1073 setpgrp (0, inherited_pgroup
);
1074 if (inherited_pgroup
!= me
)
1075 EMACS_SET_TTY_PGRP (input_fd
, &me
);
1079 /* Set the tty to our original foreground group. */
1081 widen_foreground_group ()
1083 if (inherited_pgroup
!= getpid ())
1084 EMACS_SET_TTY_PGRP (input_fd
, &inherited_pgroup
);
1085 setpgrp (0, inherited_pgroup
);
1088 #endif /* BSD_PGRPS */
1090 /* Getting and setting emacs_tty structures. */
1092 /* Set *TC to the parameters associated with the terminal FD.
1093 Return zero if all's well, or -1 if we ran into an error we
1094 couldn't deal with. */
1096 emacs_get_tty (fd
, settings
)
1098 struct emacs_tty
*settings
;
1100 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
1102 /* We have those nifty POSIX tcmumbleattr functions. */
1103 bzero (&settings
->main
, sizeof (settings
->main
));
1104 if (tcgetattr (fd
, &settings
->main
) < 0)
1109 /* The SYSV-style interface? */
1110 if (ioctl (fd
, TCGETA
, &settings
->main
) < 0)
1115 /* Vehemently Monstrous System? :-) */
1116 if (! (SYS$
QIOW (0, fd
, IO$_SENSEMODE
, settings
, 0, 0,
1117 &settings
->main
.class, 12, 0, 0, 0, 0)
1123 /* I give up - I hope you have the BSD ioctls. */
1124 if (ioctl (fd
, TIOCGETP
, &settings
->main
) < 0)
1126 #endif /* not DOS_NT */
1131 /* Suivant - Do we have to get struct ltchars data? */
1133 if (ioctl (fd
, TIOCGLTC
, &settings
->ltchars
) < 0)
1137 /* How about a struct tchars and a wordful of lmode bits? */
1139 if (ioctl (fd
, TIOCGETC
, &settings
->tchars
) < 0
1140 || ioctl (fd
, TIOCLGET
, &settings
->lmode
) < 0)
1144 /* We have survived the tempest. */
1149 /* Set the parameters of the tty on FD according to the contents of
1150 *SETTINGS. If FLUSHP is non-zero, we discard input.
1151 Return 0 if all went well, and -1 if anything failed. */
1154 emacs_set_tty (fd
, settings
, flushp
)
1156 struct emacs_tty
*settings
;
1159 /* Set the primary parameters - baud rate, character size, etcetera. */
1162 /* We have those nifty POSIX tcmumbleattr functions.
1163 William J. Smith <wjs@wiis.wang.com> writes:
1164 "POSIX 1003.1 defines tcsetattr to return success if it was
1165 able to perform any of the requested actions, even if some
1166 of the requested actions could not be performed.
1167 We must read settings back to ensure tty setup properly.
1168 AIX requires this to keep tty from hanging occasionally." */
1169 /* This make sure that we don't loop indefinitely in here. */
1170 for (i
= 0 ; i
< 10 ; i
++)
1171 if (tcsetattr (fd
, flushp
? TCSAFLUSH
: TCSADRAIN
, &settings
->main
) < 0)
1182 bzero (&new, sizeof (new));
1183 /* Get the current settings, and see if they're what we asked for. */
1184 tcgetattr (fd
, &new);
1185 /* We cannot use memcmp on the whole structure here because under
1186 * aix386 the termios structure has some reserved field that may
1189 if ( new.c_iflag
== settings
->main
.c_iflag
1190 && new.c_oflag
== settings
->main
.c_oflag
1191 && new.c_cflag
== settings
->main
.c_cflag
1192 && new.c_lflag
== settings
->main
.c_lflag
1193 && memcmp (new.c_cc
, settings
->main
.c_cc
, NCCS
) == 0)
1201 /* The SYSV-style interface? */
1202 if (ioctl (fd
, flushp
? TCSETAF
: TCSETAW
, &settings
->main
) < 0)
1207 /* Vehemently Monstrous System? :-) */
1208 if (! (SYS$
QIOW (0, fd
, IO$_SETMODE
, &input_iosb
, 0, 0,
1209 &settings
->main
.class, 12, 0, 0, 0, 0)
1215 /* I give up - I hope you have the BSD ioctls. */
1216 if (ioctl (fd
, (flushp
) ? TIOCSETP
: TIOCSETN
, &settings
->main
) < 0)
1218 #endif /* not DOS_NT */
1224 /* Suivant - Do we have to get struct ltchars data? */
1226 if (ioctl (fd
, TIOCSLTC
, &settings
->ltchars
) < 0)
1230 /* How about a struct tchars and a wordful of lmode bits? */
1232 if (ioctl (fd
, TIOCSETC
, &settings
->tchars
) < 0
1233 || ioctl (fd
, TIOCLSET
, &settings
->lmode
) < 0)
1237 /* We have survived the tempest. */
1242 /* The initial tty mode bits */
1243 struct emacs_tty old_tty
;
1245 /* 1 if we have been through init_sys_modes. */
1248 /* 1 if outer tty status has been recorded. */
1252 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1257 #ifndef F_SETOWN_BUG
1259 int old_fcntl_owner
;
1260 #endif /* F_SETOWN */
1261 #endif /* F_SETOWN_BUG */
1263 /* This may also be defined in stdio,
1264 but if so, this does no harm,
1265 and using the same name avoids wasting the other one's space. */
1268 extern char *_sobuf
;
1270 #if defined (USG) || defined (DGUX)
1271 unsigned char _sobuf
[BUFSIZ
+8];
1273 char _sobuf
[BUFSIZ
];
1278 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
1281 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
1287 struct emacs_tty tty
;
1290 Vwindow_system
= intern ("mac");
1291 Vwindow_system_version
= make_number (1);
1293 /* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1294 #ifndef subprocesses
1295 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
1296 "*Non-nil means delete processes immediately when they exit.\n\
1297 nil means don't delete them until `list-processes' is run.");
1298 delete_exited_processes
= 0;
1301 #ifndef HAVE_X_WINDOWS
1302 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
1303 "List of directories to search for bitmap files for X.");
1304 Vx_bitmap_file_path
= decode_env_path ((char *) 0, ".");
1307 #endif /* not macintosh */
1311 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
1312 extern int (*interrupt_signal
) ();
1316 Vtty_erase_char
= Qnil
;
1323 input_ef
= get_kbd_event_flag ();
1324 /* LIB$GET_EF (&input_ef); */
1325 SYS$
CLREF (input_ef
);
1326 waiting_for_ast
= 0;
1328 timer_ef
= get_timer_event_flag ();
1329 /* LIB$GET_EF (&timer_ef); */
1330 SYS$
CLREF (timer_ef
);
1334 LIB$
GET_EF (&process_ef
);
1335 SYS$
CLREF (process_ef
);
1337 if (input_ef
/ 32 != process_ef
/ 32)
1338 croak ("Input and process event flags in different clusters.");
1340 if (input_ef
/ 32 != timer_ef
/ 32)
1341 croak ("Input and timer event flags in different clusters.");
1343 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1344 ((unsigned) 1 << (process_ef
% 32));
1346 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1347 ((unsigned) 1 << (timer_ef
% 32));
1349 sys_access_reinit ();
1351 #endif /* not VMS */
1354 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1355 narrow_foreground_group ();
1358 #ifdef HAVE_WINDOW_SYSTEM
1359 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1360 needs the initialization code below. */
1361 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1364 EMACS_GET_TTY (input_fd
, &old_tty
);
1370 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1371 XSETINT (Vtty_erase_char
, old_tty
.main
.c_cc
[VERASE
]);
1374 /* This allows meta to be sent on 8th bit. */
1375 tty
.main
.c_iflag
&= ~INPCK
; /* don't check input for parity */
1377 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
1378 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
1379 #ifdef INLCR /* I'm just being cautious,
1380 since I can't check how widespread INLCR is--rms. */
1381 tty
.main
.c_iflag
&= ~INLCR
; /* Disable map of NL to CR on input */
1384 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
1386 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
1387 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
1389 tty
.main
.c_lflag
&= ~IEXTEN
; /* Disable other editing characters. */
1391 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
1394 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
1396 tty
.main
.c_iflag
&= ~IXANY
;
1400 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
1401 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
1403 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
1407 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
1408 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
1411 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
1412 /* Set up C-g for both SIGQUIT and SIGINT.
1413 We don't know which we will get, but we handle both alike
1414 so which one it really gives us does not matter. */
1415 tty
.main
.c_cc
[VQUIT
] = quit_char
;
1416 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
1417 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
1419 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
1423 #if defined (mips) || defined (HAVE_TCATTR)
1425 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
1428 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
1429 #endif /* V_DSUSP */
1430 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1431 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
1434 tty
.main
.c_cc
[VLNEXT
] = CDISABLE
;
1437 tty
.main
.c_cc
[VREPRINT
] = CDISABLE
;
1438 #endif /* VREPRINT */
1440 tty
.main
.c_cc
[VWERASE
] = CDISABLE
;
1441 #endif /* VWERASE */
1443 tty
.main
.c_cc
[VDISCARD
] = CDISABLE
;
1444 #endif /* VDISCARD */
1449 tty
.main
.c_cc
[VSTART
] = '\021';
1452 tty
.main
.c_cc
[VSTOP
] = '\023';
1458 tty
.main
.c_cc
[VSTART
] = CDISABLE
;
1461 tty
.main
.c_cc
[VSTOP
] = CDISABLE
;
1464 #endif /* mips or HAVE_TCATTR */
1466 #ifdef SET_LINE_DISCIPLINE
1467 /* Need to explicitly request TERMIODISC line discipline or
1468 Ultrix's termios does not work correctly. */
1469 tty
.main
.c_line
= SET_LINE_DISCIPLINE
;
1473 /* AIX enhanced edit loses NULs, so disable it. */
1474 tty
.main
.c_line
= 0;
1475 tty
.main
.c_iflag
&= ~ASCEDIT
;
1477 tty
.main
.c_cc
[VSTRT
] = 255;
1478 tty
.main
.c_cc
[VSTOP
] = 255;
1479 tty
.main
.c_cc
[VSUSP
] = 255;
1480 tty
.main
.c_cc
[VDSUSP
] = 255;
1481 #endif /* IBMR2AIX */
1485 tty
.main
.c_cc
[VSTART
] = '\021';
1488 tty
.main
.c_cc
[VSTOP
] = '\023';
1491 /* Also, PTY overloads NUL and BREAK.
1492 don't ignore break, but don't signal either, so it looks like NUL.
1493 This really serves a purpose only if running in an XTERM window
1494 or via TELNET or the like, but does no harm elsewhere. */
1495 tty
.main
.c_iflag
&= ~IGNBRK
;
1496 tty
.main
.c_iflag
&= ~BRKINT
;
1498 #else /* if not HAVE_TERMIO */
1500 tty
.main
.tt_char
|= TT$M_NOECHO
;
1502 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
1504 tty
.main
.tt_char
|= TT$M_TTSYNC
;
1506 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
1507 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
1508 #else /* not VMS (BSD, that is) */
1510 XSETINT (Vtty_erase_char
, tty
.main
.sg_erase
);
1511 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
1513 tty
.main
.sg_flags
|= ANYP
;
1514 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
1515 #endif /* not DOS_NT */
1516 #endif /* not VMS (BSD, that is) */
1517 #endif /* not HAVE_TERMIO */
1519 /* If going to use CBREAK mode, we must request C-g to interrupt
1520 and turn off start and stop chars, etc. If not going to use
1521 CBREAK mode, do this anyway so as to turn off local flow
1522 control for user coming over network on 4.2; in this case,
1523 only t_stopc and t_startc really matter. */
1526 /* Note: if not using CBREAK mode, it makes no difference how we
1528 tty
.tchars
= new_tchars
;
1529 tty
.tchars
.t_intrc
= quit_char
;
1532 tty
.tchars
.t_startc
= '\021';
1533 tty
.tchars
.t_stopc
= '\023';
1536 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
1538 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1539 anything, and leaving it in breaks the meta key. Go figure. */
1540 tty
.lmode
&= ~LLITOUT
;
1547 #endif /* HAVE_TCHARS */
1548 #endif /* not HAVE_TERMIO */
1551 tty
.ltchars
= new_ltchars
;
1552 #endif /* HAVE_LTCHARS */
1553 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1555 internal_terminal_init ();
1559 EMACS_SET_TTY (input_fd
, &tty
, 0);
1561 /* This code added to insure that, if flow-control is not to be used,
1562 we have an unlocked terminal at the start. */
1565 if (!flow_control
) ioctl (input_fd
, TCXONC
, 1);
1569 if (!flow_control
) ioctl (input_fd
, TIOCSTART
, 0);
1573 #if defined (HAVE_TERMIOS) || defined (HPUX9)
1575 if (!flow_control
) tcflow (input_fd
, TCOON
);
1583 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1584 to be only LF. This is the way that is done. */
1587 if (ioctl (1, HFTGETID
, &tty
) != -1)
1588 write (1, "\033[20l", 5);
1594 /* Appears to do nothing when in PASTHRU mode.
1595 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1596 interrupt_signal, oob_chars, 0, 0, 0, 0);
1598 queue_kbd_input (0);
1603 #ifndef F_SETOWN_BUG
1604 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1606 && ! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1608 old_fcntl_owner
= fcntl (input_fd
, F_GETOWN
, 0);
1609 fcntl (input_fd
, F_SETOWN
, getpid ());
1610 init_sigio (input_fd
);
1612 #endif /* F_GETOWN */
1613 #endif /* F_SETOWN_BUG */
1614 #endif /* F_SETFL */
1617 if (interrupt_input
)
1618 init_sigio (input_fd
);
1621 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1625 /* This symbol is defined on recent USG systems.
1626 Someone says without this call USG won't really buffer the file
1627 even with a call to setbuf. */
1628 setvbuf (stdout
, (char *) _sobuf
, _IOFBF
, sizeof _sobuf
);
1630 setbuf (stdout
, (char *) _sobuf
);
1632 #ifdef HAVE_WINDOW_SYSTEM
1633 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1634 needs the initialization code below. */
1635 if (EQ (Vwindow_system
, Qnil
)
1637 /* When running in tty mode on NT/Win95, we have a read_socket
1638 hook, but still need the rest of the initialization code below. */
1639 && (! read_socket_hook
)
1643 set_terminal_modes ();
1646 && FRAMEP (Vterminal_frame
)
1647 && FRAME_TERMCAP_P (XFRAME (Vterminal_frame
)))
1648 init_frame_faces (XFRAME (Vterminal_frame
));
1650 if (term_initted
&& no_redraw_on_reenter
)
1652 if (display_completed
)
1653 direct_output_forward_char (0);
1658 if (FRAMEP (Vterminal_frame
))
1659 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
1665 /* Return nonzero if safe to use tabs in output.
1666 At the time this is called, init_sys_modes has not been done yet. */
1671 struct emacs_tty tty
;
1673 EMACS_GET_TTY (input_fd
, &tty
);
1674 return EMACS_TTY_TABS_OK (&tty
);
1677 /* Get terminal size from system.
1678 Store number of lines into *HEIGHTP and width into *WIDTHP.
1679 We store 0 if there's no valid information. */
1682 get_frame_size (widthp
, heightp
)
1683 int *widthp
, *heightp
;
1689 struct winsize size
;
1691 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1692 *widthp
= *heightp
= 0;
1695 *widthp
= size
.ws_col
;
1696 *heightp
= size
.ws_row
;
1702 /* SunOS - style. */
1703 struct ttysize size
;
1705 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1706 *widthp
= *heightp
= 0;
1709 *widthp
= size
.ts_cols
;
1710 *heightp
= size
.ts_lines
;
1716 struct sensemode tty
;
1718 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1719 &tty
.class, 12, 0, 0, 0, 0);
1720 *widthp
= tty
.scr_wid
;
1721 *heightp
= tty
.scr_len
;
1725 *widthp
= ScreenCols ();
1726 *heightp
= ScreenRows ();
1727 #else /* system doesn't know size */
1732 #endif /* not VMS */
1733 #endif /* not SunOS-style */
1734 #endif /* not BSD-style */
1737 /* Set the logical window size associated with descriptor FD
1738 to HEIGHT and WIDTH. This is used mainly with ptys. */
1741 set_window_size (fd
, height
, width
)
1742 int fd
, height
, width
;
1747 struct winsize size
;
1748 size
.ws_row
= height
;
1749 size
.ws_col
= width
;
1751 if (ioctl (fd
, TIOCSWINSZ
, &size
) == -1)
1752 return 0; /* error */
1759 /* SunOS - style. */
1760 struct ttysize size
;
1761 size
.ts_lines
= height
;
1762 size
.ts_cols
= width
;
1764 if (ioctl (fd
, TIOCGSIZE
, &size
) == -1)
1770 #endif /* not SunOS-style */
1771 #endif /* not BSD-style */
1775 /* Prepare the terminal for exiting Emacs; move the cursor to the
1776 bottom of the frame, turn off interrupt-driven I/O, etc. */
1789 #ifdef HAVE_WINDOW_SYSTEM
1790 /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
1791 needs the clean-up code below. */
1792 if (!EQ (Vwindow_system
, Qnil
)
1794 /* When running in tty mode on NT/Win95, we have a read_socket
1795 hook, but still need the rest of the clean-up code below. */
1801 sf
= SELECTED_FRAME ();
1802 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1803 clear_end_of_line (FRAME_WIDTH (sf
));
1804 /* clear_end_of_line may move the cursor */
1805 cursor_to (FRAME_HEIGHT (sf
) - 1, 0);
1806 #if defined (IBMR2AIX) && defined (AIXHFT)
1808 /* HFT devices normally use ^J as a LF/CR. We forced it to
1809 do the LF only. Now, we need to reset it. */
1812 if (ioctl (1, HFTGETID
, &tty
) != -1)
1813 write (1, "\033[20h", 5);
1817 reset_terminal_modes ();
1821 /* Avoid possible loss of output when changing terminal modes. */
1822 fsync (fileno (stdout
));
1827 #ifndef F_SETOWN_BUG
1828 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1829 if (interrupt_input
)
1832 fcntl (input_fd
, F_SETOWN
, old_fcntl_owner
);
1834 #endif /* F_SETOWN */
1835 #endif /* F_SETOWN_BUG */
1837 fcntl (input_fd
, F_SETFL
, fcntl (input_fd
, F_GETFL
, 0) & ~O_NDELAY
);
1839 #endif /* F_SETFL */
1841 if (interrupt_input
)
1846 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1849 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1853 #ifdef SET_LINE_DISCIPLINE
1854 /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
1855 A different old line discipline is therefore not restored, yet.
1856 Restore the old line discipline by hand. */
1857 ioctl (0, TIOCSETD
, &old_tty
.main
.c_line
);
1865 widen_foreground_group ();
1871 /* Set up the proper status flags for use of a pty. */
1877 /* I'm told that TOICREMOTE does not mean control chars
1878 "can't be sent" but rather that they don't have
1879 input-editing or signaling effects.
1880 That should be good, because we have other ways
1881 to do those things in Emacs.
1882 However, telnet mode seems not to work on 4.2.
1883 So TIOCREMOTE is turned off now. */
1885 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1886 will hang. In particular, the "timeout" feature (which
1887 causes a read to return if there is no data available)
1888 does this. Also it is known that telnet mode will hang
1889 in such a way that Emacs must be stopped (perhaps this
1890 is the same problem).
1892 If TIOCREMOTE is turned off, then there is a bug in
1893 hp-ux which sometimes loses data. Apparently the
1894 code which blocks the master process when the internal
1895 buffer fills up does not work. Other than this,
1896 though, everything else seems to work fine.
1898 Since the latter lossage is more benign, we may as well
1899 lose that way. -- cph */
1904 ioctl (fd
, FIONBIO
, &on
);
1909 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1910 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1911 /* cause EMACS not to die when it should, i.e., when its own controlling */
1912 /* tty goes away. I've complained to the AIX developers, and they may */
1913 /* change this behavior, but I'm not going to hold my breath. */
1914 signal (SIGHUP
, SIG_IGN
);
1917 #endif /* HAVE_PTYS */
1921 /* Assigning an input channel is done at the start of Emacs execution.
1922 This is called each time Emacs is resumed, also, but does nothing
1923 because input_chain is no longer zero. */
1932 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1938 /* Deassigning the input channel is done before exiting. */
1943 return SYS$
DASSGN (input_fd
);
1948 /* Request reading one character into the keyboard buffer.
1949 This is done as soon as the buffer becomes empty. */
1955 extern kbd_input_ast ();
1957 waiting_for_ast
= 0;
1959 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1960 &input_iosb
, kbd_input_ast
, 1,
1961 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1966 /* Ast routine that is called when keyboard input comes in
1967 in accord with the SYS$QIO above. */
1972 register int c
= -1;
1973 int old_errno
= errno
;
1974 extern EMACS_TIME
*input_available_clear_time
;
1976 if (waiting_for_ast
)
1977 SYS$
SETEF (input_ef
);
1978 waiting_for_ast
= 0;
1981 if (input_count
== 25)
1983 printf ("Ast # %d,", input_count
);
1984 printf (" iosb = %x, %x, %x, %x",
1985 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1988 if (input_iosb
.offset
)
1992 printf (", char = 0%o", c
);
2004 struct input_event e
;
2005 e
.kind
= ascii_keystroke
;
2006 XSETINT (e
.code
, c
);
2007 e
.frame_or_window
= selected_frame
;
2008 kbd_buffer_store_event (&e
);
2010 if (input_available_clear_time
)
2011 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
2015 /* Wait until there is something in kbd_buffer. */
2018 wait_for_kbd_input ()
2020 extern int have_process_input
, process_exited
;
2022 /* If already something, avoid doing system calls. */
2023 if (detect_input_pending ())
2027 /* Clear a flag, and tell ast routine above to set it. */
2028 SYS$
CLREF (input_ef
);
2029 waiting_for_ast
= 1;
2030 /* Check for timing error: ast happened while we were doing that. */
2031 if (!detect_input_pending ())
2033 /* No timing error: wait for flag to be set. */
2034 set_waiting_for_input (0);
2035 SYS$
WFLOR (input_ef
, input_eflist
);
2036 clear_waiting_for_input (0);
2037 if (!detect_input_pending ())
2038 /* Check for subprocess input availability */
2040 int dsp
= have_process_input
|| process_exited
;
2042 SYS$
CLREF (process_ef
);
2043 if (have_process_input
)
2044 process_command_input ();
2049 update_mode_lines
++;
2050 prepare_menu_bars ();
2051 redisplay_preserve_echo_area ();
2055 waiting_for_ast
= 0;
2058 /* Get rid of any pending QIO, when we are about to suspend
2059 or when we want to throw away pending input.
2060 We wait for a positive sign that the AST routine has run
2061 and therefore there is no I/O request queued when we return.
2062 SYS$SETAST is used to avoid a timing error. */
2068 printf ("At end_kbd_input.\n");
2072 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
2074 SYS$
CANCEL (input_fd
);
2079 /* Clear a flag, and tell ast routine above to set it. */
2080 SYS$
CLREF (input_ef
);
2081 waiting_for_ast
= 1;
2083 SYS$
CANCEL (input_fd
);
2085 SYS$
WAITFR (input_ef
);
2086 waiting_for_ast
= 0;
2089 /* Wait for either input available or time interval expiry. */
2092 input_wait_timeout (timeval
)
2093 int timeval
; /* Time to wait, in seconds */
2096 static int zero
= 0;
2097 static int large
= -10000000;
2099 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2101 /* If already something, avoid doing system calls. */
2102 if (detect_input_pending ())
2106 /* Clear a flag, and tell ast routine above to set it. */
2107 SYS$
CLREF (input_ef
);
2108 waiting_for_ast
= 1;
2109 /* Check for timing error: ast happened while we were doing that. */
2110 if (!detect_input_pending ())
2112 /* No timing error: wait for flag to be set. */
2114 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2115 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
2117 waiting_for_ast
= 0;
2120 /* The standard `sleep' routine works some other way
2121 and it stops working if you have ever quit out of it.
2122 This one continues to work. */
2128 static int zero
= 0;
2129 static int large
= -10000000;
2131 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
2134 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
2135 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
2153 croak ("request sigio");
2159 croak ("unrequest sigio");
2164 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2169 #ifndef SYSTEM_MALLOC
2176 /* Some systems that cannot dump also cannot implement these. */
2179 * Return the address of the start of the text segment prior to
2180 * doing an unexec. After unexec the return value is undefined.
2181 * See crt0.c for further explanation and _start.
2185 #ifndef HAVE_TEXT_START
2190 return ((char *) TEXT_START
);
2194 return ((char *) csrt
);
2195 #else /* not GOULD */
2196 extern int _start ();
2197 return ((char *) _start
);
2199 #endif /* TEXT_START */
2201 #endif /* not HAVE_TEXT_START */
2204 * Return the address of the start of the data segment prior to
2205 * doing an unexec. After unexec the return value is undefined.
2206 * See crt0.c for further information and definition of data_start.
2208 * Apparently, on BSD systems this is etext at startup. On
2209 * USG systems (swapping) this is highly mmu dependent and
2210 * is also dependent on whether or not the program is running
2211 * with shared text. Generally there is a (possibly large)
2212 * gap between end of text and start of data with shared text.
2214 * On Uniplus+ systems with shared text, data starts at a
2215 * fixed address. Each port (from a given oem) is generally
2216 * different, and the specific value of the start of data can
2217 * be obtained via the UniPlus+ specific "uvar" system call,
2218 * however the method outlined in crt0.c seems to be more portable.
2220 * Probably what will have to happen when a USG unexec is available,
2221 * at least on UniPlus, is temacs will have to be made unshared so
2222 * that text and data are contiguous. Then once loadup is complete,
2223 * unexec will produce a shared executable where the data can be
2224 * at the normal shared text boundary and the startofdata variable
2225 * will be patched by unexec to the correct value.
2233 return ((char *) DATA_START
);
2235 #ifdef ORDINARY_LINK
2237 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
2238 * data_start isn't defined. We take the address of environ, which
2239 * is known to live at or near the start of the system crt0.c, and
2240 * we don't sweat the handful of bytes that might lose.
2242 extern char **environ
;
2244 return ((char *) &environ
);
2246 extern int data_start
;
2247 return ((char *) &data_start
);
2248 #endif /* ORDINARY_LINK */
2249 #endif /* DATA_START */
2251 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
2254 /* Some systems that cannot dump also cannot implement these. */
2257 * Return the address of the end of the text segment prior to
2258 * doing an unexec. After unexec the return value is undefined.
2265 return ((char *) TEXT_END
);
2268 return ((char *) &etext
);
2273 * Return the address of the end of the data segment prior to
2274 * doing an unexec. After unexec the return value is undefined.
2281 return ((char *) DATA_END
);
2284 return ((char *) &edata
);
2288 #endif /* not CANNOT_DUMP */
2290 /* init_system_name sets up the string for the Lisp function
2291 system-name to return. */
2297 extern Lisp_Object Vsystem_name
;
2302 #include <sys/socket.h>
2304 #endif /* HAVE_SOCKETS */
2305 #endif /* not VMS */
2306 #endif /* not BSD4_1 */
2312 Vsystem_name
= build_string (sysname
);
2316 if ((sp
= egetenv ("SYS$NODE")) == 0)
2317 Vsystem_name
= build_string ("vax-vms");
2318 else if ((end
= index (sp
, ':')) == 0)
2319 Vsystem_name
= build_string (sp
);
2321 Vsystem_name
= make_string (sp
, end
- sp
);
2323 #ifndef HAVE_GETHOSTNAME
2326 Vsystem_name
= build_string (uts
.nodename
);
2327 #else /* HAVE_GETHOSTNAME */
2328 unsigned int hostname_size
= 256;
2329 char *hostname
= (char *) alloca (hostname_size
);
2331 /* Try to get the host name; if the buffer is too short, try
2332 again. Apparently, the only indication gethostname gives of
2333 whether the buffer was large enough is the presence or absence
2334 of a '\0' in the string. Eech. */
2337 gethostname (hostname
, hostname_size
- 1);
2338 hostname
[hostname_size
- 1] = '\0';
2340 /* Was the buffer large enough for the '\0'? */
2341 if (strlen (hostname
) < hostname_size
- 1)
2344 hostname_size
<<= 1;
2345 hostname
= (char *) alloca (hostname_size
);
2348 /* Turn the hostname into the official, fully-qualified hostname.
2349 Don't do this if we're going to dump; this can confuse system
2350 libraries on some machines and make the dumped emacs core dump. */
2353 #endif /* not CANNOT_DUMP */
2354 if (! index (hostname
, '.'))
2358 for (count
= 0;; count
++)
2363 hp
= gethostbyname (hostname
);
2365 if (! (hp
== 0 && h_errno
== TRY_AGAIN
))
2370 Fsleep_for (make_number (1), Qnil
);
2374 char *fqdn
= (char *) hp
->h_name
;
2377 if (!index (fqdn
, '.'))
2379 /* We still don't have a fully qualified domain name.
2380 Try to find one in the list of alternate names */
2381 char **alias
= hp
->h_aliases
;
2382 while (*alias
&& !index (*alias
, '.'))
2389 /* Convert the host name to lower case. */
2390 /* Using ctype.h here would introduce a possible locale
2391 dependence that is probably wrong for hostnames. */
2395 if (*p
>= 'A' && *p
<= 'Z')
2402 #endif /* HAVE_SOCKETS */
2403 /* We used to try using getdomainname here,
2404 but NIIBE Yutaka <gniibe@etl.go.jp> says that
2405 getdomainname gets the NIS/YP domain which often is not the same
2406 as in Internet domain name. */
2407 #if 0 /* Turned off because sysinfo is not really likely to return the
2408 correct Internet domain. */
2409 #if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
2410 if (! index (hostname
, '.'))
2412 /* The hostname is not fully qualified. Append the domain name. */
2414 int hostlen
= strlen (hostname
);
2415 int domain_size
= 256;
2419 char *domain
= (char *) alloca (domain_size
+ 1);
2420 char *fqdn
= (char *) alloca (hostlen
+ 1 + domain_size
+ 1);
2421 int sys_domain_size
= sysinfo (SI_SRPC_DOMAIN
, domain
, domain_size
);
2422 if (sys_domain_size
<= 0)
2424 if (domain_size
< sys_domain_size
)
2426 domain_size
= sys_domain_size
;
2429 strcpy (fqdn
, hostname
);
2430 if (domain
[0] == '.')
2431 strcpy (fqdn
+ hostlen
, domain
);
2432 else if (domain
[0] != 0)
2434 fqdn
[hostlen
] = '.';
2435 strcpy (fqdn
+ hostlen
+ 1, domain
);
2441 #endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
2443 Vsystem_name
= build_string (hostname
);
2444 #endif /* HAVE_GETHOSTNAME */
2449 for (p
= XSTRING (Vsystem_name
)->data
; *p
; p
++)
2450 if (*p
== ' ' || *p
== '\t')
2457 #if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2459 #include "sysselect.h"
2462 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
2463 /* Cause explanatory error message at compile time,
2464 since the select emulation is not good enough for X. */
2465 int *x
= &x_windows_lose_if_no_select_system_call
;
2468 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2469 * Only checks read descriptors.
2471 /* How long to wait between checking fds in select */
2472 #define SELECT_PAUSE 1
2475 /* For longjmp'ing back to read_input_waiting. */
2477 jmp_buf read_alarm_throw
;
2479 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2480 The read_socket_hook function sets this to 1 while it is waiting. */
2482 int read_alarm_should_throw
;
2490 #else /* not BSD4_1 */
2491 signal (SIGALRM
, SIG_IGN
);
2492 #endif /* not BSD4_1 */
2493 if (read_alarm_should_throw
)
2494 longjmp (read_alarm_throw
, 1);
2498 /* Only rfds are checked. */
2500 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2502 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2503 EMACS_TIME
*timeout
;
2505 int ravail
= 0, old_alarm
;
2509 extern int proc_buffered_char
[];
2510 #ifndef subprocesses
2511 int process_tick
= 0, update_tick
= 0;
2513 extern int process_tick
, update_tick
;
2515 SIGTYPE (*old_trap
) ();
2518 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2519 /* If we're using X, then the native select will work; we only need the
2520 emulation for non-X usage. */
2521 if (!NILP (Vwindow_system
))
2522 return select (nfds
, rfds
, wfds
, efds
, timeout
);
2524 timeoutval
= timeout
? EMACS_SECS (*timeout
) : 100000;
2525 local_timeout
= &timeoutval
;
2537 /* If we are looking only for the terminal, with no timeout,
2538 just read it and wait -- that's more efficient. */
2539 if (*local_timeout
== 100000 && process_tick
== update_tick
2540 && FD_ISSET (0, &orfds
))
2543 for (fd
= 1; fd
< nfds
; ++fd
)
2544 if (FD_ISSET (fd
, &orfds
))
2546 if (! detect_input_pending ())
2547 read_input_waiting ();
2553 /* Once a second, till the timer expires, check all the flagged read
2554 * descriptors to see if any input is available. If there is some then
2555 * set the corresponding bit in the return copy of rfds.
2559 register int to_check
, fd
;
2563 for (to_check
= nfds
, fd
= 0; --to_check
>= 0; fd
++)
2565 if (FD_ISSET (fd
, &orfds
))
2567 int avail
= 0, status
= 0;
2570 avail
= detect_input_pending (); /* Special keyboard handler */
2574 status
= ioctl (fd
, FIONREAD
, &avail
);
2575 #else /* no FIONREAD */
2576 /* Hoping it will return -1 if nothing available
2577 or 0 if all 0 chars requested are read. */
2578 if (proc_buffered_char
[fd
] >= 0)
2582 avail
= read (fd
, &buf
, 1);
2584 proc_buffered_char
[fd
] = buf
;
2586 #endif /* no FIONREAD */
2588 if (status
>= 0 && avail
> 0)
2596 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
2598 old_alarm
= alarm (0);
2599 old_trap
= signal (SIGALRM
, select_alarm
);
2601 alarm (SELECT_PAUSE
);
2602 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2603 while (select_alarmed
== 0 && *local_timeout
!= 0
2604 && process_tick
== update_tick
)
2606 /* If we are interested in terminal input,
2607 wait by reading the terminal.
2608 That makes instant wakeup for terminal input at least. */
2609 if (FD_ISSET (0, &orfds
))
2611 read_input_waiting ();
2612 if (detect_input_pending ())
2618 (*local_timeout
) -= SELECT_PAUSE
;
2619 /* Reset the old alarm if there was one */
2621 signal (SIGALRM
, old_trap
);
2624 /* Reset or forge an interrupt for the original handler. */
2625 old_alarm
-= SELECT_PAUSE
;
2627 kill (getpid (), SIGALRM
); /* Fake an alarm with the orig' handler */
2631 if (*local_timeout
== 0) /* Stop on timer being cleared */
2636 #endif /* not WINDOWSNT */
2638 /* Read keyboard input into the standard buffer,
2639 waiting for at least one character. */
2641 /* Make all keyboard buffers much bigger when using a window system. */
2642 #ifdef HAVE_WINDOW_SYSTEM
2643 #define BUFFER_SIZE_FACTOR 16
2645 #define BUFFER_SIZE_FACTOR 1
2649 read_input_waiting ()
2651 struct input_event e
;
2653 extern int quit_char
;
2655 if (read_socket_hook
)
2657 struct input_event buf
[256];
2659 read_alarm_should_throw
= 0;
2660 if (! setjmp (read_alarm_throw
))
2661 nread
= (*read_socket_hook
) (0, buf
, 256, 1);
2665 /* Scan the chars for C-g and store them in kbd_buffer. */
2666 for (i
= 0; i
< nread
; i
++)
2668 kbd_buffer_store_event (&buf
[i
]);
2669 /* Don't look at input that follows a C-g too closely.
2670 This reduces lossage due to autorepeat on C-g. */
2671 if (buf
[i
].kind
== ascii_keystroke
2672 && buf
[i
].code
== quit_char
)
2679 nread
= read (fileno (stdin
), buf
, 1);
2681 /* Scan the chars for C-g and store them in kbd_buffer. */
2682 e
.kind
= ascii_keystroke
;
2683 e
.frame_or_window
= selected_frame
;
2685 for (i
= 0; i
< nread
; i
++)
2687 /* Convert chars > 0177 to meta events if desired.
2688 We do this under the same conditions that read_avail_input does. */
2689 if (read_socket_hook
== 0)
2691 /* If the user says she has a meta key, then believe her. */
2692 if (meta_key
== 1 && (buf
[i
] & 0x80))
2693 e
.modifiers
= meta_modifier
;
2698 XSETINT (e
.code
, buf
[i
]);
2699 kbd_buffer_store_event (&e
);
2700 /* Don't look at input that follows a C-g too closely.
2701 This reduces lossage due to autorepeat on C-g. */
2702 if (buf
[i
] == quit_char
)
2708 #endif /* not HAVE_SELECT */
2709 #endif /* not VMS */
2710 #endif /* not MSDOS */
2714 * Partially emulate 4.2 open call.
2715 * open is defined as this in 4.1.
2717 * - added by Michael Bloom @ Citicorp/TTI
2722 sys_open (path
, oflag
, mode
)
2726 if (oflag
& O_CREAT
)
2727 return creat (path
, mode
);
2729 return open (path
, oflag
);
2738 lmode
= LINTRUP
| lmode
;
2739 ioctl (fd
, TIOCLSET
, &lmode
);
2747 lmode
= ~LINTRUP
& lmode
;
2748 ioctl (0, TIOCLSET
, &lmode
);
2756 interrupts_deferred
= 0;
2764 interrupts_deferred
= 1;
2767 /* still inside #ifdef BSD4_1 */
2770 int sigheld
; /* Mask of held signals */
2776 sigheld
|= sigbit (signum
);
2784 sigheld
|= sigbit (signum
);
2791 sigheld
&= ~sigbit (signum
);
2796 sigfree () /* Free all held signals */
2799 for (i
= 0; i
< NSIG
; i
++)
2800 if (sigheld
& sigbit (i
))
2808 return 1 << (i
- 1);
2810 #endif /* subprocesses */
2813 /* POSIX signals support - DJB */
2814 /* Anyone with POSIX signals should have ANSI C declarations */
2816 #ifdef POSIX_SIGNALS
2818 sigset_t empty_mask
, full_mask
;
2823 sigemptyset (&empty_mask
);
2824 sigfillset (&full_mask
);
2828 sys_signal (int signal_number
, signal_handler_t action
)
2830 struct sigaction new_action
, old_action
;
2831 sigemptyset (&new_action
.sa_mask
);
2832 new_action
.sa_handler
= action
;
2834 /* Emacs mostly works better with restartable system services. If this
2835 * flag exists, we probably want to turn it on here.
2837 new_action
.sa_flags
= SA_RESTART
;
2839 new_action
.sa_flags
= 0;
2841 sigaction (signal_number
, &new_action
, &old_action
);
2842 return (old_action
.sa_handler
);
2846 /* If we're compiling with GCC, we don't need this function, since it
2847 can be written as a macro. */
2849 sys_sigmask (int sig
)
2852 sigemptyset (&mask
);
2853 sigaddset (&mask
, sig
);
2858 /* I'd like to have these guys return pointers to the mask storage in here,
2859 but there'd be trouble if the code was saving multiple masks. I'll be
2860 safe and pass the structure. It normally won't be more than 2 bytes
2864 sys_sigblock (sigset_t new_mask
)
2867 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
2872 sys_sigunblock (sigset_t new_mask
)
2875 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
2880 sys_sigsetmask (sigset_t new_mask
)
2883 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
2887 #endif /* POSIX_SIGNALS */
2895 /* Figure out how many bits the system's random number generator uses.
2896 `random' and `lrand48' are assumed to return 31 usable bits.
2897 BSD `rand' returns a 31 bit value but the low order bits are unusable;
2898 so we'll shift it and treat it like the 15-bit USG `rand'. */
2902 # define RAND_BITS 31
2903 # else /* !HAVE_RANDOM */
2904 # ifdef HAVE_LRAND48
2905 # define RAND_BITS 31
2906 # define random lrand48
2907 # else /* !HAVE_LRAND48 */
2908 # define RAND_BITS 15
2909 # if RAND_MAX == 32767
2910 # define random rand
2911 # else /* RAND_MAX != 32767 */
2912 # if RAND_MAX == 2147483647
2913 # define random() (rand () >> 16)
2914 # else /* RAND_MAX != 2147483647 */
2916 # define random rand
2918 # define random() (rand () >> 16)
2920 # endif /* RAND_MAX != 2147483647 */
2921 # endif /* RAND_MAX != 32767 */
2922 # endif /* !HAVE_LRAND48 */
2923 # endif /* !HAVE_RANDOM */
2924 #endif /* !RAND_BITS */
2931 srandom ((unsigned int)arg
);
2933 # ifdef HAVE_LRAND48
2936 srand ((unsigned int)arg
);
2942 * Build a full Emacs-sized word out of whatever we've got.
2943 * This suffices even for a 64-bit architecture with a 15-bit rand.
2948 long val
= random ();
2949 #if VALBITS > RAND_BITS
2950 val
= (val
<< RAND_BITS
) ^ random ();
2951 #if VALBITS > 2*RAND_BITS
2952 val
= (val
<< RAND_BITS
) ^ random ();
2953 #if VALBITS > 3*RAND_BITS
2954 val
= (val
<< RAND_BITS
) ^ random ();
2955 #if VALBITS > 4*RAND_BITS
2956 val
= (val
<< RAND_BITS
) ^ random ();
2957 #endif /* need at least 5 */
2958 #endif /* need at least 4 */
2959 #endif /* need at least 3 */
2960 #endif /* need at least 2 */
2961 return val
& ((1L << VALBITS
) - 1);
2964 #ifdef WRONG_NAME_INSQUE
2977 /* If any place else asks for the TERM variable,
2978 allow it to be overridden with the EMACS_TERM variable
2979 before attempting to translate the logical name TERM. As a last
2980 resort, ask for VAX C's special idea of the TERM variable. */
2987 static char buf
[256];
2988 static struct dsc$descriptor_s equiv
2989 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
2990 static struct dsc$descriptor_s d_name
2991 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
2994 if (!strcmp (name
, "TERM"))
2996 val
= (char *) getenv ("EMACS_TERM");
3001 d_name
.dsc$w_length
= strlen (name
);
3002 d_name
.dsc$a_pointer
= name
;
3003 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
3005 char *str
= (char *) xmalloc (eqlen
+ 1);
3006 bcopy (buf
, str
, eqlen
);
3008 /* This is a storage leak, but a pain to fix. With luck,
3009 no one will ever notice. */
3012 return (char *) getenv (name
);
3017 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3018 to force a call on the debugger from within the image. */
3023 LIB$
SIGNAL (SS$_DEBUG
);
3029 #ifdef LINK_CRTL_SHARE
3030 #ifdef SHARABLE_LIB_BUG
3031 /* Variables declared noshare and initialized in sharable libraries
3032 cannot be shared. The VMS linker incorrectly forces you to use a private
3033 version which is uninitialized... If not for this "feature", we
3034 could use the C library definition of sys_nerr and sys_errlist. */
3036 char *sys_errlist
[] =
3040 "no such file or directory",
3042 "interrupted system call",
3044 "no such device or address",
3045 "argument list too long",
3046 "exec format error",
3049 "no more processes",
3050 "not enough memory",
3051 "permission denied",
3053 "block device required",
3054 "mount devices busy",
3056 "cross-device link",
3061 "file table overflow",
3062 "too many open files",
3066 "no space left on device",
3068 "read-only file system",
3074 "vax/vms specific error code nontranslatable error"
3076 #endif /* SHARABLE_LIB_BUG */
3077 #endif /* LINK_CRTL_SHARE */
3080 #ifndef HAVE_STRERROR
3086 extern char *sys_errlist
[];
3087 extern int sys_nerr
;
3089 if (errnum
>= 0 && errnum
< sys_nerr
)
3090 return sys_errlist
[errnum
];
3091 return (char *) "Unknown error";
3093 #endif /* not WINDOWSNT */
3094 #endif /* ! HAVE_STRERROR */
3096 #ifdef INTERRUPTIBLE_OPEN
3100 sys_open (path
, oflag
, mode
)
3104 register int rtnval
;
3106 while ((rtnval
= open (path
, oflag
, mode
)) == -1
3107 && (errno
== EINTR
));
3111 #endif /* INTERRUPTIBLE_OPEN */
3113 #ifdef INTERRUPTIBLE_CLOSE
3120 register int rtnval
;
3122 while ((rtnval
= close (fd
)) == -1
3123 && (errno
== EINTR
))
3126 /* If close is interrupted SunOS 4.1 may or may not have closed the
3127 file descriptor. If it did the second close will fail with
3128 errno = EBADF. That means we have succeeded. */
3129 if (rtnval
== -1 && did_retry
&& errno
== EBADF
)
3135 #endif /* INTERRUPTIBLE_CLOSE */
3137 #ifdef INTERRUPTIBLE_IO
3140 sys_read (fildes
, buf
, nbyte
)
3145 register int rtnval
;
3147 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
3148 && (errno
== EINTR
));
3153 sys_write (fildes
, buf
, nbyte
)
3158 register int rtnval
, bytes_written
;
3164 rtnval
= write (fildes
, buf
, nbyte
);
3171 return (bytes_written
? bytes_written
: -1);
3176 bytes_written
+= rtnval
;
3178 return (bytes_written
);
3181 #endif /* INTERRUPTIBLE_IO */
3186 * Substitute fork for vfork on USG flavors.
3194 #endif /* not WINDOWSNT */
3195 #endif /* not HAVE_VFORK */
3199 * All of the following are for USG.
3201 * On USG systems the system calls are INTERRUPTIBLE by signals
3202 * that the user program has elected to catch. Thus the system call
3203 * must be retried in these cases. To handle this without massive
3204 * changes in the source code, we remap the standard system call names
3205 * to names for our own functions in sysdep.c that do the system call
3206 * with retries. Actually, for portability reasons, it is good
3207 * programming practice, as this example shows, to limit all actual
3208 * system calls to a single occurrence in the source. Sure, this
3209 * adds an extra level of function call overhead but it is almost
3210 * always negligible. Fred Fish, Unisoft Systems Inc.
3213 #ifndef HAVE_SYS_SIGLIST
3214 char *sys_siglist
[NSIG
+ 1] =
3217 /* AIX has changed the signals a bit */
3218 "bogus signal", /* 0 */
3219 "hangup", /* 1 SIGHUP */
3220 "interrupt", /* 2 SIGINT */
3221 "quit", /* 3 SIGQUIT */
3222 "illegal instruction", /* 4 SIGILL */
3223 "trace trap", /* 5 SIGTRAP */
3224 "IOT instruction", /* 6 SIGIOT */
3225 "crash likely", /* 7 SIGDANGER */
3226 "floating point exception", /* 8 SIGFPE */
3227 "kill", /* 9 SIGKILL */
3228 "bus error", /* 10 SIGBUS */
3229 "segmentation violation", /* 11 SIGSEGV */
3230 "bad argument to system call", /* 12 SIGSYS */
3231 "write on a pipe with no one to read it", /* 13 SIGPIPE */
3232 "alarm clock", /* 14 SIGALRM */
3233 "software termination signum", /* 15 SIGTERM */
3234 "user defined signal 1", /* 16 SIGUSR1 */
3235 "user defined signal 2", /* 17 SIGUSR2 */
3236 "death of a child", /* 18 SIGCLD */
3237 "power-fail restart", /* 19 SIGPWR */
3238 "bogus signal", /* 20 */
3239 "bogus signal", /* 21 */
3240 "bogus signal", /* 22 */
3241 "bogus signal", /* 23 */
3242 "bogus signal", /* 24 */
3243 "LAN I/O interrupt", /* 25 SIGAIO */
3244 "PTY I/O interrupt", /* 26 SIGPTY */
3245 "I/O intervention required", /* 27 SIGIOINT */
3247 "HFT grant", /* 28 SIGGRANT */
3248 "HFT retract", /* 29 SIGRETRACT */
3249 "HFT sound done", /* 30 SIGSOUND */
3250 "HFT input ready", /* 31 SIGMSG */
3253 "bogus signal", /* 0 */
3254 "hangup", /* 1 SIGHUP */
3255 "interrupt", /* 2 SIGINT */
3256 "quit", /* 3 SIGQUIT */
3257 "illegal instruction", /* 4 SIGILL */
3258 "trace trap", /* 5 SIGTRAP */
3259 "IOT instruction", /* 6 SIGIOT */
3260 "EMT instruction", /* 7 SIGEMT */
3261 "floating point exception", /* 8 SIGFPE */
3262 "kill", /* 9 SIGKILL */
3263 "bus error", /* 10 SIGBUS */
3264 "segmentation violation", /* 11 SIGSEGV */
3265 "bad argument to system call", /* 12 SIGSYS */
3266 "write on a pipe with no one to read it", /* 13 SIGPIPE */
3267 "alarm clock", /* 14 SIGALRM */
3268 "software termination signum", /* 15 SIGTERM */
3269 "user defined signal 1", /* 16 SIGUSR1 */
3270 "user defined signal 2", /* 17 SIGUSR2 */
3271 "death of a child", /* 18 SIGCLD */
3272 "power-fail restart", /* 19 SIGPWR */
3274 "window size change", /* 20 SIGWINCH */
3275 "urgent socket condition", /* 21 SIGURG */
3276 "pollable event occurred", /* 22 SIGPOLL */
3277 "stop (cannot be caught or ignored)", /* 23 SIGSTOP */
3278 "user stop requested from tty", /* 24 SIGTSTP */
3279 "stopped process has been continued", /* 25 SIGCONT */
3280 "background tty read attempted", /* 26 SIGTTIN */
3281 "background tty write attempted", /* 27 SIGTTOU */
3282 "virtual timer expired", /* 28 SIGVTALRM */
3283 "profiling timer expired", /* 29 SIGPROF */
3284 "exceeded cpu limit", /* 30 SIGXCPU */
3285 "exceeded file size limit", /* 31 SIGXFSZ */
3286 "process's lwps are blocked", /* 32 SIGWAITING */
3287 "special signal used by thread library", /* 33 SIGLWP */
3289 "Special Signal Used By CPR", /* 34 SIGFREEZE */
3292 "Special Signal Used By CPR", /* 35 SIGTHAW */
3295 #endif /* not AIX */
3298 #endif /* HAVE_SYS_SIGLIST */
3301 * Warning, this function may not duplicate 4.2 action properly
3302 * under error conditions.
3306 /* In 4.1, param.h fails to define this. */
3307 #define MAXPATHLEN 1024
3316 char *npath
, *spath
;
3317 extern char *getcwd ();
3319 BLOCK_INPUT
; /* getcwd uses malloc */
3320 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
3323 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3324 up to first slash. Should be harmless on other systems. */
3325 while (*npath
&& *npath
!= '/')
3327 strcpy (pathname
, npath
);
3328 free (spath
); /* getcwd uses malloc */
3333 #endif /* HAVE_GETWD */
3336 * Emulate rename using unlink/link. Note that this is
3337 * only partially correct. Also, doesn't enforce restriction
3338 * that files be of same type (regular->regular, dir->dir, etc).
3347 if (access (from
, 0) == 0)
3350 if (link (from
, to
) == 0)
3351 if (unlink (from
) == 0)
3363 /* HPUX curses library references perror, but as far as we know
3364 it won't be called. Anyway this definition will do for now. */
3370 #endif /* not HAVE_PERROR */
3376 * Emulate BSD dup2. First close newd if it already exists.
3377 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3378 * until we are, then close the unsuccessful ones.
3385 register int fd
, ret
;
3390 fd
= fcntl (oldd
, F_DUPFD
, newd
);
3392 error ("can't dup2 (%i,%i) : %s", oldd
, newd
, strerror (errno
));
3399 ret
= dup2 (old
,new);
3405 #endif /* not HAVE_DUP2 */
3408 * Gettimeofday. Simulate as much as possible. Only accurate
3409 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3410 * Only needed when subprocesses are defined.
3415 #ifndef HAVE_GETTIMEOFDAY
3420 gettimeofday (tp
, tzp
)
3422 struct timezone
*tzp
;
3424 extern long time ();
3426 tp
->tv_sec
= time ((long *)0);
3429 tzp
->tz_minuteswest
= -1;
3436 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3439 * This function will go away as soon as all the stubs fixed. (fnf)
3446 printf ("%s not yet implemented\r\n", badfunc
);
3455 char *sys_siglist
[NSIG
+ 1] =
3457 "null signal", /* 0 SIGNULL */
3458 "hangup", /* 1 SIGHUP */
3459 "interrupt", /* 2 SIGINT */
3460 "quit", /* 3 SIGQUIT */
3461 "illegal instruction", /* 4 SIGILL */
3462 "trace trap", /* 5 SIGTRAP */
3463 "abort termination", /* 6 SIGABRT */
3464 "SIGEMT", /* 7 SIGEMT */
3465 "floating point exception", /* 8 SIGFPE */
3466 "kill", /* 9 SIGKILL */
3467 "bus error", /* 10 SIGBUS */
3468 "segmentation violation", /* 11 SIGSEGV */
3469 "bad argument to system call", /* 12 SIGSYS */
3470 "write on a pipe with no reader", /* 13 SIGPIPE */
3471 "alarm clock", /* 14 SIGALRM */
3472 "software termination signal", /* 15 SIGTERM */
3473 "user defined signal 1", /* 16 SIGUSR1 */
3474 "user defined signal 2", /* 17 SIGUSR2 */
3475 "child stopped or terminated", /* 18 SIGCLD */
3476 "power-fail restart", /* 19 SIGPWR */
3477 "window size changed", /* 20 SIGWINCH */
3478 "undefined", /* 21 */
3479 "pollable event occurred", /* 22 SIGPOLL */
3480 "sendable stop signal not from tty", /* 23 SIGSTOP */
3481 "stop signal from tty", /* 24 SIGSTP */
3482 "continue a stopped process", /* 25 SIGCONT */
3483 "attempted background tty read", /* 26 SIGTTIN */
3484 "attempted background tty write", /* 27 SIGTTOU */
3485 "undefined", /* 28 */
3486 "undefined", /* 29 */
3487 "undefined", /* 30 */
3488 "undefined", /* 31 */
3489 "undefined", /* 32 */
3490 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
3491 "I/O is possible", /* 34 SIGIO */
3492 "exceeded cpu time limit", /* 35 SIGXCPU */
3493 "exceeded file size limit", /* 36 SIGXFSZ */
3494 "virtual time alarm", /* 37 SIGVTALRM */
3495 "profiling time alarm", /* 38 SIGPROF */
3496 "undefined", /* 39 */
3497 "file record locks revoked", /* 40 SIGLOST */
3498 "undefined", /* 41 */
3499 "undefined", /* 42 */
3500 "undefined", /* 43 */
3501 "undefined", /* 44 */
3502 "undefined", /* 45 */
3503 "undefined", /* 46 */
3504 "undefined", /* 47 */
3505 "undefined", /* 48 */
3506 "undefined", /* 49 */
3507 "undefined", /* 50 */
3508 "undefined", /* 51 */
3509 "undefined", /* 52 */
3510 "undefined", /* 53 */
3511 "undefined", /* 54 */
3512 "undefined", /* 55 */
3513 "undefined", /* 56 */
3514 "undefined", /* 57 */
3515 "undefined", /* 58 */
3516 "undefined", /* 59 */
3517 "undefined", /* 60 */
3518 "undefined", /* 61 */
3519 "undefined", /* 62 */
3520 "undefined", /* 63 */
3521 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
3527 /* Directory routines for systems that don't have them. */
3529 #ifdef SYSV_SYSTEM_DIR
3533 #if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3537 register DIR *dirp
; /* stream from opendir */
3541 rtnval
= sys_close (dirp
->dd_fd
);
3543 /* Some systems (like Solaris) allocate the buffer and the DIR all
3544 in one block. Why in the world are we freeing this ourselves
3546 #if ! (defined (sun) && defined (USG5_4))
3547 xfree ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
3549 xfree ((char *) dirp
);
3553 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3554 #endif /* SYSV_SYSTEM_DIR */
3556 #ifdef NONSYSTEM_DIR_LIBRARY
3560 char *filename
; /* name of directory */
3562 register DIR *dirp
; /* -> malloc'ed storage */
3563 register int fd
; /* file descriptor for read */
3564 struct stat sbuf
; /* result of fstat */
3566 fd
= sys_open (filename
, 0);
3571 if (fstat (fd
, &sbuf
) < 0
3572 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
3573 || (dirp
= (DIR *) malloc (sizeof (DIR))) == 0)
3577 return 0; /* bad luck today */
3582 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
3589 register DIR *dirp
; /* stream from opendir */
3591 sys_close (dirp
->dd_fd
);
3592 xfree ((char *) dirp
);
3600 ino_t od_ino
; /* inode */
3601 char od_name
[DIRSIZ
]; /* filename */
3603 #endif /* not VMS */
3605 struct direct dir_static
; /* simulated directory contents */
3610 register DIR *dirp
; /* stream from opendir */
3613 register struct olddir
*dp
; /* -> directory data */
3615 register struct dir$_name
*dp
; /* -> directory data */
3616 register struct dir$_version
*dv
; /* -> version data */
3621 if (dirp
->dd_loc
>= dirp
->dd_size
)
3622 dirp
->dd_loc
= dirp
->dd_size
= 0;
3624 if (dirp
->dd_size
== 0 /* refill buffer */
3625 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3629 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
3630 dirp
->dd_loc
+= sizeof (struct olddir
);
3632 if (dp
->od_ino
!= 0) /* not deleted entry */
3634 dir_static
.d_ino
= dp
->od_ino
;
3635 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
3636 dir_static
.d_name
[DIRSIZ
] = '\0';
3637 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3638 dir_static
.d_reclen
= sizeof (struct direct
)
3640 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3641 return &dir_static
; /* -> simulated structure */
3644 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3645 if (dirp
->dd_loc
== 0)
3646 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
3647 : dp
->dir$b_namecount
;
3648 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
3649 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3650 dir_static
.d_namlen
= dp
->dir$b_namecount
;
3651 dir_static
.d_reclen
= sizeof (struct direct
)
3653 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3654 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3655 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
3656 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
3663 /* readdirver is just like readdir except it returns all versions of a file
3664 as separate entries. */
3669 register DIR *dirp
; /* stream from opendir */
3671 register struct dir$_name
*dp
; /* -> directory data */
3672 register struct dir$_version
*dv
; /* -> version data */
3674 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
3675 dirp
->dd_loc
= dirp
->dd_size
= 0;
3677 if (dirp
->dd_size
== 0 /* refill buffer */
3678 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3681 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3682 if (dirp
->dd_loc
== 0)
3683 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
3684 : dp
->dir$b_namecount
;
3685 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
3686 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3687 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
3688 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3689 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3690 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
3691 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3692 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
3698 #endif /* NONSYSTEM_DIR_LIBRARY */
3702 set_file_times (filename
, atime
, mtime
)
3704 EMACS_TIME atime
, mtime
;
3707 struct timeval tv
[2];
3710 return utimes (filename
, tv
);
3711 #else /* not HAVE_UTIMES */
3713 utb
.actime
= EMACS_SECS (atime
);
3714 utb
.modtime
= EMACS_SECS (mtime
);
3715 return utime (filename
, &utb
);
3716 #endif /* not HAVE_UTIMES */
3719 /* mkdir and rmdir functions, for systems which don't have them. */
3723 * Written by Robert Rother, Mariah Corporation, August 1985.
3725 * If you want it, it's yours. All I ask in return is that if you
3726 * figure out how to do this in a Bourne Shell script you send me
3728 * sdcsvax!rmr or rmr@uscd
3730 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3731 * subroutine. 11Mar86; hoptoad!gnu
3733 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3734 * subroutine didn't return EEXIST. It does now.
3740 #ifdef MKDIR_PROTOTYPE
3744 mkdir (dpath
, dmode
)
3749 int cpid
, status
, fd
;
3750 struct stat statbuf
;
3752 if (stat (dpath
, &statbuf
) == 0)
3754 errno
= EEXIST
; /* Stat worked, so it already exists */
3758 /* If stat fails for a reason other than non-existence, return error */
3759 if (errno
!= ENOENT
)
3762 synch_process_alive
= 1;
3763 switch (cpid
= fork ())
3766 case -1: /* Error in fork */
3767 return (-1); /* Errno is set already */
3769 case 0: /* Child process */
3771 * Cheap hack to set mode of new directory. Since this
3772 * child process is going away anyway, we zap its umask.
3773 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3774 * directory. Does anybody care?
3776 status
= umask (0); /* Get current umask */
3777 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
3778 fd
= sys_open ("/dev/null", 2);
3785 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
3786 _exit (-1); /* Can't exec /bin/mkdir */
3788 default: /* Parent process */
3789 wait_for_termination (cpid
);
3792 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3794 errno
= EIO
; /* We don't know why, but */
3795 return -1; /* /bin/mkdir failed */
3800 #endif /* not HAVE_MKDIR */
3807 int cpid
, status
, fd
;
3808 struct stat statbuf
;
3810 if (stat (dpath
, &statbuf
) != 0)
3812 /* Stat just set errno. We don't have to */
3816 synch_process_alive
= 1;
3817 switch (cpid
= fork ())
3820 case -1: /* Error in fork */
3821 return (-1); /* Errno is set already */
3823 case 0: /* Child process */
3824 fd
= sys_open ("/dev/null", 2);
3831 execl ("/bin/rmdir", "rmdir", dpath
, (char *) 0);
3832 _exit (-1); /* Can't exec /bin/rmdir */
3834 default: /* Parent process */
3835 wait_for_termination (cpid
);
3838 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3840 errno
= EIO
; /* We don't know why, but */
3841 return -1; /* /bin/rmdir failed */
3846 #endif /* !HAVE_RMDIR */
3850 /* Functions for VMS */
3852 #include "vms-pwd.h"
3857 /* Return as a string the VMS error string pertaining to STATUS.
3858 Reuses the same static buffer each time it is called. */
3862 int status
; /* VMS status code */
3866 static char buf
[257];
3868 bufadr
[0] = sizeof buf
- 1;
3869 bufadr
[1] = (int) buf
;
3870 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
3871 return "untranslatable VMS error status";
3879 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3880 * not work correctly. (It also doesn't work well in version 2.3.)
3885 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3886 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3890 unsigned short s_buflen
;
3891 unsigned short s_code
;
3893 unsigned short *s_retlenadr
;
3897 #define buflen s.s_buflen
3898 #define code s.s_code
3899 #define bufadr s.s_bufadr
3900 #define retlenadr s.s_retlenadr
3902 #define R_OK 4 /* test for read permission */
3903 #define W_OK 2 /* test for write permission */
3904 #define X_OK 1 /* test for execute (search) permission */
3905 #define F_OK 0 /* test for presence of file */
3908 sys_access (path
, mode
)
3912 static char *user
= NULL
;
3915 /* translate possible directory spec into .DIR file name, so brain-dead
3916 * access can treat the directory like a file. */
3917 if (directory_file_name (path
, dir_fn
))
3921 return access (path
, mode
);
3922 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
3928 unsigned short int dummy
;
3930 static int constant
= ACL$C_FILE
;
3931 DESCRIPTOR (path_desc
, path
);
3932 DESCRIPTOR (user_desc
, user
);
3936 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
3939 acces
|= CHP$M_READ
;
3941 acces
|= CHP$M_WRITE
;
3942 itemlst
[0].buflen
= sizeof (int);
3943 itemlst
[0].code
= CHP$_FLAGS
;
3944 itemlst
[0].bufadr
= (char *) &flags
;
3945 itemlst
[0].retlenadr
= &dummy
;
3946 itemlst
[1].buflen
= sizeof (int);
3947 itemlst
[1].code
= CHP$_ACCESS
;
3948 itemlst
[1].bufadr
= (char *) &acces
;
3949 itemlst
[1].retlenadr
= &dummy
;
3950 itemlst
[2].end
= CHP$_END
;
3951 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
3952 return stat
== SS$_NORMAL
? 0 : -1;
3956 #else /* not VMS4_4 */
3959 #define ACE$M_WRITE 2
3960 #define ACE$C_KEYID 1
3962 static unsigned short memid
, grpid
;
3963 static unsigned int uic
;
3965 /* Called from init_sys_modes, so it happens not very often
3966 but at least each time Emacs is loaded. */
3968 sys_access_reinit ()
3974 sys_access (filename
, type
)
3980 int status
, size
, i
, typecode
, acl_controlled
;
3981 unsigned int *aclptr
, *aclend
, aclbuf
[60];
3982 union prvdef prvmask
;
3984 /* Get UIC and GRP values for protection checking. */
3987 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
3990 memid
= uic
& 0xFFFF;
3994 if (type
!= 2) /* not checking write access */
3995 return access (filename
, type
);
3997 /* Check write protection. */
3999 #define CHECKPRIV(bit) (prvmask.bit)
4000 #define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
4002 /* Find privilege bits */
4003 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
4005 error ("Unable to find privileges: %s", vmserrstr (status
));
4006 if (CHECKPRIV (PRV$V_BYPASS
))
4007 return 0; /* BYPASS enabled */
4009 fab
.fab$b_fac
= FAB$M_GET
;
4010 fab
.fab$l_fna
= filename
;
4011 fab
.fab$b_fns
= strlen (filename
);
4012 fab
.fab$l_xab
= &xab
;
4013 xab
= cc$rms_xabpro
;
4014 xab
.xab$l_aclbuf
= aclbuf
;
4015 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
4016 status
= SYS$
OPEN (&fab
, 0, 0);
4019 SYS$
CLOSE (&fab
, 0, 0);
4020 /* Check system access */
4021 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITABLE (XAB$V_SYS
))
4023 /* Check ACL entries, if any */
4025 if (xab
.xab$w_acllen
> 0)
4028 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
4029 while (*aclptr
&& aclptr
< aclend
)
4031 size
= (*aclptr
& 0xff) / 4;
4032 typecode
= (*aclptr
>> 8) & 0xff;
4033 if (typecode
== ACE$C_KEYID
)
4034 for (i
= size
- 1; i
> 1; i
--)
4035 if (aclptr
[i
] == uic
)
4038 if (aclptr
[1] & ACE$M_WRITE
)
4039 return 0; /* Write access through ACL */
4041 aclptr
= &aclptr
[size
];
4043 if (acl_controlled
) /* ACL specified, prohibits write access */
4046 /* No ACL entries specified, check normal protection */
4047 if (WRITABLE (XAB$V_WLD
)) /* World writable */
4049 if (WRITABLE (XAB$V_GRP
) &&
4050 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
4051 return 0; /* Group writable */
4052 if (WRITABLE (XAB$V_OWN
) &&
4053 (xab
.xab$l_uic
& 0xFFFF) == memid
)
4054 return 0; /* Owner writable */
4056 return -1; /* Not writable */
4058 #endif /* not VMS4_4 */
4061 static char vtbuf
[NAM$C_MAXRSS
+1];
4063 /* translate a vms file spec to a unix path */
4065 sys_translate_vms (vfile
)
4076 /* leading device or logical name is a root directory */
4077 if (p
= strchr (vfile
, ':'))
4086 if (*p
== '[' || *p
== '<')
4088 while (*++vfile
!= *p
+ 2)
4092 if (vfile
[-1] == *p
)
4115 static char utbuf
[NAM$C_MAXRSS
+1];
4117 /* translate a unix path to a VMS file spec */
4119 sys_translate_unix (ufile
)
4142 if (index (&ufile
[1], '/'))
4149 if (index (&ufile
[1], '/'))
4156 if (strncmp (ufile
, "./", 2) == 0)
4163 ufile
++; /* skip the dot */
4164 if (index (&ufile
[1], '/'))
4169 else if (strncmp (ufile
, "../", 3) == 0)
4177 ufile
+= 2; /* skip the dots */
4178 if (index (&ufile
[1], '/'))
4203 extern char *getcwd ();
4205 #define MAXPATHLEN 1024
4207 ptr
= xmalloc (MAXPATHLEN
);
4208 val
= getcwd (ptr
, MAXPATHLEN
);
4214 strcpy (pathname
, ptr
);
4223 long item_code
= JPI$_OWNER
;
4224 unsigned long parent_id
;
4227 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
4230 vaxc$errno
= status
;
4240 return (getgid () << 16) | getuid ();
4244 sys_read (fildes
, buf
, nbyte
)
4249 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
4254 sys_write (fildes
, buf
, nbyte
)
4259 register int nwrote
, rtnval
= 0;
4261 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
4267 return rtnval
? rtnval
: -1;
4268 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
4269 return rtnval
? rtnval
: -1;
4270 return (rtnval
+ nwrote
);
4275 * VAX/VMS VAX C RTL really loses. It insists that records
4276 * end with a newline (carriage return) character, and if they
4277 * don't it adds one (nice of it isn't it!)
4279 * Thus we do this stupidity below.
4283 sys_write (fildes
, buf
, nbytes
)
4286 unsigned int nbytes
;
4293 fstat (fildes
, &st
);
4299 /* Handle fixed-length files with carriage control. */
4300 if (st
.st_fab_rfm
== FAB$C_FIX
4301 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
4303 len
= st
.st_fab_mrs
;
4304 retval
= write (fildes
, p
, min (len
, nbytes
));
4307 retval
++; /* This skips the implied carriage control */
4311 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4312 while (*e
!= '\n' && e
> p
) e
--;
4313 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
4314 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
4316 retval
= write (fildes
, p
, len
);
4327 /* Create file NEW copying its attributes from file OLD. If
4328 OLD is 0 or does not exist, create based on the value of
4331 /* Protection value the file should ultimately have.
4332 Set by create_copy_attrs, and use by rename_sansversions. */
4333 static unsigned short int fab_final_pro
;
4336 creat_copy_attrs (old
, new)
4339 struct FAB fab
= cc$rms_fab
;
4340 struct XABPRO xabpro
;
4341 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
4342 extern int vms_stmlf_recfm
;
4346 fab
.fab$b_fac
= FAB$M_GET
;
4347 fab
.fab$l_fna
= old
;
4348 fab
.fab$b_fns
= strlen (old
);
4349 fab
.fab$l_xab
= (char *) &xabpro
;
4350 xabpro
= cc$rms_xabpro
;
4351 xabpro
.xab$l_aclbuf
= aclbuf
;
4352 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
4353 /* Call $OPEN to fill in the fab & xabpro fields. */
4354 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4356 SYS$
CLOSE (&fab
, 0, 0);
4357 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
4358 if (xabpro
.xab$w_acllen
> 0)
4360 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
4361 /* If the acl buffer was too short, redo open with longer one.
4362 Wouldn't need to do this if there were some system imposed
4363 limit on the size of an ACL, but I can't find any such. */
4365 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
4366 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
4367 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4368 SYS$
CLOSE (&fab
, 0, 0);
4374 xabpro
.xab$l_aclbuf
= 0;
4379 fab
.fab$l_fna
= new;
4380 fab
.fab$b_fns
= strlen (new);
4384 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
4385 fab
.fab$b_rat
= FAB$M_CR
;
4388 /* Set the file protections such that we will be able to manipulate
4389 this file. Once we are done writing and renaming it, we will set
4390 the protections back. */
4392 fab_final_pro
= xabpro
.xab$w_pro
;
4394 SYS$
SETDFPROT (0, &fab_final_pro
);
4395 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
4397 /* Create the new file with either default attrs or attrs copied
4399 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
4401 SYS$
CLOSE (&fab
, 0, 0);
4402 /* As this is a "replacement" for creat, return a file descriptor
4403 opened for writing. */
4404 return open (new, O_WRONLY
);
4409 #include <varargs.h>
4412 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4417 sys_creat (va_alist
)
4420 va_list list_incrementer
;
4423 int rfd
; /* related file descriptor */
4424 int fd
; /* Our new file descriptor */
4431 extern int vms_stmlf_recfm
;
4434 va_start (list_incrementer
);
4435 name
= va_arg (list_incrementer
, char *);
4436 mode
= va_arg (list_incrementer
, int);
4438 rfd
= va_arg (list_incrementer
, int);
4439 va_end (list_incrementer
);
4442 /* Use information from the related file descriptor to set record
4443 format of the newly created file. */
4444 fstat (rfd
, &st_buf
);
4445 switch (st_buf
.st_fab_rfm
)
4448 strcpy (rfm
, "rfm = fix");
4449 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
4450 strcpy (rat
, "rat = ");
4451 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4453 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4454 strcat (rat
, "ftn");
4455 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4456 strcat (rat
, "prn");
4457 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4458 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4459 strcat (rat
, ", blk");
4461 strcat (rat
, "blk");
4462 return creat (name
, 0, rfm
, rat
, mrs
);
4465 strcpy (rfm
, "rfm = vfc");
4466 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
4467 strcpy (rat
, "rat = ");
4468 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4470 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4471 strcat (rat
, "ftn");
4472 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4473 strcat (rat
, "prn");
4474 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4475 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4476 strcat (rat
, ", blk");
4478 strcat (rat
, "blk");
4479 return creat (name
, 0, rfm
, rat
, fsz
);
4482 strcpy (rfm
, "rfm = stm");
4486 strcpy (rfm
, "rfm = stmcr");
4490 strcpy (rfm
, "rfm = stmlf");
4494 strcpy (rfm
, "rfm = udf");
4498 strcpy (rfm
, "rfm = var");
4501 strcpy (rat
, "rat = ");
4502 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4504 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4505 strcat (rat
, "ftn");
4506 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4507 strcat (rat
, "prn");
4508 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4509 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4510 strcat (rat
, ", blk");
4512 strcat (rat
, "blk");
4516 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
4517 strcpy (rat
, "rat=cr");
4519 /* Until the VAX C RTL fixes the many bugs with modes, always use
4520 mode 0 to get the user's default protection. */
4521 fd
= creat (name
, 0, rfm
, rat
);
4522 if (fd
< 0 && errno
== EEXIST
)
4524 if (unlink (name
) < 0)
4525 report_file_error ("delete", build_string (name
));
4526 fd
= creat (name
, 0, rfm
, rat
);
4532 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4534 sys_fwrite (ptr
, size
, num
, fp
)
4535 register char * ptr
;
4538 register int tot
= num
* size
;
4546 * The VMS C library routine creat actually creates a new version of an
4547 * existing file rather than truncating the old version. There are times
4548 * when this is not the desired behavior, for instance, when writing an
4549 * auto save file (you only want one version), or when you don't have
4550 * write permission in the directory containing the file (but the file
4551 * itself is writable). Hence this routine, which is equivalent to
4552 * "close (creat (fn, 0));" on Unix if fn already exists.
4558 struct FAB xfab
= cc$rms_fab
;
4559 struct RAB xrab
= cc$rms_rab
;
4562 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
4563 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
4564 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
4565 xfab
.fab$l_fna
= fn
;
4566 xfab
.fab$b_fns
= strlen (fn
);
4567 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
4569 xrab
.rab$l_fab
= &xfab
;
4571 /* This gibberish opens the file, positions to the first record, and
4572 deletes all records from there until the end of file. */
4573 if ((SYS$
OPEN (&xfab
) & 01) == 01)
4575 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
4576 (SYS$
FIND (&xrab
) & 01) == 01 &&
4577 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
4588 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4589 SYSPRV or a readable SYSUAF.DAT. */
4595 * Routine to read the VMS User Authorization File and return
4596 * a specific user's record.
4599 static struct UAF retuaf
;
4602 get_uaf_name (uname
)
4609 uaf_fab
= cc$rms_fab
;
4610 uaf_rab
= cc$rms_rab
;
4611 /* initialize fab fields */
4612 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4613 uaf_fab
.fab$b_fns
= 21;
4614 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4615 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4616 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4617 /* initialize rab fields */
4618 uaf_rab
.rab$l_fab
= &uaf_fab
;
4619 /* open the User Authorization File */
4620 status
= SYS$
OPEN (&uaf_fab
);
4624 vaxc$errno
= status
;
4627 status
= SYS$
CONNECT (&uaf_rab
);
4631 vaxc$errno
= status
;
4634 /* read the requested record - index is in uname */
4635 uaf_rab
.rab$l_kbf
= uname
;
4636 uaf_rab
.rab$b_ksz
= strlen (uname
);
4637 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4638 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4639 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4640 status
= SYS$
GET (&uaf_rab
);
4644 vaxc$errno
= status
;
4647 /* close the User Authorization File */
4648 status
= SYS$
DISCONNECT (&uaf_rab
);
4652 vaxc$errno
= status
;
4655 status
= SYS$
CLOSE (&uaf_fab
);
4659 vaxc$errno
= status
;
4673 uaf_fab
= cc$rms_fab
;
4674 uaf_rab
= cc$rms_rab
;
4675 /* initialize fab fields */
4676 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4677 uaf_fab
.fab$b_fns
= 21;
4678 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4679 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4680 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4681 /* initialize rab fields */
4682 uaf_rab
.rab$l_fab
= &uaf_fab
;
4683 /* open the User Authorization File */
4684 status
= SYS$
OPEN (&uaf_fab
);
4688 vaxc$errno
= status
;
4691 status
= SYS$
CONNECT (&uaf_rab
);
4695 vaxc$errno
= status
;
4698 /* read the requested record - index is in uic */
4699 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
4700 uaf_rab
.rab$l_kbf
= (char *) &uic
;
4701 uaf_rab
.rab$b_ksz
= sizeof uic
;
4702 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4703 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4704 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4705 status
= SYS$
GET (&uaf_rab
);
4709 vaxc$errno
= status
;
4712 /* close the User Authorization File */
4713 status
= SYS$
DISCONNECT (&uaf_rab
);
4717 vaxc$errno
= status
;
4720 status
= SYS$
CLOSE (&uaf_fab
);
4724 vaxc$errno
= status
;
4730 static struct passwd retpw
;
4738 /* copy these out first because if the username is 32 chars, the next
4739 section will overwrite the first byte of the UIC */
4740 retpw
.pw_uid
= up
->uaf$w_mem
;
4741 retpw
.pw_gid
= up
->uaf$w_grp
;
4743 /* I suppose this is not the best style, to possibly overwrite one
4744 byte beyond the end of the field, but what the heck... */
4745 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
4746 while (ptr
[-1] == ' ')
4749 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
4751 /* the rest of these are counted ascii strings */
4752 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
4753 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
4754 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
4755 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
4756 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
4757 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
4758 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
4759 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
4763 #else /* not READ_SYSUAF */
4764 static struct passwd retpw
;
4765 #endif /* not READ_SYSUAF */
4776 unsigned char * full
;
4777 #endif /* READ_SYSUAF */
4782 if ('a' <= *ptr
&& *ptr
<= 'z')
4787 if (!(up
= get_uaf_name (name
)))
4789 return cnv_uaf_pw (up
);
4791 if (strcmp (name
, getenv ("USER")) == 0)
4793 retpw
.pw_uid
= getuid ();
4794 retpw
.pw_gid
= getgid ();
4795 strcpy (retpw
.pw_name
, name
);
4796 if (full
= egetenv ("FULLNAME"))
4797 strcpy (retpw
.pw_gecos
, full
);
4799 *retpw
.pw_gecos
= '\0';
4800 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
4801 *retpw
.pw_shell
= '\0';
4806 #endif /* not READ_SYSUAF */
4816 if (!(up
= get_uaf_uic (uid
)))
4818 return cnv_uaf_pw (up
);
4820 if (uid
== sys_getuid ())
4821 return getpwnam (egetenv ("USER"));
4824 #endif /* not READ_SYSUAF */
4827 /* return total address space available to the current process. This is
4828 the sum of the current p0 size, p1 size and free page table entries
4834 unsigned long free_pages
;
4835 unsigned long frep0va
;
4836 unsigned long frep1va
;
4839 item_code
= JPI$_FREPTECNT
;
4840 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
4843 vaxc$errno
= status
;
4848 item_code
= JPI$_FREP0VA
;
4849 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
4852 vaxc$errno
= status
;
4855 item_code
= JPI$_FREP1VA
;
4856 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
4859 vaxc$errno
= status
;
4863 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
4867 define_logical_name (varname
, string
)
4871 struct dsc$descriptor_s strdsc
=
4872 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
4873 struct dsc$descriptor_s envdsc
=
4874 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4875 struct dsc$descriptor_s lnmdsc
=
4876 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4878 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
4882 delete_logical_name (varname
)
4885 struct dsc$descriptor_s envdsc
=
4886 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4887 struct dsc$descriptor_s lnmdsc
=
4888 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4890 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
4908 error ("execvp system call not implemented");
4917 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
4918 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
4919 char from_esn
[NAM$C_MAXRSS
];
4920 char to_esn
[NAM$C_MAXRSS
];
4922 from_fab
.fab$l_fna
= from
;
4923 from_fab
.fab$b_fns
= strlen (from
);
4924 from_fab
.fab$l_nam
= &from_nam
;
4925 from_fab
.fab$l_fop
= FAB$M_NAM
;
4927 from_nam
.nam$l_esa
= from_esn
;
4928 from_nam
.nam$b_ess
= sizeof from_esn
;
4930 to_fab
.fab$l_fna
= to
;
4931 to_fab
.fab$b_fns
= strlen (to
);
4932 to_fab
.fab$l_nam
= &to_nam
;
4933 to_fab
.fab$l_fop
= FAB$M_NAM
;
4935 to_nam
.nam$l_esa
= to_esn
;
4936 to_nam
.nam$b_ess
= sizeof to_esn
;
4938 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
4944 if (status
== RMS$_DEV
)
4948 vaxc$errno
= status
;
4953 /* This function renames a file like `rename', but it strips
4954 the version number from the "to" filename, such that the "to" file is
4955 will always be a new version. It also sets the file protection once it is
4956 finished. The protection that we will use is stored in fab_final_pro,
4957 and was set when we did a creat_copy_attrs to create the file that we
4960 We could use the chmod function, but Eunichs uses 3 bits per user category
4961 to describe the protection, and VMS uses 4 (write and delete are separate
4962 bits). To maintain portability, the VMS implementation of `chmod' wires
4963 the W and D bits together. */
4966 static struct fibdef fib
; /* We need this initialized to zero */
4967 char vms_file_written
[NAM$C_MAXRSS
];
4970 rename_sans_version (from
,to
)
4977 struct FAB to_fab
= cc$rms_fab
;
4978 struct NAM to_nam
= cc$rms_nam
;
4979 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
4980 struct dsc$descriptor fib_attr
[2]
4981 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
4982 char to_esn
[NAM$C_MAXRSS
];
4984 $
DESCRIPTOR (disk
,to_esn
);
4986 to_fab
.fab$l_fna
= to
;
4987 to_fab
.fab$b_fns
= strlen (to
);
4988 to_fab
.fab$l_nam
= &to_nam
;
4989 to_fab
.fab$l_fop
= FAB$M_NAM
;
4991 to_nam
.nam$l_esa
= to_esn
;
4992 to_nam
.nam$b_ess
= sizeof to_esn
;
4994 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
4996 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
4997 *(to_nam
.nam$l_ver
) = '\0';
4999 stat
= rename (from
, to_esn
);
5003 strcpy (vms_file_written
, to_esn
);
5005 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
5006 to_fab
.fab$b_fns
= strlen (vms_file_written
);
5008 /* Now set the file protection to the correct value */
5009 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
5011 /* Copy these fields into the fib */
5012 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
5013 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
5014 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
5016 SYS$
CLOSE (&to_fab
, 0, 0);
5018 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
5021 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
5022 0, 0, 0, &fib_attr
, 0);
5025 stat
= SYS$
DASSGN (chan
);
5028 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
5039 unsigned short fid
[3];
5040 char esa
[NAM$C_MAXRSS
];
5043 fab
.fab$l_fop
= FAB$M_OFP
;
5044 fab
.fab$l_fna
= file
;
5045 fab
.fab$b_fns
= strlen (file
);
5046 fab
.fab$l_nam
= &nam
;
5049 nam
.nam$l_esa
= esa
;
5050 nam
.nam$b_ess
= NAM$C_MAXRSS
;
5052 status
= SYS$
PARSE (&fab
);
5053 if ((status
& 1) == 0)
5056 vaxc$errno
= status
;
5059 status
= SYS$
SEARCH (&fab
);
5060 if ((status
& 1) == 0)
5063 vaxc$errno
= status
;
5067 fid
[0] = nam
.nam$w_fid
[0];
5068 fid
[1] = nam
.nam$w_fid
[1];
5069 fid
[2] = nam
.nam$w_fid
[2];
5071 fab
.fab$l_fna
= new;
5072 fab
.fab$b_fns
= strlen (new);
5074 status
= SYS$
PARSE (&fab
);
5075 if ((status
& 1) == 0)
5078 vaxc$errno
= status
;
5082 nam
.nam$w_fid
[0] = fid
[0];
5083 nam
.nam$w_fid
[1] = fid
[1];
5084 nam
.nam$w_fid
[2] = fid
[2];
5086 nam
.nam$l_esa
= nam
.nam$l_name
;
5087 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
5089 status
= SYS$
ENTER (&fab
);
5090 if ((status
& 1) == 0)
5093 vaxc$errno
= status
;
5104 printf ("%s not yet implemented\r\n", badfunc
);
5112 /* Arrange to return a range centered on zero. */
5113 return rand () - (1 << 30);
5125 /* Called from init_sys_modes. */
5131 /* If we're not on an HFT we shouldn't do any of this. We determine
5132 if we are on an HFT by trying to get an HFT error code. If this
5133 call fails, we're not on an HFT. */
5135 if (ioctl (0, HFQERROR
, &junk
) < 0)
5137 #else /* not IBMR2AIX */
5138 if (ioctl (0, HFQEIO
, 0) < 0)
5140 #endif /* not IBMR2AIX */
5142 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5143 as the rubout key's ASCII code. Here this is changed. The bug is that
5144 there's no way to determine the old mapping, so in reset_sys_modes
5145 we need to assume that the normal map had been present. Of course, this
5146 code also doesn't help if on a terminal emulator which doesn't understand
5150 struct hfkeymap keymap
;
5152 buf
.hf_bufp
= (char *)&keymap
;
5153 buf
.hf_buflen
= sizeof (keymap
);
5154 keymap
.hf_nkeys
= 2;
5155 keymap
.hfkey
[0].hf_kpos
= 15;
5156 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5158 keymap
.hfkey
[0].hf_keyidh
= '<';
5159 #else /* not IBMR2AIX */
5160 keymap
.hfkey
[0].hf_page
= '<';
5161 #endif /* not IBMR2AIX */
5162 keymap
.hfkey
[0].hf_char
= 127;
5163 keymap
.hfkey
[1].hf_kpos
= 15;
5164 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5166 keymap
.hfkey
[1].hf_keyidh
= '<';
5167 #else /* not IBMR2AIX */
5168 keymap
.hfkey
[1].hf_page
= '<';
5169 #endif /* not IBMR2AIX */
5170 keymap
.hfkey
[1].hf_char
= 127;
5171 hftctl (0, HFSKBD
, &buf
);
5173 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5175 line_ins_del_ok
= char_ins_del_ok
= 0;
5178 /* Reset the rubout key to backspace. */
5184 struct hfkeymap keymap
;
5188 if (ioctl (0, HFQERROR
, &junk
) < 0)
5190 #else /* not IBMR2AIX */
5191 if (ioctl (0, HFQEIO
, 0) < 0)
5193 #endif /* not IBMR2AIX */
5195 buf
.hf_bufp
= (char *)&keymap
;
5196 buf
.hf_buflen
= sizeof (keymap
);
5197 keymap
.hf_nkeys
= 2;
5198 keymap
.hfkey
[0].hf_kpos
= 15;
5199 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
5201 keymap
.hfkey
[0].hf_keyidh
= '<';
5202 #else /* not IBMR2AIX */
5203 keymap
.hfkey
[0].hf_page
= '<';
5204 #endif /* not IBMR2AIX */
5205 keymap
.hfkey
[0].hf_char
= 8;
5206 keymap
.hfkey
[1].hf_kpos
= 15;
5207 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
5209 keymap
.hfkey
[1].hf_keyidh
= '<';
5210 #else /* not IBMR2AIX */
5211 keymap
.hfkey
[1].hf_page
= '<';
5212 #endif /* not IBMR2AIX */
5213 keymap
.hfkey
[1].hf_char
= 8;
5214 hftctl (0, HFSKBD
, &buf
);
5221 /* These are included on Sunos 4.1 when we do not use shared libraries.
5222 X11 libraries may refer to these functions but (we hope) do not
5223 actually call them. */
5243 #endif /* USE_DL_STUBS */
5252 register int length
;
5256 long max_str
= 65535;
5258 while (length
> max_str
) {
5259 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5264 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
5266 while (length
-- > 0)
5268 #endif /* not VMS */
5271 #endif /* no bzero */
5272 #endif /* BSTRING */
5274 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
5277 /* Saying `void' requires a declaration, above, where bcopy is used
5278 and that declaration causes pain for systems where bcopy is a macro. */
5279 bcopy (b1
, b2
, length
)
5282 register int length
;
5285 long max_str
= 65535;
5287 while (length
> max_str
) {
5288 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
5294 (void) LIB$
MOVC3 (&length
, b1
, b2
);
5296 while (length
-- > 0)
5298 #endif /* not VMS */
5300 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
5305 bcmp (b1
, b2
, length
) /* This could be a macro! */
5308 register int length
;
5311 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
5312 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
5314 return STR$
COMPARE (&src1
, &src2
);
5316 while (length
-- > 0)
5321 #endif /* not VMS */
5323 #endif /* no bcmp */
5324 #endif /* not BSTRING */
5326 /* All the Macintosh stuffs go here */
5331 #include <MacTypes.h>
5332 #include <TextUtils.h>
5333 #include <Folders.h>
5336 #include <sys/stat.h>
5339 #include <sys/param.h>
5341 /* Convert a Mac pathname to Unix form. A Mac full pathname is one
5342 that does not begin with a ':' and contains at least one ':'. A Mac
5343 full pathname causes an '/' to be prepended to the Unix pathname.
5344 The algorithm for the rest of the pathname is as follows:
5345 For each segment between two ':',
5346 if it is non-null, copy as is and then add a '/' at the end,
5347 otherwise, insert a "../" into the Unix pathname.
5348 Returns 1 if successful; 0 if fails. */
5351 Mac2UnixPathname (const char *mfn
, char *ufn
, int ufnbuflen
)
5353 const char *p
, *q
, *pe
;
5360 p
= strchr (mfn
, ':');
5361 if (p
!= 0 && p
!= mfn
) /* full pathname */
5368 pe
= mfn
+ strlen (mfn
);
5371 q
= strchr (p
, ':');
5375 { /* two consecutive ':' */
5376 if (strlen (ufn
) + 3 >= ufnbuflen
)
5378 strcat (ufn
, "../");
5382 if (strlen (ufn
) + (q
- p
) + 1 >= ufnbuflen
)
5384 strncat (ufn
, p
, q
- p
);
5391 if (strlen (ufn
) + (pe
- p
) >= ufnbuflen
)
5393 strncat (ufn
, p
, pe
- p
); /* no separator for last one */
5401 extern char *GetTempDirName ();
5403 /* Convert a Unix pathname to Mac form. Approximately reverse of the
5404 above in algorithm. */
5406 Unix2MacPathname (const char *ufn
, char *mfn
, int mfnbuflen
)
5408 const char *p
, *q
, *pe
;
5409 char expandedPathname
[MAXPATHLEN
+1];
5418 /* Check for and handle volume names. Last comparison: strangely
5419 somewhere `/.emacs' is passed. A temporary fix for now. */
5420 if (*p
== '/' && strchr (p
+1, '/') == NULL
&& strcmp (p
, "/.emacs") != 0)
5422 if (strlen (p
) + 1 > mfnbuflen
)
5429 if (strncmp (p
, "~emacs/", 7) == 0)
5430 { /* expand to emacs dir found by InitEmacsPasswdDir */
5431 struct passwd
*pw
= getpwnam ("emacs");
5433 if (strlen (pw
->pw_dir
) + strlen (p
) > MAXPATHLEN
)
5435 strcpy (expandedPathname
, pw
->pw_dir
);
5436 strcat (expandedPathname
, p
);
5437 p
= expandedPathname
;
5438 /* Now p points to the pathname with emacs dir prefix. */
5440 else if (strncmp (p
, "/tmp/", 5) == 0)
5442 char *t
= GetTempDirName ();
5444 if (strlen (t
) + strlen (p
) > MAXPATHLEN
)
5446 strcpy (expandedPathname
, t
);
5447 strcat (expandedPathname
, p
);
5448 p
= expandedPathname
;
5449 /* Now p points to the pathname with emacs dir prefix. */
5451 else if (*p
!= '/') /* relative pathname */
5457 pe
= p
+ strlen (p
);
5460 q
= strchr (p
, '/');
5463 if (q
- p
== 2 && *p
== '.' && *(p
+1) == '.')
5465 if (strlen (mfn
) + 1 >= mfnbuflen
)
5471 if (strlen (mfn
) + (q
- p
) + 1 >= mfnbuflen
)
5473 strncat (mfn
, p
, q
- p
);
5480 if (strlen (mfn
) + (pe
- p
) >= mfnbuflen
)
5482 strncat (mfn
, p
, pe
- p
);
5490 /* The following functions with "sys_" prefix are stubs to Unix
5491 functions that have already been implemented by CW or MPW. The
5492 calls to them in Emacs source course are #define'd to call the sys_
5493 versions by the header files s-mac.h. In these stubs pathnames are
5494 converted between their Unix and Mac forms. */
5495 /* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5497 #define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5499 /* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5501 #define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5503 /* Define our own stat function for both MrC and CW. The reason for
5504 doing this: "stat" is both the name of a struct and function name:
5505 can't use the same trick like that for sys_open, sys_close, etc. to
5506 redirect Emacs's calls to our own version that converts Unix style
5507 filenames to Mac style filename because all sorts of compilation
5508 errors will be generated if stat is #define'd to be sys_stat. */
5511 stat (const char *path
, struct stat
*buf
)
5513 char MacPathname
[MAXPATHLEN
+1];
5516 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5519 c2pstr (MacPathname
);
5520 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5521 cipb
.hFileInfo
.ioVRefNum
= 0;
5522 cipb
.hFileInfo
.ioDirID
= 0;
5523 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5525 errno
= PBGetCatInfo (&cipb
, false);
5526 if (errno
== -43) /* -43: fnfErr defined in Errors.h */
5531 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5532 { /* bit 4 = 1 for directories */
5533 buf
->st_mode
= S_IFDIR
| S_IREAD
| S_IEXEC
;
5534 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5535 buf
->st_mode
|= S_IWRITE
;
5536 buf
->st_ino
= cipb
.dirInfo
.ioDrDirID
;
5537 buf
->st_dev
= cipb
.dirInfo
.ioVRefNum
;
5538 buf
->st_size
= cipb
.dirInfo
.ioDrNmFls
; /* size of dir = number of files and dirs */
5539 buf
->st_atime
= buf
->st_mtime
= cipb
.dirInfo
.ioDrMdDat
- MAC_UNIX_EPOCH_DIFF
;
5540 buf
->st_ctime
= cipb
.dirInfo
.ioDrCrDat
- MAC_UNIX_EPOCH_DIFF
;
5544 buf
->st_mode
= S_IFREG
| S_IREAD
;
5545 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x1)) /* bit 1 = 1 for locked files/directories */
5546 buf
->st_mode
|= S_IWRITE
;
5547 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5548 buf
->st_mode
|= S_IEXEC
;
5549 buf
->st_ino
= cipb
.hFileInfo
.ioDirID
;
5550 buf
->st_dev
= cipb
.hFileInfo
.ioVRefNum
;
5551 buf
->st_size
= cipb
.hFileInfo
.ioFlLgLen
;
5552 buf
->st_atime
= buf
->st_mtime
= cipb
.hFileInfo
.ioFlMdDat
- MAC_UNIX_EPOCH_DIFF
;
5553 buf
->st_ctime
= cipb
.hFileInfo
.ioFlCrDat
- MAC_UNIX_EPOCH_DIFF
;
5556 buf
->st_uid
= getuid ();
5557 buf
->st_gid
= getgid ();
5565 /* CW defines fstat in stat.mac.c while MPW does not provide this
5566 function. Without the information of how to get from a file
5567 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5568 to implement this function. Fortunately, there is only one place
5569 where this function is called in our configuration: in fileio.c,
5570 where only the st_dev and st_ino fields are used to determine
5571 whether two fildes point to different i-nodes to prevent copying
5572 a file onto itself equal. What we have here probably needs
5575 fstat (int fildes
, struct stat
*buf
)
5578 buf
->st_ino
= fildes
;
5579 return 0; /* success */
5582 #endif /* __MRC__ */
5584 /* From Think Reference code example */
5586 mkdir (const char *dirname
, int mode
)
5588 #pragma unused (mode)
5591 char MacPathname
[MAXPATHLEN
+1];
5593 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5596 c2pstr (MacPathname
);
5597 hfpb
.ioNamePtr
= MacPathname
;
5598 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5599 hfpb
.ioDirID
= 0; /*parent is the root */
5601 /* Just return the Mac OSErr code for now. */
5602 errno
= PBDirCreate ((HParmBlkPtr
) &hfpb
, false);
5603 return errno
== noErr
? 0 : -1;
5607 rmdir (const char *dirname
)
5610 char MacPathname
[MAXPATHLEN
+1];
5612 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
5615 c2pstr (MacPathname
);
5616 hfpb
.ioNamePtr
= MacPathname
;
5617 hfpb
.ioVRefNum
= 0; /*ignored unless name is invalid */
5618 hfpb
.ioDirID
= 0; /*parent is the root */
5620 errno
= PBHDelete ((HParmBlkPtr
) &hfpb
, false);
5621 return errno
== noErr
? 0 : -1;
5626 /* No implementation yet. */
5628 execvp (const char *path
, ...)
5633 #endif /* __MRC__ */
5636 utime (const char *path
, const struct utimbuf
*times
)
5638 char MacPathname
[MAXPATHLEN
+1];
5641 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5644 c2pstr (MacPathname
);
5645 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5646 cipb
.hFileInfo
.ioVRefNum
= 0;
5647 cipb
.hFileInfo
.ioDirID
= 0;
5648 /* Set to 0 to get information about specific dir or file. */
5649 cipb
.hFileInfo
.ioFDirIndex
= 0;
5651 errno
= PBGetCatInfo (&cipb
, false);
5655 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10)
5656 { /* bit 4 = 1 for directories */
5658 cipb
.dirInfo
.ioDrMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5660 GetDateTime (&cipb
.dirInfo
.ioDrMdDat
);
5665 cipb
.hFileInfo
.ioFlMdDat
= times
->modtime
+ MAC_UNIX_EPOCH_DIFF
;
5667 GetDateTime (&cipb
.hFileInfo
.ioFlMdDat
);
5670 errno
= PBSetCatInfo (&cipb
, false);
5671 return errno
== noErr
? 0 : -1;
5678 /* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5680 access (const char *path
, int mode
)
5682 char MacPathname
[MAXPATHLEN
+1];
5685 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5688 c2pstr (MacPathname
);
5689 cipb
.hFileInfo
.ioNamePtr
= MacPathname
;
5690 cipb
.hFileInfo
.ioVRefNum
= 0;
5691 cipb
.hFileInfo
.ioDirID
= 0;
5692 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
5694 errno
= PBGetCatInfo (&cipb
, false);
5698 if (mode
== F_OK
) /* got this far, file exists */
5702 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* path refers to a directory */
5706 if (cipb
.hFileInfo
.ioFlFndrInfo
.fdType
== 'APPL')
5713 return (cipb
.hFileInfo
.ioFlAttrib
& 0x1) ? -1 : 0; /* don't allow if lock bit on */
5718 #define DEV_NULL_FD 0x10000
5722 sys_open (const char *path
, int oflag
)
5724 char MacPathname
[MAXPATHLEN
+1];
5726 if (strcmp (path
, "/dev/null") == 0)
5727 return DEV_NULL_FD
; /* some bogus fd to be ignored in write */
5729 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5732 return open (MacPathname
, oflag
);
5737 sys_creat (const char *path
, mode_t mode
)
5739 char MacPathname
[MAXPATHLEN
+1];
5741 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5744 return creat (MacPathname
, mode
);
5749 sys_unlink (const char *path
)
5751 char MacPathname
[MAXPATHLEN
+1];
5753 if (Unix2MacPathname (path
, MacPathname
, MAXPATHLEN
+1) == 0)
5756 return unlink (MacPathname
);
5761 sys_read (int fildes
, char *buf
, int count
)
5764 { /* if stdin, call (non-echoing) "getch" in console.h */
5765 if (MacKeyPending ())
5766 { /* don't wait for a key if none has been pressed */
5767 *buf
= MacGetChar ();
5774 return read (fildes
, buf
, count
);
5779 sys_write (int fildes
, char *buf
, int count
)
5781 if (fildes
== DEV_NULL_FD
)
5784 return write (fildes
, buf
, count
);
5789 sys_rename (const char * old_name
, const char * new_name
)
5791 char MacOldName
[MAXPATHLEN
+1], MacNewName
[MAXPATHLEN
+1];
5793 if (strcmp (old_name
, new_name
) == 0)
5796 if (Unix2MacPathname (old_name
, MacOldName
, MAXPATHLEN
+1) == 0)
5799 if (Unix2MacPathname (new_name
, MacNewName
, MAXPATHLEN
+1) == 0)
5802 return rename (MacOldName
, MacNewName
);
5806 extern FILE *fopen (const char *name
, const char *mode
);
5808 sys_fopen (const char *name
, const char *mode
)
5810 char MacPathname
[MAXPATHLEN
+1];
5812 if (Unix2MacPathname (name
, MacPathname
, MAXPATHLEN
+1) == 0)
5815 return fopen (MacPathname
, mode
);
5820 long targetTicks
= 0;
5823 __sigfun alarm_signal_func
= (__sigfun
) 0;
5825 __signal_func_ptr alarm_signal_func
= (__signal_func_ptr
) 0;
5830 /* These functions simulate SIG_ALRM. The stub for function signal
5831 stores the signal handler function in alarm_signal_func if a
5832 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5833 which emacs calls periodically. A pending alarm is represented by
5834 a non-zero targetTicks value. CheckAlarm calls the handler
5835 function pointed to by alarm_signal_func if one has been set up and
5836 an alarm is pending. */
5840 if (targetTicks
&& TickCount () > targetTicks
)
5843 if (alarm_signal_func
)
5844 (*alarm_signal_func
)(SIGALRM
);
5848 /* Called in sys_select to wait for an alarm signal to arrive. */
5852 unsigned long finalTick
;
5854 if (!targetTicks
) /* no alarm pending */
5857 while (TickCount () <= targetTicks
)
5858 Delay (1UL, &finalTick
); /* wait for 1/60 second before trying again */
5861 if (alarm_signal_func
)
5862 (*alarm_signal_func
)(SIGALRM
);
5870 long remaining
= targetTicks
? (TickCount () - targetTicks
) / 60 : 0;
5872 targetTicks
= seconds
? TickCount () + 60 * seconds
: 0;
5874 return (remaining
< 0) ? 0 : (unsigned int) remaining
;
5879 extern __sigfun
signal (int signal
, __sigfun signal_func
);
5881 sys_signal (int signal_num
, __sigfun signal_func
)
5883 extern __signal_func_ptr
signal (int signal
, __signal_func_ptr signal_func
);
5885 sys_signal (int signal_num
, __signal_func_ptr signal_func
)
5890 if (signal_num
!= SIGALRM
)
5891 return signal (signal_num
, signal_func
);
5895 __sigfun old_signal_func
;
5897 __signal_func_ptr old_signal_func
;
5901 old_signal_func
= alarm_signal_func
;
5902 alarm_signal_func
= signal_func
;
5903 return old_signal_func
;
5907 /* The time functions adjust time values according to the difference
5908 between the Unix and CW epoches. */
5911 extern struct tm
*gmtime (const time_t *);
5913 sys_gmtime (const time_t *timer
)
5915 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5917 return gmtime (&unixTime
);
5921 extern struct tm
*localtime (const time_t *);
5923 sys_localtime (const time_t *timer
)
5925 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5927 return localtime (&unixTime
);
5931 extern char *ctime (const time_t *);
5933 sys_ctime (const time_t *timer
)
5935 time_t unixTime
= *timer
+ CW_UNIX_EPOCH_DIFF
;
5937 return ctime (&unixTime
);
5941 extern time_t time (time_t *);
5943 sys_time (time_t *timer
)
5945 time_t macTime
= time (NULL
) - CW_UNIX_EPOCH_DIFF
;
5953 /* no subprocesses, empty wait */
5961 croak (char *badfunc
)
5963 printf ("%s not yet implemented\r\n", badfunc
);
5968 index (const char * str
, int chr
)
5970 return strchr (str
, chr
);
5974 char **environ
= &e
[0];
5977 mktemp (char *template)
5982 len
= strlen (template);
5984 while (k
>= 0 && template[k
] == 'X')
5987 k
++; /* make k index of first 'X' */
5991 /* Zero filled, number of digits equal to the number of X's. */
5992 sprintf (&template[k
], "%0*d", len
-k
, seqnum
++);
6000 /* Emulate getpwuid, getpwnam and others. */
6002 #define PASSWD_FIELD_SIZE 256
6004 static char myPasswdName
[PASSWD_FIELD_SIZE
];
6005 static char myPasswdDir
[MAXPATHLEN
+1];
6007 static struct passwd myPasswd
=
6013 /* Initialized by main () in macterm.c to pathname of emacs directory. */
6014 char emacsPasswdDir
[MAXPATHLEN
+1];
6017 InitEmacsPasswdDir ()
6021 if (getwd (emacsPasswdDir
) && getwd (myPasswdDir
))
6023 /* Need pathname of first ancestor that begins with `emacs' since
6024 Mac emacs application is somewhere in the emacs-20.3 tree. */
6025 int len
= strlen (emacsPasswdDir
);
6026 /* J points to the "/" following the directory name being compared. */
6029 while (i
>= 0 && !found
)
6031 while (i
>= 0 && emacsPasswdDir
[i
] != '/')
6033 if (emacsPasswdDir
[i
] == '/' && i
+5 < len
)
6034 found
= (strncmp (&(emacsPasswdDir
[i
+1]), "emacs", 5) == 0);
6036 emacsPasswdDir
[j
+1] = '\0';
6046 { /* setting to "/" probably won't work,
6047 but set it to something anyway. */
6048 strcpy (emacsPasswdDir
, "/");
6049 strcpy (myPasswdDir
, "/");
6053 static struct passwd emacsPasswd
=
6059 static int myPasswdInited
= 0;
6066 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6067 where Emacs was started. */
6069 ownerName
= (char **) GetResource ('STR ',-16096);
6073 BlockMove ((unsigned char *) *ownerName
,
6074 (unsigned char *) myPasswdName
, *ownerName
[0] + 1);
6075 HUnlock (ownerName
);
6076 p2cstr ((unsigned char *) myPasswdName
);
6079 myPasswdName
[0] = 0;
6083 getpwuid (uid_t uid
)
6085 if (!myPasswdInited
)
6095 getpwnam (const char *name
)
6097 if (strcmp (name
, "emacs") == 0)
6098 return &emacsPasswd
;
6100 if (!myPasswdInited
)
6109 /* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6110 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6138 request_sigio (void)
6149 unrequest_sigio (void)
6153 /* djgpp does not implement pipe either. */
6155 pipe (int _fildes
[2])
6161 /* Hard and symbolic links. */
6163 symlink (const char *name1
, const char *name2
)
6170 link (const char *name1
, const char *name2
)
6177 lstat (const char *path
, struct stat
*sb
)
6179 return stat (path
, sb
);
6183 readlink (const char *path
, char *buf
, int bufsiz
)
6190 umask (mode_t numask
)
6192 static mode_t mask
= 022;
6193 mode_t oldmask
= mask
;
6199 chmod (const char *path
, mode_t mode
)
6201 /* say it always succeed for now */
6209 return fcntl (oldd
, F_DUPFD
, 0);
6211 /* current implementation of fcntl in fcntl.mac.c simply returns old
6213 return fcntl (oldd
, F_DUPFD
);
6219 /* This is from the original sysdep.c. Emulate BSD dup2. First close
6220 newd if it already exists. Then, attempt to dup oldd. If not
6221 successful, call dup2 recursively until we are, then close the
6222 unsuccessful ones. */
6224 dup2 (int oldd
, int newd
)
6235 ret
= dup2 (oldd
, newd
);
6240 /* let it fail for now */
6254 ioctl (int d
, int request
, void *argp
)
6263 if (fildes
>=0 && fildes
<= 2)
6294 sleep (unsigned int seconds
)
6296 unsigned long finalTick
;
6298 Delay (seconds
* 60UL, &finalTick
);
6301 #endif /* __MRC__ */
6310 #endif /* __MWERKS__ */
6312 /* Return the path to the directory in which Emacs can create
6313 temporary files. The MacOS "temporary items" directory cannot be
6314 used because it removes the file written by a process when it
6315 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6316 again not exactly). And of course Emacs needs to read back the
6317 files written by its subprocesses. So here we write the files to a
6318 directory "Emacs" in the Preferences Folder. This directory is
6319 created if it does not exist. */
6323 static char *TempDirName
= NULL
;
6327 Str255 dirName
, fullPath
;
6329 char unixDirName
[MAXPATHLEN
+1];
6332 /* Cache directory name with pointer TempDirName.
6333 Look for it only the first time. */
6336 err
= FindFolder (kOnSystemDisk
, kPreferencesFolderType
,
6337 kCreateFolder
, &vRefNum
, &dirID
);
6342 cpb
.dirInfo
.ioNamePtr
= dirName
;
6343 cpb
.dirInfo
.ioDrParID
= dirID
;
6345 /* Standard ref num to full path name loop */
6347 cpb
.dirInfo
.ioVRefNum
= vRefNum
;
6348 cpb
.dirInfo
.ioFDirIndex
= -1;
6349 cpb
.dirInfo
.ioDrDirID
= cpb
.dirInfo
.ioDrParID
;
6351 err
= PBGetCatInfo (&cpb
, false);
6354 strcat (dirName
, ":");
6355 if (strlen (fullPath
) + strlen (dirName
) <= MAXPATHLEN
)
6357 strcat (dirName
, fullPath
);
6358 strcpy (fullPath
, dirName
);
6363 while (cpb
.dirInfo
.ioDrDirID
!= fsRtDirID
&& err
== noErr
);
6365 if (strlen (fullPath
) + 6 <= MAXPATHLEN
)
6366 strcat (fullPath
, "Emacs:");
6370 if (Mac2UnixPathname (fullPath
, unixDirName
, MAXPATHLEN
+1) == 0)
6373 dir
= opendir (unixDirName
); /* check whether temp directory exists */
6376 else if (mkdir (unixDirName
, 0700) != 0) /* create it if not */
6379 TempDirName
= (char *) malloc (strlen (unixDirName
) + 1);
6380 strcpy (TempDirName
, unixDirName
);
6387 getenv (const char * name
)
6389 if (strcmp (name
, "TERM") == 0)
6391 else if (strcmp (name
, "TERMCAP") == 0)
6392 /* for debugging purpose when code was still outputting to dumb terminal */
6393 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6394 :le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6395 :us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6396 :rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6397 :ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6398 :pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6399 else if (strcmp (name
, "TMPDIR") == 0)
6400 return GetTempDirName ();
6406 /* see Interfaces&Libraries:Interfaces:CIncludes:signal.h */
6407 char *sys_siglist
[] =
6409 "Zero is not a signal!!!",
6411 "Interactive user interrupt", /* 2 */ "BAD",
6412 "Floating point exception", /* 4 */ "BAD", "BAD", "BAD",
6413 "Illegal instruction", /* 8 */ "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD",
6414 "Segment violation", /* 16 */ "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD",
6418 char *sys_siglist
[] =
6420 "Zero is not a signal!!!",
6422 "Floating point exception",
6423 "Illegal instruction",
6424 "Interactive user interrupt",
6425 "Segment violation",
6433 #include <utsname.h>
6436 uname (struct utsname
*name
)
6439 systemName
= GetString (-16413); /* IM - Resource Manager Reference */
6442 BlockMove (*systemName
, name
->nodename
, (*systemName
)[0]+1);
6443 p2cstr (name
->nodename
);
6450 #include <Processes.h>
6453 /* Event class of HLE sent to subprocess. */
6454 const OSType kEmacsSubprocessSend
= 'ESND';
6455 /* Event class of HLE sent back from subprocess. */
6456 const OSType kEmacsSubprocessReply
= 'ERPY';
6459 mystrchr (char *s
, char c
)
6461 while (*s
&& *s
!= c
)
6487 mystrcpy (char *to
, char *from
)
6498 /* Start a Mac subprocess. Arguments for it is passed in argv (null
6499 terminated). The process should run with the default directory
6500 "workdir", read input from "infn", and write output and error to
6501 "outfn" and "errfn", resp. The Process Manager call
6502 LaunchApplication is used to start the subprocess. We use high
6503 level events as the mechanism to pass arguments to the subprocess
6504 and to make Emacs wait for the subprocess to terminate and pass
6505 back a result code. The bulk of the code here packs the arguments
6506 into one message to be passed together with the high level event.
6507 Emacs also sometimes starts a subprocess using a shell to perform
6508 wildcard filename expansion. Since we don't really have a shell on
6509 the Mac, this case is detected and the starting of the shell is
6510 by-passed. We really need to add code here to do filename
6511 expansion to support such functionality. */
6513 run_mac_command (argv
, workdir
, infn
, outfn
, errfn
)
6514 unsigned char **argv
;
6515 const char *workdir
;
6516 const char *infn
, *outfn
, errfn
;
6518 char macappname
[MAXPATHLEN
+1], macworkdir
[MAXPATHLEN
+1];
6519 char macinfn
[MAXPATHLEN
+1], macoutfn
[MAXPATHLEN
+1], macerrfn
[MAXPATHLEN
+1];
6520 int paramlen
, argc
, newargc
, j
, retries
;
6521 char **newargv
, *param
, *p
;
6524 LaunchParamBlockRec lpbr
;
6525 EventRecord sendEvent
, replyEvent
;
6526 RgnHandle cursorRegionHdl
;
6528 unsigned long refCon
, len
;
6530 if (Unix2MacPathname (workdir
, macworkdir
, MAXPATHLEN
+1) == 0)
6532 if (Unix2MacPathname (infn
, macinfn
, MAXPATHLEN
+1) == 0)
6534 if (Unix2MacPathname (outfn
, macoutfn
, MAXPATHLEN
+1) == 0)
6536 if (Unix2MacPathname (errfn
, macerrfn
, MAXPATHLEN
+1) == 0)
6539 paramlen
= strlen (macworkdir
) + strlen (macinfn
) + strlen (macoutfn
) + strlen (macerrfn
) + 4;
6540 /* count nulls at end of strings */
6549 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6550 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6551 j
= strlen (argv
[0]);
6552 if (j
>= 3 && strcmp (argv
[0]+j
-3, "/sh") == 0 && argc
== 3 && strcmp (argv
[1], "-c") == 0)
6554 char *command
, *t
, tempmacpathname
[MAXPATHLEN
+1];
6556 /* The arguments for the command in argv[2] are separated by spaces. Count them and put
6557 the count in newargc. */
6558 command
= (char *) alloca (strlen (argv
[2])+2);
6559 strcpy (command
, argv
[2]);
6560 if (command
[strlen (command
) - 1] != ' ')
6561 strcat (command
, " ");
6565 t
= mystrchr (t
, ' ');
6569 t
= mystrchr (t
+1, ' ');
6572 newargv
= (char **) alloca (sizeof (char *) * newargc
);
6575 for (j
= 0; j
< newargc
; j
++)
6577 newargv
[j
] = (char *) alloca (strlen (t
) + 1);
6578 mystrcpy (newargv
[j
], t
);
6581 paramlen
+= strlen (newargv
[j
]) + 1;
6584 if (strncmp (newargv
[0], "~emacs/", 7) == 0)
6586 if (Unix2MacPathname (newargv
[0], tempmacpathname
, MAXPATHLEN
+1) == 0)
6590 { /* sometimes Emacs call "sh" without a path for the command */
6592 char *t
= (char *) alloca (strlen (newargv
[0]) + 7 + 1);
6593 strcpy (t
, "~emacs/");
6594 strcat (t
, newargv
[0]);
6597 openp (Vexec_path
, build_string (newargv
[0]), EXEC_SUFFIXES
, &path
, 1);
6601 if (Unix2MacPathname (XSTRING (path
)->data
, tempmacpathname
, MAXPATHLEN
+1) == 0)
6604 strcpy (macappname
, tempmacpathname
);
6608 if (Unix2MacPathname (argv
[0], macappname
, MAXPATHLEN
+1) == 0)
6611 newargv
= (char **) alloca (sizeof (char *) * argc
);
6613 for (j
= 1; j
< argc
; j
++)
6615 if (strncmp (argv
[j
], "~emacs/", 7) == 0)
6617 char *t
= strchr (argv
[j
], ' ');
6620 char tempcmdname
[MAXPATHLEN
+1], tempmaccmdname
[MAXPATHLEN
+1];
6621 strncpy (tempcmdname
, argv
[j
], t
-argv
[j
]);
6622 tempcmdname
[t
-argv
[j
]] = '\0';
6623 if (Unix2MacPathname (tempcmdname
, tempmaccmdname
, MAXPATHLEN
+1) == 0)
6625 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
) + strlen (t
) + 1);
6626 strcpy (newargv
[j
], tempmaccmdname
);
6627 strcat (newargv
[j
], t
);
6631 char tempmaccmdname
[MAXPATHLEN
+1];
6632 if (Unix2MacPathname (argv
[j
], tempmaccmdname
, MAXPATHLEN
+1) == 0)
6634 newargv
[j
] = (char *) alloca (strlen (tempmaccmdname
)+1);
6635 strcpy (newargv
[j
], tempmaccmdname
);
6639 newargv
[j
] = argv
[j
];
6640 paramlen
+= strlen (newargv
[j
]) + 1;
6644 /* After expanding all the arguments, we now know the length of the parameter block to be
6645 sent to the subprocess as a message attached to the HLE. */
6646 param
= (char *) malloc (paramlen
+ 1);
6651 *p
++ = newargc
; /* first byte of message contains number of arguments for command */
6652 strcpy (p
, macworkdir
);
6653 p
+= strlen (macworkdir
);
6654 *p
++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6655 strcpy (p
, macinfn
);
6656 p
+= strlen (macinfn
);
6658 strcpy (p
, macoutfn
);
6659 p
+= strlen (macoutfn
);
6661 strcpy (p
, macerrfn
);
6662 p
+= strlen (macerrfn
);
6664 for (j
= 1; j
< newargc
; j
++) {
6665 strcpy (p
, newargv
[j
]);
6666 p
+= strlen (newargv
[j
]);
6670 c2pstr (macappname
);
6672 iErr
= FSMakeFSSpec (0, 0, macappname
, &spec
);
6674 if (iErr
!= noErr
) {
6679 lpbr
.launchBlockID
= extendedBlock
;
6680 lpbr
.launchEPBLength
= extendedBlockLen
;
6681 lpbr
.launchControlFlags
= launchContinue
+ launchNoFileFlags
;
6682 lpbr
.launchAppSpec
= &spec
;
6683 lpbr
.launchAppParameters
= NULL
;
6685 iErr
= LaunchApplication (&lpbr
); /* call the subprocess */
6686 if (iErr
!= noErr
) {
6691 sendEvent
.what
= kHighLevelEvent
;
6692 sendEvent
.message
= kEmacsSubprocessSend
; /* Event ID stored in "where" unused */
6695 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6696 iErr
= PostHighLevelEvent (&sendEvent
, &lpbr
.launchProcessSN
, 0, param
, paramlen
+ 1, receiverIDisPSN
);
6698 while (iErr
== sessClosedErr
&& retries
-- > 0);
6700 if (iErr
!= noErr
) {
6705 cursorRegionHdl
= NewRgn ();
6707 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6709 if (WaitNextEvent (highLevelEventMask
, &replyEvent
, 180, cursorRegionHdl
) && replyEvent
.message
== kEmacsSubprocessReply
)
6712 /* The return code is sent through the refCon */
6713 iErr
= AcceptHighLevelEvent (&targ
, &refCon
, NULL
, &len
);
6714 if (iErr
!= noErr
) {
6715 DisposeHandle ((Handle
) cursorRegionHdl
);
6720 DisposeHandle ((Handle
) cursorRegionHdl
);
6727 opendir (const char *dirname
)
6729 char MacPathname
[MAXPATHLEN
+1];
6734 dirp
= (DIR *) malloc (sizeof (DIR));
6738 /* Handle special case when dirname is "/": sets up for readir to
6739 get all mount volumes. */
6740 if (strcmp (dirname
, "/") == 0) {
6741 dirp
->getting_volumes
= 1; /* special all mounted volumes DIR struct */
6742 dirp
->current_index
= 1; /* index for first volume */
6746 /* Handle typical cases: not accessing all mounted volumes. */
6747 if (Unix2MacPathname (dirname
, MacPathname
, MAXPATHLEN
+1) == 0)
6750 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6751 len
= strlen (MacPathname
);
6752 if (MacPathname
[len
- 1] != ':' && len
< MAXPATHLEN
)
6753 strcat (MacPathname
, ":");
6755 c2pstr (MacPathname
);
6756 cipb
.hFileInfo
.ioNamePtr
= MacPathname
; /* using full pathname so vRefNum and dirID ignored */
6757 cipb
.hFileInfo
.ioVRefNum
= 0;
6758 cipb
.hFileInfo
.ioDirID
= 0;
6759 cipb
.hFileInfo
.ioFDirIndex
= 0; /* set to 0 to get information about specific dir or file */
6761 errno
= PBGetCatInfo (&cipb
, false);
6762 if (errno
!= noErr
) {
6767 if (!(cipb
.hFileInfo
.ioFlAttrib
& 0x10)) /* bit 4 = 1 for directories */
6768 return 0; /* not a directory */
6770 dirp
->dir_id
= cipb
.dirInfo
.ioDrDirID
; /* used later in readdir */
6771 dirp
->getting_volumes
= 0;
6772 dirp
->current_index
= 1; /* index for first file/directory */
6788 HParamBlockRec HPBlock
;
6790 static struct dirent s_dirent
;
6791 static Str255 s_name
;
6794 /* Handle the root directory containing the mounted volumes. Call
6795 PBHGetVInfo specifying an index to obtain the info for a volume.
6796 PBHGetVInfo returns an error when it receives an index beyond the
6797 last volume, at which time we should return a nil dirent struct
6799 if (dp
->getting_volumes
) {
6800 HPBlock
.volumeParam
.ioNamePtr
= s_name
;
6801 HPBlock
.volumeParam
.ioVRefNum
= 0;
6802 HPBlock
.volumeParam
.ioVolIndex
= dp
->current_index
;
6804 errno
= PBHGetVInfo (&HPBlock
, false);
6805 if (errno
!= noErr
) {
6811 strcat (s_name
, "/"); /* need "/" for stat to work correctly */
6813 dp
->current_index
++;
6815 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
;
6816 s_dirent
.d_name
= s_name
;
6821 cipb
.hFileInfo
.ioVRefNum
= 0;
6822 cipb
.hFileInfo
.ioNamePtr
= s_name
; /* location to receive filename returned */
6824 /* return only visible files */
6827 cipb
.hFileInfo
.ioDirID
= dp
->dir_id
; /* directory ID found by opendir */
6828 cipb
.hFileInfo
.ioFDirIndex
= dp
->current_index
;
6830 errno
= PBGetCatInfo (&cipb
, false);
6831 if (errno
!= noErr
) {
6836 /* insist on an visibile entry */
6837 if (cipb
.hFileInfo
.ioFlAttrib
& 0x10) /* directory? */
6838 done
= !(cipb
.dirInfo
.ioDrUsrWds
.frFlags
& fInvisible
);
6840 done
= !(cipb
.hFileInfo
.ioFlFndrInfo
.fdFlags
& fInvisible
);
6842 dp
->current_index
++;
6847 s_dirent
.d_ino
= cipb
.dirInfo
.ioDrDirID
; /* value unimportant: non-zero for valid file */
6848 s_dirent
.d_name
= s_name
;
6857 char MacPathname
[MAXPATHLEN
+1];
6858 Str255 directoryName
;
6862 MacPathname
[0] = '\0';
6863 directoryName
[0] = '\0';
6864 cipb
.dirInfo
.ioDrParID
= 0;
6865 cipb
.dirInfo
.ioNamePtr
= directoryName
; /* empty string = default directory */
6868 cipb
.dirInfo
.ioVRefNum
= 0;
6869 cipb
.dirInfo
.ioFDirIndex
= -1;
6870 cipb
.dirInfo
.ioDrDirID
= cipb
.dirInfo
.ioDrParID
; /* go up to parent each time */
6872 errno
= PBGetCatInfo (&cipb
, false);
6873 if (errno
!= noErr
) {
6878 p2cstr (directoryName
);
6879 strcat (directoryName
, ":");
6880 strcat (directoryName
, MacPathname
); /* attach to front since going up directory tree */
6881 strcpy (MacPathname
, directoryName
);
6882 } while (cipb
.dirInfo
.ioDrDirID
!= fsRtDirID
); /* until volume's root directory */
6884 if (Mac2UnixPathname (MacPathname
, path
, MAXPATHLEN
+1) == 0)
6890 #endif /* macintosh */