*** empty log message ***
[emacs.git] / src / sysdep.c
blob7283f7d9e06f1b2056af293320dc17bf4abde8b0
1 /* Interfaces to system-dependent kernel and library entries.
2 Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
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. */
21 #include <signal.h>
22 #include <setjmp.h>
24 #include "config.h"
25 #include "lisp.h"
26 #undef NULL
28 #define min(x,y) ((x) > (y) ? (y) : (x))
30 /* In this file, open, read and write refer to the system calls,
31 not our sugared interfaces sys_open, sys_read and sys_write.
32 Contrariwise, for systems where we use the system calls directly,
33 define sys_read, etc. here as aliases for them. */
34 #ifndef read
35 #define sys_read read
36 #define sys_write write
37 #endif /* `read' is not a macro */
39 #undef read
40 #undef write
42 #ifndef close
43 #define sys_close close
44 #else
45 #undef close
46 #endif
48 #ifndef open
49 #define sys_open open
50 #else /* `open' is a macro */
51 #undef open
52 #endif /* `open' is a macro */
54 #include <stdio.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <errno.h>
59 extern int errno;
60 #ifndef VMS
61 extern char *sys_errlist[];
62 #endif
64 #ifdef VMS
65 #include <rms.h>
66 #include <ttdef.h>
67 #include <tt2def.h>
68 #include <iodef.h>
69 #include <ssdef.h>
70 #include <descrip.h>
71 #include <fibdef.h>
72 #include <atrdef.h>
73 #include <ctype.h>
74 #include <string.h>
75 #ifdef __GNUC__
76 #include <sys/file.h>
77 #else
78 #include <file.h>
79 #endif
80 #undef F_SETFL
81 #ifndef RAB$C_BID
82 #include <rab.h>
83 #endif
84 #define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
85 #endif /* VMS */
87 #ifndef BSD4_1
88 #ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
89 because the vms compiler doesn't grok `defined' */
90 #include <fcntl.h>
91 #endif
92 #ifdef USG
93 #include <fcntl.h>
94 #endif
95 #endif /* not 4.1 bsd */
97 /* Get DGUX definition for FASYNC - DJB */
98 #ifdef DGUX
99 #include <sys/file.h>
100 #endif /* DGUX */
102 #include <sys/ioctl.h>
103 #include "systerm.h"
105 #ifdef BSD
106 #ifdef BSD4_1
107 #include <wait.h>
108 #else /* not 4.1 */
109 #include <sys/wait.h>
110 #endif /* not 4.1 */
111 #endif /* BSD */
113 #ifdef BROKEN_TIOCGWINSZ
114 #undef TIOCGWINSZ
115 #endif
117 #ifdef USG
118 #include <sys/utsname.h>
119 #include <string.h>
120 #ifndef MEMORY_IN_STRING_H
121 #include <memory.h>
122 #endif
123 #ifdef TIOCGWINSZ
124 #ifdef NEED_SIOCTL
125 #include <sys/sioctl.h>
126 #endif
127 #ifdef NEED_PTEM_H
128 #include <sys/stream.h>
129 #include <sys/ptem.h>
130 #endif
131 #endif /* TIOCGWINSZ */
132 #endif /* USG */
134 extern int quit_char;
136 #include "frame.h"
137 #include "window.h"
138 #include "termhooks.h"
139 #include "termchar.h"
140 #include "termopts.h"
141 #include "dispextern.h"
142 #include "process.h"
144 #ifdef NONSYSTEM_DIR_LIBRARY
145 #include "ndir.h"
146 #endif /* NONSYSTEM_DIR_LIBRARY */
148 #include "syssignal.h"
149 #include "systime.h"
151 static int baud_convert[] =
152 #ifdef BAUD_CONVERT
153 BAUD_CONVERT;
154 #else
156 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
157 1800, 2400, 4800, 9600, 19200, 38400
159 #endif
161 extern short ospeed;
163 /* The file descriptor for Emacs's input terminal.
164 Under Unix, this is always left zero;
165 under VMS, we place the input channel number here.
166 This allows us to write more code that works for both VMS and Unix. */
167 static int input_fd;
169 #ifdef VMS
170 static struct iosb
172 short status;
173 short offset;
174 short termlen;
175 short term;
176 } input_iosb;
178 int kbd_input_ast ();
180 int waiting_for_ast;
181 int stop_input;
182 int input_ef = 0;
183 int timer_ef = 0;
184 int process_ef = 0;
185 int input_eflist;
186 int timer_eflist;
188 static $DESCRIPTOR (input_dsc, "TT");
189 static int terminator_mask[2] = { 0, 0 };
191 static struct sensemode {
192 short status;
193 unsigned char xmit_baud;
194 unsigned char rcv_baud;
195 unsigned char crfill;
196 unsigned char lffill;
197 unsigned char parity;
198 unsigned char unused;
199 char class;
200 char type;
201 short scr_wid;
202 unsigned long tt_char : 24, scr_len : 8;
203 unsigned long tt2_char;
204 } sensemode_iosb;
205 #endif /* VMS */
207 discard_tty_input ()
209 struct emacs_tty buf;
211 if (noninteractive)
212 return;
214 /* Discarding input is not safe when the input could contain
215 replies from the X server. So don't do it. */
216 if (read_socket_hook)
217 return;
219 #ifdef VMS
220 end_kbd_input ();
221 SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
222 &buf.main, 0, 0, terminator_mask, 0, 0);
223 queue_kbd_input ();
224 #else /* not VMS */
225 #ifdef APOLLO
227 int zero = 0;
228 ioctl (0, TIOCFLUSH, &zero);
230 #else /* not Apollo */
231 EMACS_GET_TTY (input_fd, &buf);
232 EMACS_SET_TTY (input_fd, &buf, 0);
233 #endif /* not Apollo */
234 #endif /* not VMS */
237 #ifdef SIGTSTP
239 stuff_char (c)
240 char c;
242 /* Should perhaps error if in batch mode */
243 #ifdef TIOCSTI
244 ioctl (0, TIOCSTI, &c);
245 #else /* no TIOCSTI */
246 error ("Cannot stuff terminal input characters in this version of Unix.");
247 #endif /* no TIOCSTI */
250 #endif /* SIGTSTP */
252 init_baud_rate ()
254 if (noninteractive)
255 ospeed = 0;
256 else
258 #ifdef VMS
259 struct sensemode sg;
261 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
262 &sg.class, 12, 0, 0, 0, 0 );
263 ospeed = sg.xmit_baud;
264 #else /* not VMS */
265 #ifdef HAVE_TERMIO
266 struct termio sg;
268 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
269 tcgetattr (0, &sg);
270 ospeed = sg.c_cflag & CBAUD;
271 #else /* neither VMS nor TERMIO */
272 #ifdef HAVE_TERMIOS
273 struct termios sg;
275 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
276 tcgetattr (0, &sg);
277 ospeed = sg.c_cflag & CBAUD;
278 #else /* neither VMS nor TERMIO nor TERMIOS */
279 struct sgttyb sg;
281 sg.sg_ospeed = B9600;
282 ioctl (0, TIOCGETP, &sg);
283 ospeed = sg.sg_ospeed;
284 #endif /* not HAVE_TERMIOS */
285 #endif /* not HAVE_TERMIO */
286 #endif /* not VMS */
289 baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
290 ? baud_convert[ospeed] : 9600);
291 if (baud_rate == 0)
292 baud_rate = 1200;
295 /*ARGSUSED*/
296 set_exclusive_use (fd)
297 int fd;
299 #ifdef FIOCLEX
300 ioctl (fd, FIOCLEX, 0);
301 #endif
302 /* Ok to do nothing if this feature does not exist */
305 #ifndef subprocesses
307 wait_without_blocking ()
309 #ifdef BSD
310 wait3 (0, WNOHANG | WUNTRACED, 0);
311 #else
312 croak ("wait_without_blocking");
313 #endif
314 synch_process_alive = 0;
317 #endif /* not subprocesses */
319 int wait_debugging; /* Set nonzero to make following function work under dbx
320 (at least for bsd). */
322 SIGTYPE
323 wait_for_termination_signal ()
326 /* Wait for subprocess with process id `pid' to terminate and
327 make sure it will get eliminated (not remain forever as a zombie) */
329 wait_for_termination (pid)
330 int pid;
332 while (1)
334 #ifdef subprocesses
335 #ifdef VMS
336 int status;
338 status = sys$forcex (&pid, 0, 0);
339 break;
340 #else /* not VMS */
342 /* Exit if the process has terminated. */
343 if (!synch_process_alive)
344 break;
345 /* Otherwise wait 1 second or until a signal comes in. */
346 signal (SIGALRM, wait_for_termination_signal);
347 alarm (1);
348 pause ();
349 alarm (0);
350 signal (SIGALRM, SIG_IGN);
351 #endif /* not VMS */
352 #else /* not subprocesses */
353 #ifndef BSD4_1
354 if (kill (pid, 0) < 0)
355 break;
356 wait (0);
357 #else /* BSD4_1 */
358 int status;
359 status = wait (0);
360 if (status == pid || status == -1)
361 break;
362 #endif /* BSD4_1 */
363 #endif /* not subprocesses */
367 #ifdef subprocesses
370 * flush any pending output
371 * (may flush input as well; it does not matter the way we use it)
374 flush_pending_output (channel)
375 int channel;
377 #ifdef HAVE_TERMIOS
378 /* If we try this, we get hit with SIGTTIN, because
379 the child's tty belongs to the child's pgrp. */
380 #else
381 #ifdef TCFLSH
382 ioctl (channel, TCFLSH, 1);
383 #else
384 #ifdef TIOCFLUSH
385 int zero = 0;
386 /* 3rd arg should be ignored
387 but some 4.2 kernels actually want the address of an int
388 and nonzero means something different. */
389 ioctl (channel, TIOCFLUSH, &zero);
390 #endif
391 #endif
392 #endif
395 #ifndef VMS
396 /* Set up the terminal at the other end of a pseudo-terminal that
397 we will be controlling an inferior through.
398 It should not echo or do line-editing, since that is done
399 in Emacs. No padding needed for insertion into an Emacs buffer. */
401 child_setup_tty (out)
402 int out;
404 struct emacs_tty s;
406 EMACS_GET_TTY (out, &s);
408 #ifdef HAVE_TERMIO
409 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
410 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
411 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
412 /* No output delays */
413 s.main.c_lflag &= ~ECHO; /* Disable echo */
414 s.main.c_lflag |= ISIG; /* Enable signals */
415 s.main.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on
416 input */
417 s.main.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on
418 output */
419 #if 0
420 /* Said to be unnecesary: */
421 s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
422 s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */
423 #endif
425 s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
426 s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
427 s.main.c_cc[VERASE] = 0377; /* disable erase processing */
428 s.main.c_cc[VKILL] = 0377; /* disable kill processing */
430 #ifdef HPUX
431 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
432 #endif /* HPUX */
434 #ifdef AIX
435 /* AIX enhanced edit loses NULs, so disable it */
436 #ifndef IBMR2AIX
437 s.main.c_line = 0;
438 s.main.c_iflag &= ~ASCEDIT;
439 #endif
440 /* Also, PTY overloads NUL and BREAK.
441 don't ignore break, but don't signal either, so it looks like NUL. */
442 s.main.c_iflag &= ~IGNBRK;
443 s.main.c_iflag &= ~BRKINT;
444 /* QUIT and INTR work better as signals, so disable character forms */
445 s.main.c_cc[VQUIT] = 0377;
446 s.main.c_cc[VINTR] = 0377;
447 s.main.c_cc[VEOL] = 0377;
448 s.main.c_lflag &= ~ISIG;
449 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
450 #endif /* AIX */
452 #else /* not HAVE_TERMIO */
454 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
455 | CBREAK | TANDEM);
456 s.main.sg_erase = 0377;
457 s.main.sg_kill = 0377;
459 #endif /* not HAVE_TERMIO */
461 EMACS_SET_TTY (out, &s, 0);
463 #ifdef BSD4_1
464 if (interrupt_input)
465 reset_sigio ();
466 #endif /* BSD4_1 */
467 #ifdef RTU
469 int zero = 0;
470 ioctl (out, FIOASYNC, &zero);
472 #endif /* RTU */
474 #endif /* not VMS */
476 #endif /* subprocesses */
478 /*ARGSUSED*/
479 setpgrp_of_tty (pid)
480 int pid;
482 EMACS_SET_TTY_PGRP (input_fd, &pid);
485 /* Record a signal code and the handler for it. */
486 struct save_signal
488 int code;
489 SIGTYPE (*handler) ();
492 /* Suspend the Emacs process; give terminal to its superior. */
494 sys_suspend ()
496 #ifdef VMS
497 unsigned long parent_id;
499 parent_id = getppid ();
500 if (parent_id && parent_id != 0xffffffff)
502 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
503 int status = LIB$ATTACH (&parent_id) & 1;
504 signal (SIGINT, oldsig);
505 return status;
507 else
509 struct {
510 int l;
511 char *a;
512 } d_prompt;
513 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
514 d_prompt.a = "Emacs: "; /* Just a reminder */
515 lib$spawn (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
516 return 1;
518 return -1;
519 #else
520 #ifdef SIGTSTP
522 EMACS_KILLPG (getpgrp (0), SIGTSTP);
524 #else /* No SIGTSTP */
525 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
526 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
527 kill (getpid (), SIGQUIT);
529 #else /* No SIGTSTP or USG_JOBCTRL */
531 /* On a system where suspending is not implemented,
532 instead fork a subshell and let it talk directly to the terminal
533 while we wait. */
534 int pid = fork ();
535 struct save_signal saved_handlers[5];
537 saved_handlers[0].code = SIGINT;
538 saved_handlers[1].code = SIGQUIT;
539 saved_handlers[2].code = SIGTERM;
540 #ifdef SIGIO
541 saved_handlers[3].code = SIGIO;
542 saved_handlers[4].code = 0;
543 #else
544 saved_handlers[3].code = 0;
545 #endif
547 if (pid == -1)
548 error ("Can't spawn subshell");
549 if (pid == 0)
551 char *sh;
553 sh = (char *) egetenv ("SHELL");
554 if (sh == 0)
555 sh = "sh";
556 /* Use our buffer's default directory for the subshell. */
558 Lisp_Object dir;
559 unsigned char *str;
560 int len;
562 /* mentioning current_buffer->buffer would mean including buffer.h,
563 which somehow wedges the hp compiler. So instead... */
565 dir = intern ("default-directory");
566 /* Can't use NULL */
567 if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
568 goto xyzzy;
569 dir = Fsymbol_value (dir);
570 if (XTYPE (dir) != Lisp_String)
571 goto xyzzy;
573 str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
574 len = XSTRING (dir)->size;
575 bcopy (XSTRING (dir)->data, str, len);
576 if (str[len - 1] != '/') str[len++] = '/';
577 str[len] = 0;
578 chdir (str);
580 xyzzy:
581 #ifdef subprocesses
582 close_process_descs (); /* Close Emacs's pipes/ptys */
583 #endif
584 nice (-nice (0)); /* Give the new shell the default piority */
585 execlp (sh, sh, 0);
586 write (1, "Can't execute subshell", 22);
587 _exit (1);
590 save_signal_handlers (saved_handlers);
591 wait_for_termination (pid);
592 restore_signal_handlers (saved_handlers);
594 #endif /* no USG_JOBCTRL */
595 #endif /* no SIGTSTP */
596 #endif /* not VMS */
599 save_signal_handlers (saved_handlers)
600 struct save_signal *saved_handlers;
602 while (saved_handlers->code)
604 saved_handlers->handler
605 = (SIGTYPE (*) ()) signal (saved_handlers->code, SIG_IGN);
606 saved_handlers++;
610 restore_signal_handlers (saved_handlers)
611 struct save_signal *saved_handlers;
613 while (saved_handlers->code)
615 signal (saved_handlers->code, saved_handlers->handler);
616 saved_handlers++;
620 #ifdef F_SETFL
622 int old_fcntl_flags;
624 init_sigio ()
626 #ifdef FASYNC
627 old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
628 #endif
629 request_sigio ();
632 reset_sigio ()
634 unrequest_sigio ();
637 #ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */
639 request_sigio ()
641 #ifdef SIGWINCH
642 sigunblock (sigmask (SIGWINCH));
643 #endif
644 fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
646 interrupts_deferred = 0;
649 unrequest_sigio ()
651 #ifdef SIGWINCH
652 sigblock (sigmask (SIGWINCH));
653 #endif
654 fcntl (0, F_SETFL, old_fcntl_flags);
655 interrupts_deferred = 1;
658 #else /* no FASYNC */
659 #ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
661 request_sigio ()
663 int on = 1;
664 ioctl (0, FIOASYNC, &on);
665 interrupts_deferred = 0;
668 unrequest_sigio ()
670 int off = 0;
672 ioctl (0, FIOASYNC, &off);
673 interrupts_deferred = 1;
676 #else /* not FASYNC, not STRIDE */
678 request_sigio ()
680 croak ("request_sigio");
683 unrequest_sigio ()
685 croak ("unrequest_sigio");
688 #endif /* STRIDE */
689 #endif /* FASYNC */
690 #endif /* F_SETFL */
692 /* The initial tty mode bits */
693 struct emacs_tty old_tty;
695 int term_initted; /* 1 if outer tty status has been recorded */
697 #ifdef BSD4_1
698 /* BSD 4.1 needs to keep track of the lmode bits in order to start
699 sigio. */
700 int lmode;
701 #endif
703 #ifdef F_SETOWN
704 int old_fcntl_owner;
705 #endif /* F_SETOWN */
707 /* This may also be defined in stdio,
708 but if so, this does no harm,
709 and using the same name avoids wasting the other one's space. */
711 #if defined (USG) || defined (DGUX)
712 unsigned char _sobuf[BUFSIZ+8];
713 #else
714 char _sobuf[BUFSIZ];
715 #endif
717 #ifdef TIOCGLTC
718 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
719 #endif
720 #ifdef TIOCGETC
721 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
722 #endif
724 init_sys_modes ()
726 struct emacs_tty tty;
728 #ifdef VMS
729 #if 0
730 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
731 extern int (*interrupt_signal) ();
732 #endif
733 #endif
735 if (noninteractive)
736 return;
738 #ifdef VMS
739 if (!input_ef)
740 input_ef = get_kbd_event_flag ();
741 /* LIB$GET_EF (&input_ef); */
742 SYS$CLREF (input_ef);
743 waiting_for_ast = 0;
744 if (!timer_ef)
745 timer_ef = get_timer_event_flag ();
746 /* LIB$GET_EF (&timer_ef); */
747 SYS$CLREF (timer_ef);
748 if (!process_ef)
750 LIB$GET_EF (&process_ef);
751 SYS$CLREF (process_ef);
753 if (input_ef / 32 != process_ef / 32)
754 croak ("Input and process event flags in different clusters.");
755 if (input_ef / 32 != timer_ef / 32)
756 croak ("Input and process event flags in different clusters.");
757 input_eflist = ((unsigned) 1 << (input_ef % 32)) |
758 ((unsigned) 1 << (process_ef % 32));
759 timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
760 ((unsigned) 1 << (timer_ef % 32));
761 #ifndef VMS4_4
762 sys_access_reinit ();
763 #endif
764 #endif /* not VMS */
766 EMACS_GET_TTY (input_fd, &old_tty);
768 if (!read_socket_hook && EQ (Vwindow_system, Qnil))
770 tty = old_tty;
772 #ifdef HAVE_TERMIO
773 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
774 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
775 #ifdef ISTRIP
776 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
777 #endif
778 tty.main.c_lflag &= ~ECHO; /* Disable echo */
779 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
780 tty.main.c_lflag |= ISIG; /* Enable signals */
781 if (flow_control)
783 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
784 #ifdef IXANY
785 tty.main.c_iflag &= ~IXANY;
786 #endif /* IXANY */
788 else
789 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
790 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
791 on output */
792 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
793 #ifdef CS8
794 if (meta_key)
796 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
797 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
799 #endif
800 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
801 /* Set up C-g for both SIGQUIT and SIGINT.
802 We don't know which we will get, but we handle both alike
803 so which one it really gives us does not matter. */
804 tty.main.c_cc[VQUIT] = quit_char;
805 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
806 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
807 #ifdef VSWTCH
808 tty.main.c_cc[VSWTCH] = CDEL; /* Turn off shell layering use
809 of C-z */
810 #endif /* VSWTCH */
811 #if defined (mips) || defined (HAVE_TCATTR)
812 /* The following code looks like the right thing in general,
813 but it is said to cause a crash on USG V.4.
814 Let's play safe by turning it on only for the MIPS. */
815 #ifdef VSUSP
816 tty.main.c_cc[VSUSP] = CDEL; /* Turn off mips handling of C-z. */
817 #endif /* VSUSP */
818 #ifdef V_DSUSP
819 tty.main.c_cc[V_DSUSP] = CDEL; /* Turn off mips handling of C-y. */
820 #endif /* V_DSUSP */
821 #endif /* mips or HAVE_TCATTR */
822 #ifdef AIX
823 #ifndef IBMR2AIX
824 /* AIX enhanced edit loses NULs, so disable it */
825 tty.main.c_line = 0;
826 tty.main.c_iflag &= ~ASCEDIT;
827 #else
828 tty.main.c_cc[VSTRT] = 255;
829 tty.main.c_cc[VSTOP] = 255;
830 tty.main.c_cc[VSUSP] = 255;
831 tty.main.c_cc[VDSUSP] = 255;
832 #endif /* IBMR2AIX */
833 /* Also, PTY overloads NUL and BREAK.
834 don't ignore break, but don't signal either, so it looks like NUL.
835 This really serves a purpose only if running in an XTERM window
836 or via TELNET or the like, but does no harm elsewhere. */
837 tty.main.c_iflag &= ~IGNBRK;
838 tty.main.c_iflag &= ~BRKINT;
839 #endif
840 #else /* if not HAVE_TERMIO */
841 #ifdef VMS
842 tty.main.tt_char |= TT$M_NOECHO;
843 if (meta_key)
844 tty.main.tt_char |= TT$M_EIGHTBIT
845 if (flow_control)
846 tty.main.tt_char |= TT$M_TTSYNC;
847 else
848 tty.main.tt_char &= ~TT$M_TTSYNC;
849 tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
850 #else /* not VMS (BSD, that is) */
851 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
852 if (meta_key)
853 tty.main.sg_flags |= ANYP;
854 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
855 #endif /* not VMS (BSD, that is) */
856 #endif /* not HAVE_TERMIO */
858 /* If going to use CBREAK mode, we must request C-g to interrupt
859 and turn off start and stop chars, etc. If not going to use
860 CBREAK mode, do this anyway so as to turn off local flow
861 control for user coming over network on 4.2; in this case,
862 only t_stopc and t_startc really matter. */
863 #ifndef HAVE_TERMIO
864 #ifdef TIOCGETC
865 /* Note: if not using CBREAK mode, it makes no difference how we
866 set this */
867 tty.tchars = new_tchars;
868 tty.tchars.t_intrc = quit_char;
869 if (flow_control)
871 tty.tchars.t_startc = '\021';
872 tty.tchars.t_stopc = '\023';
875 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
876 #ifndef LPASS8
877 #define LPASS8 0
878 #endif
880 #ifdef BSD4_1
881 #define LNOFLSH 0100000
882 #endif
884 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
886 #ifdef BSD4_1
887 lmode = tty.lmode;
888 #endif
890 #endif /* TIOCGETC */
891 #endif /* not HAVE_TERMIO */
893 #ifdef TIOCGLTC
894 tty.ltchars = new_ltchars;
895 #endif /* TIOCGLTC */
897 EMACS_SET_TTY (input_fd, &tty, 0);
899 /* This code added to insure that, if flow-control is not to be used,
900 we have an unlocked terminal at the start. */
902 #ifdef TCXONC
903 if (!flow_control) ioctl (0, TCXONC, 1);
904 #endif
905 #ifndef APOLLO
906 #ifdef TIOCSTART
907 if (!flow_control) ioctl (0, TIOCSTART, 0);
908 #endif
909 #endif
911 #ifdef AIX
912 hft_init ();
913 #ifdef IBMR2AIX
915 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
916 to be only LF. This is the way that is done. */
917 struct termio tty;
919 if (ioctl (1, HFTGETID, &tty) != -1)
920 write (1, "\033[20l", 5);
922 #endif
923 #endif
925 #ifdef VMS
926 /* Appears to do nothing when in PASTHRU mode.
927 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
928 interrupt_signal, oob_chars, 0, 0, 0, 0);
930 queue_kbd_input (0);
931 #endif /* VMS */
934 #ifdef F_SETFL
935 #ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */
936 if (interrupt_input)
938 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
939 fcntl (0, F_SETOWN, getpid ());
940 init_sigio ();
942 #endif /* F_GETOWN */
943 #endif /* F_SETFL */
945 #ifdef BSD4_1
946 if (interrupt_input)
947 init_sigio ();
948 #endif
950 #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
951 #undef _IOFBF
952 #endif
953 #ifdef _IOFBF
954 /* This symbol is defined on recent USG systems.
955 Someone says without this call USG won't really buffer the file
956 even with a call to setbuf. */
957 setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
958 #else
959 setbuf (stdout, _sobuf);
960 #endif
961 set_terminal_modes ();
962 if (term_initted && no_redraw_on_reenter)
964 if (display_completed)
965 direct_output_forward_char (0);
967 else
969 frame_garbaged = 1;
970 #ifdef MULTI_FRAME
971 if (FRAMEP (Vterminal_frame))
972 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
973 #endif
976 term_initted = 1;
979 /* Return nonzero if safe to use tabs in output.
980 At the time this is called, init_sys_modes has not been done yet. */
982 tabs_safe_p ()
984 struct emacs_tty tty;
986 EMACS_GET_TTY (input_fd, &tty);
987 return EMACS_TTY_TABS_OK (&tty);
990 /* Get terminal size from system.
991 Store number of lines into *heightp and width into *widthp.
992 If zero or a negative number is stored, the value is not valid. */
994 get_frame_size (widthp, heightp)
995 int *widthp, *heightp;
998 #ifdef TIOCGWINSZ
1000 /* BSD-style. */
1001 struct winsize size;
1003 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1004 *widthp = *heightp = 0;
1005 else
1007 *widthp = size.ws_col;
1008 *heightp = size.ws_row;
1011 #else
1012 #ifdef TIOCGSIZE
1014 /* SunOS - style. */
1015 struct ttysize size;
1017 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1018 *widthp = *heightp = 0;
1019 else
1021 *widthp = size.ts_cols;
1022 *heightp = size.ts_lines;
1025 #else
1026 #ifdef VMS
1028 struct sensemode tty;
1030 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
1031 &tty.class, 12, 0, 0, 0, 0);
1032 *widthp = tty.scr_wid;
1033 *heightp = tty.scr_len;
1035 #else /* system doesn't know size */
1037 *widthp = 0;
1038 *heightp = 0;
1040 #endif /* not VMS */
1041 #endif /* not SunOS-style */
1042 #endif /* not BSD-style */
1046 /* Prepare the terminal for exiting Emacs; move the cursor to the
1047 bottom of the frame, turn off interrupt-driven I/O, etc. */
1048 reset_sys_modes ()
1050 if (noninteractive)
1052 fflush (stdout);
1053 return;
1055 if (!term_initted)
1056 return;
1057 if (read_socket_hook || !EQ (Vwindow_system, Qnil))
1058 return;
1059 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
1060 clear_end_of_line (FRAME_WIDTH (selected_frame));
1061 /* clear_end_of_line may move the cursor */
1062 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
1063 #ifdef IBMR2AIX
1065 /* HFT devices normally use ^J as a LF/CR. We forced it to
1066 do the LF only. Now, we need to reset it. */
1067 struct termio tty;
1069 if (ioctl (1, HFTGETID, &tty) != -1)
1070 write (1, "\033[20h", 5);
1072 #endif
1074 reset_terminal_modes ();
1075 fflush (stdout);
1076 #ifdef BSD
1077 #ifndef BSD4_1
1078 /* Avoid possible loss of output when changing terminal modes. */
1079 fsync (fileno (stdout));
1080 #endif
1081 #endif
1083 #ifdef F_SETFL
1084 #ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */
1085 if (interrupt_input)
1087 reset_sigio ();
1088 fcntl (0, F_SETOWN, old_fcntl_owner);
1090 #endif /* F_SETOWN */
1091 #endif /* F_SETFL */
1092 #ifdef BSD4_1
1093 if (interrupt_input)
1094 reset_sigio ();
1095 #endif /* BSD4_1 */
1097 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
1100 #ifdef AIX
1101 hft_reset ();
1102 #endif
1105 #ifdef HAVE_PTYS
1107 /* Set up the proper status flags for use of a pty. */
1109 setup_pty (fd)
1110 int fd;
1112 /* I'm told that TOICREMOTE does not mean control chars
1113 "can't be sent" but rather that they don't have
1114 input-editing or signaling effects.
1115 That should be good, because we have other ways
1116 to do those things in Emacs.
1117 However, telnet mode seems not to work on 4.2.
1118 So TIOCREMOTE is turned off now. */
1120 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1121 will hang. In particular, the "timeout" feature (which
1122 causes a read to return if there is no data available)
1123 does this. Also it is known that telnet mode will hang
1124 in such a way that Emacs must be stopped (perhaps this
1125 is the same problem).
1127 If TIOCREMOTE is turned off, then there is a bug in
1128 hp-ux which sometimes loses data. Apparently the
1129 code which blocks the master process when the internal
1130 buffer fills up does not work. Other than this,
1131 though, everything else seems to work fine.
1133 Since the latter lossage is more benign, we may as well
1134 lose that way. -- cph */
1135 #ifdef FIONBIO
1136 #ifdef SYSV_PTYS
1138 int on = 1;
1139 ioctl (fd, FIONBIO, &on);
1141 #endif
1142 #endif
1143 #ifdef IBMRTAIX
1144 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1145 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1146 /* cause EMACS not to die when it should, i.e., when its own controlling */
1147 /* tty goes away. I've complained to the AIX developers, and they may */
1148 /* change this behavior, but I'm not going to hold my breath. */
1149 signal (SIGHUP, SIG_IGN);
1150 #endif
1152 #endif /* HAVE_PTYS */
1154 #ifdef VMS
1156 /* Assigning an input channel is done at the start of Emacs execution.
1157 This is called each time Emacs is resumed, also, but does nothing
1158 because input_chain is no longer zero. */
1160 init_vms_input ()
1162 int status;
1164 if (input_fd == 0)
1166 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
1167 if (! (status & 1))
1168 LIB$STOP (status);
1172 /* Deassigning the input channel is done before exiting. */
1174 stop_vms_input ()
1176 return SYS$DASSGN (input_fd);
1179 short input_buffer;
1181 /* Request reading one character into the keyboard buffer.
1182 This is done as soon as the buffer becomes empty. */
1184 queue_kbd_input ()
1186 int status;
1187 waiting_for_ast = 0;
1188 stop_input = 0;
1189 status = SYS$QIO (0, input_fd, IO$_READVBLK,
1190 &input_iosb, kbd_input_ast, 1,
1191 &input_buffer, 1, 0, terminator_mask, 0, 0);
1194 int input_count;
1196 /* Ast routine that is called when keyboard input comes in
1197 in accord with the SYS$QIO above. */
1199 kbd_input_ast ()
1201 register int c = -1;
1202 int old_errno = errno;
1203 extern EMACS_TIME *input_available_clear_time;
1205 if (waiting_for_ast)
1206 SYS$SETEF (input_ef);
1207 waiting_for_ast = 0;
1208 input_count++;
1209 #ifdef ASTDEBUG
1210 if (input_count == 25)
1211 exit (1);
1212 printf ("Ast # %d,", input_count);
1213 printf (" iosb = %x, %x, %x, %x",
1214 input_iosb.offset, input_iosb.status, input_iosb.termlen,
1215 input_iosb.term);
1216 #endif
1217 if (input_iosb.offset)
1219 c = input_buffer;
1220 #ifdef ASTDEBUG
1221 printf (", char = 0%o", c);
1222 #endif
1224 #ifdef ASTDEBUG
1225 printf ("\n");
1226 fflush (stdout);
1227 sleep (1);
1228 #endif
1229 if (! stop_input)
1230 queue_kbd_input ();
1231 if (c >= 0)
1233 struct input_event e;
1234 e.kind = ascii_keystroke;
1235 XSET (buf[i].code, Lisp_Int, cbuf[i]);
1236 e.frame = selected_frame;
1237 kbd_buffer_store_event (&e);
1240 if (input_available_clear_time)
1241 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
1242 errno = old_errno;
1245 /* Wait until there is something in kbd_buffer. */
1247 wait_for_kbd_input ()
1249 extern int have_process_input, process_exited;
1251 /* If already something, avoid doing system calls. */
1252 if (detect_input_pending ())
1254 return;
1256 /* Clear a flag, and tell ast routine above to set it. */
1257 SYS$CLREF (input_ef);
1258 waiting_for_ast = 1;
1259 /* Check for timing error: ast happened while we were doing that. */
1260 if (!detect_input_pending ())
1262 /* No timing error: wait for flag to be set. */
1263 set_waiting_for_input (0);
1264 SYS$WFLOR (input_ef, input_eflist);
1265 clear_waiting_for_input (0);
1266 if (!detect_input_pending ())
1267 /* Check for subprocess input availability */
1269 int dsp = have_process_input || process_exited;
1271 SYS$CLREF (process_ef);
1272 if (have_process_input)
1273 process_command_input ();
1274 if (process_exited)
1275 process_exit ();
1276 if (dsp)
1278 update_mode_lines++;
1279 redisplay_preserve_echo_area ();
1283 waiting_for_ast = 0;
1286 /* Get rid of any pending QIO, when we are about to suspend
1287 or when we want to throw away pending input.
1288 We wait for a positive sign that the AST routine has run
1289 and therefore there is no I/O request queued when we return.
1290 SYS$SETAST is used to avoid a timing error. */
1292 end_kbd_input ()
1294 #ifdef ASTDEBUG
1295 printf ("At end_kbd_input.\n");
1296 fflush (stdout);
1297 sleep (1);
1298 #endif
1299 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
1301 SYS$CANCEL (input_fd);
1302 return;
1305 SYS$SETAST (0);
1306 /* Clear a flag, and tell ast routine above to set it. */
1307 SYS$CLREF (input_ef);
1308 waiting_for_ast = 1;
1309 stop_input = 1;
1310 SYS$CANCEL (input_fd);
1311 SYS$SETAST (1);
1312 SYS$WAITFR (input_ef);
1313 waiting_for_ast = 0;
1316 /* Wait for either input available or time interval expiry. */
1318 input_wait_timeout (timeval)
1319 int timeval; /* Time to wait, in seconds */
1321 int time [2];
1322 static int zero = 0;
1323 static int large = -10000000;
1325 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1327 /* If already something, avoid doing system calls. */
1328 if (detect_input_pending ())
1330 return;
1332 /* Clear a flag, and tell ast routine above to set it. */
1333 SYS$CLREF (input_ef);
1334 waiting_for_ast = 1;
1335 /* Check for timing error: ast happened while we were doing that. */
1336 if (!detect_input_pending ())
1338 /* No timing error: wait for flag to be set. */
1339 SYS$CANTIM (1, 0);
1340 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1341 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
1343 waiting_for_ast = 0;
1346 /* The standard `sleep' routine works some other way
1347 and it stops working if you have ever quit out of it.
1348 This one continues to work. */
1350 sys_sleep (timeval)
1351 int timeval;
1353 int time [2];
1354 static int zero = 0;
1355 static int large = -10000000;
1357 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1359 SYS$CANTIM (1, 0);
1360 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1361 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
1364 init_sigio ()
1366 request_sigio ();
1369 reset_sigio ()
1371 unrequest_sigio ();
1374 request_sigio ()
1376 croak ("request sigio");
1379 unrequest_sigio ()
1381 croak ("unrequest sigio");
1384 #endif /* VMS */
1386 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1387 #ifndef CANNOT_DUMP
1388 #define NEED_STARTS
1389 #endif
1391 #ifndef SYSTEM_MALLOC
1392 #ifndef NEED_STARTS
1393 #define NEED_STARTS
1394 #endif
1395 #endif
1397 #ifdef NEED_STARTS
1398 /* Some systems that cannot dump also cannot implement these. */
1401 * Return the address of the start of the text segment prior to
1402 * doing an unexec. After unexec the return value is undefined.
1403 * See crt0.c for further explanation and _start.
1407 #ifndef CANNOT_UNEXEC
1408 char *
1409 start_of_text ()
1411 #ifdef TEXT_START
1412 return ((char *) TEXT_START);
1413 #else
1414 #ifdef GOULD
1415 extern csrt ();
1416 return ((char *) csrt);
1417 #else /* not GOULD */
1418 extern int _start ();
1419 return ((char *) _start);
1420 #endif /* GOULD */
1421 #endif /* TEXT_START */
1423 #endif /* not CANNOT_UNEXEC */
1426 * Return the address of the start of the data segment prior to
1427 * doing an unexec. After unexec the return value is undefined.
1428 * See crt0.c for further information and definition of data_start.
1430 * Apparently, on BSD systems this is etext at startup. On
1431 * USG systems (swapping) this is highly mmu dependent and
1432 * is also dependent on whether or not the program is running
1433 * with shared text. Generally there is a (possibly large)
1434 * gap between end of text and start of data with shared text.
1436 * On Uniplus+ systems with shared text, data starts at a
1437 * fixed address. Each port (from a given oem) is generally
1438 * different, and the specific value of the start of data can
1439 * be obtained via the UniPlus+ specific "uvar" system call,
1440 * however the method outlined in crt0.c seems to be more portable.
1442 * Probably what will have to happen when a USG unexec is available,
1443 * at least on UniPlus, is temacs will have to be made unshared so
1444 * that text and data are contiguous. Then once loadup is complete,
1445 * unexec will produce a shared executable where the data can be
1446 * at the normal shared text boundry and the startofdata variable
1447 * will be patched by unexec to the correct value.
1451 char *
1452 start_of_data ()
1454 #ifdef DATA_START
1455 return ((char *) DATA_START);
1456 #else
1457 extern int data_start;
1458 return ((char *) &data_start);
1459 #endif
1461 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1463 #ifndef CANNOT_DUMP
1464 /* Some systems that cannot dump also cannot implement these. */
1467 * Return the address of the end of the text segment prior to
1468 * doing an unexec. After unexec the return value is undefined.
1471 char *
1472 end_of_text ()
1474 #ifdef TEXT_END
1475 return ((char *) TEXT_END);
1476 #else
1477 extern int etext;
1478 return ((char *) &etext);
1479 #endif
1483 * Return the address of the end of the data segment prior to
1484 * doing an unexec. After unexec the return value is undefined.
1487 char *
1488 end_of_data ()
1490 #ifdef DATA_END
1491 return ((char *) DATA_END);
1492 #else
1493 extern int edata;
1494 return ((char *) &edata);
1495 #endif
1498 #endif /* not CANNOT_DUMP */
1500 /* Get_system_name returns as its value
1501 a string for the Lisp function system-name to return. */
1503 #ifdef BSD4_1
1504 #include <whoami.h>
1505 #endif
1507 #ifdef USG
1508 /* Can't have this within the function since `static' is #defined to nothing */
1509 static struct utsname get_system_name_name;
1510 #endif
1512 char *
1513 get_system_name ()
1515 #ifdef USG
1516 uname (&get_system_name_name);
1517 return (get_system_name_name.nodename);
1518 #else /* Not USG */
1519 #ifdef BSD4_1
1520 return sysname;
1521 #else /* not USG, not 4.1 */
1522 static char system_name_saved[32];
1523 #ifdef VMS
1524 char *sp;
1525 if ((sp = egetenv ("SYS$NODE")) == 0)
1526 sp = "vax-vms";
1527 else
1529 char *end;
1531 if ((end = index (sp, ':')) != 0)
1532 *end = '\0';
1534 strcpy (system_name_saved, sp);
1535 #else /* not VMS */
1536 gethostname (system_name_saved, sizeof (system_name_saved));
1537 #endif /* not VMS */
1538 return system_name_saved;
1539 #endif /* not USG, not 4.1 */
1540 #endif /* not USG */
1543 #ifndef VMS
1544 #ifndef HAVE_SELECT
1546 #ifdef HAVE_X_WINDOWS
1547 /* Cause explanatory error message at compile time,
1548 since the select emulation is not good enough for X. */
1549 int *x = &x_windows_lose_if_no_select_system_call;
1550 #endif
1552 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1553 * Only checks read descriptors.
1555 /* How long to wait between checking fds in select */
1556 #define SELECT_PAUSE 1
1557 int select_alarmed;
1559 /* For longjmp'ing back to read_input_waiting. */
1561 jmp_buf read_alarm_throw;
1563 /* Nonzero if the alarm signal should throw back to read_input_waiting.
1564 The read_socket_hook function sets this to 1 while it is waiting. */
1566 int read_alarm_should_throw;
1568 SIGTYPE
1569 select_alarm ()
1571 select_alarmed = 1;
1572 #ifdef BSD4_1
1573 sigrelse (SIGALRM);
1574 #else /* not BSD4_1 */
1575 signal (SIGALRM, SIG_IGN);
1576 #endif /* not BSD4_1 */
1577 if (read_alarm_should_throw)
1578 longjmp (read_alarm_throw, 1);
1581 /* Only rfds are checked. */
1583 select (nfds, rfds, wfds, efds, timeout)
1584 int nfds;
1585 int *rfds, *wfds, *efds, *timeout;
1587 int ravail = 0, orfds = 0, old_alarm;
1588 int timeoutval = timeout ? *timeout : 100000;
1589 int *local_timeout = &timeoutval;
1590 extern int proc_buffered_char[];
1591 #ifndef subprocesses
1592 int process_tick = 0, update_tick = 0;
1593 #else
1594 extern int process_tick, update_tick;
1595 #endif
1596 SIGTYPE (*old_trap) ();
1597 unsigned char buf;
1599 if (rfds)
1601 orfds = *rfds;
1602 *rfds = 0;
1604 if (wfds)
1605 *wfds = 0;
1606 if (efds)
1607 *efds = 0;
1609 /* If we are looking only for the terminal, with no timeout,
1610 just read it and wait -- that's more efficient. */
1611 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
1613 if (! detect_input_pending ())
1614 read_input_waiting ();
1615 *rfds = 1;
1616 return 1;
1619 /* Once a second, till the timer expires, check all the flagged read
1620 * descriptors to see if any input is available. If there is some then
1621 * set the corresponding bit in the return copy of rfds.
1623 while (1)
1625 register int to_check, bit, fd;
1627 if (rfds)
1629 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
1631 if (orfds & bit)
1633 int avail = 0, status = 0;
1635 if (bit == 1)
1636 avail = detect_input_pending (); /* Special keyboard handler */
1637 else
1639 #ifdef FIONREAD
1640 status = ioctl (fd, FIONREAD, &avail);
1641 #else /* no FIONREAD */
1642 /* Hoping it will return -1 if nothing available
1643 or 0 if all 0 chars requested are read. */
1644 if (proc_buffered_char[fd] >= 0)
1645 avail = 1;
1646 else
1648 avail = read (fd, &buf, 1);
1649 if (avail > 0)
1650 proc_buffered_char[fd] = buf;
1652 #endif /* no FIONREAD */
1654 if (status >= 0 && avail > 0)
1656 (*rfds) |= bit;
1657 ravail++;
1662 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1663 break;
1664 old_alarm = alarm (0);
1665 old_trap = (int (*)()) signal (SIGALRM, select_alarm);
1666 select_alarmed = 0;
1667 alarm (SELECT_PAUSE);
1668 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1669 while (select_alarmed == 0 && *local_timeout != 0
1670 && process_tick == update_tick)
1672 /* If we are interested in terminal input,
1673 wait by reading the terminal.
1674 That makes instant wakeup for terminal input at least. */
1675 if (orfds & 1)
1677 read_input_waiting ();
1678 if (detect_input_pending ())
1679 select_alarmed = 1;
1681 else
1682 pause ();
1684 (*local_timeout) -= SELECT_PAUSE;
1685 /* Reset the old alarm if there was one */
1686 alarm (0);
1687 signal (SIGALRM, old_trap);
1688 if (old_alarm != 0)
1690 /* Reset or forge an interrupt for the original handler. */
1691 old_alarm -= SELECT_PAUSE;
1692 if (old_alarm <= 0)
1693 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
1694 else
1695 alarm (old_alarm);
1697 if (*local_timeout == 0) /* Stop on timer being cleared */
1698 break;
1700 return ravail;
1703 /* Read keyboard input into the standard buffer,
1704 waiting for at least one character. */
1706 /* Make all keyboard buffers much bigger when using X windows. */
1707 #ifdef HAVE_X_WINDOWS
1708 #define BUFFER_SIZE_FACTOR 16
1709 #else
1710 #define BUFFER_SIZE_FACTOR 1
1711 #endif
1713 read_input_waiting ()
1715 char buf[256 * BUFFER_SIZE_FACTOR];
1716 struct input_event e;
1717 int nread;
1719 if (read_socket_hook)
1721 read_alarm_should_throw = 0;
1722 if (! setjmp (read_alarm_throw))
1723 nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
1724 else
1725 nread = -1;
1727 else
1728 nread = read (fileno (stdin), buf, 1);
1730 /* Scan the chars for C-g and store them in kbd_buffer. */
1731 e.kind = ascii_keystroke;
1732 e.frame = selected_frame;
1733 for (i = 0; i < nread; i++)
1735 XSET (e.code, Lisp_Int, buf[i]);
1736 kbd_buffer_store_event (&e);
1737 /* Don't look at input that follows a C-g too closely.
1738 This reduces lossage due to autorepeat on C-g. */
1739 if (buf[i] == Ctl ('G'))
1740 break;
1744 #endif /* not HAVE_SELECT */
1745 #endif /* not VMS */
1747 #ifdef BSD4_1
1748 /* VARARGS */
1749 setpriority ()
1751 return 0;
1755 * Partially emulate 4.2 open call.
1756 * open is defined as this in 4.1.
1758 * - added by Michael Bloom @ Citicorp/TTI
1763 sys_open (path, oflag, mode)
1764 char *path;
1765 int oflag, mode;
1767 if (oflag & O_CREAT)
1768 return creat (path, mode);
1769 else
1770 return open (path, oflag);
1773 init_sigio ()
1775 if (noninteractive)
1776 return;
1777 lmode = LINTRUP | lmode;
1778 ioctl (0, TIOCLSET, &lmode);
1781 reset_sigio ()
1783 if (noninteractive)
1784 return;
1785 lmode = ~LINTRUP & lmode;
1786 ioctl (0, TIOCLSET, &lmode);
1789 request_sigio ()
1791 sigrelse (SIGTINT);
1793 interrupts_deferred = 0;
1796 unrequest_sigio ()
1798 sighold (SIGTINT);
1800 interrupts_deferred = 1;
1803 /* still inside #ifdef BSD4_1 */
1804 #ifdef subprocesses
1806 int sigheld; /* Mask of held signals */
1808 sigholdx (signum)
1809 int signum;
1811 sigheld |= sigbit (signum);
1812 sighold (signum);
1815 sigisheld (signum)
1816 int signum;
1818 sigheld |= sigbit (signum);
1821 sigunhold (signum)
1822 int signum;
1824 sigheld &= ~sigbit (signum);
1825 sigrelse (signum);
1828 sigfree () /* Free all held signals */
1830 int i;
1831 for (i = 0; i < NSIG; i++)
1832 if (sigheld & sigbit (i))
1833 sigrelse (i);
1834 sigheld = 0;
1837 sigbit (i)
1839 return 1 << (i - 1);
1841 #endif /* subprocesses */
1842 #endif /* BSD4_1 */
1844 /* POSIX signals support - DJB */
1845 /* Anyone with POSIX signals should have ANSI C declarations */
1847 #ifdef POSIX_SIGNALS
1849 sigset_t old_mask, empty_mask, full_mask, temp_mask;
1850 static struct sigaction new_action, old_action;
1852 init_signals ()
1854 #ifdef POSIX_SIGNALS
1855 sigemptyset (&signal_empty_mask);
1856 sigfillset (&signal_full_mask);
1857 #endif
1860 int (*signal_handler_t) ();
1862 signal_handler_t
1863 sys_signal (int signal_number, signal_handler_t action)
1865 #ifdef DGUX
1866 /* This gets us restartable system calls for efficiency.
1867 The "else" code will works as well. */
1868 return (berk_signal (signal_number, action));
1869 #else
1870 sigemptyset (&new_action.sa_mask);
1871 new_action.sa_handler = action;
1872 new_action.sa_flags = NULL;
1873 sigaction (signal_number, &new_action, &old_action);
1874 return (old_action.sa_handler);
1875 #endif /* DGUX */
1878 #ifndef __GNUC__
1879 /* If we're compiling with GCC, we don't need this function, since it
1880 can be written as a macro. */
1881 sigset_t
1882 sys_sigmask (int sig)
1884 sigset_t mask;
1885 sigemptyset (&mask);
1886 sigaddset (&mask, sig);
1887 return mask;
1889 #endif
1892 sys_sigpause (sigset_t new_mask)
1894 /* pause emulating berk sigpause... */
1895 sigsuspend (&new_mask);
1896 return (EINTR);
1899 /* I'd like to have these guys return pointers to the mask storage in here,
1900 but there'd be trouble if the code was saving multiple masks. I'll be
1901 safe and pass the structure. It normally won't be more than 2 bytes
1902 anyhow. - DJB */
1904 sigset_t
1905 sys_sigblock (sigset_t new_mask)
1907 sigset_t old_mask;
1908 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
1909 return (old_mask);
1912 sigset_t
1913 sys_sigunblock (sigset_t new_mask)
1915 sigset_t old_mask;
1916 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
1917 return (old_mask);
1920 sigset_t
1921 sys_sigsetmask (sigset_t new_mask)
1923 sigset_t old_mask;
1924 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
1925 return (old_mask);
1928 #endif /* POSIX_SIGNALS */
1930 #ifndef BSTRING
1932 void
1933 bzero (b, length)
1934 register char *b;
1935 register int length;
1937 #ifdef VMS
1938 short zero = 0;
1939 long max_str = 65535;
1941 while (length > max_str) {
1942 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
1943 length -= max_str;
1944 b += max_str;
1946 max_str = length;
1947 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
1948 #else
1949 while (length-- > 0)
1950 *b++ = 0;
1951 #endif /* not VMS */
1954 /* Saying `void' requires a declaration, above, where bcopy is used
1955 and that declaration causes pain for systems where bcopy is a macro. */
1956 bcopy (b1, b2, length)
1957 register char *b1;
1958 register char *b2;
1959 register int length;
1961 #ifdef VMS
1962 long max_str = 65535;
1964 while (length > max_str) {
1965 (void) LIB$MOVC3 (&max_str, b1, b2);
1966 length -= max_str;
1967 b1 += max_str;
1968 b2 += max_str;
1970 max_str = length;
1971 (void) LIB$MOVC3 (&length, b1, b2);
1972 #else
1973 while (length-- > 0)
1974 *b2++ = *b1++;
1975 #endif /* not VMS */
1979 bcmp (b1, b2, length) /* This could be a macro! */
1980 register char *b1;
1981 register char *b2;
1982 register int length;
1984 #ifdef VMS
1985 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
1986 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
1988 return STR$COMPARE (&src1, &src2);
1989 #else
1990 while (length-- > 0)
1991 if (*b1++ != *b2++)
1992 return 1;
1994 return 0;
1995 #endif /* not VMS */
1997 #endif /* not BSTRING */
1999 #ifdef USG
2001 * The BSD random returns numbers in the range of
2002 * 0 to 2e31 - 1. The USG rand returns numbers in the
2003 * range of 0 to 2e15 - 1. This is probably not significant
2004 * in this usage.
2007 long
2008 random ()
2010 /* Arrange to return a range centered on zero. */
2011 return (rand () << 15) + rand () - (1 << 29);
2014 srandom (arg)
2015 int arg;
2017 srand (arg);
2020 #endif /* USG */
2022 #ifdef BSD4_1
2023 long random ()
2025 /* Arrange to return a range centered on zero. */
2026 return (rand () << 15) + rand () - (1 << 29);
2029 srandom (arg)
2030 int arg;
2032 srand (arg);
2034 #endif /* BSD4_1 */
2036 #ifdef WRONG_NAME_INSQUE
2038 insque (q,p)
2039 caddr_t q,p;
2041 _insque (q,p);
2044 #endif
2046 #ifdef VMS
2048 #ifdef getenv
2049 /* If any place else asks for the TERM variable,
2050 allow it to be overridden with the EMACS_TERM variable
2051 before attempting to translate the logical name TERM. As a last
2052 resort, ask for VAX C's special idea of the TERM variable. */
2053 #undef getenv
2054 char *
2055 sys_getenv (name)
2056 char *name;
2058 register char *val;
2059 static char buf[256];
2060 static struct dsc$descriptor_s equiv
2061 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2062 static struct dsc$descriptor_s d_name
2063 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2064 short eqlen;
2066 if (!strcmp (name, "TERM"))
2068 val = (char *) getenv ("EMACS_TERM");
2069 if (val)
2070 return val;
2073 d_name.dsc$w_length = strlen (name);
2074 d_name.dsc$a_pointer = name;
2075 if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
2077 char *str = (char *) xmalloc (eqlen + 1);
2078 bcopy (buf, str, eqlen);
2079 str[eqlen] = '\0';
2080 /* This is a storage leak, but a pain to fix. With luck,
2081 no one will ever notice. */
2082 return str;
2084 return (char *) getenv (name);
2086 #endif /* getenv */
2088 #ifdef abort
2089 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2090 to force a call on the debugger from within the image. */
2091 #undef abort
2092 sys_abort ()
2094 reset_sys_modes ();
2095 LIB$SIGNAL (SS$_DEBUG);
2097 #endif /* abort */
2098 #endif /* VMS */
2100 #ifdef VMS
2101 #ifdef LINK_CRTL_SHARE
2102 #ifdef SHAREABLE_LIB_BUG
2103 /* Variables declared noshare and initialized in shareable libraries
2104 cannot be shared. The VMS linker incorrectly forces you to use a private
2105 version which is uninitialized... If not for this "feature", we
2106 could use the C library definition of sys_nerr and sys_errlist. */
2107 int sys_nerr = 35;
2108 char *sys_errlist[] =
2110 "error 0",
2111 "not owner",
2112 "no such file or directory",
2113 "no such process",
2114 "interrupted system call",
2115 "i/o error",
2116 "no such device or address",
2117 "argument list too long",
2118 "exec format error",
2119 "bad file number",
2120 "no child process",
2121 "no more processes",
2122 "not enough memory",
2123 "permission denied",
2124 "bad address",
2125 "block device required",
2126 "mount devices busy",
2127 "file exists",
2128 "cross-device link",
2129 "no such device",
2130 "not a directory",
2131 "is a directory",
2132 "invalid argument",
2133 "file table overflow",
2134 "too many open files",
2135 "not a typewriter",
2136 "text file busy",
2137 "file too big",
2138 "no space left on device",
2139 "illegal seek",
2140 "read-only file system",
2141 "too many links",
2142 "broken pipe",
2143 "math argument",
2144 "result too large",
2145 "I/O stream empty",
2146 "vax/vms specific error code nontranslatable error"
2148 #endif /* SHAREABLE_LIB_BUG */
2149 #endif /* LINK_CRTL_SHARE */
2150 #endif /* VMS */
2152 #ifdef INTERRUPTIBLE_OPEN
2155 /* VARARGS 2 */
2156 sys_open (path, oflag, mode)
2157 char *path;
2158 int oflag, mode;
2160 register int rtnval;
2162 while ((rtnval = open (path, oflag, mode)) == -1
2163 && (errno == EINTR));
2164 return (rtnval);
2167 #endif /* INTERRUPTIBLE_OPEN */
2169 #ifdef INTERRUPTIBLE_CLOSE
2171 sys_close (fd)
2172 int fd;
2174 register int rtnval;
2176 while ((rtnval = close (fd)) == -1
2177 && (errno == EINTR));
2178 return rtnval;
2181 #endif /* INTERRUPTIBLE_CLOSE */
2183 #ifdef INTERRUPTIBLE_IO
2186 sys_read (fildes, buf, nbyte)
2187 int fildes;
2188 char *buf;
2189 unsigned int nbyte;
2191 register int rtnval;
2193 while ((rtnval = read (fildes, buf, nbyte)) == -1
2194 && (errno == EINTR));
2195 return (rtnval);
2199 sys_write (fildes, buf, nbyte)
2200 int fildes;
2201 char *buf;
2202 unsigned int nbyte;
2204 register int rtnval;
2206 while ((rtnval = write (fildes, buf, nbyte)) == -1
2207 && (errno == EINTR));
2208 return (rtnval);
2211 #endif /* INTERRUPTIBLE_IO */
2213 #ifdef USG
2215 * All of the following are for USG.
2217 * On USG systems the system calls are INTERRUPTIBLE by signals
2218 * that the user program has elected to catch. Thus the system call
2219 * must be retried in these cases. To handle this without massive
2220 * changes in the source code, we remap the standard system call names
2221 * to names for our own functions in sysdep.c that do the system call
2222 * with retries. Actually, for portability reasons, it is good
2223 * programming practice, as this example shows, to limit all actual
2224 * system calls to a single occurance in the source. Sure, this
2225 * adds an extra level of function call overhead but it is almost
2226 * always negligible. Fred Fish, Unisoft Systems Inc.
2229 char *sys_siglist[NSIG + 1] =
2231 #ifdef AIX
2232 /* AIX has changed the signals a bit */
2233 "bogus signal", /* 0 */
2234 "hangup", /* 1 SIGHUP */
2235 "interrupt", /* 2 SIGINT */
2236 "quit", /* 3 SIGQUIT */
2237 "illegal instruction", /* 4 SIGILL */
2238 "trace trap", /* 5 SIGTRAP */
2239 "IOT instruction", /* 6 SIGIOT */
2240 "crash likely", /* 7 SIGDANGER */
2241 "floating point exception", /* 8 SIGFPE */
2242 "kill", /* 9 SIGKILL */
2243 "bus error", /* 10 SIGBUS */
2244 "segmentation violation", /* 11 SIGSEGV */
2245 "bad argument to system call", /* 12 SIGSYS */
2246 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2247 "alarm clock", /* 14 SIGALRM */
2248 "software termination signum", /* 15 SIGTERM */
2249 "user defined signal 1", /* 16 SIGUSR1 */
2250 "user defined signal 2", /* 17 SIGUSR2 */
2251 "death of a child", /* 18 SIGCLD */
2252 "power-fail restart", /* 19 SIGPWR */
2253 "bogus signal", /* 20 */
2254 "bogus signal", /* 21 */
2255 "bogus signal", /* 22 */
2256 "bogus signal", /* 23 */
2257 "bogus signal", /* 24 */
2258 "LAN I/O interrupt", /* 25 SIGAIO */
2259 "PTY I/O interrupt", /* 26 SIGPTY */
2260 "I/O intervention required", /* 27 SIGIOINT */
2261 "HFT grant", /* 28 SIGGRANT */
2262 "HFT retract", /* 29 SIGRETRACT */
2263 "HFT sound done", /* 30 SIGSOUND */
2264 "HFT input ready", /* 31 SIGMSG */
2265 #else /* not AIX */
2266 "bogus signal", /* 0 */
2267 "hangup", /* 1 SIGHUP */
2268 "interrupt", /* 2 SIGINT */
2269 "quit", /* 3 SIGQUIT */
2270 "illegal instruction", /* 4 SIGILL */
2271 "trace trap", /* 5 SIGTRAP */
2272 "IOT instruction", /* 6 SIGIOT */
2273 "EMT instruction", /* 7 SIGEMT */
2274 "floating point exception", /* 8 SIGFPE */
2275 "kill", /* 9 SIGKILL */
2276 "bus error", /* 10 SIGBUS */
2277 "segmentation violation", /* 11 SIGSEGV */
2278 "bad argument to system call", /* 12 SIGSYS */
2279 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2280 "alarm clock", /* 14 SIGALRM */
2281 "software termination signum", /* 15 SIGTERM */
2282 "user defined signal 1", /* 16 SIGUSR1 */
2283 "user defined signal 2", /* 17 SIGUSR2 */
2284 "death of a child", /* 18 SIGCLD */
2285 "power-fail restart", /* 19 SIGPWR */
2286 #endif /* not AIX */
2291 * Warning, this function may not duplicate 4.2 action properly
2292 * under error conditions.
2295 #ifndef MAXPATHLEN
2296 /* In 4.1, param.h fails to define this. */
2297 #define MAXPATHLEN 1024
2298 #endif
2300 #ifndef HAVE_GETWD
2302 char *
2303 getwd (pathname)
2304 char *pathname;
2306 char *npath, *spath;
2307 extern char *getcwd ();
2309 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2310 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2311 up to first slash. Should be harmless on other systems. */
2312 while (*npath && *npath != '/')
2313 npath++;
2314 strcpy (pathname, npath);
2315 free (spath); /* getcwd uses malloc */
2316 return pathname;
2319 #endif /* HAVE_GETWD */
2322 * Emulate rename using unlink/link. Note that this is
2323 * only partially correct. Also, doesn't enforce restriction
2324 * that files be of same type (regular->regular, dir->dir, etc).
2327 #ifndef HAVE_RENAME
2329 rename (from, to)
2330 char *from;
2331 char *to;
2333 if (access (from, 0) == 0)
2335 unlink (to);
2336 if (link (from, to) == 0)
2337 if (unlink (from) == 0)
2338 return (0);
2340 return (-1);
2343 #endif
2345 /* Set priority value to PRIO. */
2348 setpriority (which, who, prio)
2349 int which, who, prio;
2351 int nice ();
2353 nice (prio - nice (0));
2354 return (0);
2357 #ifndef HAVE_VFORK
2360 * Substitute fork for vfork on USG flavors.
2363 vfork ()
2365 return (fork ());
2368 #endif /* not HAVE_VFORK */
2370 #ifdef MISSING_UTIMES
2372 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2374 utimes ()
2377 #endif
2379 #ifdef IRIS_UTIME
2381 /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2382 utimbuf structure defined anywhere but in the man page. */
2384 struct utimbuf
2386 long actime;
2387 long modtime;
2390 utimes (name, tvp)
2391 char *name;
2392 struct timeval tvp[];
2394 struct utimbuf utb;
2395 utb.actime = tvp[0].tv_sec;
2396 utb.modtime = tvp[1].tv_sec;
2397 utime (name, &utb);
2399 #endif /* IRIS_UTIME */
2402 #ifdef HPUX
2403 #ifndef HAVE_PERROR
2405 /* HPUX curses library references perror, but as far as we know
2406 it won't be called. Anyway this definition will do for now. */
2408 perror ()
2412 #endif /* not HAVE_PERROR */
2413 #endif /* HPUX */
2415 #ifndef HAVE_DUP2
2418 * Emulate BSD dup2. First close newd if it already exists.
2419 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2420 * until we are, then close the unsuccessful ones.
2423 dup2 (oldd, newd)
2424 int oldd;
2425 int newd;
2427 register int fd, ret;
2429 sys_close (newd);
2431 #ifdef F_DUPFD
2432 fd = fcntl (oldd, F_DUPFD, newd);
2433 if (fd != newd)
2434 error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
2435 #else
2436 fd = dup (old);
2437 if (fd == -1)
2438 return -1;
2439 if (fd == new)
2440 return new;
2441 ret = dup2 (old,new);
2442 sys_close (fd);
2443 return ret;
2444 #endif
2447 #endif /* not HAVE_DUP2 */
2450 * Gettimeofday. Simulate as much as possible. Only accurate
2451 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2452 * Only needed when subprocesses are defined.
2455 #ifdef subprocesses
2456 #ifndef VMS
2457 #ifndef HAVE_GETTIMEOFDAY
2458 #ifdef HAVE_TIMEVAL
2460 /* ARGSUSED */
2461 gettimeofday (tp, tzp)
2462 struct timeval *tp;
2463 struct timezone *tzp;
2465 extern long time ();
2467 tp->tv_sec = time ((long *)0);
2468 tp->tv_usec = 0;
2469 tzp->tz_minuteswest = -1;
2472 #endif
2473 #endif
2474 #endif
2475 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
2478 * This function will go away as soon as all the stubs fixed. (fnf)
2481 croak (badfunc)
2482 char *badfunc;
2484 printf ("%s not yet implemented\r\n", badfunc);
2485 reset_sys_modes ();
2486 exit (1);
2489 #endif /* USG */
2491 #ifdef DGUX
2493 char *sys_siglist[NSIG + 1] =
2495 "null signal", /* 0 SIGNULL */
2496 "hangup", /* 1 SIGHUP */
2497 "interrupt", /* 2 SIGINT */
2498 "quit", /* 3 SIGQUIT */
2499 "illegal instruction", /* 4 SIGILL */
2500 "trace trap", /* 5 SIGTRAP */
2501 "abort termination", /* 6 SIGABRT */
2502 "SIGEMT", /* 7 SIGEMT */
2503 "floating point exception", /* 8 SIGFPE */
2504 "kill", /* 9 SIGKILL */
2505 "bus error", /* 10 SIGBUS */
2506 "segmentation violation", /* 11 SIGSEGV */
2507 "bad argument to system call", /* 12 SIGSYS */
2508 "write on a pipe with no reader", /* 13 SIGPIPE */
2509 "alarm clock", /* 14 SIGALRM */
2510 "software termination signal", /* 15 SIGTERM */
2511 "user defined signal 1", /* 16 SIGUSR1 */
2512 "user defined signal 2", /* 17 SIGUSR2 */
2513 "child stopped or terminated", /* 18 SIGCLD */
2514 "power-fail restart", /* 19 SIGPWR */
2515 "window size changed", /* 20 SIGWINCH */
2516 "undefined", /* 21 */
2517 "pollable event occured", /* 22 SIGPOLL */
2518 "sendable stop signal not from tty", /* 23 SIGSTOP */
2519 "stop signal from tty", /* 24 SIGSTP */
2520 "continue a stopped process", /* 25 SIGCONT */
2521 "attempted background tty read", /* 26 SIGTTIN */
2522 "attempted background tty write", /* 27 SIGTTOU */
2523 "undefined", /* 28 */
2524 "undefined", /* 29 */
2525 "undefined", /* 30 */
2526 "undefined", /* 31 */
2527 "undefined", /* 32 */
2528 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
2529 "I/O is possible", /* 34 SIGIO */
2530 "exceeded cpu time limit", /* 35 SIGXCPU */
2531 "exceeded file size limit", /* 36 SIGXFSZ */
2532 "virtual time alarm", /* 37 SIGVTALRM */
2533 "profiling time alarm", /* 38 SIGPROF */
2534 "undefined", /* 39 */
2535 "file record locks revoked", /* 40 SIGLOST */
2536 "undefined", /* 41 */
2537 "undefined", /* 42 */
2538 "undefined", /* 43 */
2539 "undefined", /* 44 */
2540 "undefined", /* 45 */
2541 "undefined", /* 46 */
2542 "undefined", /* 47 */
2543 "undefined", /* 48 */
2544 "undefined", /* 49 */
2545 "undefined", /* 50 */
2546 "undefined", /* 51 */
2547 "undefined", /* 52 */
2548 "undefined", /* 53 */
2549 "undefined", /* 54 */
2550 "undefined", /* 55 */
2551 "undefined", /* 56 */
2552 "undefined", /* 57 */
2553 "undefined", /* 58 */
2554 "undefined", /* 59 */
2555 "undefined", /* 60 */
2556 "undefined", /* 61 */
2557 "undefined", /* 62 */
2558 "undefined", /* 63 */
2559 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
2563 #endif /* DGUX */
2565 /* Directory routines for systems that don't have them. */
2567 #ifdef SYSV_SYSTEM_DIR
2569 #include <dirent.h>
2571 #ifndef AIX
2573 closedir (dirp)
2574 register DIR *dirp; /* stream from opendir */
2576 sys_close (dirp->dd_fd);
2577 free ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
2578 free ((char *) dirp);
2580 #endif /* not AIX */
2581 #endif /* SYSV_SYSTEM_DIR */
2583 #ifdef NONSYSTEM_DIR_LIBRARY
2585 DIR *
2586 opendir (filename)
2587 char *filename; /* name of directory */
2589 register DIR *dirp; /* -> malloc'ed storage */
2590 register int fd; /* file descriptor for read */
2591 struct stat sbuf; /* result of fstat */
2593 fd = sys_open (filename, 0);
2594 if (fd < 0)
2595 return 0;
2597 if (fstat (fd, &sbuf) < 0
2598 || (sbuf.st_mode & S_IFMT) != S_IFDIR
2599 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2601 sys_close (fd);
2602 return 0; /* bad luck today */
2605 dirp->dd_fd = fd;
2606 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2608 return dirp;
2611 void
2612 closedir (dirp)
2613 register DIR *dirp; /* stream from opendir */
2615 sys_close (dirp->dd_fd);
2616 free ((char *) dirp);
2620 #ifndef VMS
2621 #define DIRSIZ 14
2622 struct olddir
2624 ino_t od_ino; /* inode */
2625 char od_name[DIRSIZ]; /* filename */
2627 #endif /* not VMS */
2629 struct direct dir_static; /* simulated directory contents */
2631 /* ARGUSED */
2632 struct direct *
2633 readdir (dirp)
2634 register DIR *dirp; /* stream from opendir */
2636 #ifndef VMS
2637 register struct olddir *dp; /* -> directory data */
2638 #else /* VMS */
2639 register struct dir$_name *dp; /* -> directory data */
2640 register struct dir$_version *dv; /* -> version data */
2641 #endif /* VMS */
2643 for (; ;)
2645 if (dirp->dd_loc >= dirp->dd_size)
2646 dirp->dd_loc = dirp->dd_size = 0;
2648 if (dirp->dd_size == 0 /* refill buffer */
2649 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2650 return 0;
2652 #ifndef VMS
2653 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
2654 dirp->dd_loc += sizeof (struct olddir);
2656 if (dp->od_ino != 0) /* not deleted entry */
2658 dir_static.d_ino = dp->od_ino;
2659 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
2660 dir_static.d_name[DIRSIZ] = '\0';
2661 dir_static.d_namlen = strlen (dir_static.d_name);
2662 dir_static.d_reclen = sizeof (struct direct)
2663 - MAXNAMLEN + 3
2664 + dir_static.d_namlen - dir_static.d_namlen % 4;
2665 return &dir_static; /* -> simulated structure */
2667 #else /* VMS */
2668 dp = (struct dir$_name *) dirp->dd_buf;
2669 if (dirp->dd_loc == 0)
2670 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
2671 : dp->dir$b_namecount;
2672 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
2673 dir_static.d_ino = dv->dir$w_fid_num;
2674 dir_static.d_namlen = dp->dir$b_namecount;
2675 dir_static.d_reclen = sizeof (struct direct)
2676 - MAXNAMLEN + 3
2677 + dir_static.d_namlen - dir_static.d_namlen % 4;
2678 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2679 dir_static.d_name[dir_static.d_namlen] = '\0';
2680 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
2681 return &dir_static;
2682 #endif /* VMS */
2686 #ifdef VMS
2687 /* readdirver is just like readdir except it returns all versions of a file
2688 as separate entries. */
2690 /* ARGUSED */
2691 struct direct *
2692 readdirver (dirp)
2693 register DIR *dirp; /* stream from opendir */
2695 register struct dir$_name *dp; /* -> directory data */
2696 register struct dir$_version *dv; /* -> version data */
2698 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
2699 dirp->dd_loc = dirp->dd_size = 0;
2701 if (dirp->dd_size == 0 /* refill buffer */
2702 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2703 return 0;
2705 dp = (struct dir$_name *) dirp->dd_buf;
2706 if (dirp->dd_loc == 0)
2707 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
2708 : dp->dir$b_namecount;
2709 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
2710 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2711 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
2712 dir_static.d_namlen = strlen (dir_static.d_name);
2713 dir_static.d_ino = dv->dir$w_fid_num;
2714 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
2715 + dir_static.d_namlen - dir_static.d_namlen % 4;
2716 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
2717 return &dir_static;
2720 #endif /* VMS */
2722 #endif /* NONSYSTEM_DIR_LIBRARY */
2724 /* Functions for VMS */
2725 #ifdef VMS
2726 #include "vms-pwd.h"
2727 #include <acldef.h>
2728 #include <chpdef.h>
2729 #include <jpidef.h>
2731 /* Return as a string the VMS error string pertaining to STATUS.
2732 Reuses the same static buffer each time it is called. */
2734 char *
2735 vmserrstr (status)
2736 int status; /* VMS status code */
2738 int bufadr[2];
2739 short len;
2740 static char buf[257];
2742 bufadr[0] = sizeof buf - 1;
2743 bufadr[1] = (int) buf;
2744 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
2745 return "untranslatable VMS error status";
2746 buf[len] = '\0';
2747 return buf;
2750 #ifdef access
2751 #undef access
2753 /* The following is necessary because 'access' emulation by VMS C (2.0) does
2754 * not work correctly. (It also doesn't work well in version 2.3.)
2757 #ifdef VMS4_4
2759 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
2760 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
2762 typedef union {
2763 struct {
2764 unsigned short s_buflen;
2765 unsigned short s_code;
2766 char *s_bufadr;
2767 unsigned short *s_retlenadr;
2768 } s;
2769 int end;
2770 } item;
2771 #define buflen s.s_buflen
2772 #define code s.s_code
2773 #define bufadr s.s_bufadr
2774 #define retlenadr s.s_retlenadr
2776 #define R_OK 4 /* test for read permission */
2777 #define W_OK 2 /* test for write permission */
2778 #define X_OK 1 /* test for execute (search) permission */
2779 #define F_OK 0 /* test for presence of file */
2782 sys_access (path, mode)
2783 char *path;
2784 int mode;
2786 static char *user = NULL;
2787 char dir_fn[512];
2789 /* translate possible directory spec into .DIR file name, so brain-dead
2790 * access can treat the directory like a file. */
2791 if (directory_file_name (path, dir_fn))
2792 path = dir_fn;
2794 if (mode == F_OK)
2795 return access (path, mode);
2796 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
2797 return -1;
2799 int stat;
2800 int flags;
2801 int acces;
2802 unsigned short int dummy;
2803 item itemlst[3];
2804 static int constant = ACL$C_FILE;
2805 DESCRIPTOR (path_desc, path);
2806 DESCRIPTOR (user_desc, user);
2808 flags = 0;
2809 acces = 0;
2810 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
2811 return stat;
2812 if (mode & R_OK)
2813 acces |= CHP$M_READ;
2814 if (mode & W_OK)
2815 acces |= CHP$M_WRITE;
2816 itemlst[0].buflen = sizeof (int);
2817 itemlst[0].code = CHP$_FLAGS;
2818 itemlst[0].bufadr = (char *) &flags;
2819 itemlst[0].retlenadr = &dummy;
2820 itemlst[1].buflen = sizeof (int);
2821 itemlst[1].code = CHP$_ACCESS;
2822 itemlst[1].bufadr = (char *) &acces;
2823 itemlst[1].retlenadr = &dummy;
2824 itemlst[2].end = CHP$_END;
2825 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
2826 return stat == SS$_NORMAL ? 0 : -1;
2830 #else /* not VMS4_4 */
2832 #include <prvdef.h>
2833 #define ACE$M_WRITE 2
2834 #define ACE$C_KEYID 1
2836 static unsigned short memid, grpid;
2837 static unsigned int uic;
2839 /* Called from init_sys_modes, so it happens not very often
2840 but at least each time Emacs is loaded. */
2841 sys_access_reinit ()
2843 uic = 0;
2847 sys_access (filename, type)
2848 char * filename;
2849 int type;
2851 struct FAB fab;
2852 struct XABPRO xab;
2853 int status, size, i, typecode, acl_controlled;
2854 unsigned int *aclptr, *aclend, aclbuf[60];
2855 union prvdef prvmask;
2857 /* Get UIC and GRP values for protection checking. */
2858 if (uic == 0)
2860 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
2861 if (! (status & 1))
2862 return -1;
2863 memid = uic & 0xFFFF;
2864 grpid = uic >> 16;
2867 if (type != 2) /* not checking write access */
2868 return access (filename, type);
2870 /* Check write protection. */
2872 #define CHECKPRIV(bit) (prvmask.bit)
2873 #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
2875 /* Find privilege bits */
2876 status = sys$setprv (0, 0, 0, prvmask);
2877 if (! (status & 1))
2878 error ("Unable to find privileges: %s", vmserrstr (status));
2879 if (CHECKPRIV (PRV$V_BYPASS))
2880 return 0; /* BYPASS enabled */
2881 fab = cc$rms_fab;
2882 fab.fab$b_fac = FAB$M_GET;
2883 fab.fab$l_fna = filename;
2884 fab.fab$b_fns = strlen (filename);
2885 fab.fab$l_xab = &xab;
2886 xab = cc$rms_xabpro;
2887 xab.xab$l_aclbuf = aclbuf;
2888 xab.xab$w_aclsiz = sizeof (aclbuf);
2889 status = sys$open (&fab, 0, 0);
2890 if (! (status & 1))
2891 return -1;
2892 sys$close (&fab, 0, 0);
2893 /* Check system access */
2894 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
2895 return 0;
2896 /* Check ACL entries, if any */
2897 acl_controlled = 0;
2898 if (xab.xab$w_acllen > 0)
2900 aclptr = aclbuf;
2901 aclend = &aclbuf[xab.xab$w_acllen / 4];
2902 while (*aclptr && aclptr < aclend)
2904 size = (*aclptr & 0xff) / 4;
2905 typecode = (*aclptr >> 8) & 0xff;
2906 if (typecode == ACE$C_KEYID)
2907 for (i = size - 1; i > 1; i--)
2908 if (aclptr[i] == uic)
2910 acl_controlled = 1;
2911 if (aclptr[1] & ACE$M_WRITE)
2912 return 0; /* Write access through ACL */
2914 aclptr = &aclptr[size];
2916 if (acl_controlled) /* ACL specified, prohibits write access */
2917 return -1;
2919 /* No ACL entries specified, check normal protection */
2920 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
2921 return 0;
2922 if (WRITEABLE (XAB$V_GRP) &&
2923 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
2924 return 0; /* Group writeable */
2925 if (WRITEABLE (XAB$V_OWN) &&
2926 (xab.xab$l_uic & 0xFFFF) == memid)
2927 return 0; /* Owner writeable */
2929 return -1; /* Not writeable */
2931 #endif /* not VMS4_4 */
2932 #endif /* access */
2934 static char vtbuf[NAM$C_MAXRSS+1];
2936 /* translate a vms file spec to a unix path */
2937 char *
2938 sys_translate_vms (vfile)
2939 char * vfile;
2941 char * p;
2942 char * targ;
2944 if (!vfile)
2945 return 0;
2947 targ = vtbuf;
2949 /* leading device or logical name is a root directory */
2950 if (p = strchr (vfile, ':'))
2952 *targ++ = '/';
2953 while (vfile < p)
2954 *targ++ = *vfile++;
2955 vfile++;
2956 *targ++ = '/';
2958 p = vfile;
2959 if (*p == '[' || *p == '<')
2961 while (*++vfile != *p + 2)
2962 switch (*vfile)
2964 case '.':
2965 if (vfile[-1] == *p)
2966 *targ++ = '.';
2967 *targ++ = '/';
2968 break;
2970 case '-':
2971 *targ++ = '.';
2972 *targ++ = '.';
2973 break;
2975 default:
2976 *targ++ = *vfile;
2977 break;
2979 vfile++;
2980 *targ++ = '/';
2982 while (*vfile)
2983 *targ++ = *vfile++;
2985 return vtbuf;
2988 static char utbuf[NAM$C_MAXRSS+1];
2990 /* translate a unix path to a VMS file spec */
2991 char *
2992 sys_translate_unix (ufile)
2993 char * ufile;
2995 int slash_seen = 0;
2996 char *p;
2997 char * targ;
2999 if (!ufile)
3000 return 0;
3002 targ = utbuf;
3004 if (*ufile == '/')
3006 ufile++;
3009 while (*ufile)
3011 switch (*ufile)
3013 case '/':
3014 if (slash_seen)
3015 if (index (&ufile[1], '/'))
3016 *targ++ = '.';
3017 else
3018 *targ++ = ']';
3019 else
3021 *targ++ = ':';
3022 if (index (&ufile[1], '/'))
3023 *targ++ = '[';
3024 slash_seen = 1;
3026 break;
3028 case '.':
3029 if (strncmp (ufile, "./", 2) == 0)
3031 if (!slash_seen)
3033 *targ++ = '[';
3034 slash_seen = 1;
3036 ufile++; /* skip the dot */
3037 if (index (&ufile[1], '/'))
3038 *targ++ = '.';
3039 else
3040 *targ++ = ']';
3042 else if (strncmp (ufile, "../", 3) == 0)
3044 if (!slash_seen)
3046 *targ++ = '[';
3047 slash_seen = 1;
3049 *targ++ = '-';
3050 ufile += 2; /* skip the dots */
3051 if (index (&ufile[1], '/'))
3052 *targ++ = '.';
3053 else
3054 *targ++ = ']';
3056 else
3057 *targ++ = *ufile;
3058 break;
3060 default:
3061 *targ++ = *ufile;
3062 break;
3064 ufile++;
3066 *targ = '\0';
3068 return utbuf;
3071 char *
3072 getwd (pathname)
3073 char *pathname;
3075 char *ptr;
3076 strcpy (pathname, egetenv ("PATH"));
3078 ptr = pathname;
3079 while (*ptr)
3081 if ('a' <= *ptr && *ptr <= 'z')
3082 *ptr -= 040;
3083 ptr++;
3085 return pathname;
3088 getppid ()
3090 long item_code = JPI$_OWNER;
3091 unsigned long parent_id;
3092 int status;
3094 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3096 errno = EVMSERR;
3097 vaxc$errno = status;
3098 return -1;
3100 return parent_id;
3103 #undef getuid
3104 unsigned
3105 sys_getuid ()
3107 return (getgid () << 16) | getuid ();
3111 sys_read (fildes, buf, nbyte)
3112 int fildes;
3113 char *buf;
3114 unsigned int nbyte;
3116 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3119 #if 0
3121 sys_write (fildes, buf, nbyte)
3122 int fildes;
3123 char *buf;
3124 unsigned int nbyte;
3126 register int nwrote, rtnval = 0;
3128 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3129 nbyte -= nwrote;
3130 buf += nwrote;
3131 rtnval += nwrote;
3133 if (nwrote < 0)
3134 return rtnval ? rtnval : -1;
3135 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3136 return rtnval ? rtnval : -1;
3137 return (rtnval + nwrote);
3139 #endif /* 0 */
3142 * VAX/VMS VAX C RTL really loses. It insists that records
3143 * end with a newline (carriage return) character, and if they
3144 * don't it adds one (nice of it isn't it!)
3146 * Thus we do this stupidity below.
3150 sys_write (fildes, buf, nbytes)
3151 int fildes;
3152 char *buf;
3153 unsigned int nbytes;
3155 register char *p;
3156 register char *e;
3157 int sum = 0;
3158 struct stat st;
3160 fstat (fildes, &st);
3161 p = buf;
3162 while (nbytes > 0)
3164 int len, retval;
3166 /* Handle fixed-length files with carriage control. */
3167 if (st.st_fab_rfm == FAB$C_FIX
3168 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3170 len = st.st_fab_mrs;
3171 retval = write (fildes, p, min (len, nbytes));
3172 if (retval != len)
3173 return -1;
3174 retval++; /* This skips the implied carriage control */
3176 else
3178 e = p + min (MAXIOSIZE, nbytes) - 1;
3179 while (*e != '\n' && e > p) e--;
3180 if (p == e) /* Ok.. so here we add a newline... sigh. */
3181 e = p + min (MAXIOSIZE, nbytes) - 1;
3182 len = e + 1 - p;
3183 retval = write (fildes, p, len);
3184 if (retval != len)
3185 return -1;
3187 p += retval;
3188 sum += retval;
3189 nbytes -= retval;
3191 return sum;
3194 /* Create file NEW copying its attributes from file OLD. If
3195 OLD is 0 or does not exist, create based on the value of
3196 vms_stmlf_recfm. */
3198 /* Protection value the file should ultimately have.
3199 Set by create_copy_attrs, and use by rename_sansversions. */
3200 static unsigned short int fab_final_pro;
3203 creat_copy_attrs (old, new)
3204 char *old, *new;
3206 struct FAB fab = cc$rms_fab;
3207 struct XABPRO xabpro;
3208 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3209 extern int vms_stmlf_recfm;
3211 if (old)
3213 fab.fab$b_fac = FAB$M_GET;
3214 fab.fab$l_fna = old;
3215 fab.fab$b_fns = strlen (old);
3216 fab.fab$l_xab = (char *) &xabpro;
3217 xabpro = cc$rms_xabpro;
3218 xabpro.xab$l_aclbuf = aclbuf;
3219 xabpro.xab$w_aclsiz = sizeof aclbuf;
3220 /* Call $OPEN to fill in the fab & xabpro fields. */
3221 if (sys$open (&fab, 0, 0) & 1)
3223 sys$close (&fab, 0, 0);
3224 fab.fab$l_alq = 0; /* zero the allocation quantity */
3225 if (xabpro.xab$w_acllen > 0)
3227 if (xabpro.xab$w_acllen > sizeof aclbuf)
3228 /* If the acl buffer was too short, redo open with longer one.
3229 Wouldn't need to do this if there were some system imposed
3230 limit on the size of an ACL, but I can't find any such. */
3232 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
3233 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
3234 if (sys$open (&fab, 0, 0) & 1)
3235 sys$close (&fab, 0, 0);
3236 else
3237 old = 0;
3240 else
3241 xabpro.xab$l_aclbuf = 0;
3243 else
3244 old = 0;
3246 fab.fab$l_fna = new;
3247 fab.fab$b_fns = strlen (new);
3248 if (!old)
3250 fab.fab$l_xab = 0;
3251 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
3252 fab.fab$b_rat = FAB$M_CR;
3255 /* Set the file protections such that we will be able to manipulate
3256 this file. Once we are done writing and renaming it, we will set
3257 the protections back. */
3258 if (old)
3259 fab_final_pro = xabpro.xab$w_pro;
3260 else
3261 sys$setdfprot (0, &fab_final_pro);
3262 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
3264 /* Create the new file with either default attrs or attrs copied
3265 from old file. */
3266 if (!(SYS$CREATE (&fab, 0, 0) & 1))
3267 return -1;
3268 sys$close (&fab, 0, 0);
3269 /* As this is a "replacement" for creat, return a file descriptor
3270 opened for writing. */
3271 return open (new, O_WRONLY);
3274 #ifdef creat
3275 #undef creat
3276 #include <varargs.h>
3277 #ifdef __GNUC__
3278 #ifndef va_count
3279 #define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3280 #endif
3281 #endif
3283 sys_creat (va_alist)
3284 va_dcl
3286 va_list list_incrementor;
3287 char *name;
3288 int mode;
3289 int rfd; /* related file descriptor */
3290 int fd; /* Our new file descriptor */
3291 int count;
3292 struct stat st_buf;
3293 char rfm[12];
3294 char rat[15];
3295 char mrs[13];
3296 char fsz[13];
3297 extern int vms_stmlf_recfm;
3299 va_count (count);
3300 va_start (list_incrementor);
3301 name = va_arg (list_incrementor, char *);
3302 mode = va_arg (list_incrementor, int);
3303 if (count > 2)
3304 rfd = va_arg (list_incrementor, int);
3305 va_end (list_incrementor);
3306 if (count > 2)
3308 /* Use information from the related file descriptor to set record
3309 format of the newly created file. */
3310 fstat (rfd, &st_buf);
3311 switch (st_buf.st_fab_rfm)
3313 case FAB$C_FIX:
3314 strcpy (rfm, "rfm = fix");
3315 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
3316 strcpy (rat, "rat = ");
3317 if (st_buf.st_fab_rat & FAB$M_CR)
3318 strcat (rat, "cr");
3319 else if (st_buf.st_fab_rat & FAB$M_FTN)
3320 strcat (rat, "ftn");
3321 else if (st_buf.st_fab_rat & FAB$M_PRN)
3322 strcat (rat, "prn");
3323 if (st_buf.st_fab_rat & FAB$M_BLK)
3324 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3325 strcat (rat, ", blk");
3326 else
3327 strcat (rat, "blk");
3328 return creat (name, 0, rfm, rat, mrs);
3330 case FAB$C_VFC:
3331 strcpy (rfm, "rfm = vfc");
3332 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
3333 strcpy (rat, "rat = ");
3334 if (st_buf.st_fab_rat & FAB$M_CR)
3335 strcat (rat, "cr");
3336 else if (st_buf.st_fab_rat & FAB$M_FTN)
3337 strcat (rat, "ftn");
3338 else if (st_buf.st_fab_rat & FAB$M_PRN)
3339 strcat (rat, "prn");
3340 if (st_buf.st_fab_rat & FAB$M_BLK)
3341 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3342 strcat (rat, ", blk");
3343 else
3344 strcat (rat, "blk");
3345 return creat (name, 0, rfm, rat, fsz);
3347 case FAB$C_STM:
3348 strcpy (rfm, "rfm = stm");
3349 break;
3351 case FAB$C_STMCR:
3352 strcpy (rfm, "rfm = stmcr");
3353 break;
3355 case FAB$C_STMLF:
3356 strcpy (rfm, "rfm = stmlf");
3357 break;
3359 case FAB$C_UDF:
3360 strcpy (rfm, "rfm = udf");
3361 break;
3363 case FAB$C_VAR:
3364 strcpy (rfm, "rfm = var");
3365 break;
3367 strcpy (rat, "rat = ");
3368 if (st_buf.st_fab_rat & FAB$M_CR)
3369 strcat (rat, "cr");
3370 else if (st_buf.st_fab_rat & FAB$M_FTN)
3371 strcat (rat, "ftn");
3372 else if (st_buf.st_fab_rat & FAB$M_PRN)
3373 strcat (rat, "prn");
3374 if (st_buf.st_fab_rat & FAB$M_BLK)
3375 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3376 strcat (rat, ", blk");
3377 else
3378 strcat (rat, "blk");
3380 else
3382 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3383 strcpy (rat, "rat=cr");
3385 /* Until the VAX C RTL fixes the many bugs with modes, always use
3386 mode 0 to get the user's default protection. */
3387 fd = creat (name, 0, rfm, rat);
3388 if (fd < 0 && errno == EEXIST)
3390 if (unlink (name) < 0)
3391 report_file_error ("delete", build_string (name));
3392 fd = creat (name, 0, rfm, rat);
3394 return fd;
3396 #endif /* creat */
3398 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3399 sys_fwrite (ptr, size, num, fp)
3400 register char * ptr;
3401 FILE * fp;
3403 register int tot = num * size;
3405 while (tot--)
3406 fputc (*ptr++, fp);
3410 * The VMS C library routine creat actually creates a new version of an
3411 * existing file rather than truncating the old version. There are times
3412 * when this is not the desired behavior, for instance, when writing an
3413 * auto save file (you only want one version), or when you don't have
3414 * write permission in the directory containing the file (but the file
3415 * itself is writable). Hence this routine, which is equivalent to
3416 * "close (creat (fn, 0));" on Unix if fn already exists.
3419 vms_truncate (fn)
3420 char *fn;
3422 struct FAB xfab = cc$rms_fab;
3423 struct RAB xrab = cc$rms_rab;
3424 int status;
3426 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3427 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3428 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3429 xfab.fab$l_fna = fn;
3430 xfab.fab$b_fns = strlen (fn);
3431 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3432 xfab.fab$b_dns = 2;
3433 xrab.rab$l_fab = &xfab;
3435 /* This gibberish opens the file, positions to the first record, and
3436 deletes all records from there until the end of file. */
3437 if ((sys$open (&xfab) & 01) == 01)
3439 if ((sys$connect (&xrab) & 01) == 01 &&
3440 (sys$find (&xrab) & 01) == 01 &&
3441 (sys$truncate (&xrab) & 01) == 01)
3442 status = 0;
3443 else
3444 status = -1;
3446 else
3447 status = -1;
3448 sys$close (&xfab);
3449 return status;
3452 /* Define this symbol to actually read SYSUAF.DAT. This requires either
3453 SYSPRV or a readable SYSUAF.DAT. */
3455 #ifdef READ_SYSUAF
3457 * getuaf.c
3459 * Routine to read the VMS User Authorization File and return
3460 * a specific user's record.
3463 static struct UAF retuaf;
3465 struct UAF *
3466 get_uaf_name (uname)
3467 char * uname;
3469 register status;
3470 struct FAB uaf_fab;
3471 struct RAB uaf_rab;
3473 uaf_fab = cc$rms_fab;
3474 uaf_rab = cc$rms_rab;
3475 /* initialize fab fields */
3476 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3477 uaf_fab.fab$b_fns = 21;
3478 uaf_fab.fab$b_fac = FAB$M_GET;
3479 uaf_fab.fab$b_org = FAB$C_IDX;
3480 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3481 /* initialize rab fields */
3482 uaf_rab.rab$l_fab = &uaf_fab;
3483 /* open the User Authorization File */
3484 status = sys$open (&uaf_fab);
3485 if (!(status&1))
3487 errno = EVMSERR;
3488 vaxc$errno = status;
3489 return 0;
3491 status = sys$connect (&uaf_rab);
3492 if (!(status&1))
3494 errno = EVMSERR;
3495 vaxc$errno = status;
3496 return 0;
3498 /* read the requested record - index is in uname */
3499 uaf_rab.rab$l_kbf = uname;
3500 uaf_rab.rab$b_ksz = strlen (uname);
3501 uaf_rab.rab$b_rac = RAB$C_KEY;
3502 uaf_rab.rab$l_ubf = (char *)&retuaf;
3503 uaf_rab.rab$w_usz = sizeof retuaf;
3504 status = sys$get (&uaf_rab);
3505 if (!(status&1))
3507 errno = EVMSERR;
3508 vaxc$errno = status;
3509 return 0;
3511 /* close the User Authorization File */
3512 status = sys$disconnect (&uaf_rab);
3513 if (!(status&1))
3515 errno = EVMSERR;
3516 vaxc$errno = status;
3517 return 0;
3519 status = sys$close (&uaf_fab);
3520 if (!(status&1))
3522 errno = EVMSERR;
3523 vaxc$errno = status;
3524 return 0;
3526 return &retuaf;
3529 struct UAF *
3530 get_uaf_uic (uic)
3531 unsigned long uic;
3533 register status;
3534 struct FAB uaf_fab;
3535 struct RAB uaf_rab;
3537 uaf_fab = cc$rms_fab;
3538 uaf_rab = cc$rms_rab;
3539 /* initialize fab fields */
3540 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3541 uaf_fab.fab$b_fns = 21;
3542 uaf_fab.fab$b_fac = FAB$M_GET;
3543 uaf_fab.fab$b_org = FAB$C_IDX;
3544 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3545 /* initialize rab fields */
3546 uaf_rab.rab$l_fab = &uaf_fab;
3547 /* open the User Authorization File */
3548 status = sys$open (&uaf_fab);
3549 if (!(status&1))
3551 errno = EVMSERR;
3552 vaxc$errno = status;
3553 return 0;
3555 status = sys$connect (&uaf_rab);
3556 if (!(status&1))
3558 errno = EVMSERR;
3559 vaxc$errno = status;
3560 return 0;
3562 /* read the requested record - index is in uic */
3563 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3564 uaf_rab.rab$l_kbf = (char *) &uic;
3565 uaf_rab.rab$b_ksz = sizeof uic;
3566 uaf_rab.rab$b_rac = RAB$C_KEY;
3567 uaf_rab.rab$l_ubf = (char *)&retuaf;
3568 uaf_rab.rab$w_usz = sizeof retuaf;
3569 status = sys$get (&uaf_rab);
3570 if (!(status&1))
3572 errno = EVMSERR;
3573 vaxc$errno = status;
3574 return 0;
3576 /* close the User Authorization File */
3577 status = sys$disconnect (&uaf_rab);
3578 if (!(status&1))
3580 errno = EVMSERR;
3581 vaxc$errno = status;
3582 return 0;
3584 status = sys$close (&uaf_fab);
3585 if (!(status&1))
3587 errno = EVMSERR;
3588 vaxc$errno = status;
3589 return 0;
3591 return &retuaf;
3594 static struct passwd retpw;
3596 struct passwd *
3597 cnv_uaf_pw (up)
3598 struct UAF * up;
3600 char * ptr;
3602 /* copy these out first because if the username is 32 chars, the next
3603 section will overwrite the first byte of the UIC */
3604 retpw.pw_uid = up->uaf$w_mem;
3605 retpw.pw_gid = up->uaf$w_grp;
3607 /* I suppose this is not the best sytle, to possibly overwrite one
3608 byte beyond the end of the field, but what the heck... */
3609 ptr = &up->uaf$t_username[UAF$S_USERNAME];
3610 while (ptr[-1] == ' ')
3611 ptr--;
3612 *ptr = '\0';
3613 strcpy (retpw.pw_name, up->uaf$t_username);
3615 /* the rest of these are counted ascii strings */
3616 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3617 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3618 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3619 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3620 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3621 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3622 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3623 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3625 return &retpw;
3627 #else /* not READ_SYSUAF */
3628 static struct passwd retpw;
3629 #endif /* not READ_SYSUAF */
3631 struct passwd *
3632 getpwnam (name)
3633 char * name;
3635 #ifdef READ_SYSUAF
3636 struct UAF *up;
3637 #else
3638 char * user;
3639 char * dir;
3640 unsigned char * full;
3641 #endif /* READ_SYSUAF */
3642 char *ptr = name;
3644 while (*ptr)
3646 if ('a' <= *ptr && *ptr <= 'z')
3647 *ptr -= 040;
3648 ptr++;
3650 #ifdef READ_SYSUAF
3651 if (!(up = get_uaf_name (name)))
3652 return 0;
3653 return cnv_uaf_pw (up);
3654 #else
3655 if (strcmp (name, getenv ("USER")) == 0)
3657 retpw.pw_uid = getuid ();
3658 retpw.pw_gid = getgid ();
3659 strcpy (retpw.pw_name, name);
3660 if (full = egetenv ("FULLNAME"))
3661 strcpy (retpw.pw_gecos, full);
3662 else
3663 *retpw.pw_gecos = '\0';
3664 strcpy (retpw.pw_dir, egetenv ("HOME"));
3665 *retpw.pw_shell = '\0';
3666 return &retpw;
3668 else
3669 return 0;
3670 #endif /* not READ_SYSUAF */
3673 struct passwd *
3674 getpwuid (uid)
3675 unsigned long uid;
3677 #ifdef READ_SYSUAF
3678 struct UAF * up;
3680 if (!(up = get_uaf_uic (uid)))
3681 return 0;
3682 return cnv_uaf_pw (up);
3683 #else
3684 if (uid == sys_getuid ())
3685 return getpwnam (egetenv ("USER"));
3686 else
3687 return 0;
3688 #endif /* not READ_SYSUAF */
3691 /* return total address space available to the current process. This is
3692 the sum of the current p0 size, p1 size and free page table entries
3693 available. */
3694 vlimit ()
3696 int item_code;
3697 unsigned long free_pages;
3698 unsigned long frep0va;
3699 unsigned long frep1va;
3700 register status;
3702 item_code = JPI$_FREPTECNT;
3703 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
3705 errno = EVMSERR;
3706 vaxc$errno = status;
3707 return -1;
3709 free_pages *= 512;
3711 item_code = JPI$_FREP0VA;
3712 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
3714 errno = EVMSERR;
3715 vaxc$errno = status;
3716 return -1;
3718 item_code = JPI$_FREP1VA;
3719 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
3721 errno = EVMSERR;
3722 vaxc$errno = status;
3723 return -1;
3726 return free_pages + frep0va + (0x7fffffff - frep1va);
3729 define_logical_name (varname, string)
3730 char *varname;
3731 char *string;
3733 struct dsc$descriptor_s strdsc =
3734 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
3735 struct dsc$descriptor_s envdsc =
3736 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3737 struct dsc$descriptor_s lnmdsc =
3738 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3740 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
3743 delete_logical_name (varname)
3744 char *varname;
3746 struct dsc$descriptor_s envdsc =
3747 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3748 struct dsc$descriptor_s lnmdsc =
3749 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3751 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
3754 ulimit ()
3757 setpriority ()
3760 setpgrp ()
3763 execvp ()
3765 error ("execvp system call not implemented");
3769 rename (from, to)
3770 char *from, *to;
3772 int status;
3773 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
3774 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
3775 char from_esn[NAM$C_MAXRSS];
3776 char to_esn[NAM$C_MAXRSS];
3778 from_fab.fab$l_fna = from;
3779 from_fab.fab$b_fns = strlen (from);
3780 from_fab.fab$l_nam = &from_nam;
3781 from_fab.fab$l_fop = FAB$M_NAM;
3783 from_nam.nam$l_esa = from_esn;
3784 from_nam.nam$b_ess = sizeof from_esn;
3786 to_fab.fab$l_fna = to;
3787 to_fab.fab$b_fns = strlen (to);
3788 to_fab.fab$l_nam = &to_nam;
3789 to_fab.fab$l_fop = FAB$M_NAM;
3791 to_nam.nam$l_esa = to_esn;
3792 to_nam.nam$b_ess = sizeof to_esn;
3794 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
3796 if (status & 1)
3797 return 0;
3798 else
3800 if (status == RMS$_DEV)
3801 errno = EXDEV;
3802 else
3803 errno = EVMSERR;
3804 vaxc$errno = status;
3805 return -1;
3809 /* This function renames a file like `rename', but it strips
3810 the version number from the "to" filename, such that the "to" file is
3811 will always be a new version. It also sets the file protection once it is
3812 finished. The protection that we will use is stored in fab_final_pro,
3813 and was set when we did a creat_copy_attrs to create the file that we
3814 are renaming.
3816 We could use the chmod function, but Eunichs uses 3 bits per user category
3817 to describe the protection, and VMS uses 4 (write and delete are seperate
3818 bits). To maintain portability, the VMS implementation of `chmod' wires
3819 the W and D bits together. */
3822 static struct fibdef fib; /* We need this initialized to zero */
3823 char vms_file_written[NAM$C_MAXRSS];
3826 rename_sans_version (from,to)
3827 char *from, *to;
3829 short int chan;
3830 int stat;
3831 short int iosb[4];
3832 int status;
3833 struct FAB to_fab = cc$rms_fab;
3834 struct NAM to_nam = cc$rms_nam;
3835 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
3836 struct dsc$descriptor fib_attr[2]
3837 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
3838 char to_esn[NAM$C_MAXRSS];
3840 $DESCRIPTOR (disk,to_esn);
3842 to_fab.fab$l_fna = to;
3843 to_fab.fab$b_fns = strlen (to);
3844 to_fab.fab$l_nam = &to_nam;
3845 to_fab.fab$l_fop = FAB$M_NAM;
3847 to_nam.nam$l_esa = to_esn;
3848 to_nam.nam$b_ess = sizeof to_esn;
3850 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
3852 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
3853 *(to_nam.nam$l_ver) = '\0';
3855 stat = rename (from, to_esn);
3856 if (stat < 0)
3857 return stat;
3859 strcpy (vms_file_written, to_esn);
3861 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
3862 to_fab.fab$b_fns = strlen (vms_file_written);
3864 /* Now set the file protection to the correct value */
3865 sys$open (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
3867 /* Copy these fields into the fib */
3868 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
3869 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
3870 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
3872 sys$close (&to_fab, 0, 0);
3874 stat = sys$assign (&disk, &chan, 0, 0); /* open a channel to the disk */
3875 if (!stat)
3876 lib$signal (stat);
3877 stat = sys$qiow (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
3878 0, 0, 0, &fib_attr, 0);
3879 if (!stat)
3880 lib$signal (stat);
3881 stat = sys$dassgn (chan);
3882 if (!stat)
3883 lib$signal (stat);
3884 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
3885 return 0;
3888 link (file, new)
3889 char * file, * new;
3891 register status;
3892 struct FAB fab;
3893 struct NAM nam;
3894 unsigned short fid[3];
3895 char esa[NAM$C_MAXRSS];
3897 fab = cc$rms_fab;
3898 fab.fab$l_fop = FAB$M_OFP;
3899 fab.fab$l_fna = file;
3900 fab.fab$b_fns = strlen (file);
3901 fab.fab$l_nam = &nam;
3903 nam = cc$rms_nam;
3904 nam.nam$l_esa = esa;
3905 nam.nam$b_ess = NAM$C_MAXRSS;
3907 status = SYS$PARSE (&fab);
3908 if ((status & 1) == 0)
3910 errno = EVMSERR;
3911 vaxc$errno = status;
3912 return -1;
3914 status = SYS$SEARCH (&fab);
3915 if ((status & 1) == 0)
3917 errno = EVMSERR;
3918 vaxc$errno = status;
3919 return -1;
3922 fid[0] = nam.nam$w_fid[0];
3923 fid[1] = nam.nam$w_fid[1];
3924 fid[2] = nam.nam$w_fid[2];
3926 fab.fab$l_fna = new;
3927 fab.fab$b_fns = strlen (new);
3929 status = SYS$PARSE (&fab);
3930 if ((status & 1) == 0)
3932 errno = EVMSERR;
3933 vaxc$errno = status;
3934 return -1;
3937 nam.nam$w_fid[0] = fid[0];
3938 nam.nam$w_fid[1] = fid[1];
3939 nam.nam$w_fid[2] = fid[2];
3941 nam.nam$l_esa = nam.nam$l_name;
3942 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
3944 status = SYS$ENTER (&fab);
3945 if ((status & 1) == 0)
3947 errno = EVMSERR;
3948 vaxc$errno = status;
3949 return -1;
3952 return 0;
3955 croak (badfunc)
3956 char *badfunc;
3958 printf ("%s not yet implemented\r\n", badfunc);
3959 reset_sys_modes ();
3960 exit (1);
3963 long
3964 random ()
3966 /* Arrange to return a range centered on zero. */
3967 return rand () - (1 << 30);
3970 srandom (seed)
3972 srand (seed);
3974 #endif /* VMS */
3976 #ifdef AIX
3978 /* Called from init_sys_modes. */
3979 hft_init ()
3981 int junk;
3983 /* If we're not on an HFT we shouldn't do any of this. We determine
3984 if we are on an HFT by trying to get an HFT error code. If this
3985 call fails, we're not on an HFT. */
3986 #ifdef IBMR2AIX
3987 if (ioctl (0, HFQERROR, &junk) < 0)
3988 return;
3989 #else /* not IBMR2AIX */
3990 if (ioctl (0, HFQEIO, 0) < 0)
3991 return;
3992 #endif /* not IBMR2AIX */
3994 /* On AIX the default hft keyboard mapping uses backspace rather than delete
3995 as the rubout key's ASCII code. Here this is changed. The bug is that
3996 there's no way to determine the old mapping, so in reset_sys_modes
3997 we need to assume that the normal map had been present. Of course, this
3998 code also doesn't help if on a terminal emulator which doesn't understand
3999 HFT VTD's. */
4001 struct hfbuf buf;
4002 struct hfkeymap keymap;
4004 buf.hf_bufp = (char *)&keymap;
4005 buf.hf_buflen = sizeof (keymap);
4006 keymap.hf_nkeys = 2;
4007 keymap.hfkey[0].hf_kpos = 15;
4008 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4009 #ifdef IBMR2AIX
4010 keymap.hfkey[0].hf_keyidh = '<';
4011 #else /* not IBMR2AIX */
4012 keymap.hfkey[0].hf_page = '<';
4013 #endif /* not IBMR2AIX */
4014 keymap.hfkey[0].hf_char = 127;
4015 keymap.hfkey[1].hf_kpos = 15;
4016 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4017 #ifdef IBMR2AIX
4018 keymap.hfkey[1].hf_keyidh = '<';
4019 #else /* not IBMR2AIX */
4020 keymap.hfkey[1].hf_page = '<';
4021 #endif /* not IBMR2AIX */
4022 keymap.hfkey[1].hf_char = 127;
4023 hftctl (0, HFSKBD, &buf);
4025 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4026 at times. */
4027 line_ins_del_ok = char_ins_del_ok = 0;
4030 /* Reset the rubout key to backspace. */
4032 hft_reset ()
4034 struct hfbuf buf;
4035 struct hfkeymap keymap;
4036 int junk;
4038 #ifdef IBMR2AIX
4039 if (ioctl (0, HFQERROR, &junk) < 0)
4040 return;
4041 #else /* not IBMR2AIX */
4042 if (ioctl (0, HFQEIO, 0) < 0)
4043 return;
4044 #endif /* not IBMR2AIX */
4046 buf.hf_bufp = (char *)&keymap;
4047 buf.hf_buflen = sizeof (keymap);
4048 keymap.hf_nkeys = 2;
4049 keymap.hfkey[0].hf_kpos = 15;
4050 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4051 #ifdef IBMR2AIX
4052 keymap.hfkey[0].hf_keyidh = '<';
4053 #else /* not IBMR2AIX */
4054 keymap.hfkey[0].hf_page = '<';
4055 #endif /* not IBMR2AIX */
4056 keymap.hfkey[0].hf_char = 8;
4057 keymap.hfkey[1].hf_kpos = 15;
4058 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4059 #ifdef IBMR2AIX
4060 keymap.hfkey[1].hf_keyidh = '<';
4061 #else /* not IBMR2AIX */
4062 keymap.hfkey[1].hf_page = '<';
4063 #endif /* not IBMR2AIX */
4064 keymap.hfkey[1].hf_char = 8;
4065 hftctl (0, HFSKBD, &buf);
4068 #endif /* AIX */