1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 1986, 1987, 1988, 1992 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
28 #define min(x,y) ((x) > (y) ? (y) : (x))
30 /* In this file, open, read and write refer to the system calls,
31 not our sugared interfaces sys_open, sys_read and sys_write.
32 Contrariwise, for systems where we use the system calls directly,
33 define sys_read, etc. here as aliases for them. */
36 #define sys_write write
37 #endif /* `read' is not a macro */
43 #define sys_close close
50 #else /* `open' is a macro */
52 #endif /* `open' is a macro */
54 /* Does anyone other than VMS need this? */
56 #define sys_fwrite fwrite
62 #include <sys/types.h>
68 extern char *sys_errlist
[];
91 #define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
95 #ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
96 because the vms compiler doesn't grok `defined' */
104 #endif /* not 4.1 bsd */
106 /* Get DGUX definition for FASYNC - DJB */
108 #include <sys/file.h>
111 #include <sys/ioctl.h>
118 #include <sys/wait.h>
122 #ifdef BROKEN_TIOCGWINSZ
127 #include <sys/utsname.h>
129 #ifndef MEMORY_IN_STRING_H
134 #include <sys/sioctl.h>
137 #include <sys/stream.h>
138 #include <sys/ptem.h>
140 #endif /* TIOCGWINSZ */
143 extern int quit_char
;
147 #include "termhooks.h"
148 #include "termchar.h"
149 #include "termopts.h"
150 #include "dispextern.h"
153 #ifdef NONSYSTEM_DIR_LIBRARY
155 #endif /* NONSYSTEM_DIR_LIBRARY */
157 #include "syssignal.h"
160 static int baud_convert
[] =
165 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
166 1800, 2400, 4800, 9600, 19200, 38400
172 /* The file descriptor for Emacs's input terminal.
173 Under Unix, this is always left zero;
174 under VMS, we place the input channel number here.
175 This allows us to write more code that works for both VMS and Unix. */
180 struct emacs_tty buf
;
185 /* Discarding input is not safe when the input could contain
186 replies from the X server. So don't do it. */
187 if (read_socket_hook
)
192 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
193 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
199 ioctl (0, TIOCFLUSH
, &zero
);
201 #else /* not Apollo */
202 EMACS_GET_TTY (input_fd
, &buf
);
203 EMACS_SET_TTY (input_fd
, &buf
, 0);
204 #endif /* not Apollo */
213 /* Should perhaps error if in batch mode */
215 ioctl (0, TIOCSTI
, &c
);
216 #else /* no TIOCSTI */
217 error ("Cannot stuff terminal input characters in this version of Unix.");
218 #endif /* no TIOCSTI */
232 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
233 &sg
.class, 12, 0, 0, 0, 0 );
234 ospeed
= sg
.xmit_baud
;
239 sg
.c_cflag
= (sg
.c_cflag
& ~CBAUD
) | B9600
;
241 ospeed
= sg
.c_cflag
& CBAUD
;
242 #else /* neither VMS nor TERMIOS */
246 sg
.c_cflag
= (sg
.c_cflag
& ~CBAUD
) | B9600
;
250 ioctl (fd
, TCGETA
, &sg
);
252 ospeed
= sg
.c_cflag
& CBAUD
;
253 #else /* neither VMS nor TERMIOS nor TERMIO */
256 sg
.sg_ospeed
= B9600
;
257 ioctl (0, TIOCGETP
, &sg
);
258 ospeed
= sg
.sg_ospeed
;
259 #endif /* not HAVE_TERMIO */
260 #endif /* not HAVE_TERMIOS */
264 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
265 ? baud_convert
[ospeed
] : 9600);
271 set_exclusive_use (fd
)
275 ioctl (fd
, FIOCLEX
, 0);
277 /* Ok to do nothing if this feature does not exist */
282 wait_without_blocking ()
285 wait3 (0, WNOHANG
| WUNTRACED
, 0);
287 croak ("wait_without_blocking");
289 synch_process_alive
= 0;
292 #endif /* not subprocesses */
294 int wait_debugging
; /* Set nonzero to make following function work under dbx
295 (at least for bsd). */
298 wait_for_termination_signal ()
301 /* Wait for subprocess with process id `pid' to terminate and
302 make sure it will get eliminated (not remain forever as a zombie) */
304 wait_for_termination (pid
)
313 status
= SYS$
FORCEX (&pid
, 0, 0);
317 /* Exit if the process has terminated. */
318 if (!synch_process_alive
)
320 /* Otherwise wait 1 second or until a signal comes in. */
321 signal (SIGALRM
, wait_for_termination_signal
);
325 signal (SIGALRM
, SIG_IGN
);
327 #else /* not subprocesses */
329 if (kill (pid
, 0) < 0)
335 if (status
== pid
|| status
== -1)
338 #endif /* not subprocesses */
345 * flush any pending output
346 * (may flush input as well; it does not matter the way we use it)
349 flush_pending_output (channel
)
353 /* If we try this, we get hit with SIGTTIN, because
354 the child's tty belongs to the child's pgrp. */
357 ioctl (channel
, TCFLSH
, 1);
361 /* 3rd arg should be ignored
362 but some 4.2 kernels actually want the address of an int
363 and nonzero means something different. */
364 ioctl (channel
, TIOCFLUSH
, &zero
);
371 /* Set up the terminal at the other end of a pseudo-terminal that
372 we will be controlling an inferior through.
373 It should not echo or do line-editing, since that is done
374 in Emacs. No padding needed for insertion into an Emacs buffer. */
376 child_setup_tty (out
)
381 EMACS_GET_TTY (out
, &s
);
383 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
384 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
385 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
386 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
387 /* No output delays */
388 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
389 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
390 s
.main
.c_iflag
&= ~IUCLC
; /* Disable map of upper case to lower on
392 s
.main
.c_oflag
&= ~OLCUC
; /* Disable map of lower case to upper on
395 /* Said to be unnecesary: */
396 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
397 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
400 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
401 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
402 s
.main
.c_cc
[VERASE
] = 0377; /* disable erase processing */
403 s
.main
.c_cc
[VKILL
] = 0377; /* disable kill processing */
406 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
410 /* AIX enhanced edit loses NULs, so disable it */
413 s
.main
.c_iflag
&= ~ASCEDIT
;
415 /* Also, PTY overloads NUL and BREAK.
416 don't ignore break, but don't signal either, so it looks like NUL. */
417 s
.main
.c_iflag
&= ~IGNBRK
;
418 s
.main
.c_iflag
&= ~BRKINT
;
419 /* QUIT and INTR work better as signals, so disable character forms */
420 s
.main
.c_cc
[VQUIT
] = 0377;
421 s
.main
.c_cc
[VINTR
] = 0377;
422 s
.main
.c_cc
[VEOL
] = 0377;
423 s
.main
.c_lflag
&= ~ISIG
;
424 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
427 #else /* not HAVE_TERMIO */
429 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
431 s
.main
.sg_erase
= 0377;
432 s
.main
.sg_kill
= 0377;
434 #endif /* not HAVE_TERMIO */
436 EMACS_SET_TTY (out
, &s
, 0);
445 ioctl (out
, FIOASYNC
, &zero
);
451 #endif /* subprocesses */
457 EMACS_SET_TTY_PGRP (input_fd
, &pid
);
460 /* Record a signal code and the handler for it. */
464 SIGTYPE (*handler
) ();
467 /* Suspend the Emacs process; give terminal to its superior. */
472 /* "Foster" parentage allows emacs to return to a subprocess that attached
473 to the current emacs as a cheaper than starting a whole new process. This
474 is set up by KEPTEDITOR.COM. */
475 unsigned long parent_id
, foster_parent_id
;
478 fpid_string
= getenv ("EMACS_PARENT_PID");
479 if (fpid_string
!= NULL
)
481 sscanf (fpid_string
, "%x", &foster_parent_id
);
482 if (foster_parent_id
!= 0)
483 parent_id
= foster_parent_id
;
485 parent_id
= getppid ();
488 parent_id
= getppid ();
490 free (fpid_string
); /* On VMS, this was malloc'd */
492 if (parent_id
&& parent_id
!= 0xffffffff)
494 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
495 int status
= LIB$
ATTACH (&parent_id
) & 1;
496 signal (SIGINT
, oldsig
);
505 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
506 d_prompt
.a
= "Emacs: "; /* Just a reminder */
507 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
514 EMACS_KILLPG (getpgrp (0), SIGTSTP
);
516 #else /* No SIGTSTP */
517 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
518 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
519 kill (getpid (), SIGQUIT
);
521 #else /* No SIGTSTP or USG_JOBCTRL */
523 /* On a system where suspending is not implemented,
524 instead fork a subshell and let it talk directly to the terminal
527 struct save_signal saved_handlers
[5];
529 saved_handlers
[0].code
= SIGINT
;
530 saved_handlers
[1].code
= SIGQUIT
;
531 saved_handlers
[2].code
= SIGTERM
;
533 saved_handlers
[3].code
= SIGIO
;
534 saved_handlers
[4].code
= 0;
536 saved_handlers
[3].code
= 0;
540 error ("Can't spawn subshell");
545 sh
= (char *) egetenv ("SHELL");
548 /* Use our buffer's default directory for the subshell. */
554 /* mentioning current_buffer->buffer would mean including buffer.h,
555 which somehow wedges the hp compiler. So instead... */
557 dir
= intern ("default-directory");
559 if (XFASTINT (Fboundp (dir
)) == XFASTINT (Qnil
))
561 dir
= Fsymbol_value (dir
);
562 if (XTYPE (dir
) != Lisp_String
)
565 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
566 len
= XSTRING (dir
)->size
;
567 bcopy (XSTRING (dir
)->data
, str
, len
);
568 if (str
[len
- 1] != '/') str
[len
++] = '/';
574 close_process_descs (); /* Close Emacs's pipes/ptys */
579 extern int emacs_priority
;
582 nice (-emacs_priority
);
587 write (1, "Can't execute subshell", 22);
591 save_signal_handlers (saved_handlers
);
592 wait_for_termination (pid
);
593 restore_signal_handlers (saved_handlers
);
595 #endif /* no USG_JOBCTRL */
596 #endif /* no SIGTSTP */
600 save_signal_handlers (saved_handlers
)
601 struct save_signal
*saved_handlers
;
603 while (saved_handlers
->code
)
605 saved_handlers
->handler
606 = (SIGTYPE (*) ()) signal (saved_handlers
->code
, SIG_IGN
);
611 restore_signal_handlers (saved_handlers
)
612 struct save_signal
*saved_handlers
;
614 while (saved_handlers
->code
)
616 signal (saved_handlers
->code
, saved_handlers
->handler
);
628 old_fcntl_flags
= fcntl (0, F_GETFL
, 0) & ~FASYNC
;
638 #ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */
643 sigunblock (sigmask (SIGWINCH
));
645 fcntl (0, F_SETFL
, old_fcntl_flags
| FASYNC
);
647 interrupts_deferred
= 0;
653 sigblock (sigmask (SIGWINCH
));
655 fcntl (0, F_SETFL
, old_fcntl_flags
);
656 interrupts_deferred
= 1;
659 #else /* no FASYNC */
660 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
665 ioctl (0, FIOASYNC
, &on
);
666 interrupts_deferred
= 0;
673 ioctl (0, FIOASYNC
, &off
);
674 interrupts_deferred
= 1;
677 #else /* not FASYNC, not STRIDE */
681 croak ("request_sigio");
686 croak ("unrequest_sigio");
693 /* The initial tty mode bits */
694 struct emacs_tty old_tty
;
696 int term_initted
; /* 1 if outer tty status has been recorded */
699 /* BSD 4.1 needs to keep track of the lmode bits in order to start
706 #endif /* F_SETOWN */
708 /* This may also be defined in stdio,
709 but if so, this does no harm,
710 and using the same name avoids wasting the other one's space. */
712 #if defined (USG) || defined (DGUX)
713 unsigned char _sobuf
[BUFSIZ
+8];
719 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
722 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
727 struct emacs_tty tty
;
731 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
732 extern int (*interrupt_signal
) ();
741 input_ef
= get_kbd_event_flag ();
742 /* LIB$GET_EF (&input_ef); */
743 SYS$
CLREF (input_ef
);
746 timer_ef
= get_timer_event_flag ();
747 /* LIB$GET_EF (&timer_ef); */
748 SYS$
CLREF (timer_ef
);
751 LIB$
GET_EF (&process_ef
);
752 SYS$
CLREF (process_ef
);
754 if (input_ef
/ 32 != process_ef
/ 32)
755 croak ("Input and process event flags in different clusters.");
756 if (input_ef
/ 32 != timer_ef
/ 32)
757 croak ("Input and process event flags in different clusters.");
758 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
759 ((unsigned) 1 << (process_ef
% 32));
760 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
761 ((unsigned) 1 << (timer_ef
% 32));
763 sys_access_reinit ();
767 EMACS_GET_TTY (input_fd
, &old_tty
);
769 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
773 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
774 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
775 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
777 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
779 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
780 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
782 tty
.main
.c_iflag
&= ~IEXTEN
; /* Disable other editing characters. */
784 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
787 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
789 tty
.main
.c_iflag
&= ~IXANY
;
793 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
794 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
796 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
800 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
801 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
804 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
805 /* Set up C-g for both SIGQUIT and SIGINT.
806 We don't know which we will get, but we handle both alike
807 so which one it really gives us does not matter. */
808 tty
.main
.c_cc
[VQUIT
] = quit_char
;
809 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
810 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
812 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
815 #if defined (mips) || defined (HAVE_TCATTR)
817 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
820 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
822 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
823 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
825 #endif /* mips or HAVE_TCATTR */
828 /* AIX enhanced edit loses NULs, so disable it */
830 tty
.main
.c_iflag
&= ~ASCEDIT
;
832 tty
.main
.c_cc
[VSTRT
] = 255;
833 tty
.main
.c_cc
[VSTOP
] = 255;
834 tty
.main
.c_cc
[VSUSP
] = 255;
835 tty
.main
.c_cc
[VDSUSP
] = 255;
836 #endif /* IBMR2AIX */
837 /* Also, PTY overloads NUL and BREAK.
838 don't ignore break, but don't signal either, so it looks like NUL.
839 This really serves a purpose only if running in an XTERM window
840 or via TELNET or the like, but does no harm elsewhere. */
841 tty
.main
.c_iflag
&= ~IGNBRK
;
842 tty
.main
.c_iflag
&= ~BRKINT
;
844 #else /* if not HAVE_TERMIO */
846 tty
.main
.tt_char
|= TT$M_NOECHO
;
848 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
850 tty
.main
.tt_char
|= TT$M_TTSYNC
;
852 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
853 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
854 #else /* not VMS (BSD, that is) */
855 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
857 tty
.main
.sg_flags
|= ANYP
;
858 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
859 #endif /* not VMS (BSD, that is) */
860 #endif /* not HAVE_TERMIO */
862 /* If going to use CBREAK mode, we must request C-g to interrupt
863 and turn off start and stop chars, etc. If not going to use
864 CBREAK mode, do this anyway so as to turn off local flow
865 control for user coming over network on 4.2; in this case,
866 only t_stopc and t_startc really matter. */
869 /* Note: if not using CBREAK mode, it makes no difference how we
871 tty
.tchars
= new_tchars
;
872 tty
.tchars
.t_intrc
= quit_char
;
875 tty
.tchars
.t_startc
= '\021';
876 tty
.tchars
.t_stopc
= '\023';
879 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
885 #define LNOFLSH 0100000
888 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
894 #endif /* TIOCGETC */
895 #endif /* not HAVE_TERMIO */
898 tty
.ltchars
= new_ltchars
;
899 #endif /* TIOCGLTC */
901 EMACS_SET_TTY (input_fd
, &tty
, 0);
903 /* This code added to insure that, if flow-control is not to be used,
904 we have an unlocked terminal at the start. */
907 if (!flow_control
) ioctl (0, TCXONC
, 1);
911 if (!flow_control
) ioctl (0, TIOCSTART
, 0);
919 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
920 to be only LF. This is the way that is done. */
923 if (ioctl (1, HFTGETID
, &tty
) != -1)
924 write (1, "\033[20l", 5);
930 /* Appears to do nothing when in PASTHRU mode.
931 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
932 interrupt_signal, oob_chars, 0, 0, 0, 0);
939 #ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */
942 old_fcntl_owner
= fcntl (0, F_GETOWN
, 0);
943 fcntl (0, F_SETOWN
, getpid ());
946 #endif /* F_GETOWN */
954 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
958 /* This symbol is defined on recent USG systems.
959 Someone says without this call USG won't really buffer the file
960 even with a call to setbuf. */
961 setvbuf (stdout
, _sobuf
, _IOFBF
, sizeof _sobuf
);
963 setbuf (stdout
, _sobuf
);
965 set_terminal_modes ();
966 if (term_initted
&& no_redraw_on_reenter
)
968 if (display_completed
)
969 direct_output_forward_char (0);
975 if (FRAMEP (Vterminal_frame
))
976 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
983 /* Return nonzero if safe to use tabs in output.
984 At the time this is called, init_sys_modes has not been done yet. */
988 struct emacs_tty tty
;
990 EMACS_GET_TTY (input_fd
, &tty
);
991 return EMACS_TTY_TABS_OK (&tty
);
994 /* Get terminal size from system.
995 Store number of lines into *heightp and width into *widthp.
996 If zero or a negative number is stored, the value is not valid. */
998 get_frame_size (widthp
, heightp
)
999 int *widthp
, *heightp
;
1005 struct winsize size
;
1007 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1008 *widthp
= *heightp
= 0;
1011 *widthp
= size
.ws_col
;
1012 *heightp
= size
.ws_row
;
1018 /* SunOS - style. */
1019 struct ttysize size
;
1021 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1022 *widthp
= *heightp
= 0;
1025 *widthp
= size
.ts_cols
;
1026 *heightp
= size
.ts_lines
;
1032 struct sensemode tty
;
1034 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1035 &tty
.class, 12, 0, 0, 0, 0);
1036 *widthp
= tty
.scr_wid
;
1037 *heightp
= tty
.scr_len
;
1039 #else /* system doesn't know size */
1044 #endif /* not VMS */
1045 #endif /* not SunOS-style */
1046 #endif /* not BSD-style */
1050 /* Prepare the terminal for exiting Emacs; move the cursor to the
1051 bottom of the frame, turn off interrupt-driven I/O, etc. */
1061 if (read_socket_hook
|| !EQ (Vwindow_system
, Qnil
))
1063 cursor_to (FRAME_HEIGHT (selected_frame
) - 1, 0);
1064 clear_end_of_line (FRAME_WIDTH (selected_frame
));
1065 /* clear_end_of_line may move the cursor */
1066 cursor_to (FRAME_HEIGHT (selected_frame
) - 1, 0);
1069 /* HFT devices normally use ^J as a LF/CR. We forced it to
1070 do the LF only. Now, we need to reset it. */
1073 if (ioctl (1, HFTGETID
, &tty
) != -1)
1074 write (1, "\033[20h", 5);
1078 reset_terminal_modes ();
1082 /* Avoid possible loss of output when changing terminal modes. */
1083 fsync (fileno (stdout
));
1088 #ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */
1089 if (interrupt_input
)
1092 fcntl (0, F_SETOWN
, old_fcntl_owner
);
1094 #endif /* F_SETOWN */
1095 #endif /* F_SETFL */
1097 if (interrupt_input
)
1101 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1111 /* Set up the proper status flags for use of a pty. */
1116 /* I'm told that TOICREMOTE does not mean control chars
1117 "can't be sent" but rather that they don't have
1118 input-editing or signaling effects.
1119 That should be good, because we have other ways
1120 to do those things in Emacs.
1121 However, telnet mode seems not to work on 4.2.
1122 So TIOCREMOTE is turned off now. */
1124 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1125 will hang. In particular, the "timeout" feature (which
1126 causes a read to return if there is no data available)
1127 does this. Also it is known that telnet mode will hang
1128 in such a way that Emacs must be stopped (perhaps this
1129 is the same problem).
1131 If TIOCREMOTE is turned off, then there is a bug in
1132 hp-ux which sometimes loses data. Apparently the
1133 code which blocks the master process when the internal
1134 buffer fills up does not work. Other than this,
1135 though, everything else seems to work fine.
1137 Since the latter lossage is more benign, we may as well
1138 lose that way. -- cph */
1143 ioctl (fd
, FIONBIO
, &on
);
1148 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1149 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1150 /* cause EMACS not to die when it should, i.e., when its own controlling */
1151 /* tty goes away. I've complained to the AIX developers, and they may */
1152 /* change this behavior, but I'm not going to hold my breath. */
1153 signal (SIGHUP
, SIG_IGN
);
1156 #endif /* HAVE_PTYS */
1160 /* Assigning an input channel is done at the start of Emacs execution.
1161 This is called each time Emacs is resumed, also, but does nothing
1162 because input_chain is no longer zero. */
1170 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1176 /* Deassigning the input channel is done before exiting. */
1180 return SYS$
DASSGN (input_fd
);
1185 /* Request reading one character into the keyboard buffer.
1186 This is done as soon as the buffer becomes empty. */
1191 waiting_for_ast
= 0;
1193 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1194 &input_iosb
, kbd_input_ast
, 1,
1195 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1200 /* Ast routine that is called when keyboard input comes in
1201 in accord with the SYS$QIO above. */
1205 register int c
= -1;
1206 int old_errno
= errno
;
1207 extern EMACS_TIME
*input_available_clear_time
;
1209 if (waiting_for_ast
)
1210 SYS$
SETEF (input_ef
);
1211 waiting_for_ast
= 0;
1214 if (input_count
== 25)
1216 printf ("Ast # %d,", input_count
);
1217 printf (" iosb = %x, %x, %x, %x",
1218 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1221 if (input_iosb
.offset
)
1225 printf (", char = 0%o", c
);
1235 /* I don't know what this is doing! The variables buf, cbuf and i are
1236 not declared. This is new from version 18, what does it do?
1239 struct input_event e;
1240 e.kind = ascii_keystroke;
1241 XSET (buf[i].code, Lisp_Int, cbuf[i]);
1242 e.frame = selected_frame;
1243 kbd_buffer_store_event (&e);
1246 if (input_available_clear_time
)
1247 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
1251 /* Wait until there is something in kbd_buffer. */
1253 wait_for_kbd_input ()
1255 extern int have_process_input
, process_exited
;
1257 /* If already something, avoid doing system calls. */
1258 if (detect_input_pending ())
1262 /* Clear a flag, and tell ast routine above to set it. */
1263 SYS$
CLREF (input_ef
);
1264 waiting_for_ast
= 1;
1265 /* Check for timing error: ast happened while we were doing that. */
1266 if (!detect_input_pending ())
1268 /* No timing error: wait for flag to be set. */
1269 set_waiting_for_input (0);
1270 SYS$
WFLOR (input_ef
, input_eflist
);
1271 clear_waiting_for_input (0);
1272 if (!detect_input_pending ())
1273 /* Check for subprocess input availability */
1275 int dsp
= have_process_input
|| process_exited
;
1277 SYS$
CLREF (process_ef
);
1278 if (have_process_input
)
1279 process_command_input ();
1284 update_mode_lines
++;
1285 redisplay_preserve_echo_area ();
1289 waiting_for_ast
= 0;
1292 /* Get rid of any pending QIO, when we are about to suspend
1293 or when we want to throw away pending input.
1294 We wait for a positive sign that the AST routine has run
1295 and therefore there is no I/O request queued when we return.
1296 SYS$SETAST is used to avoid a timing error. */
1301 printf ("At end_kbd_input.\n");
1305 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
1307 SYS$
CANCEL (input_fd
);
1312 /* Clear a flag, and tell ast routine above to set it. */
1313 SYS$
CLREF (input_ef
);
1314 waiting_for_ast
= 1;
1316 SYS$
CANCEL (input_fd
);
1318 SYS$
WAITFR (input_ef
);
1319 waiting_for_ast
= 0;
1322 /* Wait for either input available or time interval expiry. */
1324 input_wait_timeout (timeval
)
1325 int timeval
; /* Time to wait, in seconds */
1328 static int zero
= 0;
1329 static int large
= -10000000;
1331 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
1333 /* If already something, avoid doing system calls. */
1334 if (detect_input_pending ())
1338 /* Clear a flag, and tell ast routine above to set it. */
1339 SYS$
CLREF (input_ef
);
1340 waiting_for_ast
= 1;
1341 /* Check for timing error: ast happened while we were doing that. */
1342 if (!detect_input_pending ())
1344 /* No timing error: wait for flag to be set. */
1346 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
1347 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
1349 waiting_for_ast
= 0;
1352 /* The standard `sleep' routine works some other way
1353 and it stops working if you have ever quit out of it.
1354 This one continues to work. */
1360 static int zero
= 0;
1361 static int large
= -10000000;
1363 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
1366 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
1367 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
1382 croak ("request sigio");
1387 croak ("unrequest sigio");
1392 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1397 #ifndef SYSTEM_MALLOC
1404 /* Some systems that cannot dump also cannot implement these. */
1407 * Return the address of the start of the text segment prior to
1408 * doing an unexec. After unexec the return value is undefined.
1409 * See crt0.c for further explanation and _start.
1413 #ifndef CANNOT_UNEXEC
1418 return ((char *) TEXT_START
);
1422 return ((char *) csrt
);
1423 #else /* not GOULD */
1424 extern int _start ();
1425 return ((char *) _start
);
1427 #endif /* TEXT_START */
1429 #endif /* not CANNOT_UNEXEC */
1432 * Return the address of the start of the data segment prior to
1433 * doing an unexec. After unexec the return value is undefined.
1434 * See crt0.c for further information and definition of data_start.
1436 * Apparently, on BSD systems this is etext at startup. On
1437 * USG systems (swapping) this is highly mmu dependent and
1438 * is also dependent on whether or not the program is running
1439 * with shared text. Generally there is a (possibly large)
1440 * gap between end of text and start of data with shared text.
1442 * On Uniplus+ systems with shared text, data starts at a
1443 * fixed address. Each port (from a given oem) is generally
1444 * different, and the specific value of the start of data can
1445 * be obtained via the UniPlus+ specific "uvar" system call,
1446 * however the method outlined in crt0.c seems to be more portable.
1448 * Probably what will have to happen when a USG unexec is available,
1449 * at least on UniPlus, is temacs will have to be made unshared so
1450 * that text and data are contiguous. Then once loadup is complete,
1451 * unexec will produce a shared executable where the data can be
1452 * at the normal shared text boundry and the startofdata variable
1453 * will be patched by unexec to the correct value.
1461 return ((char *) DATA_START
);
1463 extern int data_start
;
1464 return ((char *) &data_start
);
1467 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1470 /* Some systems that cannot dump also cannot implement these. */
1473 * Return the address of the end of the text segment prior to
1474 * doing an unexec. After unexec the return value is undefined.
1481 return ((char *) TEXT_END
);
1484 return ((char *) &etext
);
1489 * Return the address of the end of the data segment prior to
1490 * doing an unexec. After unexec the return value is undefined.
1497 return ((char *) DATA_END
);
1500 return ((char *) &edata
);
1504 #endif /* not CANNOT_DUMP */
1506 /* Get_system_name returns as its value
1507 a string for the Lisp function system-name to return. */
1513 /* Can't have this within the function since `static' is #defined to
1514 nothing for some USG systems. */
1516 #ifdef HAVE_GETHOSTNAME
1517 static char get_system_name_name
[256];
1518 #else /* not HAVE_GETHOSTNAME */
1519 static struct utsname get_system_name_name
;
1520 #endif /* not HAVE_GETHOSTNAME */
1527 #ifdef HAVE_GETHOSTNAME
1528 gethostname (get_system_name_name
, sizeof (get_system_name_name
));
1529 return get_system_name_name
;
1530 #else /* not HAVE_GETHOSTNAME */
1531 uname (&get_system_name_name
);
1532 return (get_system_name_name
.nodename
);
1533 #endif /* not HAVE_GETHOSTNAME */
1537 #else /* not USG, not 4.1 */
1538 static char system_name_saved
[32];
1541 if ((sp
= egetenv ("SYS$NODE")) == 0)
1547 if ((end
= index (sp
, ':')) != 0)
1550 strcpy (system_name_saved
, sp
);
1552 gethostname (system_name_saved
, sizeof (system_name_saved
));
1553 #endif /* not VMS */
1554 return system_name_saved
;
1555 #endif /* not USG, not 4.1 */
1556 #endif /* not USG */
1562 #ifdef HAVE_X_WINDOWS
1563 /* Cause explanatory error message at compile time,
1564 since the select emulation is not good enough for X. */
1565 int *x
= &x_windows_lose_if_no_select_system_call
;
1568 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1569 * Only checks read descriptors.
1571 /* How long to wait between checking fds in select */
1572 #define SELECT_PAUSE 1
1575 /* For longjmp'ing back to read_input_waiting. */
1577 jmp_buf read_alarm_throw
;
1579 /* Nonzero if the alarm signal should throw back to read_input_waiting.
1580 The read_socket_hook function sets this to 1 while it is waiting. */
1582 int read_alarm_should_throw
;
1590 #else /* not BSD4_1 */
1591 signal (SIGALRM
, SIG_IGN
);
1592 #endif /* not BSD4_1 */
1593 if (read_alarm_should_throw
)
1594 longjmp (read_alarm_throw
, 1);
1597 /* Only rfds are checked. */
1599 select (nfds
, rfds
, wfds
, efds
, timeout
)
1601 int *rfds
, *wfds
, *efds
, *timeout
;
1603 int ravail
= 0, orfds
= 0, old_alarm
;
1604 int timeoutval
= timeout
? *timeout
: 100000;
1605 int *local_timeout
= &timeoutval
;
1606 extern int proc_buffered_char
[];
1607 #ifndef subprocesses
1608 int process_tick
= 0, update_tick
= 0;
1610 extern int process_tick
, update_tick
;
1612 SIGTYPE (*old_trap
) ();
1625 /* If we are looking only for the terminal, with no timeout,
1626 just read it and wait -- that's more efficient. */
1627 if (orfds
== 1 && *local_timeout
== 100000 && process_tick
== update_tick
)
1629 if (! detect_input_pending ())
1630 read_input_waiting ();
1635 /* Once a second, till the timer expires, check all the flagged read
1636 * descriptors to see if any input is available. If there is some then
1637 * set the corresponding bit in the return copy of rfds.
1641 register int to_check
, bit
, fd
;
1645 for (to_check
= nfds
, bit
= 1, fd
= 0; --to_check
>= 0; bit
<<= 1, fd
++)
1649 int avail
= 0, status
= 0;
1652 avail
= detect_input_pending (); /* Special keyboard handler */
1656 status
= ioctl (fd
, FIONREAD
, &avail
);
1657 #else /* no FIONREAD */
1658 /* Hoping it will return -1 if nothing available
1659 or 0 if all 0 chars requested are read. */
1660 if (proc_buffered_char
[fd
] >= 0)
1664 avail
= read (fd
, &buf
, 1);
1666 proc_buffered_char
[fd
] = buf
;
1668 #endif /* no FIONREAD */
1670 if (status
>= 0 && avail
> 0)
1678 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
1680 old_alarm
= alarm (0);
1681 old_trap
= signal (SIGALRM
, select_alarm
);
1683 alarm (SELECT_PAUSE
);
1684 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1685 while (select_alarmed
== 0 && *local_timeout
!= 0
1686 && process_tick
== update_tick
)
1688 /* If we are interested in terminal input,
1689 wait by reading the terminal.
1690 That makes instant wakeup for terminal input at least. */
1693 read_input_waiting ();
1694 if (detect_input_pending ())
1700 (*local_timeout
) -= SELECT_PAUSE
;
1701 /* Reset the old alarm if there was one */
1703 signal (SIGALRM
, old_trap
);
1706 /* Reset or forge an interrupt for the original handler. */
1707 old_alarm
-= SELECT_PAUSE
;
1709 kill (getpid (), SIGALRM
); /* Fake an alarm with the orig' handler */
1713 if (*local_timeout
== 0) /* Stop on timer being cleared */
1719 /* Read keyboard input into the standard buffer,
1720 waiting for at least one character. */
1722 /* Make all keyboard buffers much bigger when using X windows. */
1723 #ifdef HAVE_X_WINDOWS
1724 #define BUFFER_SIZE_FACTOR 16
1726 #define BUFFER_SIZE_FACTOR 1
1729 read_input_waiting ()
1731 char buf
[256 * BUFFER_SIZE_FACTOR
];
1732 struct input_event e
;
1734 extern int quit_char
;
1736 if (read_socket_hook
)
1738 read_alarm_should_throw
= 0;
1739 if (! setjmp (read_alarm_throw
))
1740 nread
= (*read_socket_hook
) (0, buf
, 256 * BUFFER_SIZE_FACTOR
, 1, 0);
1745 nread
= read (fileno (stdin
), buf
, 1);
1747 /* Scan the chars for C-g and store them in kbd_buffer. */
1748 e
.kind
= ascii_keystroke
;
1749 e
.frame
= selected_frame
;
1750 for (i
= 0; i
< nread
; i
++)
1752 XSET (e
.code
, Lisp_Int
, buf
[i
]);
1753 kbd_buffer_store_event (&e
);
1754 /* Don't look at input that follows a C-g too closely.
1755 This reduces lossage due to autorepeat on C-g. */
1756 if (buf
[i
] == quit_char
)
1761 #endif /* not HAVE_SELECT */
1762 #endif /* not VMS */
1766 * Partially emulate 4.2 open call.
1767 * open is defined as this in 4.1.
1769 * - added by Michael Bloom @ Citicorp/TTI
1774 sys_open (path
, oflag
, mode
)
1778 if (oflag
& O_CREAT
)
1779 return creat (path
, mode
);
1781 return open (path
, oflag
);
1788 lmode
= LINTRUP
| lmode
;
1789 ioctl (0, TIOCLSET
, &lmode
);
1796 lmode
= ~LINTRUP
& lmode
;
1797 ioctl (0, TIOCLSET
, &lmode
);
1804 interrupts_deferred
= 0;
1811 interrupts_deferred
= 1;
1814 /* still inside #ifdef BSD4_1 */
1817 int sigheld
; /* Mask of held signals */
1822 sigheld
|= sigbit (signum
);
1829 sigheld
|= sigbit (signum
);
1835 sigheld
&= ~sigbit (signum
);
1839 sigfree () /* Free all held signals */
1842 for (i
= 0; i
< NSIG
; i
++)
1843 if (sigheld
& sigbit (i
))
1850 return 1 << (i
- 1);
1852 #endif /* subprocesses */
1855 /* POSIX signals support - DJB */
1856 /* Anyone with POSIX signals should have ANSI C declarations */
1858 #ifdef POSIX_SIGNALS
1860 sigset_t old_mask
, empty_mask
, full_mask
, temp_mask
;
1861 static struct sigaction new_action
, old_action
;
1865 #ifdef POSIX_SIGNALS
1866 sigemptyset (&signal_empty_mask
);
1867 sigfillset (&signal_full_mask
);
1871 int (*signal_handler_t
) ();
1874 sys_signal (int signal_number
, signal_handler_t action
)
1877 /* This gets us restartable system calls for efficiency.
1878 The "else" code will works as well. */
1879 return (berk_signal (signal_number
, action
));
1881 sigemptyset (&new_action
.sa_mask
);
1882 new_action
.sa_handler
= action
;
1883 new_action
.sa_flags
= NULL
;
1884 sigaction (signal_number
, &new_action
, &old_action
);
1885 return (old_action
.sa_handler
);
1890 /* If we're compiling with GCC, we don't need this function, since it
1891 can be written as a macro. */
1893 sys_sigmask (int sig
)
1896 sigemptyset (&mask
);
1897 sigaddset (&mask
, sig
);
1903 sys_sigpause (sigset_t new_mask
)
1905 /* pause emulating berk sigpause... */
1906 sigsuspend (&new_mask
);
1910 /* I'd like to have these guys return pointers to the mask storage in here,
1911 but there'd be trouble if the code was saving multiple masks. I'll be
1912 safe and pass the structure. It normally won't be more than 2 bytes
1916 sys_sigblock (sigset_t new_mask
)
1919 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
1924 sys_sigunblock (sigset_t new_mask
)
1927 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
1932 sys_sigsetmask (sigset_t new_mask
)
1935 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
1939 #endif /* POSIX_SIGNALS */
1946 register int length
;
1950 long max_str
= 65535;
1952 while (length
> max_str
) {
1953 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
1958 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
1960 while (length
-- > 0)
1962 #endif /* not VMS */
1965 /* Saying `void' requires a declaration, above, where bcopy is used
1966 and that declaration causes pain for systems where bcopy is a macro. */
1967 bcopy (b1
, b2
, length
)
1970 register int length
;
1973 long max_str
= 65535;
1975 while (length
> max_str
) {
1976 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
1982 (void) LIB$
MOVC3 (&length
, b1
, b2
);
1984 while (length
-- > 0)
1986 #endif /* not VMS */
1990 bcmp (b1
, b2
, length
) /* This could be a macro! */
1993 register int length
;
1996 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
1997 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
1999 return STR$
COMPARE (&src1
, &src2
);
2001 while (length
-- > 0)
2006 #endif /* not VMS */
2008 #endif /* not BSTRING */
2012 * The BSD random returns numbers in the range of
2013 * 0 to 2e31 - 1. The USG rand returns numbers in the
2014 * range of 0 to 2e15 - 1. This is probably not significant
2021 /* Arrange to return a range centered on zero. */
2022 return (rand () << 15) + rand () - (1 << 29);
2036 /* Arrange to return a range centered on zero. */
2037 return (rand () << 15) + rand () - (1 << 29);
2047 #ifdef WRONG_NAME_INSQUE
2060 /* If any place else asks for the TERM variable,
2061 allow it to be overridden with the EMACS_TERM variable
2062 before attempting to translate the logical name TERM. As a last
2063 resort, ask for VAX C's special idea of the TERM variable. */
2070 static char buf
[256];
2071 static struct dsc$descriptor_s equiv
2072 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
2073 static struct dsc$descriptor_s d_name
2074 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
2077 if (!strcmp (name
, "TERM"))
2079 val
= (char *) getenv ("EMACS_TERM");
2084 d_name
.dsc$w_length
= strlen (name
);
2085 d_name
.dsc$a_pointer
= name
;
2086 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
2088 char *str
= (char *) xmalloc (eqlen
+ 1);
2089 bcopy (buf
, str
, eqlen
);
2091 /* This is a storage leak, but a pain to fix. With luck,
2092 no one will ever notice. */
2095 return (char *) getenv (name
);
2100 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2101 to force a call on the debugger from within the image. */
2106 LIB$
SIGNAL (SS$_DEBUG
);
2112 #ifdef LINK_CRTL_SHARE
2113 #ifdef SHAREABLE_LIB_BUG
2114 /* Variables declared noshare and initialized in shareable libraries
2115 cannot be shared. The VMS linker incorrectly forces you to use a private
2116 version which is uninitialized... If not for this "feature", we
2117 could use the C library definition of sys_nerr and sys_errlist. */
2119 char *sys_errlist
[] =
2123 "no such file or directory",
2125 "interrupted system call",
2127 "no such device or address",
2128 "argument list too long",
2129 "exec format error",
2132 "no more processes",
2133 "not enough memory",
2134 "permission denied",
2136 "block device required",
2137 "mount devices busy",
2139 "cross-device link",
2144 "file table overflow",
2145 "too many open files",
2149 "no space left on device",
2151 "read-only file system",
2157 "vax/vms specific error code nontranslatable error"
2159 #endif /* SHAREABLE_LIB_BUG */
2160 #endif /* LINK_CRTL_SHARE */
2163 #ifdef INTERRUPTIBLE_OPEN
2167 sys_open (path
, oflag
, mode
)
2171 register int rtnval
;
2173 while ((rtnval
= open (path
, oflag
, mode
)) == -1
2174 && (errno
== EINTR
));
2178 #endif /* INTERRUPTIBLE_OPEN */
2180 #ifdef INTERRUPTIBLE_CLOSE
2185 register int rtnval
;
2187 while ((rtnval
= close (fd
)) == -1
2188 && (errno
== EINTR
));
2192 #endif /* INTERRUPTIBLE_CLOSE */
2194 #ifdef INTERRUPTIBLE_IO
2197 sys_read (fildes
, buf
, nbyte
)
2202 register int rtnval
;
2204 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
2205 && (errno
== EINTR
));
2210 sys_write (fildes
, buf
, nbyte
)
2215 register int rtnval
;
2217 while ((rtnval
= write (fildes
, buf
, nbyte
)) == -1
2218 && (errno
== EINTR
));
2222 #endif /* INTERRUPTIBLE_IO */
2226 * All of the following are for USG.
2228 * On USG systems the system calls are INTERRUPTIBLE by signals
2229 * that the user program has elected to catch. Thus the system call
2230 * must be retried in these cases. To handle this without massive
2231 * changes in the source code, we remap the standard system call names
2232 * to names for our own functions in sysdep.c that do the system call
2233 * with retries. Actually, for portability reasons, it is good
2234 * programming practice, as this example shows, to limit all actual
2235 * system calls to a single occurance in the source. Sure, this
2236 * adds an extra level of function call overhead but it is almost
2237 * always negligible. Fred Fish, Unisoft Systems Inc.
2240 char *sys_siglist
[NSIG
+ 1] =
2243 /* AIX has changed the signals a bit */
2244 "bogus signal", /* 0 */
2245 "hangup", /* 1 SIGHUP */
2246 "interrupt", /* 2 SIGINT */
2247 "quit", /* 3 SIGQUIT */
2248 "illegal instruction", /* 4 SIGILL */
2249 "trace trap", /* 5 SIGTRAP */
2250 "IOT instruction", /* 6 SIGIOT */
2251 "crash likely", /* 7 SIGDANGER */
2252 "floating point exception", /* 8 SIGFPE */
2253 "kill", /* 9 SIGKILL */
2254 "bus error", /* 10 SIGBUS */
2255 "segmentation violation", /* 11 SIGSEGV */
2256 "bad argument to system call", /* 12 SIGSYS */
2257 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2258 "alarm clock", /* 14 SIGALRM */
2259 "software termination signum", /* 15 SIGTERM */
2260 "user defined signal 1", /* 16 SIGUSR1 */
2261 "user defined signal 2", /* 17 SIGUSR2 */
2262 "death of a child", /* 18 SIGCLD */
2263 "power-fail restart", /* 19 SIGPWR */
2264 "bogus signal", /* 20 */
2265 "bogus signal", /* 21 */
2266 "bogus signal", /* 22 */
2267 "bogus signal", /* 23 */
2268 "bogus signal", /* 24 */
2269 "LAN I/O interrupt", /* 25 SIGAIO */
2270 "PTY I/O interrupt", /* 26 SIGPTY */
2271 "I/O intervention required", /* 27 SIGIOINT */
2272 "HFT grant", /* 28 SIGGRANT */
2273 "HFT retract", /* 29 SIGRETRACT */
2274 "HFT sound done", /* 30 SIGSOUND */
2275 "HFT input ready", /* 31 SIGMSG */
2277 "bogus signal", /* 0 */
2278 "hangup", /* 1 SIGHUP */
2279 "interrupt", /* 2 SIGINT */
2280 "quit", /* 3 SIGQUIT */
2281 "illegal instruction", /* 4 SIGILL */
2282 "trace trap", /* 5 SIGTRAP */
2283 "IOT instruction", /* 6 SIGIOT */
2284 "EMT instruction", /* 7 SIGEMT */
2285 "floating point exception", /* 8 SIGFPE */
2286 "kill", /* 9 SIGKILL */
2287 "bus error", /* 10 SIGBUS */
2288 "segmentation violation", /* 11 SIGSEGV */
2289 "bad argument to system call", /* 12 SIGSYS */
2290 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2291 "alarm clock", /* 14 SIGALRM */
2292 "software termination signum", /* 15 SIGTERM */
2293 "user defined signal 1", /* 16 SIGUSR1 */
2294 "user defined signal 2", /* 17 SIGUSR2 */
2295 "death of a child", /* 18 SIGCLD */
2296 "power-fail restart", /* 19 SIGPWR */
2297 #endif /* not AIX */
2302 * Warning, this function may not duplicate 4.2 action properly
2303 * under error conditions.
2307 /* In 4.1, param.h fails to define this. */
2308 #define MAXPATHLEN 1024
2317 char *npath
, *spath
;
2318 extern char *getcwd ();
2320 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
2321 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2322 up to first slash. Should be harmless on other systems. */
2323 while (*npath
&& *npath
!= '/')
2325 strcpy (pathname
, npath
);
2326 free (spath
); /* getcwd uses malloc */
2330 #endif /* HAVE_GETWD */
2333 * Emulate rename using unlink/link. Note that this is
2334 * only partially correct. Also, doesn't enforce restriction
2335 * that files be of same type (regular->regular, dir->dir, etc).
2344 if (access (from
, 0) == 0)
2347 if (link (from
, to
) == 0)
2348 if (unlink (from
) == 0)
2359 * Substitute fork for vfork on USG flavors.
2367 #endif /* not HAVE_VFORK */
2369 #ifdef MISSING_UTIMES
2371 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2380 /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2381 utimbuf structure defined anywhere but in the man page. */
2391 struct timeval tvp
[];
2394 utb
.actime
= tvp
[0].tv_sec
;
2395 utb
.modtime
= tvp
[1].tv_sec
;
2398 #endif /* IRIS_UTIME */
2404 /* HPUX curses library references perror, but as far as we know
2405 it won't be called. Anyway this definition will do for now. */
2411 #endif /* not HAVE_PERROR */
2417 * Emulate BSD dup2. First close newd if it already exists.
2418 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2419 * until we are, then close the unsuccessful ones.
2426 register int fd
, ret
;
2431 fd
= fcntl (oldd
, F_DUPFD
, newd
);
2433 error ("can't dup2 (%i,%i) : %s", oldd
, newd
, sys_errlist
[errno
]);
2440 ret
= dup2 (old
,new);
2446 #endif /* not HAVE_DUP2 */
2449 * Gettimeofday. Simulate as much as possible. Only accurate
2450 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2451 * Only needed when subprocesses are defined.
2456 #ifndef HAVE_GETTIMEOFDAY
2460 gettimeofday (tp
, tzp
)
2462 struct timezone
*tzp
;
2464 extern long time ();
2466 tp
->tv_sec
= time ((long *)0);
2468 tzp
->tz_minuteswest
= -1;
2474 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
2477 * This function will go away as soon as all the stubs fixed. (fnf)
2483 printf ("%s not yet implemented\r\n", badfunc
);
2492 char *sys_siglist
[NSIG
+ 1] =
2494 "null signal", /* 0 SIGNULL */
2495 "hangup", /* 1 SIGHUP */
2496 "interrupt", /* 2 SIGINT */
2497 "quit", /* 3 SIGQUIT */
2498 "illegal instruction", /* 4 SIGILL */
2499 "trace trap", /* 5 SIGTRAP */
2500 "abort termination", /* 6 SIGABRT */
2501 "SIGEMT", /* 7 SIGEMT */
2502 "floating point exception", /* 8 SIGFPE */
2503 "kill", /* 9 SIGKILL */
2504 "bus error", /* 10 SIGBUS */
2505 "segmentation violation", /* 11 SIGSEGV */
2506 "bad argument to system call", /* 12 SIGSYS */
2507 "write on a pipe with no reader", /* 13 SIGPIPE */
2508 "alarm clock", /* 14 SIGALRM */
2509 "software termination signal", /* 15 SIGTERM */
2510 "user defined signal 1", /* 16 SIGUSR1 */
2511 "user defined signal 2", /* 17 SIGUSR2 */
2512 "child stopped or terminated", /* 18 SIGCLD */
2513 "power-fail restart", /* 19 SIGPWR */
2514 "window size changed", /* 20 SIGWINCH */
2515 "undefined", /* 21 */
2516 "pollable event occured", /* 22 SIGPOLL */
2517 "sendable stop signal not from tty", /* 23 SIGSTOP */
2518 "stop signal from tty", /* 24 SIGSTP */
2519 "continue a stopped process", /* 25 SIGCONT */
2520 "attempted background tty read", /* 26 SIGTTIN */
2521 "attempted background tty write", /* 27 SIGTTOU */
2522 "undefined", /* 28 */
2523 "undefined", /* 29 */
2524 "undefined", /* 30 */
2525 "undefined", /* 31 */
2526 "undefined", /* 32 */
2527 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
2528 "I/O is possible", /* 34 SIGIO */
2529 "exceeded cpu time limit", /* 35 SIGXCPU */
2530 "exceeded file size limit", /* 36 SIGXFSZ */
2531 "virtual time alarm", /* 37 SIGVTALRM */
2532 "profiling time alarm", /* 38 SIGPROF */
2533 "undefined", /* 39 */
2534 "file record locks revoked", /* 40 SIGLOST */
2535 "undefined", /* 41 */
2536 "undefined", /* 42 */
2537 "undefined", /* 43 */
2538 "undefined", /* 44 */
2539 "undefined", /* 45 */
2540 "undefined", /* 46 */
2541 "undefined", /* 47 */
2542 "undefined", /* 48 */
2543 "undefined", /* 49 */
2544 "undefined", /* 50 */
2545 "undefined", /* 51 */
2546 "undefined", /* 52 */
2547 "undefined", /* 53 */
2548 "undefined", /* 54 */
2549 "undefined", /* 55 */
2550 "undefined", /* 56 */
2551 "undefined", /* 57 */
2552 "undefined", /* 58 */
2553 "undefined", /* 59 */
2554 "undefined", /* 60 */
2555 "undefined", /* 61 */
2556 "undefined", /* 62 */
2557 "undefined", /* 63 */
2558 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
2564 /* Directory routines for systems that don't have them. */
2566 #ifdef SYSV_SYSTEM_DIR
2573 register DIR *dirp
; /* stream from opendir */
2575 sys_close (dirp
->dd_fd
);
2576 free ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
2577 free ((char *) dirp
);
2579 #endif /* not AIX */
2580 #endif /* SYSV_SYSTEM_DIR */
2582 #ifdef NONSYSTEM_DIR_LIBRARY
2586 char *filename
; /* name of directory */
2588 register DIR *dirp
; /* -> malloc'ed storage */
2589 register int fd
; /* file descriptor for read */
2590 struct stat sbuf
; /* result of fstat */
2592 fd
= sys_open (filename
, 0);
2596 if (fstat (fd
, &sbuf
) < 0
2597 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
2598 || (dirp
= (DIR *) malloc (sizeof (DIR))) == 0)
2601 return 0; /* bad luck today */
2605 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
2612 register DIR *dirp
; /* stream from opendir */
2614 sys_close (dirp
->dd_fd
);
2615 free ((char *) dirp
);
2623 ino_t od_ino
; /* inode */
2624 char od_name
[DIRSIZ
]; /* filename */
2626 #endif /* not VMS */
2628 struct direct dir_static
; /* simulated directory contents */
2633 register DIR *dirp
; /* stream from opendir */
2636 register struct olddir
*dp
; /* -> directory data */
2638 register struct dir$_name
*dp
; /* -> directory data */
2639 register struct dir$_version
*dv
; /* -> version data */
2644 if (dirp
->dd_loc
>= dirp
->dd_size
)
2645 dirp
->dd_loc
= dirp
->dd_size
= 0;
2647 if (dirp
->dd_size
== 0 /* refill buffer */
2648 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
2652 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
2653 dirp
->dd_loc
+= sizeof (struct olddir
);
2655 if (dp
->od_ino
!= 0) /* not deleted entry */
2657 dir_static
.d_ino
= dp
->od_ino
;
2658 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
2659 dir_static
.d_name
[DIRSIZ
] = '\0';
2660 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
2661 dir_static
.d_reclen
= sizeof (struct direct
)
2663 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
2664 return &dir_static
; /* -> simulated structure */
2667 dp
= (struct dir$_name
*) dirp
->dd_buf
;
2668 if (dirp
->dd_loc
== 0)
2669 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
2670 : dp
->dir$b_namecount
;
2671 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
2672 dir_static
.d_ino
= dv
->dir$w_fid_num
;
2673 dir_static
.d_namlen
= dp
->dir$b_namecount
;
2674 dir_static
.d_reclen
= sizeof (struct direct
)
2676 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
2677 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
2678 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
2679 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
2686 /* readdirver is just like readdir except it returns all versions of a file
2687 as separate entries. */
2692 register DIR *dirp
; /* stream from opendir */
2694 register struct dir$_name
*dp
; /* -> directory data */
2695 register struct dir$_version
*dv
; /* -> version data */
2697 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
2698 dirp
->dd_loc
= dirp
->dd_size
= 0;
2700 if (dirp
->dd_size
== 0 /* refill buffer */
2701 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
2704 dp
= (struct dir$_name
*) dirp
->dd_buf
;
2705 if (dirp
->dd_loc
== 0)
2706 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
2707 : dp
->dir$b_namecount
;
2708 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
2709 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
2710 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
2711 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
2712 dir_static
.d_ino
= dv
->dir$w_fid_num
;
2713 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
2714 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
2715 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
2721 #endif /* NONSYSTEM_DIR_LIBRARY */
2723 /* Functions for VMS */
2725 #include "vms-pwd.h"
2730 /* Return as a string the VMS error string pertaining to STATUS.
2731 Reuses the same static buffer each time it is called. */
2735 int status
; /* VMS status code */
2739 static char buf
[257];
2741 bufadr
[0] = sizeof buf
- 1;
2742 bufadr
[1] = (int) buf
;
2743 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
2744 return "untranslatable VMS error status";
2752 /* The following is necessary because 'access' emulation by VMS C (2.0) does
2753 * not work correctly. (It also doesn't work well in version 2.3.)
2758 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
2759 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
2763 unsigned short s_buflen
;
2764 unsigned short s_code
;
2766 unsigned short *s_retlenadr
;
2770 #define buflen s.s_buflen
2771 #define code s.s_code
2772 #define bufadr s.s_bufadr
2773 #define retlenadr s.s_retlenadr
2775 #define R_OK 4 /* test for read permission */
2776 #define W_OK 2 /* test for write permission */
2777 #define X_OK 1 /* test for execute (search) permission */
2778 #define F_OK 0 /* test for presence of file */
2781 sys_access (path
, mode
)
2785 static char *user
= NULL
;
2788 /* translate possible directory spec into .DIR file name, so brain-dead
2789 * access can treat the directory like a file. */
2790 if (directory_file_name (path
, dir_fn
))
2794 return access (path
, mode
);
2795 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
2801 unsigned short int dummy
;
2803 static int constant
= ACL$C_FILE
;
2804 DESCRIPTOR (path_desc
, path
);
2805 DESCRIPTOR (user_desc
, user
);
2809 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
2812 acces
|= CHP$M_READ
;
2814 acces
|= CHP$M_WRITE
;
2815 itemlst
[0].buflen
= sizeof (int);
2816 itemlst
[0].code
= CHP$_FLAGS
;
2817 itemlst
[0].bufadr
= (char *) &flags
;
2818 itemlst
[0].retlenadr
= &dummy
;
2819 itemlst
[1].buflen
= sizeof (int);
2820 itemlst
[1].code
= CHP$_ACCESS
;
2821 itemlst
[1].bufadr
= (char *) &acces
;
2822 itemlst
[1].retlenadr
= &dummy
;
2823 itemlst
[2].end
= CHP$_END
;
2824 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
2825 return stat
== SS$_NORMAL
? 0 : -1;
2829 #else /* not VMS4_4 */
2832 #define ACE$M_WRITE 2
2833 #define ACE$C_KEYID 1
2835 static unsigned short memid
, grpid
;
2836 static unsigned int uic
;
2838 /* Called from init_sys_modes, so it happens not very often
2839 but at least each time Emacs is loaded. */
2840 sys_access_reinit ()
2846 sys_access (filename
, type
)
2852 int status
, size
, i
, typecode
, acl_controlled
;
2853 unsigned int *aclptr
, *aclend
, aclbuf
[60];
2854 union prvdef prvmask
;
2856 /* Get UIC and GRP values for protection checking. */
2859 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
2862 memid
= uic
& 0xFFFF;
2866 if (type
!= 2) /* not checking write access */
2867 return access (filename
, type
);
2869 /* Check write protection. */
2871 #define CHECKPRIV(bit) (prvmask.bit)
2872 #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
2874 /* Find privilege bits */
2875 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
2877 error ("Unable to find privileges: %s", vmserrstr (status
));
2878 if (CHECKPRIV (PRV$V_BYPASS
))
2879 return 0; /* BYPASS enabled */
2881 fab
.fab$b_fac
= FAB$M_GET
;
2882 fab
.fab$l_fna
= filename
;
2883 fab
.fab$b_fns
= strlen (filename
);
2884 fab
.fab$l_xab
= &xab
;
2885 xab
= cc$rms_xabpro
;
2886 xab
.xab$l_aclbuf
= aclbuf
;
2887 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
2888 status
= SYS$
OPEN (&fab
, 0, 0);
2891 SYS$
CLOSE (&fab
, 0, 0);
2892 /* Check system access */
2893 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITEABLE (XAB$V_SYS
))
2895 /* Check ACL entries, if any */
2897 if (xab
.xab$w_acllen
> 0)
2900 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
2901 while (*aclptr
&& aclptr
< aclend
)
2903 size
= (*aclptr
& 0xff) / 4;
2904 typecode
= (*aclptr
>> 8) & 0xff;
2905 if (typecode
== ACE$C_KEYID
)
2906 for (i
= size
- 1; i
> 1; i
--)
2907 if (aclptr
[i
] == uic
)
2910 if (aclptr
[1] & ACE$M_WRITE
)
2911 return 0; /* Write access through ACL */
2913 aclptr
= &aclptr
[size
];
2915 if (acl_controlled
) /* ACL specified, prohibits write access */
2918 /* No ACL entries specified, check normal protection */
2919 if (WRITEABLE (XAB$V_WLD
)) /* World writeable */
2921 if (WRITEABLE (XAB$V_GRP
) &&
2922 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
2923 return 0; /* Group writeable */
2924 if (WRITEABLE (XAB$V_OWN
) &&
2925 (xab
.xab$l_uic
& 0xFFFF) == memid
)
2926 return 0; /* Owner writeable */
2928 return -1; /* Not writeable */
2930 #endif /* not VMS4_4 */
2933 static char vtbuf
[NAM$C_MAXRSS
+1];
2935 /* translate a vms file spec to a unix path */
2937 sys_translate_vms (vfile
)
2948 /* leading device or logical name is a root directory */
2949 if (p
= strchr (vfile
, ':'))
2958 if (*p
== '[' || *p
== '<')
2960 while (*++vfile
!= *p
+ 2)
2964 if (vfile
[-1] == *p
)
2987 static char utbuf
[NAM$C_MAXRSS
+1];
2989 /* translate a unix path to a VMS file spec */
2991 sys_translate_unix (ufile
)
3014 if (index (&ufile
[1], '/'))
3021 if (index (&ufile
[1], '/'))
3028 if (strncmp (ufile
, "./", 2) == 0)
3035 ufile
++; /* skip the dot */
3036 if (index (&ufile
[1], '/'))
3041 else if (strncmp (ufile
, "../", 3) == 0)
3049 ufile
+= 2; /* skip the dots */
3050 if (index (&ufile
[1], '/'))
3075 strcpy (pathname
, egetenv ("PATH"));
3080 if ('a' <= *ptr
&& *ptr
<= 'z')
3089 long item_code
= JPI$_OWNER
;
3090 unsigned long parent_id
;
3093 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
3096 vaxc$errno
= status
;
3106 return (getgid () << 16) | getuid ();
3110 sys_read (fildes
, buf
, nbyte
)
3115 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
3120 sys_write (fildes
, buf
, nbyte
)
3125 register int nwrote
, rtnval
= 0;
3127 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
3133 return rtnval
? rtnval
: -1;
3134 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
3135 return rtnval
? rtnval
: -1;
3136 return (rtnval
+ nwrote
);
3141 * VAX/VMS VAX C RTL really loses. It insists that records
3142 * end with a newline (carriage return) character, and if they
3143 * don't it adds one (nice of it isn't it!)
3145 * Thus we do this stupidity below.
3149 sys_write (fildes
, buf
, nbytes
)
3152 unsigned int nbytes
;
3159 fstat (fildes
, &st
);
3165 /* Handle fixed-length files with carriage control. */
3166 if (st
.st_fab_rfm
== FAB$C_FIX
3167 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
3169 len
= st
.st_fab_mrs
;
3170 retval
= write (fildes
, p
, min (len
, nbytes
));
3173 retval
++; /* This skips the implied carriage control */
3177 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
3178 while (*e
!= '\n' && e
> p
) e
--;
3179 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
3180 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
3182 retval
= write (fildes
, p
, len
);
3193 /* Create file NEW copying its attributes from file OLD. If
3194 OLD is 0 or does not exist, create based on the value of
3197 /* Protection value the file should ultimately have.
3198 Set by create_copy_attrs, and use by rename_sansversions. */
3199 static unsigned short int fab_final_pro
;
3202 creat_copy_attrs (old
, new)
3205 struct FAB fab
= cc$rms_fab
;
3206 struct XABPRO xabpro
;
3207 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
3208 extern int vms_stmlf_recfm
;
3212 fab
.fab$b_fac
= FAB$M_GET
;
3213 fab
.fab$l_fna
= old
;
3214 fab
.fab$b_fns
= strlen (old
);
3215 fab
.fab$l_xab
= (char *) &xabpro
;
3216 xabpro
= cc$rms_xabpro
;
3217 xabpro
.xab$l_aclbuf
= aclbuf
;
3218 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
3219 /* Call $OPEN to fill in the fab & xabpro fields. */
3220 if (SYS$
OPEN (&fab
, 0, 0) & 1)
3222 SYS$
CLOSE (&fab
, 0, 0);
3223 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
3224 if (xabpro
.xab$w_acllen
> 0)
3226 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
3227 /* If the acl buffer was too short, redo open with longer one.
3228 Wouldn't need to do this if there were some system imposed
3229 limit on the size of an ACL, but I can't find any such. */
3231 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
3232 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
3233 if (SYS$
OPEN (&fab
, 0, 0) & 1)
3234 SYS$
CLOSE (&fab
, 0, 0);
3240 xabpro
.xab$l_aclbuf
= 0;
3245 fab
.fab$l_fna
= new;
3246 fab
.fab$b_fns
= strlen (new);
3250 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
3251 fab
.fab$b_rat
= FAB$M_CR
;
3254 /* Set the file protections such that we will be able to manipulate
3255 this file. Once we are done writing and renaming it, we will set
3256 the protections back. */
3258 fab_final_pro
= xabpro
.xab$w_pro
;
3260 SYS$
SETDFPROT (0, &fab_final_pro
);
3261 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
3263 /* Create the new file with either default attrs or attrs copied
3265 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
3267 SYS$
CLOSE (&fab
, 0, 0);
3268 /* As this is a "replacement" for creat, return a file descriptor
3269 opened for writing. */
3270 return open (new, O_WRONLY
);
3275 #include <varargs.h>
3278 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3282 sys_creat (va_alist
)
3285 va_list list_incrementor
;
3288 int rfd
; /* related file descriptor */
3289 int fd
; /* Our new file descriptor */
3296 extern int vms_stmlf_recfm
;
3299 va_start (list_incrementor
);
3300 name
= va_arg (list_incrementor
, char *);
3301 mode
= va_arg (list_incrementor
, int);
3303 rfd
= va_arg (list_incrementor
, int);
3304 va_end (list_incrementor
);
3307 /* Use information from the related file descriptor to set record
3308 format of the newly created file. */
3309 fstat (rfd
, &st_buf
);
3310 switch (st_buf
.st_fab_rfm
)
3313 strcpy (rfm
, "rfm = fix");
3314 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
3315 strcpy (rat
, "rat = ");
3316 if (st_buf
.st_fab_rat
& FAB$M_CR
)
3318 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
3319 strcat (rat
, "ftn");
3320 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
3321 strcat (rat
, "prn");
3322 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
3323 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
3324 strcat (rat
, ", blk");
3326 strcat (rat
, "blk");
3327 return creat (name
, 0, rfm
, rat
, mrs
);
3330 strcpy (rfm
, "rfm = vfc");
3331 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
3332 strcpy (rat
, "rat = ");
3333 if (st_buf
.st_fab_rat
& FAB$M_CR
)
3335 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
3336 strcat (rat
, "ftn");
3337 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
3338 strcat (rat
, "prn");
3339 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
3340 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
3341 strcat (rat
, ", blk");
3343 strcat (rat
, "blk");
3344 return creat (name
, 0, rfm
, rat
, fsz
);
3347 strcpy (rfm
, "rfm = stm");
3351 strcpy (rfm
, "rfm = stmcr");
3355 strcpy (rfm
, "rfm = stmlf");
3359 strcpy (rfm
, "rfm = udf");
3363 strcpy (rfm
, "rfm = var");
3366 strcpy (rat
, "rat = ");
3367 if (st_buf
.st_fab_rat
& FAB$M_CR
)
3369 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
3370 strcat (rat
, "ftn");
3371 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
3372 strcat (rat
, "prn");
3373 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
3374 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
3375 strcat (rat
, ", blk");
3377 strcat (rat
, "blk");
3381 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
3382 strcpy (rat
, "rat=cr");
3384 /* Until the VAX C RTL fixes the many bugs with modes, always use
3385 mode 0 to get the user's default protection. */
3386 fd
= creat (name
, 0, rfm
, rat
);
3387 if (fd
< 0 && errno
== EEXIST
)
3389 if (unlink (name
) < 0)
3390 report_file_error ("delete", build_string (name
));
3391 fd
= creat (name
, 0, rfm
, rat
);
3397 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3398 sys_fwrite (ptr
, size
, num
, fp
)
3399 register char * ptr
;
3402 register int tot
= num
* size
;
3409 * The VMS C library routine creat actually creates a new version of an
3410 * existing file rather than truncating the old version. There are times
3411 * when this is not the desired behavior, for instance, when writing an
3412 * auto save file (you only want one version), or when you don't have
3413 * write permission in the directory containing the file (but the file
3414 * itself is writable). Hence this routine, which is equivalent to
3415 * "close (creat (fn, 0));" on Unix if fn already exists.
3421 struct FAB xfab
= cc$rms_fab
;
3422 struct RAB xrab
= cc$rms_rab
;
3425 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
3426 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
3427 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
3428 xfab
.fab$l_fna
= fn
;
3429 xfab
.fab$b_fns
= strlen (fn
);
3430 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
3432 xrab
.rab$l_fab
= &xfab
;
3434 /* This gibberish opens the file, positions to the first record, and
3435 deletes all records from there until the end of file. */
3436 if ((SYS$
OPEN (&xfab
) & 01) == 01)
3438 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
3439 (SYS$
FIND (&xrab
) & 01) == 01 &&
3440 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
3451 /* Define this symbol to actually read SYSUAF.DAT. This requires either
3452 SYSPRV or a readable SYSUAF.DAT. */
3458 * Routine to read the VMS User Authorization File and return
3459 * a specific user's record.
3462 static struct UAF retuaf
;
3465 get_uaf_name (uname
)
3472 uaf_fab
= cc$rms_fab
;
3473 uaf_rab
= cc$rms_rab
;
3474 /* initialize fab fields */
3475 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
3476 uaf_fab
.fab$b_fns
= 21;
3477 uaf_fab
.fab$b_fac
= FAB$M_GET
;
3478 uaf_fab
.fab$b_org
= FAB$C_IDX
;
3479 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
3480 /* initialize rab fields */
3481 uaf_rab
.rab$l_fab
= &uaf_fab
;
3482 /* open the User Authorization File */
3483 status
= SYS$
OPEN (&uaf_fab
);
3487 vaxc$errno
= status
;
3490 status
= SYS$
CONNECT (&uaf_rab
);
3494 vaxc$errno
= status
;
3497 /* read the requested record - index is in uname */
3498 uaf_rab
.rab$l_kbf
= uname
;
3499 uaf_rab
.rab$b_ksz
= strlen (uname
);
3500 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
3501 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
3502 uaf_rab
.rab$w_usz
= sizeof retuaf
;
3503 status
= SYS$
GET (&uaf_rab
);
3507 vaxc$errno
= status
;
3510 /* close the User Authorization File */
3511 status
= SYS$
DISCONNECT (&uaf_rab
);
3515 vaxc$errno
= status
;
3518 status
= SYS$
CLOSE (&uaf_fab
);
3522 vaxc$errno
= status
;
3536 uaf_fab
= cc$rms_fab
;
3537 uaf_rab
= cc$rms_rab
;
3538 /* initialize fab fields */
3539 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
3540 uaf_fab
.fab$b_fns
= 21;
3541 uaf_fab
.fab$b_fac
= FAB$M_GET
;
3542 uaf_fab
.fab$b_org
= FAB$C_IDX
;
3543 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
3544 /* initialize rab fields */
3545 uaf_rab
.rab$l_fab
= &uaf_fab
;
3546 /* open the User Authorization File */
3547 status
= SYS$
OPEN (&uaf_fab
);
3551 vaxc$errno
= status
;
3554 status
= SYS$
CONNECT (&uaf_rab
);
3558 vaxc$errno
= status
;
3561 /* read the requested record - index is in uic */
3562 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
3563 uaf_rab
.rab$l_kbf
= (char *) &uic
;
3564 uaf_rab
.rab$b_ksz
= sizeof uic
;
3565 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
3566 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
3567 uaf_rab
.rab$w_usz
= sizeof retuaf
;
3568 status
= SYS$
GET (&uaf_rab
);
3572 vaxc$errno
= status
;
3575 /* close the User Authorization File */
3576 status
= SYS$
DISCONNECT (&uaf_rab
);
3580 vaxc$errno
= status
;
3583 status
= SYS$
CLOSE (&uaf_fab
);
3587 vaxc$errno
= status
;
3593 static struct passwd retpw
;
3601 /* copy these out first because if the username is 32 chars, the next
3602 section will overwrite the first byte of the UIC */
3603 retpw
.pw_uid
= up
->uaf$w_mem
;
3604 retpw
.pw_gid
= up
->uaf$w_grp
;
3606 /* I suppose this is not the best sytle, to possibly overwrite one
3607 byte beyond the end of the field, but what the heck... */
3608 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
3609 while (ptr
[-1] == ' ')
3612 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
3614 /* the rest of these are counted ascii strings */
3615 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
3616 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
3617 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
3618 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
3619 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
3620 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
3621 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
3622 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
3626 #else /* not READ_SYSUAF */
3627 static struct passwd retpw
;
3628 #endif /* not READ_SYSUAF */
3639 unsigned char * full
;
3640 #endif /* READ_SYSUAF */
3645 if ('a' <= *ptr
&& *ptr
<= 'z')
3650 if (!(up
= get_uaf_name (name
)))
3652 return cnv_uaf_pw (up
);
3654 if (strcmp (name
, getenv ("USER")) == 0)
3656 retpw
.pw_uid
= getuid ();
3657 retpw
.pw_gid
= getgid ();
3658 strcpy (retpw
.pw_name
, name
);
3659 if (full
= egetenv ("FULLNAME"))
3660 strcpy (retpw
.pw_gecos
, full
);
3662 *retpw
.pw_gecos
= '\0';
3663 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
3664 *retpw
.pw_shell
= '\0';
3669 #endif /* not READ_SYSUAF */
3679 if (!(up
= get_uaf_uic (uid
)))
3681 return cnv_uaf_pw (up
);
3683 if (uid
== sys_getuid ())
3684 return getpwnam (egetenv ("USER"));
3687 #endif /* not READ_SYSUAF */
3690 /* return total address space available to the current process. This is
3691 the sum of the current p0 size, p1 size and free page table entries
3696 unsigned long free_pages
;
3697 unsigned long frep0va
;
3698 unsigned long frep1va
;
3701 item_code
= JPI$_FREPTECNT
;
3702 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
3705 vaxc$errno
= status
;
3710 item_code
= JPI$_FREP0VA
;
3711 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
3714 vaxc$errno
= status
;
3717 item_code
= JPI$_FREP1VA
;
3718 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
3721 vaxc$errno
= status
;
3725 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
3728 define_logical_name (varname
, string
)
3732 struct dsc$descriptor_s strdsc
=
3733 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
3734 struct dsc$descriptor_s envdsc
=
3735 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
3736 struct dsc$descriptor_s lnmdsc
=
3737 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
3739 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
3742 delete_logical_name (varname
)
3745 struct dsc$descriptor_s envdsc
=
3746 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
3747 struct dsc$descriptor_s lnmdsc
=
3748 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
3750 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
3761 error ("execvp system call not implemented");
3769 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
3770 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
3771 char from_esn
[NAM$C_MAXRSS
];
3772 char to_esn
[NAM$C_MAXRSS
];
3774 from_fab
.fab$l_fna
= from
;
3775 from_fab
.fab$b_fns
= strlen (from
);
3776 from_fab
.fab$l_nam
= &from_nam
;
3777 from_fab
.fab$l_fop
= FAB$M_NAM
;
3779 from_nam
.nam$l_esa
= from_esn
;
3780 from_nam
.nam$b_ess
= sizeof from_esn
;
3782 to_fab
.fab$l_fna
= to
;
3783 to_fab
.fab$b_fns
= strlen (to
);
3784 to_fab
.fab$l_nam
= &to_nam
;
3785 to_fab
.fab$l_fop
= FAB$M_NAM
;
3787 to_nam
.nam$l_esa
= to_esn
;
3788 to_nam
.nam$b_ess
= sizeof to_esn
;
3790 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
3796 if (status
== RMS$_DEV
)
3800 vaxc$errno
= status
;
3805 /* This function renames a file like `rename', but it strips
3806 the version number from the "to" filename, such that the "to" file is
3807 will always be a new version. It also sets the file protection once it is
3808 finished. The protection that we will use is stored in fab_final_pro,
3809 and was set when we did a creat_copy_attrs to create the file that we
3812 We could use the chmod function, but Eunichs uses 3 bits per user category
3813 to describe the protection, and VMS uses 4 (write and delete are seperate
3814 bits). To maintain portability, the VMS implementation of `chmod' wires
3815 the W and D bits together. */
3818 static struct fibdef fib
; /* We need this initialized to zero */
3819 char vms_file_written
[NAM$C_MAXRSS
];
3822 rename_sans_version (from
,to
)
3829 struct FAB to_fab
= cc$rms_fab
;
3830 struct NAM to_nam
= cc$rms_nam
;
3831 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
3832 struct dsc$descriptor fib_attr
[2]
3833 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
3834 char to_esn
[NAM$C_MAXRSS
];
3836 $
DESCRIPTOR (disk
,to_esn
);
3838 to_fab
.fab$l_fna
= to
;
3839 to_fab
.fab$b_fns
= strlen (to
);
3840 to_fab
.fab$l_nam
= &to_nam
;
3841 to_fab
.fab$l_fop
= FAB$M_NAM
;
3843 to_nam
.nam$l_esa
= to_esn
;
3844 to_nam
.nam$b_ess
= sizeof to_esn
;
3846 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
3848 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
3849 *(to_nam
.nam$l_ver
) = '\0';
3851 stat
= rename (from
, to_esn
);
3855 strcpy (vms_file_written
, to_esn
);
3857 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
3858 to_fab
.fab$b_fns
= strlen (vms_file_written
);
3860 /* Now set the file protection to the correct value */
3861 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
3863 /* Copy these fields into the fib */
3864 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
3865 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
3866 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
3868 SYS$
CLOSE (&to_fab
, 0, 0);
3870 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
3873 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
3874 0, 0, 0, &fib_attr
, 0);
3877 stat
= SYS$
DASSGN (chan
);
3880 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
3890 unsigned short fid
[3];
3891 char esa
[NAM$C_MAXRSS
];
3894 fab
.fab$l_fop
= FAB$M_OFP
;
3895 fab
.fab$l_fna
= file
;
3896 fab
.fab$b_fns
= strlen (file
);
3897 fab
.fab$l_nam
= &nam
;
3900 nam
.nam$l_esa
= esa
;
3901 nam
.nam$b_ess
= NAM$C_MAXRSS
;
3903 status
= SYS$
PARSE (&fab
);
3904 if ((status
& 1) == 0)
3907 vaxc$errno
= status
;
3910 status
= SYS$
SEARCH (&fab
);
3911 if ((status
& 1) == 0)
3914 vaxc$errno
= status
;
3918 fid
[0] = nam
.nam$w_fid
[0];
3919 fid
[1] = nam
.nam$w_fid
[1];
3920 fid
[2] = nam
.nam$w_fid
[2];
3922 fab
.fab$l_fna
= new;
3923 fab
.fab$b_fns
= strlen (new);
3925 status
= SYS$
PARSE (&fab
);
3926 if ((status
& 1) == 0)
3929 vaxc$errno
= status
;
3933 nam
.nam$w_fid
[0] = fid
[0];
3934 nam
.nam$w_fid
[1] = fid
[1];
3935 nam
.nam$w_fid
[2] = fid
[2];
3937 nam
.nam$l_esa
= nam
.nam$l_name
;
3938 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
3940 status
= SYS$
ENTER (&fab
);
3941 if ((status
& 1) == 0)
3944 vaxc$errno
= status
;
3954 printf ("%s not yet implemented\r\n", badfunc
);
3962 /* Arrange to return a range centered on zero. */
3963 return rand () - (1 << 30);
3974 /* Called from init_sys_modes. */
3979 /* If we're not on an HFT we shouldn't do any of this. We determine
3980 if we are on an HFT by trying to get an HFT error code. If this
3981 call fails, we're not on an HFT. */
3983 if (ioctl (0, HFQERROR
, &junk
) < 0)
3985 #else /* not IBMR2AIX */
3986 if (ioctl (0, HFQEIO
, 0) < 0)
3988 #endif /* not IBMR2AIX */
3990 /* On AIX the default hft keyboard mapping uses backspace rather than delete
3991 as the rubout key's ASCII code. Here this is changed. The bug is that
3992 there's no way to determine the old mapping, so in reset_sys_modes
3993 we need to assume that the normal map had been present. Of course, this
3994 code also doesn't help if on a terminal emulator which doesn't understand
3998 struct hfkeymap keymap
;
4000 buf
.hf_bufp
= (char *)&keymap
;
4001 buf
.hf_buflen
= sizeof (keymap
);
4002 keymap
.hf_nkeys
= 2;
4003 keymap
.hfkey
[0].hf_kpos
= 15;
4004 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
4006 keymap
.hfkey
[0].hf_keyidh
= '<';
4007 #else /* not IBMR2AIX */
4008 keymap
.hfkey
[0].hf_page
= '<';
4009 #endif /* not IBMR2AIX */
4010 keymap
.hfkey
[0].hf_char
= 127;
4011 keymap
.hfkey
[1].hf_kpos
= 15;
4012 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
4014 keymap
.hfkey
[1].hf_keyidh
= '<';
4015 #else /* not IBMR2AIX */
4016 keymap
.hfkey
[1].hf_page
= '<';
4017 #endif /* not IBMR2AIX */
4018 keymap
.hfkey
[1].hf_char
= 127;
4019 hftctl (0, HFSKBD
, &buf
);
4021 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4023 line_ins_del_ok
= char_ins_del_ok
= 0;
4026 /* Reset the rubout key to backspace. */
4031 struct hfkeymap keymap
;
4035 if (ioctl (0, HFQERROR
, &junk
) < 0)
4037 #else /* not IBMR2AIX */
4038 if (ioctl (0, HFQEIO
, 0) < 0)
4040 #endif /* not IBMR2AIX */
4042 buf
.hf_bufp
= (char *)&keymap
;
4043 buf
.hf_buflen
= sizeof (keymap
);
4044 keymap
.hf_nkeys
= 2;
4045 keymap
.hfkey
[0].hf_kpos
= 15;
4046 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
4048 keymap
.hfkey
[0].hf_keyidh
= '<';
4049 #else /* not IBMR2AIX */
4050 keymap
.hfkey
[0].hf_page
= '<';
4051 #endif /* not IBMR2AIX */
4052 keymap
.hfkey
[0].hf_char
= 8;
4053 keymap
.hfkey
[1].hf_kpos
= 15;
4054 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
4056 keymap
.hfkey
[1].hf_keyidh
= '<';
4057 #else /* not IBMR2AIX */
4058 keymap
.hfkey
[1].hf_page
= '<';
4059 #endif /* not IBMR2AIX */
4060 keymap
.hfkey
[1].hf_char
= 8;
4061 hftctl (0, HFSKBD
, &buf
);