1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 86, 87, 88, 93, 94 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "blockinput.h"
29 #define min(x,y) ((x) > (y) ? (y) : (x))
31 /* In this file, open, read and write refer to the system calls,
32 not our sugared interfaces sys_open, sys_read and sys_write.
33 Contrariwise, for systems where we use the system calls directly,
34 define sys_read, etc. here as aliases for them. */
37 #define sys_write write
38 #endif /* `read' is not a macro */
44 #define sys_close close
51 #else /* `open' is a macro */
53 #endif /* `open' is a macro */
55 /* Does anyone other than VMS need this? */
57 #define sys_fwrite fwrite
63 #include <sys/types.h>
67 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
71 #include <sys/param.h>
96 #define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
100 #ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
101 because the vms compiler doesn't grok `defined' */
109 #endif /* not 4.1 bsd */
112 /* On some systems (DGUX comes to mind real fast) FASYNC causes
113 background writes to the terminal to stop all processes in the
114 process group when invoked under the csh (and probably any shell
115 with job control). This stops Emacs dead in its tracks when coming
121 #include <sys/ioctl.h>
126 #ifdef BROKEN_TIOCGWINSZ
132 #include <sys/utsname.h>
134 #ifndef MEMORY_IN_STRING_H
137 #if defined (TIOCGWINSZ) || defined (ISC4_0)
139 #include <sys/sioctl.h>
142 #include <sys/stream.h>
143 #include <sys/ptem.h>
145 #endif /* TIOCGWINSZ or ISC4_0 */
148 extern int quit_char
;
152 #include "termhooks.h"
153 #include "termchar.h"
154 #include "termopts.h"
155 #include "dispextern.h"
158 #ifdef NONSYSTEM_DIR_LIBRARY
160 #endif /* NONSYSTEM_DIR_LIBRARY */
162 #include "syssignal.h"
165 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
171 #define LNOFLSH 0100000
174 static int baud_convert
[] =
179 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
180 1800, 2400, 4800, 9600, 19200, 38400
186 /* The file descriptor for Emacs's input terminal.
187 Under Unix, this is normaly zero except when using X;
188 under VMS, we place the input channel number here.
189 This allows us to write more code that works for both VMS and Unix. */
192 /* Specify a different file descriptor for further input operations. */
201 /* Discard pending input on descriptor input_fd. */
205 struct emacs_tty buf
;
210 /* Discarding input is not safe when the input could contain
211 replies from the X server. So don't do it. */
212 if (read_socket_hook
)
217 SYS$
QIOW (0, input_fd
, IO$_READVBLK
|IO$M_PURGE
, input_iosb
, 0, 0,
218 &buf
.main
, 0, 0, terminator_mask
, 0, 0);
224 ioctl (input_fd
, TIOCFLUSH
, &zero
);
226 #else /* not Apollo */
227 #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
228 while (dos_keyread () != -1)
230 #else /* not MSDOS */
231 EMACS_GET_TTY (input_fd
, &buf
);
232 EMACS_SET_TTY (input_fd
, &buf
, 0);
233 #endif /* not MSDOS */
234 #endif /* not Apollo */
240 /* Arrange for character C to be read as the next input from
246 /* Should perhaps error if in batch mode */
248 ioctl (input_fd
, TIOCSTI
, &c
);
249 #else /* no TIOCSTI */
250 error ("Cannot stuff terminal input characters in this version of Unix");
251 #endif /* no TIOCSTI */
268 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &sg
, 0, 0,
269 &sg
.class, 12, 0, 0, 0, 0 );
270 ospeed
= sg
.xmit_baud
;
276 tcgetattr (input_fd
, &sg
);
277 ospeed
= cfgetospeed (&sg
);
278 #else /* neither VMS nor TERMIOS */
284 tcgetattr (input_fd
, &sg
);
286 ioctl (input_fd
, TCGETA
, &sg
);
288 ospeed
= sg
.c_cflag
& CBAUD
;
289 #else /* neither VMS nor TERMIOS nor TERMIO */
292 sg
.sg_ospeed
= B9600
;
293 if (ioctl (input_fd
, TIOCGETP
, &sg
) < 0)
295 ospeed
= sg
.sg_ospeed
;
296 #endif /* not HAVE_TERMIO */
297 #endif /* not HAVE_TERMIOS */
299 #endif /* not MSDOS */
302 baud_rate
= (ospeed
< sizeof baud_convert
/ sizeof baud_convert
[0]
303 ? baud_convert
[ospeed
] : 9600);
309 set_exclusive_use (fd
)
313 ioctl (fd
, FIOCLEX
, 0);
315 /* Ok to do nothing if this feature does not exist */
320 wait_without_blocking ()
323 wait3 (0, WNOHANG
| WUNTRACED
, 0);
325 croak ("wait_without_blocking");
327 synch_process_alive
= 0;
330 #endif /* not subprocesses */
332 int wait_debugging
; /* Set nonzero to make following function work under dbx
333 (at least for bsd). */
336 wait_for_termination_signal ()
339 /* Wait for subprocess with process id `pid' to terminate and
340 make sure it will get eliminated (not remain forever as a zombie) */
342 wait_for_termination (pid
)
351 status
= SYS$
FORCEX (&pid
, 0, 0);
354 #if defined (BSD) || (defined (HPUX) && !defined (HPUX_5))
355 /* Note that kill returns -1 even if the process is just a zombie now.
356 But inevitably a SIGCHLD interrupt should be generated
357 and child_sig will do wait3 and make the process go away. */
358 /* There is some indication that there is a bug involved with
359 termination of subprocesses, perhaps involving a kernel bug too,
360 but no idea what it is. Just as a hunch we signal SIGCHLD to see
361 if that causes the problem to go away or get worse. */
362 sigsetmask (sigmask (SIGCHLD
));
363 if (0 > kill (pid
, 0))
365 sigsetmask (SIGEMPTYMASK
);
366 kill (getpid (), SIGCHLD
);
372 sigpause (SIGEMPTYMASK
);
373 #else /* not BSD, and not HPUX version >= 6 */
374 #if defined (UNIPLUS)
375 if (0 > kill (pid
, 0))
378 #else /* neither BSD nor UNIPLUS: random sysV */
379 #ifdef POSIX_SIGNALS /* would this work for LINUX as well? */
380 sigblock (sigmask (SIGCHLD
));
381 if (0 > kill (pid
, 0))
383 sigunblock (sigmask (SIGCHLD
));
386 sigpause (SIGEMPTYMASK
);
387 #else /* not POSIX_SIGNALS */
388 #ifdef HAVE_SYSV_SIGPAUSE
390 if (0 > kill (pid
, 0))
396 #else /* not HAVE_SYSV_SIGPAUSE */
397 if (0 > kill (pid
, 0))
399 /* Using sleep instead of pause avoids timing error.
400 If the inferior dies just before the sleep,
401 we lose just one second. */
403 #endif /* not HAVE_SYSV_SIGPAUSE */
404 #endif /* not POSIX_SIGNALS */
405 #endif /* not UNIPLUS */
406 #endif /* not BSD, and not HPUX version >= 6 */
408 #else /* not subprocesses */
410 if (kill (pid
, 0) < 0)
416 if (status
== pid
|| status
== -1)
419 #endif /* not subprocesses */
426 * flush any pending output
427 * (may flush input as well; it does not matter the way we use it)
430 flush_pending_output (channel
)
434 /* If we try this, we get hit with SIGTTIN, because
435 the child's tty belongs to the child's pgrp. */
438 ioctl (channel
, TCFLSH
, 1);
442 /* 3rd arg should be ignored
443 but some 4.2 kernels actually want the address of an int
444 and nonzero means something different. */
445 ioctl (channel
, TIOCFLUSH
, &zero
);
452 /* Set up the terminal at the other end of a pseudo-terminal that
453 we will be controlling an inferior through.
454 It should not echo or do line-editing, since that is done
455 in Emacs. No padding needed for insertion into an Emacs buffer. */
457 child_setup_tty (out
)
463 EMACS_GET_TTY (out
, &s
);
465 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
466 s
.main
.c_oflag
|= OPOST
; /* Enable output postprocessing */
467 s
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL on output */
469 s
.main
.c_oflag
&= ~(NLDLY
|CRDLY
|TABDLY
|BSDLY
|VTDLY
|FFDLY
);
470 /* No output delays */
472 s
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
473 s
.main
.c_lflag
|= ISIG
; /* Enable signals */
475 s
.main
.c_iflag
&= ~IUCLC
; /* Disable downcasing on input. */
478 s
.main
.c_oflag
&= ~OLCUC
; /* Disable upcasing on output. */
480 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CSIZE
) | CS8
; /* Don't strip 8th bit */
482 /* Said to be unnecessary: */
483 s
.main
.c_cc
[VMIN
] = 1; /* minimum number of characters to accept */
484 s
.main
.c_cc
[VTIME
] = 0; /* wait forever for at least 1 character */
487 s
.main
.c_lflag
|= ICANON
; /* Enable erase/kill and eof processing */
488 s
.main
.c_cc
[VEOF
] = 04; /* insure that EOF is Control-D */
489 s
.main
.c_cc
[VERASE
] = 0377; /* disable erase processing */
490 s
.main
.c_cc
[VKILL
] = 0377; /* disable kill processing */
493 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
497 /* AIX enhanced edit loses NULs, so disable it */
500 s
.main
.c_iflag
&= ~ASCEDIT
;
502 /* Also, PTY overloads NUL and BREAK.
503 don't ignore break, but don't signal either, so it looks like NUL. */
504 s
.main
.c_iflag
&= ~IGNBRK
;
505 s
.main
.c_iflag
&= ~BRKINT
;
506 /* QUIT and INTR work better as signals, so disable character forms */
507 s
.main
.c_cc
[VINTR
] = 0377;
508 #ifdef SIGNALS_VIA_CHARACTERS
509 /* the QUIT and INTR character are used in process_send_signal
510 so set them here to something useful. */
511 if (s
.main
.c_cc
[VQUIT
] == 0377)
512 s
.main
.c_cc
[VQUIT
] = '\\'&037; /* Control-\ */
513 if (s
.main
.c_cc
[VINTR
] == 0377)
514 s
.main
.c_cc
[VINTR
] = 'C'&037; /* Control-C */
515 #else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
516 /* QUIT and INTR work better as signals, so disable character forms */
517 s
.main
.c_cc
[VQUIT
] = 0377;
518 s
.main
.c_cc
[VINTR
] = 0377;
519 s
.main
.c_lflag
&= ~ISIG
;
520 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
521 s
.main
.c_cc
[VEOL
] = 0377;
522 s
.main
.c_cflag
= (s
.main
.c_cflag
& ~CBAUD
) | B9600
; /* baud rate sanity */
525 #else /* not HAVE_TERMIO */
527 s
.main
.sg_flags
&= ~(ECHO
| CRMOD
| ANYP
| ALLDELAY
| RAW
| LCASE
529 s
.main
.sg_flags
|= LPASS8
;
530 s
.main
.sg_erase
= 0377;
531 s
.main
.sg_kill
= 0377;
532 s
.lmode
= LLITOUT
| s
.lmode
; /* Don't strip 8th bit */
534 #endif /* not HAVE_TERMIO */
536 EMACS_SET_TTY (out
, &s
, 0);
545 ioctl (out
, FIOASYNC
, &zero
);
548 #endif /* not MSDOS */
552 #endif /* subprocesses */
558 EMACS_SET_TTY_PGRP (input_fd
, &pid
);
561 /* Record a signal code and the handler for it. */
565 SIGTYPE (*handler
) ();
568 /* Suspend the Emacs process; give terminal to its superior. */
573 /* "Foster" parentage allows emacs to return to a subprocess that attached
574 to the current emacs as a cheaper than starting a whole new process. This
575 is set up by KEPTEDITOR.COM. */
576 unsigned long parent_id
, foster_parent_id
;
579 fpid_string
= getenv ("EMACS_PARENT_PID");
580 if (fpid_string
!= NULL
)
582 sscanf (fpid_string
, "%x", &foster_parent_id
);
583 if (foster_parent_id
!= 0)
584 parent_id
= foster_parent_id
;
586 parent_id
= getppid ();
589 parent_id
= getppid ();
591 xfree (fpid_string
); /* On VMS, this was malloc'd */
593 if (parent_id
&& parent_id
!= 0xffffffff)
595 SIGTYPE (*oldsig
)() = (int) signal (SIGINT
, SIG_IGN
);
596 int status
= LIB$
ATTACH (&parent_id
) & 1;
597 signal (SIGINT
, oldsig
);
606 d_prompt
.l
= sizeof ("Emacs: "); /* Our special prompt */
607 d_prompt
.a
= "Emacs: "; /* Just a reminder */
608 LIB$
SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt
, 0);
613 #if defined(SIGTSTP) && !defined(MSDOS)
616 int pgrp
= EMACS_GETPGRP (0);
617 EMACS_KILLPG (pgrp
, SIGTSTP
);
620 #else /* No SIGTSTP */
621 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
622 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
623 kill (getpid (), SIGQUIT
);
625 #else /* No SIGTSTP or USG_JOBCTRL */
627 /* On a system where suspending is not implemented,
628 instead fork a subshell and let it talk directly to the terminal
632 #endif /* no USG_JOBCTRL */
633 #endif /* no SIGTSTP */
637 /* Fork a subshell. */
642 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
644 char oldwd
[MAXPATHLEN
+1]; /* Fixed length is safe on MSDOS. */
647 struct save_signal saved_handlers
[5];
649 saved_handlers
[0].code
= SIGINT
;
650 saved_handlers
[1].code
= SIGQUIT
;
651 saved_handlers
[2].code
= SIGTERM
;
653 saved_handlers
[3].code
= SIGIO
;
654 saved_handlers
[4].code
= 0;
656 saved_handlers
[3].code
= 0;
660 error ("Can't spawn subshell");
665 #ifdef MSDOS /* MW, Aug 1993 */
668 sh
= (char *) egetenv ("SHELL");
672 /* Use our buffer's default directory for the subshell. */
678 /* mentioning current_buffer->buffer would mean including buffer.h,
679 which somehow wedges the hp compiler. So instead... */
681 dir
= intern ("default-directory");
683 if (XFASTINT (Fboundp (dir
)) == XFASTINT (Qnil
))
685 dir
= Fsymbol_value (dir
);
686 if (XTYPE (dir
) != Lisp_String
)
689 str
= (unsigned char *) alloca (XSTRING (dir
)->size
+ 2);
690 len
= XSTRING (dir
)->size
;
691 bcopy (XSTRING (dir
)->data
, str
, len
);
692 if (str
[len
- 1] != '/') str
[len
++] = '/';
698 close_process_descs (); /* Close Emacs's pipes/ptys */
701 #ifdef SET_EMACS_PRIORITY
703 extern int emacs_priority
;
705 if (emacs_priority
< 0)
706 nice (-emacs_priority
);
710 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
714 report_file_error ("Can't execute subshell", Fcons (build_string (sh
), Qnil
));
715 #else /* not MSDOS */
717 write (1, "Can't execute subshell", 22);
719 #endif /* not MSDOS */
722 save_signal_handlers (saved_handlers
);
723 synch_process_alive
= 1;
724 wait_for_termination (pid
);
725 restore_signal_handlers (saved_handlers
);
729 save_signal_handlers (saved_handlers
)
730 struct save_signal
*saved_handlers
;
732 while (saved_handlers
->code
)
734 saved_handlers
->handler
735 = (SIGTYPE (*) ()) signal (saved_handlers
->code
, SIG_IGN
);
740 restore_signal_handlers (saved_handlers
)
741 struct save_signal
*saved_handlers
;
743 while (saved_handlers
->code
)
745 signal (saved_handlers
->code
, saved_handlers
->handler
);
757 old_fcntl_flags
= fcntl (input_fd
, F_GETFL
, 0) & ~FASYNC
;
767 #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
772 sigunblock (sigmask (SIGWINCH
));
774 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
| FASYNC
);
776 interrupts_deferred
= 0;
782 sigblock (sigmask (SIGWINCH
));
784 fcntl (input_fd
, F_SETFL
, old_fcntl_flags
);
785 interrupts_deferred
= 1;
788 #else /* no FASYNC */
789 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
794 ioctl (input_fd
, FIOASYNC
, &on
);
795 interrupts_deferred
= 0;
802 ioctl (input_fd
, FIOASYNC
, &off
);
803 interrupts_deferred
= 1;
806 #else /* not FASYNC, not STRIDE */
818 sigaddset(&st
, SIGIO
);
819 ioctl (input_fd
, FIOASYNC
, &on
);
820 interrupts_deferred
= 0;
821 sigprocmask(SIG_UNBLOCK
, &st
, (sigset_t
*)0);
828 ioctl (input_fd
, FIOASYNC
, &off
);
829 interrupts_deferred
= 1;
836 croak ("request_sigio");
841 croak ("unrequest_sigio");
849 /* Saving and restoring the process group of Emacs's terminal. */
853 /* The process group of which Emacs was a member when it initially
856 If Emacs was in its own process group (i.e. inherited_pgroup ==
857 getpid ()), then we know we're running under a shell with job
858 control (Emacs would never be run as part of a pipeline).
861 If Emacs was not in its own process group, then we know we're
862 running under a shell (or a caller) that doesn't know how to
863 separate itself from Emacs (like sh). Emacs must be in its own
864 process group in order to receive SIGIO correctly. In this
865 situation, we put ourselves in our own pgroup, forcibly set the
866 tty's pgroup to our pgroup, and make sure to restore and reinstate
867 the tty's pgroup just like any other terminal setting. If
868 inherited_group was not the tty's pgroup, then we'll get a
869 SIGTTmumble when we try to change the tty's pgroup, and a CONT if
870 it goes foreground in the future, which is what should happen. */
871 int inherited_pgroup
;
873 /* Split off the foreground process group to Emacs alone.
874 When we are in the foreground, but not started in our own process
875 group, redirect the TTY to point to our own process group. We need
876 to be in our own process group to receive SIGIO properly. */
877 narrow_foreground_group ()
881 setpgrp (0, inherited_pgroup
);
882 if (inherited_pgroup
!= me
)
883 EMACS_SET_TTY_PGRP (input_fd
, &me
);
887 /* Set the tty to our original foreground group. */
888 widen_foreground_group ()
890 if (inherited_pgroup
!= getpid ())
891 EMACS_SET_TTY_PGRP (input_fd
, &inherited_pgroup
);
892 setpgrp (0, inherited_pgroup
);
895 #endif /* BSD_PGRPS */
897 /* Getting and setting emacs_tty structures. */
899 /* Set *TC to the parameters associated with the terminal FD.
900 Return zero if all's well, or -1 if we ran into an error we
901 couldn't deal with. */
903 emacs_get_tty (fd
, settings
)
905 struct emacs_tty
*settings
;
907 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
909 /* We have those nifty POSIX tcmumbleattr functions. */
910 if (tcgetattr (fd
, &settings
->main
) < 0)
915 /* The SYSV-style interface? */
916 if (ioctl (fd
, TCGETA
, &settings
->main
) < 0)
921 /* Vehemently Monstrous System? :-) */
922 if (! (SYS$
QIOW (0, fd
, IO$_SENSEMODE
, settings
, 0, 0,
923 &settings
->main
.class, 12, 0, 0, 0, 0)
929 /* I give up - I hope you have the BSD ioctls. */
930 if (ioctl (fd
, TIOCGETP
, &settings
->main
) < 0)
932 #endif /* not MSDOS */
937 /* Suivant - Do we have to get struct ltchars data? */
939 if (ioctl (fd
, TIOCGLTC
, &settings
->ltchars
) < 0)
943 /* How about a struct tchars and a wordful of lmode bits? */
945 if (ioctl (fd
, TIOCGETC
, &settings
->tchars
) < 0
946 || ioctl (fd
, TIOCLGET
, &settings
->lmode
) < 0)
950 /* We have survived the tempest. */
955 /* Set the parameters of the tty on FD according to the contents of
956 *SETTINGS. If WAITP is non-zero, we wait for all queued output to
957 be written before making the change; otherwise, we forget any
958 queued input and make the change immediately.
959 Return 0 if all went well, and -1 if anything failed. */
961 emacs_set_tty (fd
, settings
, waitp
)
963 struct emacs_tty
*settings
;
966 /* Set the primary parameters - baud rate, character size, etcetera. */
969 /* We have those nifty POSIX tcmumbleattr functions.
970 William J. Smith <wjs@wiis.wang.com> writes:
971 "POSIX 1003.1 defines tcsetattr() to return success if it was
972 able to perform any of the requested actions, even if some
973 of the requested actions could not be performed.
974 We must read settings back to ensure tty setup properly.
975 AIX requires this to keep tty from hanging occasionally." */
976 /* This make sure that we don't loop indefinitely in here. */
977 for (i
= 0 ; i
< 10 ; i
++)
978 if (tcsetattr (fd
, waitp
? TCSAFLUSH
: TCSADRAIN
, &settings
->main
) < 0)
989 /* Get the current settings, and see if they're what we asked for. */
990 tcgetattr (fd
, &new);
991 /* We cannot use memcmp on the whole structure here because under
992 * aix386 the termios structure has some reserved field that may
995 if ( new.c_iflag
== settings
->main
.c_iflag
996 && new.c_oflag
== settings
->main
.c_oflag
997 && new.c_cflag
== settings
->main
.c_cflag
998 && new.c_lflag
== settings
->main
.c_lflag
999 && memcmp(new.c_cc
, settings
->main
.c_cc
, NCCS
) == 0)
1007 /* The SYSV-style interface? */
1008 if (ioctl (fd
, waitp
? TCSETAW
: TCSETAF
, &settings
->main
) < 0)
1013 /* Vehemently Monstrous System? :-) */
1014 if (! (SYS$
QIOW (0, fd
, IO$_SETMODE
, &input_iosb
, 0, 0,
1015 &settings
->main
.class, 12, 0, 0, 0, 0)
1021 /* I give up - I hope you have the BSD ioctls. */
1022 if (ioctl (fd
, (waitp
) ? TIOCSETP
: TIOCSETN
, &settings
->main
) < 0)
1024 #endif /* not MSDOS */
1030 /* Suivant - Do we have to get struct ltchars data? */
1032 if (ioctl (fd
, TIOCSLTC
, &settings
->ltchars
) < 0)
1036 /* How about a struct tchars and a wordful of lmode bits? */
1038 if (ioctl (fd
, TIOCSETC
, &settings
->tchars
) < 0
1039 || ioctl (fd
, TIOCLSET
, &settings
->lmode
) < 0)
1043 /* We have survived the tempest. */
1048 /* The initial tty mode bits */
1049 struct emacs_tty old_tty
;
1051 int term_initted
; /* 1 if outer tty status has been recorded */
1054 /* BSD 4.1 needs to keep track of the lmode bits in order to start
1059 #ifndef F_SETOWN_BUG
1061 int old_fcntl_owner
;
1062 #endif /* F_SETOWN */
1063 #endif /* F_SETOWN_BUG */
1065 /* This may also be defined in stdio,
1066 but if so, this does no harm,
1067 and using the same name avoids wasting the other one's space. */
1069 #if defined (USG) || defined (DGUX)
1070 unsigned char _sobuf
[BUFSIZ
+8];
1072 char _sobuf
[BUFSIZ
];
1076 static struct ltchars new_ltchars
= {-1,-1,-1,-1,-1,-1};
1079 static struct tchars new_tchars
= {-1,-1,-1,-1,-1,-1};
1084 struct emacs_tty tty
;
1088 static int oob_chars
[2] = {0, 1 << 7}; /* catch C-g's */
1089 extern int (*interrupt_signal
) ();
1098 input_ef
= get_kbd_event_flag ();
1099 /* LIB$GET_EF (&input_ef); */
1100 SYS$
CLREF (input_ef
);
1101 waiting_for_ast
= 0;
1103 timer_ef
= get_timer_event_flag ();
1104 /* LIB$GET_EF (&timer_ef); */
1105 SYS$
CLREF (timer_ef
);
1109 LIB$
GET_EF (&process_ef
);
1110 SYS$
CLREF (process_ef
);
1112 if (input_ef
/ 32 != process_ef
/ 32)
1113 croak ("Input and process event flags in different clusters.");
1115 if (input_ef
/ 32 != timer_ef
/ 32)
1116 croak ("Input and timer event flags in different clusters.");
1118 input_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1119 ((unsigned) 1 << (process_ef
% 32));
1121 timer_eflist
= ((unsigned) 1 << (input_ef
% 32)) |
1122 ((unsigned) 1 << (timer_ef
% 32));
1124 sys_access_reinit ();
1126 #endif /* not VMS */
1129 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1130 narrow_foreground_group ();
1133 EMACS_GET_TTY (input_fd
, &old_tty
);
1135 if (!read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1139 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1141 /* This allows meta to be sent on 8th bit. */
1142 tty
.main
.c_iflag
&= ~INPCK
; /* don't check input for parity */
1144 tty
.main
.c_iflag
|= (IGNBRK
); /* Ignore break condition */
1145 tty
.main
.c_iflag
&= ~ICRNL
; /* Disable map of CR to NL on input */
1147 tty
.main
.c_iflag
&= ~ISTRIP
; /* don't strip 8th bit on input */
1149 tty
.main
.c_lflag
&= ~ECHO
; /* Disable echo */
1150 tty
.main
.c_lflag
&= ~ICANON
; /* Disable erase/kill processing */
1152 tty
.main
.c_lflag
&= ~IEXTEN
; /* Disable other editing characters. */
1154 tty
.main
.c_lflag
|= ISIG
; /* Enable signals */
1157 tty
.main
.c_iflag
|= IXON
; /* Enable start/stop output control */
1159 tty
.main
.c_iflag
&= ~IXANY
;
1163 tty
.main
.c_iflag
&= ~IXON
; /* Disable start/stop output control */
1164 tty
.main
.c_oflag
&= ~ONLCR
; /* Disable map of NL to CR-NL
1166 tty
.main
.c_oflag
&= ~TAB3
; /* Disable tab expansion */
1170 tty
.main
.c_cflag
|= CS8
; /* allow 8th bit on input */
1171 tty
.main
.c_cflag
&= ~PARENB
;/* Don't check parity */
1174 tty
.main
.c_cc
[VINTR
] = quit_char
; /* C-g (usually) gives SIGINT */
1175 /* Set up C-g for both SIGQUIT and SIGINT.
1176 We don't know which we will get, but we handle both alike
1177 so which one it really gives us does not matter. */
1178 tty
.main
.c_cc
[VQUIT
] = quit_char
;
1179 tty
.main
.c_cc
[VMIN
] = 1; /* Input should wait for at least 1 char */
1180 tty
.main
.c_cc
[VTIME
] = 0; /* no matter how long that takes. */
1182 tty
.main
.c_cc
[VSWTCH
] = CDISABLE
; /* Turn off shell layering use
1185 #if defined (mips) || defined (HAVE_TCATTR)
1187 tty
.main
.c_cc
[VSUSP
] = CDISABLE
; /* Turn off mips handling of C-z. */
1190 tty
.main
.c_cc
[V_DSUSP
] = CDISABLE
; /* Turn off mips handling of C-y. */
1191 #endif /* V_DSUSP */
1192 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1193 tty
.main
.c_cc
[VDSUSP
] = CDISABLE
;
1196 tty
.main
.c_cc
[VLNEXT
] = CDISABLE
;
1199 tty
.main
.c_cc
[VREPRINT
] = CDISABLE
;
1200 #endif /* VREPRINT */
1202 tty
.main
.c_cc
[VWERASE
] = CDISABLE
;
1203 #endif /* VWERASE */
1205 tty
.main
.c_cc
[VDISCARD
] = CDISABLE
;
1206 #endif /* VDISCARD */
1208 tty
.main
.c_cc
[VSTART
] = CDISABLE
;
1211 tty
.main
.c_cc
[VSTOP
] = CDISABLE
;
1213 #endif /* mips or HAVE_TCATTR */
1216 /* AIX enhanced edit loses NULs, so disable it */
1217 tty
.main
.c_line
= 0;
1218 tty
.main
.c_iflag
&= ~ASCEDIT
;
1220 tty
.main
.c_cc
[VSTRT
] = 255;
1221 tty
.main
.c_cc
[VSTOP
] = 255;
1222 tty
.main
.c_cc
[VSUSP
] = 255;
1223 tty
.main
.c_cc
[VDSUSP
] = 255;
1224 #endif /* IBMR2AIX */
1225 /* Also, PTY overloads NUL and BREAK.
1226 don't ignore break, but don't signal either, so it looks like NUL.
1227 This really serves a purpose only if running in an XTERM window
1228 or via TELNET or the like, but does no harm elsewhere. */
1229 tty
.main
.c_iflag
&= ~IGNBRK
;
1230 tty
.main
.c_iflag
&= ~BRKINT
;
1232 #else /* if not HAVE_TERMIO */
1234 tty
.main
.tt_char
|= TT$M_NOECHO
;
1236 tty
.main
.tt_char
|= TT$M_EIGHTBIT
;
1238 tty
.main
.tt_char
|= TT$M_TTSYNC
;
1240 tty
.main
.tt_char
&= ~TT$M_TTSYNC
;
1241 tty
.main
.tt2_char
|= TT2$M_PASTHRU
| TT2$M_XON
;
1242 #else /* not VMS (BSD, that is) */
1244 tty
.main
.sg_flags
&= ~(ECHO
| CRMOD
| XTABS
);
1246 tty
.main
.sg_flags
|= ANYP
;
1247 tty
.main
.sg_flags
|= interrupt_input
? RAW
: CBREAK
;
1249 #endif /* not VMS (BSD, that is) */
1250 #endif /* not HAVE_TERMIO */
1252 /* If going to use CBREAK mode, we must request C-g to interrupt
1253 and turn off start and stop chars, etc. If not going to use
1254 CBREAK mode, do this anyway so as to turn off local flow
1255 control for user coming over network on 4.2; in this case,
1256 only t_stopc and t_startc really matter. */
1259 /* Note: if not using CBREAK mode, it makes no difference how we
1261 tty
.tchars
= new_tchars
;
1262 tty
.tchars
.t_intrc
= quit_char
;
1265 tty
.tchars
.t_startc
= '\021';
1266 tty
.tchars
.t_stopc
= '\023';
1269 tty
.lmode
= LDECCTQ
| LLITOUT
| LPASS8
| LNOFLSH
| old_tty
.lmode
;
1271 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1272 anything, and leaving it in breaks the meta key. Go figure. */
1273 tty
.lmode
&= ~LLITOUT
;
1280 #endif /* HAVE_TCHARS */
1281 #endif /* not HAVE_TERMIO */
1284 tty
.ltchars
= new_ltchars
;
1285 #endif /* HAVE_LTCHARS */
1286 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1287 internal_terminal_init ();
1291 EMACS_SET_TTY (input_fd
, &tty
, 0);
1293 /* This code added to insure that, if flow-control is not to be used,
1294 we have an unlocked terminal at the start. */
1297 if (!flow_control
) ioctl (input_fd
, TCXONC
, 1);
1301 if (!flow_control
) ioctl (input_fd
, TIOCSTART
, 0);
1309 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1310 to be only LF. This is the way that is done. */
1313 if (ioctl (1, HFTGETID
, &tty
) != -1)
1314 write (1, "\033[20l", 5);
1320 /* Appears to do nothing when in PASTHRU mode.
1321 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1322 interrupt_signal, oob_chars, 0, 0, 0, 0);
1324 queue_kbd_input (0);
1329 #ifndef F_SETOWN_BUG
1330 #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
1332 && ! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1334 old_fcntl_owner
= fcntl (input_fd
, F_GETOWN
, 0);
1335 fcntl (input_fd
, F_SETOWN
, getpid ());
1338 #endif /* F_GETOWN */
1339 #endif /* F_SETOWN_BUG */
1340 #endif /* F_SETFL */
1343 if (interrupt_input
)
1347 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1351 /* This symbol is defined on recent USG systems.
1352 Someone says without this call USG won't really buffer the file
1353 even with a call to setbuf. */
1354 setvbuf (stdout
, _sobuf
, _IOFBF
, sizeof _sobuf
);
1356 setbuf (stdout
, _sobuf
);
1358 if (! read_socket_hook
&& EQ (Vwindow_system
, Qnil
))
1359 set_terminal_modes ();
1361 if (term_initted
&& no_redraw_on_reenter
)
1363 if (display_completed
)
1364 direct_output_forward_char (0);
1370 if (FRAMEP (Vterminal_frame
))
1371 FRAME_GARBAGED_P (XFRAME (Vterminal_frame
)) = 1;
1378 /* Return nonzero if safe to use tabs in output.
1379 At the time this is called, init_sys_modes has not been done yet. */
1383 struct emacs_tty tty
;
1385 EMACS_GET_TTY (input_fd
, &tty
);
1386 return EMACS_TTY_TABS_OK (&tty
);
1389 /* Get terminal size from system.
1390 Store number of lines into *HEIGHTP and width into *WIDTHP.
1391 We store 0 if there's no valid information. */
1393 get_frame_size (widthp
, heightp
)
1394 int *widthp
, *heightp
;
1400 struct winsize size
;
1402 if (ioctl (input_fd
, TIOCGWINSZ
, &size
) == -1)
1403 *widthp
= *heightp
= 0;
1406 *widthp
= size
.ws_col
;
1407 *heightp
= size
.ws_row
;
1413 /* SunOS - style. */
1414 struct ttysize size
;
1416 if (ioctl (input_fd
, TIOCGSIZE
, &size
) == -1)
1417 *widthp
= *heightp
= 0;
1420 *widthp
= size
.ts_cols
;
1421 *heightp
= size
.ts_lines
;
1427 struct sensemode tty
;
1429 SYS$
QIOW (0, input_fd
, IO$_SENSEMODE
, &tty
, 0, 0,
1430 &tty
.class, 12, 0, 0, 0, 0);
1431 *widthp
= tty
.scr_wid
;
1432 *heightp
= tty
.scr_len
;
1436 *widthp
= ScreenCols ();
1437 *heightp
= ScreenRows ();
1438 #else /* system doesn't know size */
1443 #endif /* not VMS */
1444 #endif /* not SunOS-style */
1445 #endif /* not BSD-style */
1448 /* Set the logical window size associated with descriptor FD
1449 to HEIGHT and WIDTH. This is used mainly with ptys. */
1452 set_window_size (fd
, height
, width
)
1453 int fd
, height
, width
;
1458 struct winsize size
;
1459 size
.ws_row
= height
;
1460 size
.ws_col
= width
;
1462 if (ioctl (fd
, TIOCSWINSZ
, &size
) == -1)
1463 return 0; /* error */
1470 /* SunOS - style. */
1471 struct ttysize size
;
1472 size
.ts_lines
= height
;
1473 size
.ts_cols
= width
;
1475 if (ioctl (fd
, TIOCGSIZE
, &size
) == -1)
1481 #endif /* not SunOS-style */
1482 #endif /* not BSD-style */
1486 /* Prepare the terminal for exiting Emacs; move the cursor to the
1487 bottom of the frame, turn off interrupt-driven I/O, etc. */
1497 if (read_socket_hook
|| !EQ (Vwindow_system
, Qnil
))
1499 cursor_to (FRAME_HEIGHT (selected_frame
) - 1, 0);
1500 clear_end_of_line (FRAME_WIDTH (selected_frame
));
1501 /* clear_end_of_line may move the cursor */
1502 cursor_to (FRAME_HEIGHT (selected_frame
) - 1, 0);
1505 /* HFT devices normally use ^J as a LF/CR. We forced it to
1506 do the LF only. Now, we need to reset it. */
1509 if (ioctl (1, HFTGETID
, &tty
) != -1)
1510 write (1, "\033[20h", 5);
1514 reset_terminal_modes ();
1518 /* Avoid possible loss of output when changing terminal modes. */
1519 fsync (fileno (stdout
));
1524 #ifndef F_SETOWN_BUG
1525 #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1526 if (interrupt_input
)
1529 fcntl (input_fd
, F_SETOWN
, old_fcntl_owner
);
1531 #endif /* F_SETOWN */
1532 #endif /* F_SETOWN_BUG */
1534 fcntl (input_fd
, F_SETFL
, fcntl (input_fd
, F_GETFL
, 0) & ~O_NDELAY
);
1536 #endif /* F_SETFL */
1538 if (interrupt_input
)
1542 while (EMACS_SET_TTY (input_fd
, &old_tty
, 0) < 0 && errno
== EINTR
)
1545 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1554 widen_foreground_group ();
1560 /* Set up the proper status flags for use of a pty. */
1565 /* I'm told that TOICREMOTE does not mean control chars
1566 "can't be sent" but rather that they don't have
1567 input-editing or signaling effects.
1568 That should be good, because we have other ways
1569 to do those things in Emacs.
1570 However, telnet mode seems not to work on 4.2.
1571 So TIOCREMOTE is turned off now. */
1573 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1574 will hang. In particular, the "timeout" feature (which
1575 causes a read to return if there is no data available)
1576 does this. Also it is known that telnet mode will hang
1577 in such a way that Emacs must be stopped (perhaps this
1578 is the same problem).
1580 If TIOCREMOTE is turned off, then there is a bug in
1581 hp-ux which sometimes loses data. Apparently the
1582 code which blocks the master process when the internal
1583 buffer fills up does not work. Other than this,
1584 though, everything else seems to work fine.
1586 Since the latter lossage is more benign, we may as well
1587 lose that way. -- cph */
1592 ioctl (fd
, FIONBIO
, &on
);
1597 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1598 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1599 /* cause EMACS not to die when it should, i.e., when its own controlling */
1600 /* tty goes away. I've complained to the AIX developers, and they may */
1601 /* change this behavior, but I'm not going to hold my breath. */
1602 signal (SIGHUP
, SIG_IGN
);
1605 #endif /* HAVE_PTYS */
1609 /* Assigning an input channel is done at the start of Emacs execution.
1610 This is called each time Emacs is resumed, also, but does nothing
1611 because input_chain is no longer zero. */
1619 status
= SYS$
ASSIGN (&input_dsc
, &input_fd
, 0, 0);
1625 /* Deassigning the input channel is done before exiting. */
1629 return SYS$
DASSGN (input_fd
);
1634 /* Request reading one character into the keyboard buffer.
1635 This is done as soon as the buffer becomes empty. */
1640 extern kbd_input_ast ();
1642 waiting_for_ast
= 0;
1644 status
= SYS$
QIO (0, input_fd
, IO$_READVBLK
,
1645 &input_iosb
, kbd_input_ast
, 1,
1646 &input_buffer
, 1, 0, terminator_mask
, 0, 0);
1651 /* Ast routine that is called when keyboard input comes in
1652 in accord with the SYS$QIO above. */
1656 register int c
= -1;
1657 int old_errno
= errno
;
1658 extern EMACS_TIME
*input_available_clear_time
;
1660 if (waiting_for_ast
)
1661 SYS$
SETEF (input_ef
);
1662 waiting_for_ast
= 0;
1665 if (input_count
== 25)
1667 printf ("Ast # %d,", input_count
);
1668 printf (" iosb = %x, %x, %x, %x",
1669 input_iosb
.offset
, input_iosb
.status
, input_iosb
.termlen
,
1672 if (input_iosb
.offset
)
1676 printf (", char = 0%o", c
);
1688 struct input_event e
;
1689 e
.kind
= ascii_keystroke
;
1690 XSET (e
.code
, Lisp_Int
, c
);
1692 XSET(e
.frame_or_window
, Lisp_Frame
, selected_frame
);
1694 e
.frame_or_window
= Qnil
;
1696 kbd_buffer_store_event (&e
);
1698 if (input_available_clear_time
)
1699 EMACS_SET_SECS_USECS (*input_available_clear_time
, 0, 0);
1703 /* Wait until there is something in kbd_buffer. */
1705 wait_for_kbd_input ()
1707 extern int have_process_input
, process_exited
;
1709 /* If already something, avoid doing system calls. */
1710 if (detect_input_pending ())
1714 /* Clear a flag, and tell ast routine above to set it. */
1715 SYS$
CLREF (input_ef
);
1716 waiting_for_ast
= 1;
1717 /* Check for timing error: ast happened while we were doing that. */
1718 if (!detect_input_pending ())
1720 /* No timing error: wait for flag to be set. */
1721 set_waiting_for_input (0);
1722 SYS$
WFLOR (input_ef
, input_eflist
);
1723 clear_waiting_for_input (0);
1724 if (!detect_input_pending ())
1725 /* Check for subprocess input availability */
1727 int dsp
= have_process_input
|| process_exited
;
1729 SYS$
CLREF (process_ef
);
1730 if (have_process_input
)
1731 process_command_input ();
1736 update_mode_lines
++;
1737 prepare_menu_bars ();
1738 redisplay_preserve_echo_area ();
1742 waiting_for_ast
= 0;
1745 /* Get rid of any pending QIO, when we are about to suspend
1746 or when we want to throw away pending input.
1747 We wait for a positive sign that the AST routine has run
1748 and therefore there is no I/O request queued when we return.
1749 SYS$SETAST is used to avoid a timing error. */
1754 printf ("At end_kbd_input.\n");
1758 if (LIB$
AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
1760 SYS$
CANCEL (input_fd
);
1765 /* Clear a flag, and tell ast routine above to set it. */
1766 SYS$
CLREF (input_ef
);
1767 waiting_for_ast
= 1;
1769 SYS$
CANCEL (input_fd
);
1771 SYS$
WAITFR (input_ef
);
1772 waiting_for_ast
= 0;
1775 /* Wait for either input available or time interval expiry. */
1777 input_wait_timeout (timeval
)
1778 int timeval
; /* Time to wait, in seconds */
1781 static int zero
= 0;
1782 static int large
= -10000000;
1784 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
1786 /* If already something, avoid doing system calls. */
1787 if (detect_input_pending ())
1791 /* Clear a flag, and tell ast routine above to set it. */
1792 SYS$
CLREF (input_ef
);
1793 waiting_for_ast
= 1;
1794 /* Check for timing error: ast happened while we were doing that. */
1795 if (!detect_input_pending ())
1797 /* No timing error: wait for flag to be set. */
1799 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
1800 SYS$
WFLOR (timer_ef
, timer_eflist
); /* Wait for timer expiry or input */
1802 waiting_for_ast
= 0;
1805 /* The standard `sleep' routine works some other way
1806 and it stops working if you have ever quit out of it.
1807 This one continues to work. */
1813 static int zero
= 0;
1814 static int large
= -10000000;
1816 LIB$
EMUL (&timeval
, &large
, &zero
, time
); /* Convert to VMS format */
1819 if (SYS$
SETIMR (timer_ef
, time
, 0, 1) & 1) /* Set timer */
1820 SYS$
WAITFR (timer_ef
); /* Wait for timer expiry only */
1835 croak ("request sigio");
1840 croak ("unrequest sigio");
1845 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1850 #ifndef SYSTEM_MALLOC
1857 /* Some systems that cannot dump also cannot implement these. */
1860 * Return the address of the start of the text segment prior to
1861 * doing an unexec. After unexec the return value is undefined.
1862 * See crt0.c for further explanation and _start.
1866 #if !defined (CANNOT_UNEXEC) && !defined (HAVE_TEXT_START)
1871 return ((char *) TEXT_START
);
1875 return ((char *) csrt
);
1876 #else /* not GOULD */
1877 extern int _start ();
1878 return ((char *) _start
);
1880 #endif /* TEXT_START */
1882 #endif /* not CANNOT_UNEXEC and not HAVE_TEXT_START */
1885 * Return the address of the start of the data segment prior to
1886 * doing an unexec. After unexec the return value is undefined.
1887 * See crt0.c for further information and definition of data_start.
1889 * Apparently, on BSD systems this is etext at startup. On
1890 * USG systems (swapping) this is highly mmu dependent and
1891 * is also dependent on whether or not the program is running
1892 * with shared text. Generally there is a (possibly large)
1893 * gap between end of text and start of data with shared text.
1895 * On Uniplus+ systems with shared text, data starts at a
1896 * fixed address. Each port (from a given oem) is generally
1897 * different, and the specific value of the start of data can
1898 * be obtained via the UniPlus+ specific "uvar" system call,
1899 * however the method outlined in crt0.c seems to be more portable.
1901 * Probably what will have to happen when a USG unexec is available,
1902 * at least on UniPlus, is temacs will have to be made unshared so
1903 * that text and data are contiguous. Then once loadup is complete,
1904 * unexec will produce a shared executable where the data can be
1905 * at the normal shared text boundry and the startofdata variable
1906 * will be patched by unexec to the correct value.
1914 return ((char *) DATA_START
);
1916 #ifdef ORDINARY_LINK
1918 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
1919 * data_start isn't defined. We take the address of environ, which
1920 * is known to live at or near the start of the system crt0.c, and
1921 * we don't sweat the handful of bytes that might lose.
1923 extern char **environ
;
1925 return((char *) &environ
);
1927 extern int data_start
;
1928 return ((char *) &data_start
);
1929 #endif /* ORDINARY_LINK */
1930 #endif /* DATA_START */
1932 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1935 /* Some systems that cannot dump also cannot implement these. */
1938 * Return the address of the end of the text segment prior to
1939 * doing an unexec. After unexec the return value is undefined.
1946 return ((char *) TEXT_END
);
1949 return ((char *) &etext
);
1954 * Return the address of the end of the data segment prior to
1955 * doing an unexec. After unexec the return value is undefined.
1962 return ((char *) DATA_END
);
1965 return ((char *) &edata
);
1969 #endif /* not CANNOT_DUMP */
1971 /* init_system_name sets up the string for the Lisp function
1972 system-name to return. */
1978 extern Lisp_Object Vsystem_name
;
1983 #include <sys/socket.h>
1985 #endif /* HAVE_SOCKETS */
1986 #endif /* not VMS */
1987 #endif /* not BSD4_1 */
1993 Vsystem_name
= build_string (sysname
);
1997 if ((sp
= egetenv ("SYS$NODE")) == 0)
1998 Vsystem_name
= build_string ("vax-vms");
1999 else if ((end
= index (sp
, ':')) == 0)
2000 Vsystem_name
= build_string (sp
);
2002 Vsystem_name
= make_string (sp
, end
- sp
);
2004 #ifndef HAVE_GETHOSTNAME
2007 Vsystem_name
= build_string (uts
.nodename
);
2008 #else /* HAVE_GETHOSTNAME */
2009 int hostname_size
= 256;
2010 char *hostname
= (char *) alloca (hostname_size
);
2012 /* Try to get the host name; if the buffer is too short, try
2013 again. Apparently, the only indication gethostname gives of
2014 whether the buffer was large enough is the presence or absence
2015 of a '\0' in the string. Eech. */
2018 gethostname (hostname
, hostname_size
- 1);
2019 hostname
[hostname_size
- 1] = '\0';
2021 /* Was the buffer large enough for the '\0'? */
2022 if (strlen (hostname
) < hostname_size
- 1)
2025 hostname_size
<<= 1;
2026 hostname
= (char *) alloca (hostname_size
);
2029 /* Turn the hostname into the official, fully-qualified hostname.
2030 Don't do this if we're going to dump; this can confuse system
2031 libraries on some machines and make the dumped emacs core dump. */
2034 #endif /* not CANNOT_DUMP */
2036 struct hostent
*hp
= gethostbyname (hostname
);
2039 char *fqdn
= hp
->h_name
;
2042 if (!index (fqdn
, '.'))
2044 /* We still don't have a fully qualified domain name.
2045 Try to find one in the list of alternate names */
2046 char **alias
= hp
->h_aliases
;
2047 while (*alias
&& !index (*alias
, '.'))
2054 /* Convert the host name to lower case. */
2055 /* Using ctype.h here would introduce a possible locale
2056 dependence that is probably wrong for hostnames. */
2060 if (*p
>= 'A' && *p
<= 'Z')
2067 #endif /* HAVE_SOCKETS */
2068 Vsystem_name
= build_string (hostname
);
2069 #endif /* HAVE_GETHOSTNAME */
2074 for (p
= XSTRING (Vsystem_name
)->data
; *p
; p
++)
2075 if (*p
== ' ' || *p
== '\t')
2083 #ifdef HAVE_X_WINDOWS
2084 /* Cause explanatory error message at compile time,
2085 since the select emulation is not good enough for X. */
2086 int *x
= &x_windows_lose_if_no_select_system_call
;
2089 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
2090 * Only checks read descriptors.
2092 /* How long to wait between checking fds in select */
2093 #define SELECT_PAUSE 1
2096 /* For longjmp'ing back to read_input_waiting. */
2098 jmp_buf read_alarm_throw
;
2100 /* Nonzero if the alarm signal should throw back to read_input_waiting.
2101 The read_socket_hook function sets this to 1 while it is waiting. */
2103 int read_alarm_should_throw
;
2111 #else /* not BSD4_1 */
2112 signal (SIGALRM
, SIG_IGN
);
2113 #endif /* not BSD4_1 */
2114 if (read_alarm_should_throw
)
2115 longjmp (read_alarm_throw
, 1);
2118 /* Only rfds are checked. */
2120 select (nfds
, rfds
, wfds
, efds
, timeout
)
2122 int *rfds
, *wfds
, *efds
, *timeout
;
2124 int ravail
= 0, orfds
= 0, old_alarm
;
2125 int timeoutval
= timeout
? *timeout
: 100000;
2126 int *local_timeout
= &timeoutval
;
2127 extern int proc_buffered_char
[];
2128 #ifndef subprocesses
2129 int process_tick
= 0, update_tick
= 0;
2131 extern int process_tick
, update_tick
;
2133 SIGTYPE (*old_trap
) ();
2146 /* If we are looking only for the terminal, with no timeout,
2147 just read it and wait -- that's more efficient. */
2148 if (orfds
== 1 && *local_timeout
== 100000 && process_tick
== update_tick
)
2150 if (! detect_input_pending ())
2151 read_input_waiting ();
2156 /* Once a second, till the timer expires, check all the flagged read
2157 * descriptors to see if any input is available. If there is some then
2158 * set the corresponding bit in the return copy of rfds.
2162 register int to_check
, bit
, fd
;
2166 for (to_check
= nfds
, bit
= 1, fd
= 0; --to_check
>= 0; bit
<<= 1, fd
++)
2170 int avail
= 0, status
= 0;
2173 avail
= detect_input_pending (); /* Special keyboard handler */
2177 status
= ioctl (fd
, FIONREAD
, &avail
);
2178 #else /* no FIONREAD */
2180 abort (); /* I don't think we need it. */
2181 #else /* not MSDOS */
2182 /* Hoping it will return -1 if nothing available
2183 or 0 if all 0 chars requested are read. */
2184 if (proc_buffered_char
[fd
] >= 0)
2188 avail
= read (fd
, &buf
, 1);
2190 proc_buffered_char
[fd
] = buf
;
2192 #endif /* not MSDOS */
2193 #endif /* no FIONREAD */
2195 if (status
>= 0 && avail
> 0)
2203 if (*local_timeout
== 0 || ravail
!= 0 || process_tick
!= update_tick
)
2205 old_alarm
= alarm (0);
2206 old_trap
= signal (SIGALRM
, select_alarm
);
2208 alarm (SELECT_PAUSE
);
2209 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2210 while (select_alarmed
== 0 && *local_timeout
!= 0
2211 && process_tick
== update_tick
)
2214 sleep_or_kbd_hit (SELECT_PAUSE
, (orfds
& 1) != 0);
2216 #else /* not MSDOS */
2217 /* If we are interested in terminal input,
2218 wait by reading the terminal.
2219 That makes instant wakeup for terminal input at least. */
2222 read_input_waiting ();
2223 if (detect_input_pending ())
2228 #endif /* not MSDOS */
2230 (*local_timeout
) -= SELECT_PAUSE
;
2231 /* Reset the old alarm if there was one */
2233 signal (SIGALRM
, old_trap
);
2236 /* Reset or forge an interrupt for the original handler. */
2237 old_alarm
-= SELECT_PAUSE
;
2239 kill (getpid (), SIGALRM
); /* Fake an alarm with the orig' handler */
2243 if (*local_timeout
== 0) /* Stop on timer being cleared */
2249 /* Read keyboard input into the standard buffer,
2250 waiting for at least one character. */
2252 /* Make all keyboard buffers much bigger when using X windows. */
2253 #ifdef HAVE_X_WINDOWS
2254 #define BUFFER_SIZE_FACTOR 16
2256 #define BUFFER_SIZE_FACTOR 1
2259 read_input_waiting ()
2261 struct input_event e
;
2263 extern int quit_char
;
2265 if (read_socket_hook
)
2267 struct input_event buf
[256];
2269 read_alarm_should_throw
= 0;
2270 if (! setjmp (read_alarm_throw
))
2271 nread
= (*read_socket_hook
) (0, buf
, 256, 1, 0);
2275 /* Scan the chars for C-g and store them in kbd_buffer. */
2276 for (i
= 0; i
< nread
; i
++)
2278 kbd_buffer_store_event (&buf
[i
]);
2279 /* Don't look at input that follows a C-g too closely.
2280 This reduces lossage due to autorepeat on C-g. */
2281 if (buf
[i
].kind
== ascii_keystroke
2282 && XINT(buf
[i
].code
) == quit_char
)
2289 nread
= read (fileno (stdin
), buf
, 1);
2291 /* Scan the chars for C-g and store them in kbd_buffer. */
2292 e
.kind
= ascii_keystroke
;
2293 e
.frame_or_window
= selected_frame
;
2295 for (i
= 0; i
< nread
; i
++)
2297 /* Convert chars > 0177 to meta events if desired.
2298 We do this under the same conditions that read_avail_input does. */
2299 if (read_socket_hook
== 0)
2301 /* If the user says she has a meta key, then believe her. */
2302 if (meta_key
== 1 && (buf
[i
] & 0x80))
2303 e
.modifiers
= meta_modifier
;
2308 XSET (e
.code
, Lisp_Int
, buf
[i
]);
2309 kbd_buffer_store_event (&e
);
2310 /* Don't look at input that follows a C-g too closely.
2311 This reduces lossage due to autorepeat on C-g. */
2312 if (buf
[i
] == quit_char
)
2318 #endif /* not HAVE_SELECT */
2319 #endif /* not VMS */
2323 * Partially emulate 4.2 open call.
2324 * open is defined as this in 4.1.
2326 * - added by Michael Bloom @ Citicorp/TTI
2331 sys_open (path
, oflag
, mode
)
2335 if (oflag
& O_CREAT
)
2336 return creat (path
, mode
);
2338 return open (path
, oflag
);
2345 lmode
= LINTRUP
| lmode
;
2346 ioctl (0, TIOCLSET
, &lmode
);
2353 lmode
= ~LINTRUP
& lmode
;
2354 ioctl (0, TIOCLSET
, &lmode
);
2361 interrupts_deferred
= 0;
2368 interrupts_deferred
= 1;
2371 /* still inside #ifdef BSD4_1 */
2374 int sigheld
; /* Mask of held signals */
2379 sigheld
|= sigbit (signum
);
2386 sigheld
|= sigbit (signum
);
2392 sigheld
&= ~sigbit (signum
);
2396 sigfree () /* Free all held signals */
2399 for (i
= 0; i
< NSIG
; i
++)
2400 if (sigheld
& sigbit (i
))
2407 return 1 << (i
- 1);
2409 #endif /* subprocesses */
2412 /* POSIX signals support - DJB */
2413 /* Anyone with POSIX signals should have ANSI C declarations */
2415 #ifdef POSIX_SIGNALS
2417 sigset_t old_mask
, empty_mask
, full_mask
, temp_mask
;
2418 static struct sigaction new_action
, old_action
;
2422 sigemptyset (&empty_mask
);
2423 sigfillset (&full_mask
);
2427 sys_signal (int signal_number
, signal_handler_t action
)
2430 /* This gets us restartable system calls for efficiency.
2431 The "else" code will works as well. */
2432 return (berk_signal (signal_number
, action
));
2434 sigemptyset (&new_action
.sa_mask
);
2435 new_action
.sa_handler
= action
;
2437 /* Emacs mostly works better with restartable system services. If this
2438 * flag exists, we probably want to turn it on here.
2440 new_action
.sa_flags
= SA_RESTART
;
2442 new_action
.sa_flags
= 0;
2444 sigaction (signal_number
, &new_action
, &old_action
);
2445 return (old_action
.sa_handler
);
2450 /* If we're compiling with GCC, we don't need this function, since it
2451 can be written as a macro. */
2453 sys_sigmask (int sig
)
2456 sigemptyset (&mask
);
2457 sigaddset (&mask
, sig
);
2463 sys_sigpause (sigset_t new_mask
)
2465 /* pause emulating berk sigpause... */
2466 sigsuspend (&new_mask
);
2470 /* I'd like to have these guys return pointers to the mask storage in here,
2471 but there'd be trouble if the code was saving multiple masks. I'll be
2472 safe and pass the structure. It normally won't be more than 2 bytes
2476 sys_sigblock (sigset_t new_mask
)
2479 sigprocmask (SIG_BLOCK
, &new_mask
, &old_mask
);
2484 sys_sigunblock (sigset_t new_mask
)
2487 sigprocmask (SIG_UNBLOCK
, &new_mask
, &old_mask
);
2492 sys_sigsetmask (sigset_t new_mask
)
2495 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
2499 #endif /* POSIX_SIGNALS */
2508 register int length
;
2512 long max_str
= 65535;
2514 while (length
> max_str
) {
2515 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
2520 (void) LIB$
MOVC5 (&zero
, &zero
, &zero
, &max_str
, b
);
2522 while (length
-- > 0)
2524 #endif /* not VMS */
2527 #endif /* no bzero */
2530 /* Saying `void' requires a declaration, above, where bcopy is used
2531 and that declaration causes pain for systems where bcopy is a macro. */
2532 bcopy (b1
, b2
, length
)
2535 register int length
;
2538 long max_str
= 65535;
2540 while (length
> max_str
) {
2541 (void) LIB$
MOVC3 (&max_str
, b1
, b2
);
2547 (void) LIB$
MOVC3 (&length
, b1
, b2
);
2549 while (length
-- > 0)
2551 #endif /* not VMS */
2553 #endif /* no bcopy */
2557 bcmp (b1
, b2
, length
) /* This could be a macro! */
2560 register int length
;
2563 struct dsc$descriptor_s src1
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b1
};
2564 struct dsc$descriptor_s src2
= {length
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, b2
};
2566 return STR$
COMPARE (&src1
, &src2
);
2568 while (length
-- > 0)
2573 #endif /* not VMS */
2575 #endif /* no bcmp */
2577 #endif /* not BSTRING */
2582 * The BSD random returns numbers in the range of
2583 * 0 to 2e31 - 1. The USG rand returns numbers in the
2584 * range of 0 to 2e15 - 1. This is probably not significant
2591 /* Arrange to return a range centered on zero. */
2592 return (rand () << 15) + rand () - (1 << 29);
2606 /* Arrange to return a range centered on zero. */
2607 return (rand () << 15) + rand () - (1 << 29);
2618 #ifdef WRONG_NAME_INSQUE
2631 /* If any place else asks for the TERM variable,
2632 allow it to be overridden with the EMACS_TERM variable
2633 before attempting to translate the logical name TERM. As a last
2634 resort, ask for VAX C's special idea of the TERM variable. */
2641 static char buf
[256];
2642 static struct dsc$descriptor_s equiv
2643 = {sizeof (buf
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, buf
};
2644 static struct dsc$descriptor_s d_name
2645 = {0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, 0};
2648 if (!strcmp (name
, "TERM"))
2650 val
= (char *) getenv ("EMACS_TERM");
2655 d_name
.dsc$w_length
= strlen (name
);
2656 d_name
.dsc$a_pointer
= name
;
2657 if (LIB$
SYS_TRNLOG (&d_name
, &eqlen
, &equiv
) == 1)
2659 char *str
= (char *) xmalloc (eqlen
+ 1);
2660 bcopy (buf
, str
, eqlen
);
2662 /* This is a storage leak, but a pain to fix. With luck,
2663 no one will ever notice. */
2666 return (char *) getenv (name
);
2671 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2672 to force a call on the debugger from within the image. */
2677 LIB$
SIGNAL (SS$_DEBUG
);
2683 #ifdef LINK_CRTL_SHARE
2684 #ifdef SHAREABLE_LIB_BUG
2685 /* Variables declared noshare and initialized in sharable libraries
2686 cannot be shared. The VMS linker incorrectly forces you to use a private
2687 version which is uninitialized... If not for this "feature", we
2688 could use the C library definition of sys_nerr and sys_errlist. */
2690 char *sys_errlist
[] =
2694 "no such file or directory",
2696 "interrupted system call",
2698 "no such device or address",
2699 "argument list too long",
2700 "exec format error",
2703 "no more processes",
2704 "not enough memory",
2705 "permission denied",
2707 "block device required",
2708 "mount devices busy",
2710 "cross-device link",
2715 "file table overflow",
2716 "too many open files",
2720 "no space left on device",
2722 "read-only file system",
2728 "vax/vms specific error code nontranslatable error"
2730 #endif /* SHAREABLE_LIB_BUG */
2731 #endif /* LINK_CRTL_SHARE */
2734 #ifndef HAVE_STRERROR
2739 extern char *sys_errlist
[];
2740 extern int sys_nerr
;
2742 if (errnum
>= 0 && errnum
< sys_nerr
)
2743 return sys_errlist
[errnum
];
2744 return (char *) "Unknown error";
2747 #endif /* ! HAVE_STRERROR */
2749 #ifdef INTERRUPTIBLE_OPEN
2753 sys_open (path
, oflag
, mode
)
2757 register int rtnval
;
2759 while ((rtnval
= open (path
, oflag
, mode
)) == -1
2760 && (errno
== EINTR
));
2764 #endif /* INTERRUPTIBLE_OPEN */
2766 #ifdef INTERRUPTIBLE_CLOSE
2771 register int rtnval
;
2773 while ((rtnval
= close (fd
)) == -1
2774 && (errno
== EINTR
));
2778 #endif /* INTERRUPTIBLE_CLOSE */
2780 #ifdef INTERRUPTIBLE_IO
2783 sys_read (fildes
, buf
, nbyte
)
2788 register int rtnval
;
2790 while ((rtnval
= read (fildes
, buf
, nbyte
)) == -1
2791 && (errno
== EINTR
));
2796 sys_write (fildes
, buf
, nbyte
)
2801 register int rtnval
, bytes_written
;
2807 rtnval
= write (fildes
, buf
, nbyte
);
2814 return (bytes_written
? bytes_written
: -1);
2819 bytes_written
+= rtnval
;
2821 return (bytes_written
);
2824 #endif /* INTERRUPTIBLE_IO */
2829 * Substitute fork for vfork on USG flavors.
2837 #endif /* not HAVE_VFORK */
2841 * All of the following are for USG.
2843 * On USG systems the system calls are INTERRUPTIBLE by signals
2844 * that the user program has elected to catch. Thus the system call
2845 * must be retried in these cases. To handle this without massive
2846 * changes in the source code, we remap the standard system call names
2847 * to names for our own functions in sysdep.c that do the system call
2848 * with retries. Actually, for portability reasons, it is good
2849 * programming practice, as this example shows, to limit all actual
2850 * system calls to a single occurrence in the source. Sure, this
2851 * adds an extra level of function call overhead but it is almost
2852 * always negligible. Fred Fish, Unisoft Systems Inc.
2855 #ifndef HAVE_SYS_SIGLIST
2856 char *sys_siglist
[NSIG
+ 1] =
2859 /* AIX has changed the signals a bit */
2860 "bogus signal", /* 0 */
2861 "hangup", /* 1 SIGHUP */
2862 "interrupt", /* 2 SIGINT */
2863 "quit", /* 3 SIGQUIT */
2864 "illegal instruction", /* 4 SIGILL */
2865 "trace trap", /* 5 SIGTRAP */
2866 "IOT instruction", /* 6 SIGIOT */
2867 "crash likely", /* 7 SIGDANGER */
2868 "floating point exception", /* 8 SIGFPE */
2869 "kill", /* 9 SIGKILL */
2870 "bus error", /* 10 SIGBUS */
2871 "segmentation violation", /* 11 SIGSEGV */
2872 "bad argument to system call", /* 12 SIGSYS */
2873 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2874 "alarm clock", /* 14 SIGALRM */
2875 "software termination signum", /* 15 SIGTERM */
2876 "user defined signal 1", /* 16 SIGUSR1 */
2877 "user defined signal 2", /* 17 SIGUSR2 */
2878 "death of a child", /* 18 SIGCLD */
2879 "power-fail restart", /* 19 SIGPWR */
2880 "bogus signal", /* 20 */
2881 "bogus signal", /* 21 */
2882 "bogus signal", /* 22 */
2883 "bogus signal", /* 23 */
2884 "bogus signal", /* 24 */
2885 "LAN I/O interrupt", /* 25 SIGAIO */
2886 "PTY I/O interrupt", /* 26 SIGPTY */
2887 "I/O intervention required", /* 27 SIGIOINT */
2888 "HFT grant", /* 28 SIGGRANT */
2889 "HFT retract", /* 29 SIGRETRACT */
2890 "HFT sound done", /* 30 SIGSOUND */
2891 "HFT input ready", /* 31 SIGMSG */
2893 "bogus signal", /* 0 */
2894 "hangup", /* 1 SIGHUP */
2895 "interrupt", /* 2 SIGINT */
2896 "quit", /* 3 SIGQUIT */
2897 "illegal instruction", /* 4 SIGILL */
2898 "trace trap", /* 5 SIGTRAP */
2899 "IOT instruction", /* 6 SIGIOT */
2900 "EMT instruction", /* 7 SIGEMT */
2901 "floating point exception", /* 8 SIGFPE */
2902 "kill", /* 9 SIGKILL */
2903 "bus error", /* 10 SIGBUS */
2904 "segmentation violation", /* 11 SIGSEGV */
2905 "bad argument to system call", /* 12 SIGSYS */
2906 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2907 "alarm clock", /* 14 SIGALRM */
2908 "software termination signum", /* 15 SIGTERM */
2909 "user defined signal 1", /* 16 SIGUSR1 */
2910 "user defined signal 2", /* 17 SIGUSR2 */
2911 "death of a child", /* 18 SIGCLD */
2912 "power-fail restart", /* 19 SIGPWR */
2914 "window size change", /* 20 SIGWINCH */
2915 "urgent socket condition", /* 21 SIGURG */
2916 "pollable event occured", /* 22 SIGPOLL */
2917 "stop (cannot be caught or ignored)", /* 23 SIGSTOP */
2918 "user stop requested from tty", /* 24 SIGTSTP */
2919 "stopped process has been continued", /* 25 SIGCONT */
2920 "background tty read attempted", /* 26 SIGTTIN */
2921 "background tty write attempted", /* 27 SIGTTOU */
2922 "virtual timer expired", /* 28 SIGVTALRM */
2923 "profiling timer expired", /* 29 SIGPROF */
2924 "exceeded cpu limit", /* 30 SIGXCPU */
2925 "exceeded file size limit", /* 31 SIGXFSZ */
2926 "process's lwps are blocked", /* 32 SIGWAITING */
2927 "special signal used by thread library", /* 33 SIGLWP */
2929 "Special Signal Used By CPR", /* 34 SIGFREEZE */
2932 "Special Signal Used By CPR", /* 35 SIGTHAW */
2935 #endif /* not AIX */
2938 #endif /* HAVE_SYS_SIGLIST */
2941 * Warning, this function may not duplicate 4.2 action properly
2942 * under error conditions.
2946 /* In 4.1, param.h fails to define this. */
2947 #define MAXPATHLEN 1024
2956 char *npath
, *spath
;
2957 extern char *getcwd ();
2959 BLOCK_INPUT
; /* getcwd uses malloc */
2960 spath
= npath
= getcwd ((char *) 0, MAXPATHLEN
);
2963 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2964 up to first slash. Should be harmless on other systems. */
2965 while (*npath
&& *npath
!= '/')
2967 strcpy (pathname
, npath
);
2968 free (spath
); /* getcwd uses malloc */
2973 #endif /* HAVE_GETWD */
2976 * Emulate rename using unlink/link. Note that this is
2977 * only partially correct. Also, doesn't enforce restriction
2978 * that files be of same type (regular->regular, dir->dir, etc).
2987 if (access (from
, 0) == 0)
2990 if (link (from
, to
) == 0)
2991 if (unlink (from
) == 0)
2999 #ifdef MISSING_UTIMES
3001 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
3010 /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
3011 utimbuf structure defined anywhere but in the man page. */
3021 struct timeval tvp
[];
3024 utb
.actime
= tvp
[0].tv_sec
;
3025 utb
.modtime
= tvp
[1].tv_sec
;
3028 #endif /* IRIS_UTIME */
3034 /* HPUX curses library references perror, but as far as we know
3035 it won't be called. Anyway this definition will do for now. */
3041 #endif /* not HAVE_PERROR */
3047 * Emulate BSD dup2. First close newd if it already exists.
3048 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3049 * until we are, then close the unsuccessful ones.
3056 register int fd
, ret
;
3061 fd
= fcntl (oldd
, F_DUPFD
, newd
);
3063 error ("can't dup2 (%i,%i) : %s", oldd
, newd
, strerror (errno
));
3070 ret
= dup2 (old
,new);
3076 #endif /* not HAVE_DUP2 */
3079 * Gettimeofday. Simulate as much as possible. Only accurate
3080 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3081 * Only needed when subprocesses are defined.
3086 #ifndef HAVE_GETTIMEOFDAY
3090 gettimeofday (tp
, tzp
)
3092 struct timezone
*tzp
;
3094 extern long time ();
3096 tp
->tv_sec
= time ((long *)0);
3099 tzp
->tz_minuteswest
= -1;
3105 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3108 * This function will go away as soon as all the stubs fixed. (fnf)
3114 printf ("%s not yet implemented\r\n", badfunc
);
3123 char *sys_siglist
[NSIG
+ 1] =
3125 "null signal", /* 0 SIGNULL */
3126 "hangup", /* 1 SIGHUP */
3127 "interrupt", /* 2 SIGINT */
3128 "quit", /* 3 SIGQUIT */
3129 "illegal instruction", /* 4 SIGILL */
3130 "trace trap", /* 5 SIGTRAP */
3131 "abort termination", /* 6 SIGABRT */
3132 "SIGEMT", /* 7 SIGEMT */
3133 "floating point exception", /* 8 SIGFPE */
3134 "kill", /* 9 SIGKILL */
3135 "bus error", /* 10 SIGBUS */
3136 "segmentation violation", /* 11 SIGSEGV */
3137 "bad argument to system call", /* 12 SIGSYS */
3138 "write on a pipe with no reader", /* 13 SIGPIPE */
3139 "alarm clock", /* 14 SIGALRM */
3140 "software termination signal", /* 15 SIGTERM */
3141 "user defined signal 1", /* 16 SIGUSR1 */
3142 "user defined signal 2", /* 17 SIGUSR2 */
3143 "child stopped or terminated", /* 18 SIGCLD */
3144 "power-fail restart", /* 19 SIGPWR */
3145 "window size changed", /* 20 SIGWINCH */
3146 "undefined", /* 21 */
3147 "pollable event occurred", /* 22 SIGPOLL */
3148 "sendable stop signal not from tty", /* 23 SIGSTOP */
3149 "stop signal from tty", /* 24 SIGSTP */
3150 "continue a stopped process", /* 25 SIGCONT */
3151 "attempted background tty read", /* 26 SIGTTIN */
3152 "attempted background tty write", /* 27 SIGTTOU */
3153 "undefined", /* 28 */
3154 "undefined", /* 29 */
3155 "undefined", /* 30 */
3156 "undefined", /* 31 */
3157 "undefined", /* 32 */
3158 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
3159 "I/O is possible", /* 34 SIGIO */
3160 "exceeded cpu time limit", /* 35 SIGXCPU */
3161 "exceeded file size limit", /* 36 SIGXFSZ */
3162 "virtual time alarm", /* 37 SIGVTALRM */
3163 "profiling time alarm", /* 38 SIGPROF */
3164 "undefined", /* 39 */
3165 "file record locks revoked", /* 40 SIGLOST */
3166 "undefined", /* 41 */
3167 "undefined", /* 42 */
3168 "undefined", /* 43 */
3169 "undefined", /* 44 */
3170 "undefined", /* 45 */
3171 "undefined", /* 46 */
3172 "undefined", /* 47 */
3173 "undefined", /* 48 */
3174 "undefined", /* 49 */
3175 "undefined", /* 50 */
3176 "undefined", /* 51 */
3177 "undefined", /* 52 */
3178 "undefined", /* 53 */
3179 "undefined", /* 54 */
3180 "undefined", /* 55 */
3181 "undefined", /* 56 */
3182 "undefined", /* 57 */
3183 "undefined", /* 58 */
3184 "undefined", /* 59 */
3185 "undefined", /* 60 */
3186 "undefined", /* 61 */
3187 "undefined", /* 62 */
3188 "undefined", /* 63 */
3189 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
3195 /* Directory routines for systems that don't have them. */
3197 #ifdef SYSV_SYSTEM_DIR
3201 #if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
3205 register DIR *dirp
; /* stream from opendir */
3209 rtnval
= sys_close (dirp
->dd_fd
);
3211 /* Some systems (like Solaris) allocate the buffer and the DIR all
3212 in one block. Why in the world are we freeing this ourselves
3214 #if ! (defined (sun) && defined (USG5_4))
3215 xfree ((char *) dirp
->dd_buf
); /* directory block defined in <dirent.h> */
3217 xfree ((char *) dirp
);
3221 #endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
3222 #endif /* SYSV_SYSTEM_DIR */
3224 #ifdef NONSYSTEM_DIR_LIBRARY
3228 char *filename
; /* name of directory */
3230 register DIR *dirp
; /* -> malloc'ed storage */
3231 register int fd
; /* file descriptor for read */
3232 struct stat sbuf
; /* result of fstat */
3234 fd
= sys_open (filename
, 0);
3239 if (fstat (fd
, &sbuf
) < 0
3240 || (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
3241 || (dirp
= (DIR *) malloc (sizeof (DIR))) == 0)
3245 return 0; /* bad luck today */
3250 dirp
->dd_loc
= dirp
->dd_size
= 0; /* refill needed */
3257 register DIR *dirp
; /* stream from opendir */
3259 sys_close (dirp
->dd_fd
);
3260 xfree ((char *) dirp
);
3268 ino_t od_ino
; /* inode */
3269 char od_name
[DIRSIZ
]; /* filename */
3271 #endif /* not VMS */
3273 struct direct dir_static
; /* simulated directory contents */
3278 register DIR *dirp
; /* stream from opendir */
3281 register struct olddir
*dp
; /* -> directory data */
3283 register struct dir$_name
*dp
; /* -> directory data */
3284 register struct dir$_version
*dv
; /* -> version data */
3289 if (dirp
->dd_loc
>= dirp
->dd_size
)
3290 dirp
->dd_loc
= dirp
->dd_size
= 0;
3292 if (dirp
->dd_size
== 0 /* refill buffer */
3293 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3297 dp
= (struct olddir
*) &dirp
->dd_buf
[dirp
->dd_loc
];
3298 dirp
->dd_loc
+= sizeof (struct olddir
);
3300 if (dp
->od_ino
!= 0) /* not deleted entry */
3302 dir_static
.d_ino
= dp
->od_ino
;
3303 strncpy (dir_static
.d_name
, dp
->od_name
, DIRSIZ
);
3304 dir_static
.d_name
[DIRSIZ
] = '\0';
3305 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3306 dir_static
.d_reclen
= sizeof (struct direct
)
3308 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3309 return &dir_static
; /* -> simulated structure */
3312 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3313 if (dirp
->dd_loc
== 0)
3314 dirp
->dd_loc
= (dp
->dir$b_namecount
&1) ? dp
->dir$b_namecount
+ 1
3315 : dp
->dir$b_namecount
;
3316 dv
= (struct dir$_version
*)&dp
->dir$t_name
[dirp
->dd_loc
];
3317 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3318 dir_static
.d_namlen
= dp
->dir$b_namecount
;
3319 dir_static
.d_reclen
= sizeof (struct direct
)
3321 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3322 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3323 dir_static
.d_name
[dir_static
.d_namlen
] = '\0';
3324 dirp
->dd_loc
= dirp
->dd_size
; /* only one record at a time */
3331 /* readdirver is just like readdir except it returns all versions of a file
3332 as separate entries. */
3337 register DIR *dirp
; /* stream from opendir */
3339 register struct dir$_name
*dp
; /* -> directory data */
3340 register struct dir$_version
*dv
; /* -> version data */
3342 if (dirp
->dd_loc
>= dirp
->dd_size
- sizeof (struct dir$_name
))
3343 dirp
->dd_loc
= dirp
->dd_size
= 0;
3345 if (dirp
->dd_size
== 0 /* refill buffer */
3346 && (dirp
->dd_size
= sys_read (dirp
->dd_fd
, dirp
->dd_buf
, DIRBLKSIZ
)) <= 0)
3349 dp
= (struct dir$_name
*) dirp
->dd_buf
;
3350 if (dirp
->dd_loc
== 0)
3351 dirp
->dd_loc
= (dp
->dir$b_namecount
& 1) ? dp
->dir$b_namecount
+ 1
3352 : dp
->dir$b_namecount
;
3353 dv
= (struct dir$_version
*) &dp
->dir$t_name
[dirp
->dd_loc
];
3354 strncpy (dir_static
.d_name
, dp
->dir$t_name
, dp
->dir$b_namecount
);
3355 sprintf (&dir_static
.d_name
[dp
->dir$b_namecount
], ";%d", dv
->dir$w_version
);
3356 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3357 dir_static
.d_ino
= dv
->dir$w_fid_num
;
3358 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3
3359 + dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3360 dirp
->dd_loc
= ((char *) (++dv
) - dp
->dir$t_name
);
3366 #endif /* NONSYSTEM_DIR_LIBRARY */
3369 /* mkdir and rmdir functions, for systems which don't have them. */
3373 * Written by Robert Rother, Mariah Corporation, August 1985.
3375 * If you want it, it's yours. All I ask in return is that if you
3376 * figure out how to do this in a Bourne Shell script you send me
3378 * sdcsvax!rmr or rmr@uscd
3380 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3381 * subroutine. 11Mar86; hoptoad!gnu
3383 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3384 * subroutine didn't return EEXIST. It does now.
3390 #ifdef MKDIR_PROTOTYPE
3394 mkdir (dpath
, dmode
)
3399 int cpid
, status
, fd
;
3400 struct stat statbuf
;
3402 if (stat (dpath
, &statbuf
) == 0)
3404 errno
= EEXIST
; /* Stat worked, so it already exists */
3408 /* If stat fails for a reason other than non-existence, return error */
3409 if (errno
!= ENOENT
)
3412 synch_process_alive
= 1;
3413 switch (cpid
= fork ())
3416 case -1: /* Error in fork */
3417 return (-1); /* Errno is set already */
3419 case 0: /* Child process */
3421 * Cheap hack to set mode of new directory. Since this
3422 * child process is going away anyway, we zap its umask.
3423 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3424 * directory. Does anybody care?
3426 status
= umask (0); /* Get current umask */
3427 status
= umask (status
| (0777 & ~dmode
)); /* Set for mkdir */
3428 fd
= sys_open("/dev/null", 2);
3435 execl ("/bin/mkdir", "mkdir", dpath
, (char *) 0);
3436 _exit (-1); /* Can't exec /bin/mkdir */
3438 default: /* Parent process */
3439 wait_for_termination (cpid
);
3442 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3444 errno
= EIO
; /* We don't know why, but */
3445 return -1; /* /bin/mkdir failed */
3450 #endif /* not HAVE_MKDIR */
3457 int cpid
, status
, fd
;
3458 struct stat statbuf
;
3460 if (stat (dpath
, &statbuf
) != 0)
3462 /* Stat just set errno. We don't have to */
3466 synch_process_alive
= 1;
3467 switch (cpid
= fork ())
3470 case -1: /* Error in fork */
3471 return (-1); /* Errno is set already */
3473 case 0: /* Child process */
3474 fd
= sys_open("/dev/null", 2);
3481 wait_for_termination (cpid
);
3482 if (synch_process_death
!= 0 || synch_process_retcode
!= 0)
3483 return -1; /* /bin/rmdir failed */
3484 default: /* Parent process */
3485 while (cpid
!= wait (&status
)); /* Wait for kid to finish */
3488 if (WIFSIGNALED (status
) || WEXITSTATUS (status
) != 0)
3490 errno
= EIO
; /* We don't know why, but */
3491 return -1; /* /bin/mkdir failed */
3496 #endif /* !HAVE_RMDIR */
3500 /* Functions for VMS */
3502 #include "vms-pwd.h"
3507 /* Return as a string the VMS error string pertaining to STATUS.
3508 Reuses the same static buffer each time it is called. */
3512 int status
; /* VMS status code */
3516 static char buf
[257];
3518 bufadr
[0] = sizeof buf
- 1;
3519 bufadr
[1] = (int) buf
;
3520 if (! (SYS$
GETMSG (status
, &len
, bufadr
, 0x1, 0) & 1))
3521 return "untranslatable VMS error status";
3529 /* The following is necessary because 'access' emulation by VMS C (2.0) does
3530 * not work correctly. (It also doesn't work well in version 2.3.)
3535 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3536 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3540 unsigned short s_buflen
;
3541 unsigned short s_code
;
3543 unsigned short *s_retlenadr
;
3547 #define buflen s.s_buflen
3548 #define code s.s_code
3549 #define bufadr s.s_bufadr
3550 #define retlenadr s.s_retlenadr
3552 #define R_OK 4 /* test for read permission */
3553 #define W_OK 2 /* test for write permission */
3554 #define X_OK 1 /* test for execute (search) permission */
3555 #define F_OK 0 /* test for presence of file */
3558 sys_access (path
, mode
)
3562 static char *user
= NULL
;
3565 /* translate possible directory spec into .DIR file name, so brain-dead
3566 * access can treat the directory like a file. */
3567 if (directory_file_name (path
, dir_fn
))
3571 return access (path
, mode
);
3572 if (user
== NULL
&& (user
= (char *) getenv ("USER")) == NULL
)
3578 unsigned short int dummy
;
3580 static int constant
= ACL$C_FILE
;
3581 DESCRIPTOR (path_desc
, path
);
3582 DESCRIPTOR (user_desc
, user
);
3586 if ((mode
& X_OK
) && ((stat
= access (path
, mode
)) < 0 || mode
== X_OK
))
3589 acces
|= CHP$M_READ
;
3591 acces
|= CHP$M_WRITE
;
3592 itemlst
[0].buflen
= sizeof (int);
3593 itemlst
[0].code
= CHP$_FLAGS
;
3594 itemlst
[0].bufadr
= (char *) &flags
;
3595 itemlst
[0].retlenadr
= &dummy
;
3596 itemlst
[1].buflen
= sizeof (int);
3597 itemlst
[1].code
= CHP$_ACCESS
;
3598 itemlst
[1].bufadr
= (char *) &acces
;
3599 itemlst
[1].retlenadr
= &dummy
;
3600 itemlst
[2].end
= CHP$_END
;
3601 stat
= SYS$
CHECK_ACCESS (&constant
, &path_desc
, &user_desc
, itemlst
);
3602 return stat
== SS$_NORMAL
? 0 : -1;
3606 #else /* not VMS4_4 */
3609 #define ACE$M_WRITE 2
3610 #define ACE$C_KEYID 1
3612 static unsigned short memid
, grpid
;
3613 static unsigned int uic
;
3615 /* Called from init_sys_modes, so it happens not very often
3616 but at least each time Emacs is loaded. */
3617 sys_access_reinit ()
3623 sys_access (filename
, type
)
3629 int status
, size
, i
, typecode
, acl_controlled
;
3630 unsigned int *aclptr
, *aclend
, aclbuf
[60];
3631 union prvdef prvmask
;
3633 /* Get UIC and GRP values for protection checking. */
3636 status
= LIB$
GETJPI (&JPI$_UIC
, 0, 0, &uic
, 0, 0);
3639 memid
= uic
& 0xFFFF;
3643 if (type
!= 2) /* not checking write access */
3644 return access (filename
, type
);
3646 /* Check write protection. */
3648 #define CHECKPRIV(bit) (prvmask.bit)
3649 #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3651 /* Find privilege bits */
3652 status
= SYS$
SETPRV (0, 0, 0, prvmask
);
3654 error ("Unable to find privileges: %s", vmserrstr (status
));
3655 if (CHECKPRIV (PRV$V_BYPASS
))
3656 return 0; /* BYPASS enabled */
3658 fab
.fab$b_fac
= FAB$M_GET
;
3659 fab
.fab$l_fna
= filename
;
3660 fab
.fab$b_fns
= strlen (filename
);
3661 fab
.fab$l_xab
= &xab
;
3662 xab
= cc$rms_xabpro
;
3663 xab
.xab$l_aclbuf
= aclbuf
;
3664 xab
.xab$w_aclsiz
= sizeof (aclbuf
);
3665 status
= SYS$
OPEN (&fab
, 0, 0);
3668 SYS$
CLOSE (&fab
, 0, 0);
3669 /* Check system access */
3670 if (CHECKPRIV (PRV$V_SYSPRV
) && WRITEABLE (XAB$V_SYS
))
3672 /* Check ACL entries, if any */
3674 if (xab
.xab$w_acllen
> 0)
3677 aclend
= &aclbuf
[xab
.xab$w_acllen
/ 4];
3678 while (*aclptr
&& aclptr
< aclend
)
3680 size
= (*aclptr
& 0xff) / 4;
3681 typecode
= (*aclptr
>> 8) & 0xff;
3682 if (typecode
== ACE$C_KEYID
)
3683 for (i
= size
- 1; i
> 1; i
--)
3684 if (aclptr
[i
] == uic
)
3687 if (aclptr
[1] & ACE$M_WRITE
)
3688 return 0; /* Write access through ACL */
3690 aclptr
= &aclptr
[size
];
3692 if (acl_controlled
) /* ACL specified, prohibits write access */
3695 /* No ACL entries specified, check normal protection */
3696 if (WRITEABLE (XAB$V_WLD
)) /* World writeable */
3698 if (WRITEABLE (XAB$V_GRP
) &&
3699 (unsigned short) (xab
.xab$l_uic
>> 16) == grpid
)
3700 return 0; /* Group writeable */
3701 if (WRITEABLE (XAB$V_OWN
) &&
3702 (xab
.xab$l_uic
& 0xFFFF) == memid
)
3703 return 0; /* Owner writeable */
3705 return -1; /* Not writeable */
3707 #endif /* not VMS4_4 */
3710 static char vtbuf
[NAM$C_MAXRSS
+1];
3712 /* translate a vms file spec to a unix path */
3714 sys_translate_vms (vfile
)
3725 /* leading device or logical name is a root directory */
3726 if (p
= strchr (vfile
, ':'))
3735 if (*p
== '[' || *p
== '<')
3737 while (*++vfile
!= *p
+ 2)
3741 if (vfile
[-1] == *p
)
3764 static char utbuf
[NAM$C_MAXRSS
+1];
3766 /* translate a unix path to a VMS file spec */
3768 sys_translate_unix (ufile
)
3791 if (index (&ufile
[1], '/'))
3798 if (index (&ufile
[1], '/'))
3805 if (strncmp (ufile
, "./", 2) == 0)
3812 ufile
++; /* skip the dot */
3813 if (index (&ufile
[1], '/'))
3818 else if (strncmp (ufile
, "../", 3) == 0)
3826 ufile
+= 2; /* skip the dots */
3827 if (index (&ufile
[1], '/'))
3852 extern char *getcwd ();
3854 #define MAXPATHLEN 1024
3856 ptr
= xmalloc (MAXPATHLEN
);
3857 val
= getcwd (ptr
, MAXPATHLEN
);
3863 strcpy (pathname
, ptr
);
3871 long item_code
= JPI$_OWNER
;
3872 unsigned long parent_id
;
3875 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &parent_id
)) & 1) == 0)
3878 vaxc$errno
= status
;
3888 return (getgid () << 16) | getuid ();
3892 sys_read (fildes
, buf
, nbyte
)
3897 return read (fildes
, buf
, (nbyte
< MAXIOSIZE
? nbyte
: MAXIOSIZE
));
3902 sys_write (fildes
, buf
, nbyte
)
3907 register int nwrote
, rtnval
= 0;
3909 while (nbyte
> MAXIOSIZE
&& (nwrote
= write (fildes
, buf
, MAXIOSIZE
)) > 0) {
3915 return rtnval
? rtnval
: -1;
3916 if ((nwrote
= write (fildes
, buf
, nbyte
)) < 0)
3917 return rtnval
? rtnval
: -1;
3918 return (rtnval
+ nwrote
);
3923 * VAX/VMS VAX C RTL really loses. It insists that records
3924 * end with a newline (carriage return) character, and if they
3925 * don't it adds one (nice of it isn't it!)
3927 * Thus we do this stupidity below.
3931 sys_write (fildes
, buf
, nbytes
)
3934 unsigned int nbytes
;
3941 fstat (fildes
, &st
);
3947 /* Handle fixed-length files with carriage control. */
3948 if (st
.st_fab_rfm
== FAB$C_FIX
3949 && ((st
.st_fab_rat
& (FAB$M_FTN
| FAB$M_CR
)) != 0))
3951 len
= st
.st_fab_mrs
;
3952 retval
= write (fildes
, p
, min (len
, nbytes
));
3955 retval
++; /* This skips the implied carriage control */
3959 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
3960 while (*e
!= '\n' && e
> p
) e
--;
3961 if (p
== e
) /* Ok.. so here we add a newline... sigh. */
3962 e
= p
+ min (MAXIOSIZE
, nbytes
) - 1;
3964 retval
= write (fildes
, p
, len
);
3975 /* Create file NEW copying its attributes from file OLD. If
3976 OLD is 0 or does not exist, create based on the value of
3979 /* Protection value the file should ultimately have.
3980 Set by create_copy_attrs, and use by rename_sansversions. */
3981 static unsigned short int fab_final_pro
;
3984 creat_copy_attrs (old
, new)
3987 struct FAB fab
= cc$rms_fab
;
3988 struct XABPRO xabpro
;
3989 char aclbuf
[256]; /* Choice of size is arbitrary. See below. */
3990 extern int vms_stmlf_recfm
;
3994 fab
.fab$b_fac
= FAB$M_GET
;
3995 fab
.fab$l_fna
= old
;
3996 fab
.fab$b_fns
= strlen (old
);
3997 fab
.fab$l_xab
= (char *) &xabpro
;
3998 xabpro
= cc$rms_xabpro
;
3999 xabpro
.xab$l_aclbuf
= aclbuf
;
4000 xabpro
.xab$w_aclsiz
= sizeof aclbuf
;
4001 /* Call $OPEN to fill in the fab & xabpro fields. */
4002 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4004 SYS$
CLOSE (&fab
, 0, 0);
4005 fab
.fab$l_alq
= 0; /* zero the allocation quantity */
4006 if (xabpro
.xab$w_acllen
> 0)
4008 if (xabpro
.xab$w_acllen
> sizeof aclbuf
)
4009 /* If the acl buffer was too short, redo open with longer one.
4010 Wouldn't need to do this if there were some system imposed
4011 limit on the size of an ACL, but I can't find any such. */
4013 xabpro
.xab$l_aclbuf
= (char *) alloca (xabpro
.xab$w_acllen
);
4014 xabpro
.xab$w_aclsiz
= xabpro
.xab$w_acllen
;
4015 if (SYS$
OPEN (&fab
, 0, 0) & 1)
4016 SYS$
CLOSE (&fab
, 0, 0);
4022 xabpro
.xab$l_aclbuf
= 0;
4027 fab
.fab$l_fna
= new;
4028 fab
.fab$b_fns
= strlen (new);
4032 fab
.fab$b_rfm
= vms_stmlf_recfm
? FAB$C_STMLF
: FAB$C_VAR
;
4033 fab
.fab$b_rat
= FAB$M_CR
;
4036 /* Set the file protections such that we will be able to manipulate
4037 this file. Once we are done writing and renaming it, we will set
4038 the protections back. */
4040 fab_final_pro
= xabpro
.xab$w_pro
;
4042 SYS$
SETDFPROT (0, &fab_final_pro
);
4043 xabpro
.xab$w_pro
&= 0xff0f; /* set O:rewd for now. This is set back later. */
4045 /* Create the new file with either default attrs or attrs copied
4047 if (!(SYS$
CREATE (&fab
, 0, 0) & 1))
4049 SYS$
CLOSE (&fab
, 0, 0);
4050 /* As this is a "replacement" for creat, return a file descriptor
4051 opened for writing. */
4052 return open (new, O_WRONLY
);
4057 #include <varargs.h>
4060 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4064 sys_creat (va_alist
)
4067 va_list list_incrementer
;
4070 int rfd
; /* related file descriptor */
4071 int fd
; /* Our new file descriptor */
4078 extern int vms_stmlf_recfm
;
4081 va_start (list_incrementer
);
4082 name
= va_arg (list_incrementer
, char *);
4083 mode
= va_arg (list_incrementer
, int);
4085 rfd
= va_arg (list_incrementer
, int);
4086 va_end (list_incrementer
);
4089 /* Use information from the related file descriptor to set record
4090 format of the newly created file. */
4091 fstat (rfd
, &st_buf
);
4092 switch (st_buf
.st_fab_rfm
)
4095 strcpy (rfm
, "rfm = fix");
4096 sprintf (mrs
, "mrs = %d", st_buf
.st_fab_mrs
);
4097 strcpy (rat
, "rat = ");
4098 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4100 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4101 strcat (rat
, "ftn");
4102 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4103 strcat (rat
, "prn");
4104 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4105 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4106 strcat (rat
, ", blk");
4108 strcat (rat
, "blk");
4109 return creat (name
, 0, rfm
, rat
, mrs
);
4112 strcpy (rfm
, "rfm = vfc");
4113 sprintf (fsz
, "fsz = %d", st_buf
.st_fab_fsz
);
4114 strcpy (rat
, "rat = ");
4115 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4117 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4118 strcat (rat
, "ftn");
4119 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4120 strcat (rat
, "prn");
4121 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4122 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4123 strcat (rat
, ", blk");
4125 strcat (rat
, "blk");
4126 return creat (name
, 0, rfm
, rat
, fsz
);
4129 strcpy (rfm
, "rfm = stm");
4133 strcpy (rfm
, "rfm = stmcr");
4137 strcpy (rfm
, "rfm = stmlf");
4141 strcpy (rfm
, "rfm = udf");
4145 strcpy (rfm
, "rfm = var");
4148 strcpy (rat
, "rat = ");
4149 if (st_buf
.st_fab_rat
& FAB$M_CR
)
4151 else if (st_buf
.st_fab_rat
& FAB$M_FTN
)
4152 strcat (rat
, "ftn");
4153 else if (st_buf
.st_fab_rat
& FAB$M_PRN
)
4154 strcat (rat
, "prn");
4155 if (st_buf
.st_fab_rat
& FAB$M_BLK
)
4156 if (st_buf
.st_fab_rat
& (FAB$M_CR
|FAB$M_FTN
|FAB$M_PRN
))
4157 strcat (rat
, ", blk");
4159 strcat (rat
, "blk");
4163 strcpy (rfm
, vms_stmlf_recfm
? "rfm = stmlf" : "rfm=var");
4164 strcpy (rat
, "rat=cr");
4166 /* Until the VAX C RTL fixes the many bugs with modes, always use
4167 mode 0 to get the user's default protection. */
4168 fd
= creat (name
, 0, rfm
, rat
);
4169 if (fd
< 0 && errno
== EEXIST
)
4171 if (unlink (name
) < 0)
4172 report_file_error ("delete", build_string (name
));
4173 fd
= creat (name
, 0, rfm
, rat
);
4179 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4180 sys_fwrite (ptr
, size
, num
, fp
)
4181 register char * ptr
;
4184 register int tot
= num
* size
;
4191 * The VMS C library routine creat actually creates a new version of an
4192 * existing file rather than truncating the old version. There are times
4193 * when this is not the desired behavior, for instance, when writing an
4194 * auto save file (you only want one version), or when you don't have
4195 * write permission in the directory containing the file (but the file
4196 * itself is writable). Hence this routine, which is equivalent to
4197 * "close (creat (fn, 0));" on Unix if fn already exists.
4203 struct FAB xfab
= cc$rms_fab
;
4204 struct RAB xrab
= cc$rms_rab
;
4207 xfab
.fab$l_fop
= FAB$M_TEF
; /* free allocated but unused blocks on close */
4208 xfab
.fab$b_fac
= FAB$M_TRN
| FAB$M_GET
; /* allow truncate and get access */
4209 xfab
.fab$b_shr
= FAB$M_NIL
; /* allow no sharing - file must be locked */
4210 xfab
.fab$l_fna
= fn
;
4211 xfab
.fab$b_fns
= strlen (fn
);
4212 xfab
.fab$l_dna
= ";0"; /* default to latest version of the file */
4214 xrab
.rab$l_fab
= &xfab
;
4216 /* This gibberish opens the file, positions to the first record, and
4217 deletes all records from there until the end of file. */
4218 if ((SYS$
OPEN (&xfab
) & 01) == 01)
4220 if ((SYS$
CONNECT (&xrab
) & 01) == 01 &&
4221 (SYS$
FIND (&xrab
) & 01) == 01 &&
4222 (SYS$
TRUNCATE (&xrab
) & 01) == 01)
4233 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4234 SYSPRV or a readable SYSUAF.DAT. */
4240 * Routine to read the VMS User Authorization File and return
4241 * a specific user's record.
4244 static struct UAF retuaf
;
4247 get_uaf_name (uname
)
4254 uaf_fab
= cc$rms_fab
;
4255 uaf_rab
= cc$rms_rab
;
4256 /* initialize fab fields */
4257 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4258 uaf_fab
.fab$b_fns
= 21;
4259 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4260 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4261 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4262 /* initialize rab fields */
4263 uaf_rab
.rab$l_fab
= &uaf_fab
;
4264 /* open the User Authorization File */
4265 status
= SYS$
OPEN (&uaf_fab
);
4269 vaxc$errno
= status
;
4272 status
= SYS$
CONNECT (&uaf_rab
);
4276 vaxc$errno
= status
;
4279 /* read the requested record - index is in uname */
4280 uaf_rab
.rab$l_kbf
= uname
;
4281 uaf_rab
.rab$b_ksz
= strlen (uname
);
4282 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4283 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4284 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4285 status
= SYS$
GET (&uaf_rab
);
4289 vaxc$errno
= status
;
4292 /* close the User Authorization File */
4293 status
= SYS$
DISCONNECT (&uaf_rab
);
4297 vaxc$errno
= status
;
4300 status
= SYS$
CLOSE (&uaf_fab
);
4304 vaxc$errno
= status
;
4318 uaf_fab
= cc$rms_fab
;
4319 uaf_rab
= cc$rms_rab
;
4320 /* initialize fab fields */
4321 uaf_fab
.fab$l_fna
= "SYS$SYSTEM:SYSUAF.DAT";
4322 uaf_fab
.fab$b_fns
= 21;
4323 uaf_fab
.fab$b_fac
= FAB$M_GET
;
4324 uaf_fab
.fab$b_org
= FAB$C_IDX
;
4325 uaf_fab
.fab$b_shr
= FAB$M_GET
|FAB$M_PUT
|FAB$M_UPD
|FAB$M_DEL
;
4326 /* initialize rab fields */
4327 uaf_rab
.rab$l_fab
= &uaf_fab
;
4328 /* open the User Authorization File */
4329 status
= SYS$
OPEN (&uaf_fab
);
4333 vaxc$errno
= status
;
4336 status
= SYS$
CONNECT (&uaf_rab
);
4340 vaxc$errno
= status
;
4343 /* read the requested record - index is in uic */
4344 uaf_rab
.rab$b_krf
= 1; /* 1st alternate key */
4345 uaf_rab
.rab$l_kbf
= (char *) &uic
;
4346 uaf_rab
.rab$b_ksz
= sizeof uic
;
4347 uaf_rab
.rab$b_rac
= RAB$C_KEY
;
4348 uaf_rab
.rab$l_ubf
= (char *)&retuaf
;
4349 uaf_rab
.rab$w_usz
= sizeof retuaf
;
4350 status
= SYS$
GET (&uaf_rab
);
4354 vaxc$errno
= status
;
4357 /* close the User Authorization File */
4358 status
= SYS$
DISCONNECT (&uaf_rab
);
4362 vaxc$errno
= status
;
4365 status
= SYS$
CLOSE (&uaf_fab
);
4369 vaxc$errno
= status
;
4375 static struct passwd retpw
;
4383 /* copy these out first because if the username is 32 chars, the next
4384 section will overwrite the first byte of the UIC */
4385 retpw
.pw_uid
= up
->uaf$w_mem
;
4386 retpw
.pw_gid
= up
->uaf$w_grp
;
4388 /* I suppose this is not the best sytle, to possibly overwrite one
4389 byte beyond the end of the field, but what the heck... */
4390 ptr
= &up
->uaf$t_username
[UAF$S_USERNAME
];
4391 while (ptr
[-1] == ' ')
4394 strcpy (retpw
.pw_name
, up
->uaf$t_username
);
4396 /* the rest of these are counted ascii strings */
4397 strncpy (retpw
.pw_gecos
, &up
->uaf$t_owner
[1], up
->uaf$t_owner
[0]);
4398 retpw
.pw_gecos
[up
->uaf$t_owner
[0]] = '\0';
4399 strncpy (retpw
.pw_dir
, &up
->uaf$t_defdev
[1], up
->uaf$t_defdev
[0]);
4400 retpw
.pw_dir
[up
->uaf$t_defdev
[0]] = '\0';
4401 strncat (retpw
.pw_dir
, &up
->uaf$t_defdir
[1], up
->uaf$t_defdir
[0]);
4402 retpw
.pw_dir
[up
->uaf$t_defdev
[0] + up
->uaf$t_defdir
[0]] = '\0';
4403 strncpy (retpw
.pw_shell
, &up
->uaf$t_defcli
[1], up
->uaf$t_defcli
[0]);
4404 retpw
.pw_shell
[up
->uaf$t_defcli
[0]] = '\0';
4408 #else /* not READ_SYSUAF */
4409 static struct passwd retpw
;
4410 #endif /* not READ_SYSUAF */
4421 unsigned char * full
;
4422 #endif /* READ_SYSUAF */
4427 if ('a' <= *ptr
&& *ptr
<= 'z')
4432 if (!(up
= get_uaf_name (name
)))
4434 return cnv_uaf_pw (up
);
4436 if (strcmp (name
, getenv ("USER")) == 0)
4438 retpw
.pw_uid
= getuid ();
4439 retpw
.pw_gid
= getgid ();
4440 strcpy (retpw
.pw_name
, name
);
4441 if (full
= egetenv ("FULLNAME"))
4442 strcpy (retpw
.pw_gecos
, full
);
4444 *retpw
.pw_gecos
= '\0';
4445 strcpy (retpw
.pw_dir
, egetenv ("HOME"));
4446 *retpw
.pw_shell
= '\0';
4451 #endif /* not READ_SYSUAF */
4461 if (!(up
= get_uaf_uic (uid
)))
4463 return cnv_uaf_pw (up
);
4465 if (uid
== sys_getuid ())
4466 return getpwnam (egetenv ("USER"));
4469 #endif /* not READ_SYSUAF */
4472 /* return total address space available to the current process. This is
4473 the sum of the current p0 size, p1 size and free page table entries
4478 unsigned long free_pages
;
4479 unsigned long frep0va
;
4480 unsigned long frep1va
;
4483 item_code
= JPI$_FREPTECNT
;
4484 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &free_pages
)) & 1) == 0)
4487 vaxc$errno
= status
;
4492 item_code
= JPI$_FREP0VA
;
4493 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep0va
)) & 1) == 0)
4496 vaxc$errno
= status
;
4499 item_code
= JPI$_FREP1VA
;
4500 if (((status
= LIB$
GETJPI (&item_code
, 0, 0, &frep1va
)) & 1) == 0)
4503 vaxc$errno
= status
;
4507 return free_pages
+ frep0va
+ (0x7fffffff - frep1va
);
4510 define_logical_name (varname
, string
)
4514 struct dsc$descriptor_s strdsc
=
4515 {strlen (string
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, string
};
4516 struct dsc$descriptor_s envdsc
=
4517 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4518 struct dsc$descriptor_s lnmdsc
=
4519 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4521 return LIB$
SET_LOGICAL (&envdsc
, &strdsc
, &lnmdsc
, 0, 0);
4524 delete_logical_name (varname
)
4527 struct dsc$descriptor_s envdsc
=
4528 {strlen (varname
), DSC$K_DTYPE_T
, DSC$K_CLASS_S
, varname
};
4529 struct dsc$descriptor_s lnmdsc
=
4530 {7, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, "LNM$JOB"};
4532 return LIB$
DELETE_LOGICAL (&envdsc
, &lnmdsc
);
4543 error ("execvp system call not implemented");
4551 struct FAB from_fab
= cc$rms_fab
, to_fab
= cc$rms_fab
;
4552 struct NAM from_nam
= cc$rms_nam
, to_nam
= cc$rms_nam
;
4553 char from_esn
[NAM$C_MAXRSS
];
4554 char to_esn
[NAM$C_MAXRSS
];
4556 from_fab
.fab$l_fna
= from
;
4557 from_fab
.fab$b_fns
= strlen (from
);
4558 from_fab
.fab$l_nam
= &from_nam
;
4559 from_fab
.fab$l_fop
= FAB$M_NAM
;
4561 from_nam
.nam$l_esa
= from_esn
;
4562 from_nam
.nam$b_ess
= sizeof from_esn
;
4564 to_fab
.fab$l_fna
= to
;
4565 to_fab
.fab$b_fns
= strlen (to
);
4566 to_fab
.fab$l_nam
= &to_nam
;
4567 to_fab
.fab$l_fop
= FAB$M_NAM
;
4569 to_nam
.nam$l_esa
= to_esn
;
4570 to_nam
.nam$b_ess
= sizeof to_esn
;
4572 status
= SYS$
RENAME (&from_fab
, 0, 0, &to_fab
);
4578 if (status
== RMS$_DEV
)
4582 vaxc$errno
= status
;
4587 /* This function renames a file like `rename', but it strips
4588 the version number from the "to" filename, such that the "to" file is
4589 will always be a new version. It also sets the file protection once it is
4590 finished. The protection that we will use is stored in fab_final_pro,
4591 and was set when we did a creat_copy_attrs to create the file that we
4594 We could use the chmod function, but Eunichs uses 3 bits per user category
4595 to describe the protection, and VMS uses 4 (write and delete are separate
4596 bits). To maintain portability, the VMS implementation of `chmod' wires
4597 the W and D bits together. */
4600 static struct fibdef fib
; /* We need this initialized to zero */
4601 char vms_file_written
[NAM$C_MAXRSS
];
4604 rename_sans_version (from
,to
)
4611 struct FAB to_fab
= cc$rms_fab
;
4612 struct NAM to_nam
= cc$rms_nam
;
4613 struct dsc$descriptor fib_d
={sizeof (fib
),0,0,(char*) &fib
};
4614 struct dsc$descriptor fib_attr
[2]
4615 = {{sizeof (fab_final_pro
),ATR$C_FPRO
,0,(char*) &fab_final_pro
},{0,0,0,0}};
4616 char to_esn
[NAM$C_MAXRSS
];
4618 $
DESCRIPTOR (disk
,to_esn
);
4620 to_fab
.fab$l_fna
= to
;
4621 to_fab
.fab$b_fns
= strlen (to
);
4622 to_fab
.fab$l_nam
= &to_nam
;
4623 to_fab
.fab$l_fop
= FAB$M_NAM
;
4625 to_nam
.nam$l_esa
= to_esn
;
4626 to_nam
.nam$b_ess
= sizeof to_esn
;
4628 status
= SYS$
PARSE (&to_fab
, 0, 0); /* figure out the full file name */
4630 if (to_nam
.nam$l_fnb
&& NAM$M_EXP_VER
)
4631 *(to_nam
.nam$l_ver
) = '\0';
4633 stat
= rename (from
, to_esn
);
4637 strcpy (vms_file_written
, to_esn
);
4639 to_fab
.fab$l_fna
= vms_file_written
; /* this points to the versionless name */
4640 to_fab
.fab$b_fns
= strlen (vms_file_written
);
4642 /* Now set the file protection to the correct value */
4643 SYS$
OPEN (&to_fab
, 0, 0); /* This fills in the nam$w_fid fields */
4645 /* Copy these fields into the fib */
4646 fib
.fib$r_fid_overlay
.fib$w_fid
[0] = to_nam
.nam$w_fid
[0];
4647 fib
.fib$r_fid_overlay
.fib$w_fid
[1] = to_nam
.nam$w_fid
[1];
4648 fib
.fib$r_fid_overlay
.fib$w_fid
[2] = to_nam
.nam$w_fid
[2];
4650 SYS$
CLOSE (&to_fab
, 0, 0);
4652 stat
= SYS$
ASSIGN (&disk
, &chan
, 0, 0); /* open a channel to the disk */
4655 stat
= SYS$
QIOW (0, chan
, IO$_MODIFY
, iosb
, 0, 0, &fib_d
,
4656 0, 0, 0, &fib_attr
, 0);
4659 stat
= SYS$
DASSGN (chan
);
4662 strcpy (vms_file_written
, to_esn
); /* We will write this to the terminal*/
4672 unsigned short fid
[3];
4673 char esa
[NAM$C_MAXRSS
];
4676 fab
.fab$l_fop
= FAB$M_OFP
;
4677 fab
.fab$l_fna
= file
;
4678 fab
.fab$b_fns
= strlen (file
);
4679 fab
.fab$l_nam
= &nam
;
4682 nam
.nam$l_esa
= esa
;
4683 nam
.nam$b_ess
= NAM$C_MAXRSS
;
4685 status
= SYS$
PARSE (&fab
);
4686 if ((status
& 1) == 0)
4689 vaxc$errno
= status
;
4692 status
= SYS$
SEARCH (&fab
);
4693 if ((status
& 1) == 0)
4696 vaxc$errno
= status
;
4700 fid
[0] = nam
.nam$w_fid
[0];
4701 fid
[1] = nam
.nam$w_fid
[1];
4702 fid
[2] = nam
.nam$w_fid
[2];
4704 fab
.fab$l_fna
= new;
4705 fab
.fab$b_fns
= strlen (new);
4707 status
= SYS$
PARSE (&fab
);
4708 if ((status
& 1) == 0)
4711 vaxc$errno
= status
;
4715 nam
.nam$w_fid
[0] = fid
[0];
4716 nam
.nam$w_fid
[1] = fid
[1];
4717 nam
.nam$w_fid
[2] = fid
[2];
4719 nam
.nam$l_esa
= nam
.nam$l_name
;
4720 nam
.nam$b_esl
= nam
.nam$b_name
+ nam
.nam$b_type
+ nam
.nam$b_ver
;
4722 status
= SYS$
ENTER (&fab
);
4723 if ((status
& 1) == 0)
4726 vaxc$errno
= status
;
4736 printf ("%s not yet implemented\r\n", badfunc
);
4744 /* Arrange to return a range centered on zero. */
4745 return rand () - (1 << 30);
4756 /* Called from init_sys_modes. */
4761 /* If we're not on an HFT we shouldn't do any of this. We determine
4762 if we are on an HFT by trying to get an HFT error code. If this
4763 call fails, we're not on an HFT. */
4765 if (ioctl (0, HFQERROR
, &junk
) < 0)
4767 #else /* not IBMR2AIX */
4768 if (ioctl (0, HFQEIO
, 0) < 0)
4770 #endif /* not IBMR2AIX */
4772 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4773 as the rubout key's ASCII code. Here this is changed. The bug is that
4774 there's no way to determine the old mapping, so in reset_sys_modes
4775 we need to assume that the normal map had been present. Of course, this
4776 code also doesn't help if on a terminal emulator which doesn't understand
4780 struct hfkeymap keymap
;
4782 buf
.hf_bufp
= (char *)&keymap
;
4783 buf
.hf_buflen
= sizeof (keymap
);
4784 keymap
.hf_nkeys
= 2;
4785 keymap
.hfkey
[0].hf_kpos
= 15;
4786 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
4788 keymap
.hfkey
[0].hf_keyidh
= '<';
4789 #else /* not IBMR2AIX */
4790 keymap
.hfkey
[0].hf_page
= '<';
4791 #endif /* not IBMR2AIX */
4792 keymap
.hfkey
[0].hf_char
= 127;
4793 keymap
.hfkey
[1].hf_kpos
= 15;
4794 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
4796 keymap
.hfkey
[1].hf_keyidh
= '<';
4797 #else /* not IBMR2AIX */
4798 keymap
.hfkey
[1].hf_page
= '<';
4799 #endif /* not IBMR2AIX */
4800 keymap
.hfkey
[1].hf_char
= 127;
4801 hftctl (0, HFSKBD
, &buf
);
4803 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4805 line_ins_del_ok
= char_ins_del_ok
= 0;
4808 /* Reset the rubout key to backspace. */
4813 struct hfkeymap keymap
;
4817 if (ioctl (0, HFQERROR
, &junk
) < 0)
4819 #else /* not IBMR2AIX */
4820 if (ioctl (0, HFQEIO
, 0) < 0)
4822 #endif /* not IBMR2AIX */
4824 buf
.hf_bufp
= (char *)&keymap
;
4825 buf
.hf_buflen
= sizeof (keymap
);
4826 keymap
.hf_nkeys
= 2;
4827 keymap
.hfkey
[0].hf_kpos
= 15;
4828 keymap
.hfkey
[0].hf_kstate
= HFMAPCHAR
| HFSHFNONE
;
4830 keymap
.hfkey
[0].hf_keyidh
= '<';
4831 #else /* not IBMR2AIX */
4832 keymap
.hfkey
[0].hf_page
= '<';
4833 #endif /* not IBMR2AIX */
4834 keymap
.hfkey
[0].hf_char
= 8;
4835 keymap
.hfkey
[1].hf_kpos
= 15;
4836 keymap
.hfkey
[1].hf_kstate
= HFMAPCHAR
| HFSHFSHFT
;
4838 keymap
.hfkey
[1].hf_keyidh
= '<';
4839 #else /* not IBMR2AIX */
4840 keymap
.hfkey
[1].hf_page
= '<';
4841 #endif /* not IBMR2AIX */
4842 keymap
.hfkey
[1].hf_char
= 8;
4843 hftctl (0, HFSKBD
, &buf
);