(gud-def): Fix inclusion of the define-key.
[bpt/emacs.git] / src / sysdep.c
CommitLineData
86a5659e 1/* Interfaces to system-dependent kernel and library entries.
91bac16a 2 Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
86a5659e
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <signal.h>
22#include <setjmp.h>
23
24#include "config.h"
25#include "lisp.h"
9ac0d9e0 26#include "blockinput.h"
86a5659e
JB
27#undef NULL
28
29#define min(x,y) ((x) > (y) ? (y) : (x))
30
31/* In this file, open, read and write refer to the system calls,
32 not our sugared interfaces sys_open, sys_read and sys_write.
33 Contrariwise, for systems where we use the system calls directly,
34 define sys_read, etc. here as aliases for them. */
35#ifndef read
36#define sys_read read
37#define sys_write write
38#endif /* `read' is not a macro */
39
40#undef read
41#undef write
42
43#ifndef close
44#define sys_close close
45#else
46#undef close
47#endif
48
49#ifndef open
50#define sys_open open
51#else /* `open' is a macro */
52#undef open
53#endif /* `open' is a macro */
54
986ffb24
JB
55/* Does anyone other than VMS need this? */
56#ifndef fwrite
57#define sys_fwrite fwrite
58#else
59#undef fwrite
60#endif
61
86a5659e
JB
62#include <stdio.h>
63#include <sys/types.h>
64#include <sys/stat.h>
65#include <errno.h>
66
67extern int errno;
68#ifndef VMS
69extern char *sys_errlist[];
70#endif
71
72#ifdef VMS
73#include <rms.h>
74#include <ttdef.h>
75#include <tt2def.h>
76#include <iodef.h>
77#include <ssdef.h>
78#include <descrip.h>
79#include <fibdef.h>
80#include <atrdef.h>
81#include <ctype.h>
82#include <string.h>
83#ifdef __GNUC__
84#include <sys/file.h>
85#else
86#include <file.h>
87#endif
88#undef F_SETFL
89#ifndef RAB$C_BID
90#include <rab.h>
91#endif
92#define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
93#endif /* VMS */
94
95#ifndef BSD4_1
96#ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
97 because the vms compiler doesn't grok `defined' */
98#include <fcntl.h>
99#endif
100#ifdef USG
34567704 101#ifndef USG5
86a5659e
JB
102#include <fcntl.h>
103#endif
34567704 104#endif
86a5659e
JB
105#endif /* not 4.1 bsd */
106
107/* Get DGUX definition for FASYNC - DJB */
108#ifdef DGUX
109#include <sys/file.h>
110#endif /* DGUX */
111
112#include <sys/ioctl.h>
e04a4e0d 113#include "systty.h"
86a5659e
JB
114
115#ifdef BSD
116#ifdef BSD4_1
117#include <wait.h>
118#else /* not 4.1 */
119#include <sys/wait.h>
120#endif /* not 4.1 */
121#endif /* BSD */
122
86a5659e
JB
123#ifdef BROKEN_TIOCGWINSZ
124#undef TIOCGWINSZ
125#endif
126
86a5659e
JB
127#ifdef USG
128#include <sys/utsname.h>
129#include <string.h>
130#ifndef MEMORY_IN_STRING_H
131#include <memory.h>
132#endif
133#ifdef TIOCGWINSZ
134#ifdef NEED_SIOCTL
135#include <sys/sioctl.h>
136#endif
137#ifdef NEED_PTEM_H
138#include <sys/stream.h>
139#include <sys/ptem.h>
140#endif
141#endif /* TIOCGWINSZ */
86a5659e
JB
142#endif /* USG */
143
86a5659e
JB
144extern int quit_char;
145
0137dbf7 146#include "frame.h"
86a5659e
JB
147#include "window.h"
148#include "termhooks.h"
149#include "termchar.h"
150#include "termopts.h"
151#include "dispextern.h"
152#include "process.h"
153
154#ifdef NONSYSTEM_DIR_LIBRARY
155#include "ndir.h"
156#endif /* NONSYSTEM_DIR_LIBRARY */
157
91bac16a
JB
158#include "syssignal.h"
159#include "systime.h"
86a5659e
JB
160
161static int baud_convert[] =
162#ifdef BAUD_CONVERT
163 BAUD_CONVERT;
164#else
165 {
166 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
167 1800, 2400, 4800, 9600, 19200, 38400
168 };
169#endif
170
171extern short ospeed;
172
91bac16a
JB
173/* The file descriptor for Emacs's input terminal.
174 Under Unix, this is always left zero;
175 under VMS, we place the input channel number here.
176 This allows us to write more code that works for both VMS and Unix. */
177static int input_fd;
178
86a5659e
JB
179discard_tty_input ()
180{
91bac16a 181 struct emacs_tty buf;
86a5659e
JB
182
183 if (noninteractive)
184 return;
185
186 /* Discarding input is not safe when the input could contain
187 replies from the X server. So don't do it. */
188 if (read_socket_hook)
189 return;
190
191#ifdef VMS
192 end_kbd_input ();
91bac16a
JB
193 SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
194 &buf.main, 0, 0, terminator_mask, 0, 0);
86a5659e
JB
195 queue_kbd_input ();
196#else /* not VMS */
197#ifdef APOLLO
198 {
199 int zero = 0;
200 ioctl (0, TIOCFLUSH, &zero);
201 }
202#else /* not Apollo */
91bac16a
JB
203 EMACS_GET_TTY (input_fd, &buf);
204 EMACS_SET_TTY (input_fd, &buf, 0);
86a5659e
JB
205#endif /* not Apollo */
206#endif /* not VMS */
207}
208
209#ifdef SIGTSTP
210
211stuff_char (c)
212 char c;
213{
214/* Should perhaps error if in batch mode */
215#ifdef TIOCSTI
216 ioctl (0, TIOCSTI, &c);
217#else /* no TIOCSTI */
218 error ("Cannot stuff terminal input characters in this version of Unix.");
219#endif /* no TIOCSTI */
220}
221
222#endif /* SIGTSTP */
223
224init_baud_rate ()
225{
86a5659e
JB
226 if (noninteractive)
227 ospeed = 0;
228 else
229 {
230#ifdef VMS
91bac16a
JB
231 struct sensemode sg;
232
233 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
86a5659e 234 &sg.class, 12, 0, 0, 0, 0 );
91bac16a
JB
235 ospeed = sg.xmit_baud;
236#else /* not VMS */
e04a4e0d
JB
237#ifdef HAVE_TERMIOS
238 struct termios sg;
91bac16a
JB
239
240 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
241 tcgetattr (0, &sg);
242 ospeed = sg.c_cflag & CBAUD;
e04a4e0d
JB
243#else /* neither VMS nor TERMIOS */
244#ifdef HAVE_TERMIO
245 struct termio sg;
91bac16a
JB
246
247 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
e04a4e0d 248#ifdef HAVE_TCATTR
86a5659e 249 tcgetattr (0, &sg);
e04a4e0d 250#else
6c65530f 251 ioctl (input_fd, TCGETA, &sg);
e04a4e0d 252#endif
91bac16a 253 ospeed = sg.c_cflag & CBAUD;
e04a4e0d 254#else /* neither VMS nor TERMIOS nor TERMIO */
91bac16a
JB
255 struct sgttyb sg;
256
257 sg.sg_ospeed = B9600;
258 ioctl (0, TIOCGETP, &sg);
259 ospeed = sg.sg_ospeed;
91bac16a 260#endif /* not HAVE_TERMIO */
e04a4e0d 261#endif /* not HAVE_TERMIOS */
86a5659e 262#endif /* not VMS */
86a5659e
JB
263 }
264
265 baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
266 ? baud_convert[ospeed] : 9600);
267 if (baud_rate == 0)
268 baud_rate = 1200;
269}
270
271/*ARGSUSED*/
272set_exclusive_use (fd)
273 int fd;
274{
275#ifdef FIOCLEX
276 ioctl (fd, FIOCLEX, 0);
277#endif
278 /* Ok to do nothing if this feature does not exist */
279}
280
281#ifndef subprocesses
282
283wait_without_blocking ()
284{
285#ifdef BSD
286 wait3 (0, WNOHANG | WUNTRACED, 0);
287#else
288 croak ("wait_without_blocking");
289#endif
290 synch_process_alive = 0;
291}
292
293#endif /* not subprocesses */
294
295int wait_debugging; /* Set nonzero to make following function work under dbx
296 (at least for bsd). */
297
298SIGTYPE
299wait_for_termination_signal ()
300{}
301
302/* Wait for subprocess with process id `pid' to terminate and
303 make sure it will get eliminated (not remain forever as a zombie) */
304
305wait_for_termination (pid)
306 int pid;
307{
308 while (1)
309 {
310#ifdef subprocesses
311#ifdef VMS
312 int status;
313
986ffb24 314 status = SYS$FORCEX (&pid, 0, 0);
86a5659e
JB
315 break;
316#else /* not VMS */
4c8975ad
RS
317#if defined (BSD) || (defined (HPUX) && !defined (HPUX_5))
318 /* Note that kill returns -1 even if the process is just a zombie now.
319 But inevitably a SIGCHLD interrupt should be generated
320 and child_sig will do wait3 and make the process go away. */
321 /* There is some indication that there is a bug involved with
322 termination of subprocesses, perhaps involving a kernel bug too,
323 but no idea what it is. Just as a hunch we signal SIGCHLD to see
324 if that causes the problem to go away or get worse. */
325 sigsetmask (sigmask (SIGCHLD));
326 if (0 > kill (pid, 0))
327 {
328 sigsetmask (SIGEMPTYMASK);
329 kill (getpid (), SIGCHLD);
330 break;
331 }
332 if (wait_debugging)
333 sleep (1);
334 else
335 sigpause (SIGEMPTYMASK);
336#else /* not BSD, and not HPUX version >= 6 */
337#ifdef UNIPLUS
338 if (0 > kill (pid, 0))
339 break;
340 wait (0);
341#else /* neither BSD nor UNIPLUS: random sysV */
342#ifdef HAVE_SYSV_SIGPAUSE
343 sighold (SIGCHLD);
344 if (0 > kill (pid, 0))
345 {
346 sigrelse (SIGCHLD);
347 break;
348 }
349 sigpause (SIGCHLD);
350#else /* not HAVE_SYSV_SIGPAUSE */
351 if (0 > kill (pid, 0))
86a5659e 352 break;
4c8975ad
RS
353 /* Using sleep instead of pause avoids timing error.
354 If the inferior dies just before the sleep,
355 we lose just one second. */
356 sleep (1);
357#endif /* not HAVE_SYSV_SIGPAUSE */
358#endif /* not UNIPLUS */
359#endif /* not BSD, and not HPUX version >= 6 */
86a5659e
JB
360#endif /* not VMS */
361#else /* not subprocesses */
362#ifndef BSD4_1
363 if (kill (pid, 0) < 0)
364 break;
365 wait (0);
366#else /* BSD4_1 */
367 int status;
368 status = wait (0);
369 if (status == pid || status == -1)
370 break;
371#endif /* BSD4_1 */
372#endif /* not subprocesses */
373 }
374}
375
376#ifdef subprocesses
377
378/*
379 * flush any pending output
380 * (may flush input as well; it does not matter the way we use it)
381 */
382
383flush_pending_output (channel)
384 int channel;
385{
386#ifdef HAVE_TERMIOS
387 /* If we try this, we get hit with SIGTTIN, because
388 the child's tty belongs to the child's pgrp. */
389#else
390#ifdef TCFLSH
391 ioctl (channel, TCFLSH, 1);
392#else
393#ifdef TIOCFLUSH
394 int zero = 0;
395 /* 3rd arg should be ignored
396 but some 4.2 kernels actually want the address of an int
397 and nonzero means something different. */
398 ioctl (channel, TIOCFLUSH, &zero);
399#endif
400#endif
401#endif
402}
403
404#ifndef VMS
405/* Set up the terminal at the other end of a pseudo-terminal that
406 we will be controlling an inferior through.
407 It should not echo or do line-editing, since that is done
408 in Emacs. No padding needed for insertion into an Emacs buffer. */
409
410child_setup_tty (out)
411 int out;
412{
91bac16a
JB
413 struct emacs_tty s;
414
415 EMACS_GET_TTY (out, &s);
86a5659e 416
31be8d24 417#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
91bac16a
JB
418 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
419 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
420 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
421 /* No output delays */
422 s.main.c_lflag &= ~ECHO; /* Disable echo */
423 s.main.c_lflag |= ISIG; /* Enable signals */
424 s.main.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on
425 input */
426 s.main.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on
427 output */
428#if 0
429 /* Said to be unnecesary: */
430 s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
431 s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */
432#endif
433
434 s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
435 s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
436 s.main.c_cc[VERASE] = 0377; /* disable erase processing */
437 s.main.c_cc[VKILL] = 0377; /* disable kill processing */
438
86a5659e 439#ifdef HPUX
91bac16a 440 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e 441#endif /* HPUX */
91bac16a 442
86a5659e
JB
443#ifdef AIX
444/* AIX enhanced edit loses NULs, so disable it */
445#ifndef IBMR2AIX
91bac16a
JB
446 s.main.c_line = 0;
447 s.main.c_iflag &= ~ASCEDIT;
86a5659e
JB
448#endif
449 /* Also, PTY overloads NUL and BREAK.
450 don't ignore break, but don't signal either, so it looks like NUL. */
91bac16a
JB
451 s.main.c_iflag &= ~IGNBRK;
452 s.main.c_iflag &= ~BRKINT;
453 /* QUIT and INTR work better as signals, so disable character forms */
454 s.main.c_cc[VQUIT] = 0377;
455 s.main.c_cc[VINTR] = 0377;
456 s.main.c_cc[VEOL] = 0377;
457 s.main.c_lflag &= ~ISIG;
458 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e
JB
459#endif /* AIX */
460
461#else /* not HAVE_TERMIO */
91bac16a
JB
462
463 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
464 | CBREAK | TANDEM);
465 s.main.sg_erase = 0377;
466 s.main.sg_kill = 0377;
467
86a5659e
JB
468#endif /* not HAVE_TERMIO */
469
91bac16a 470 EMACS_SET_TTY (out, &s, 0);
86a5659e
JB
471
472#ifdef BSD4_1
473 if (interrupt_input)
474 reset_sigio ();
475#endif /* BSD4_1 */
476#ifdef RTU
477 {
478 int zero = 0;
479 ioctl (out, FIOASYNC, &zero);
480 }
481#endif /* RTU */
482}
483#endif /* not VMS */
484
485#endif /* subprocesses */
486
487/*ARGSUSED*/
488setpgrp_of_tty (pid)
489 int pid;
490{
ffd56f97 491 EMACS_SET_TTY_PGRP (input_fd, &pid);
86a5659e
JB
492}
493
494/* Record a signal code and the handler for it. */
495struct save_signal
496{
497 int code;
498 SIGTYPE (*handler) ();
499};
500
501/* Suspend the Emacs process; give terminal to its superior. */
502
503sys_suspend ()
504{
505#ifdef VMS
88191e36
RS
506 /* "Foster" parentage allows emacs to return to a subprocess that attached
507 to the current emacs as a cheaper than starting a whole new process. This
508 is set up by KEPTEDITOR.COM. */
509 unsigned long parent_id, foster_parent_id;
510 char *fpid_string;
511
512 fpid_string = getenv ("EMACS_PARENT_PID");
513 if (fpid_string != NULL)
514 {
515 sscanf (fpid_string, "%x", &foster_parent_id);
516 if (foster_parent_id != 0)
517 parent_id = foster_parent_id;
518 else
519 parent_id = getppid ();
520 }
521 else
522 parent_id = getppid ();
523
9ac0d9e0 524 xfree (fpid_string); /* On VMS, this was malloc'd */
86a5659e 525
86a5659e
JB
526 if (parent_id && parent_id != 0xffffffff)
527 {
528 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
529 int status = LIB$ATTACH (&parent_id) & 1;
530 signal (SIGINT, oldsig);
531 return status;
532 }
533 else
534 {
535 struct {
536 int l;
537 char *a;
538 } d_prompt;
539 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
540 d_prompt.a = "Emacs: "; /* Just a reminder */
986ffb24 541 LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
86a5659e
JB
542 return 1;
543 }
544 return -1;
545#else
546#ifdef SIGTSTP
547
91bac16a 548 EMACS_KILLPG (getpgrp (0), SIGTSTP);
86a5659e
JB
549
550#else /* No SIGTSTP */
551#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
552 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
553 kill (getpid (), SIGQUIT);
554
555#else /* No SIGTSTP or USG_JOBCTRL */
556
557/* On a system where suspending is not implemented,
558 instead fork a subshell and let it talk directly to the terminal
559 while we wait. */
560 int pid = fork ();
561 struct save_signal saved_handlers[5];
562
563 saved_handlers[0].code = SIGINT;
564 saved_handlers[1].code = SIGQUIT;
565 saved_handlers[2].code = SIGTERM;
566#ifdef SIGIO
567 saved_handlers[3].code = SIGIO;
568 saved_handlers[4].code = 0;
569#else
570 saved_handlers[3].code = 0;
571#endif
572
573 if (pid == -1)
574 error ("Can't spawn subshell");
575 if (pid == 0)
576 {
577 char *sh;
578
579 sh = (char *) egetenv ("SHELL");
580 if (sh == 0)
581 sh = "sh";
582 /* Use our buffer's default directory for the subshell. */
583 {
584 Lisp_Object dir;
585 unsigned char *str;
586 int len;
587
588 /* mentioning current_buffer->buffer would mean including buffer.h,
589 which somehow wedges the hp compiler. So instead... */
590
591 dir = intern ("default-directory");
592 /* Can't use NULL */
593 if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
594 goto xyzzy;
595 dir = Fsymbol_value (dir);
596 if (XTYPE (dir) != Lisp_String)
597 goto xyzzy;
598
599 str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
600 len = XSTRING (dir)->size;
601 bcopy (XSTRING (dir)->data, str, len);
602 if (str[len - 1] != '/') str[len++] = '/';
603 str[len] = 0;
604 chdir (str);
605 }
606 xyzzy:
607#ifdef subprocesses
608 close_process_descs (); /* Close Emacs's pipes/ptys */
609#endif
1593c2fe
JB
610
611#ifdef PRIO_PROCESS
612 {
613 extern int emacs_priority;
614
615 if (emacs_priority)
616 nice (-emacs_priority);
617 }
618#endif
619
86a5659e
JB
620 execlp (sh, sh, 0);
621 write (1, "Can't execute subshell", 22);
622 _exit (1);
623 }
624
625 save_signal_handlers (saved_handlers);
ffafc793 626 synch_process_alive = 1;
86a5659e
JB
627 wait_for_termination (pid);
628 restore_signal_handlers (saved_handlers);
629
630#endif /* no USG_JOBCTRL */
631#endif /* no SIGTSTP */
632#endif /* not VMS */
633}
634
635save_signal_handlers (saved_handlers)
636 struct save_signal *saved_handlers;
637{
638 while (saved_handlers->code)
639 {
508b171c
JA
640 saved_handlers->handler
641 = (SIGTYPE (*) ()) signal (saved_handlers->code, SIG_IGN);
86a5659e
JB
642 saved_handlers++;
643 }
644}
645
646restore_signal_handlers (saved_handlers)
647 struct save_signal *saved_handlers;
648{
649 while (saved_handlers->code)
650 {
651 signal (saved_handlers->code, saved_handlers->handler);
652 saved_handlers++;
653 }
654}
655\f
656#ifdef F_SETFL
657
658int old_fcntl_flags;
659
660init_sigio ()
661{
662#ifdef FASYNC
663 old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
664#endif
665 request_sigio ();
666}
667
668reset_sigio ()
669{
670 unrequest_sigio ();
671}
672
673#ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */
674
675request_sigio ()
676{
677#ifdef SIGWINCH
e065a56e 678 sigunblock (sigmask (SIGWINCH));
86a5659e
JB
679#endif
680 fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
681
682 interrupts_deferred = 0;
683}
684
685unrequest_sigio ()
686{
687#ifdef SIGWINCH
e065a56e 688 sigblock (sigmask (SIGWINCH));
86a5659e
JB
689#endif
690 fcntl (0, F_SETFL, old_fcntl_flags);
691 interrupts_deferred = 1;
692}
693
694#else /* no FASYNC */
695#ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
696
697request_sigio ()
698{
699 int on = 1;
700 ioctl (0, FIOASYNC, &on);
701 interrupts_deferred = 0;
702}
703
704unrequest_sigio ()
705{
706 int off = 0;
707
708 ioctl (0, FIOASYNC, &off);
709 interrupts_deferred = 1;
710}
711
712#else /* not FASYNC, not STRIDE */
713
714request_sigio ()
715{
716 croak ("request_sigio");
717}
718
719unrequest_sigio ()
720{
721 croak ("unrequest_sigio");
722}
723
724#endif /* STRIDE */
725#endif /* FASYNC */
726#endif /* F_SETFL */
727\f
68936329
JB
728/* Getting and setting emacs_tty structures. */
729
730/* Set *TC to the parameters associated with the terminal FD.
731 Return zero if all's well, or -1 if we ran into an error we
732 couldn't deal with. */
733int
734emacs_get_tty (fd, settings)
735 int fd;
736 struct emacs_tty *settings;
737{
738 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
739#ifdef HAVE_TCATTR
740 /* We have those nifty POSIX tcmumbleattr functions. */
741 if (tcgetattr (fd, &settings->main) < 0)
742 return -1;
743
744#else
745#ifdef HAVE_TERMIO
746 /* The SYSV-style interface? */
747 if (ioctl (fd, TCGETA, &settings->main) < 0)
748 return -1;
749
750#else
751#ifdef VMS
752 /* Vehemently Monstrous System? :-) */
753 if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
754 &settings->main.class, 12, 0, 0, 0, 0)
755 & 1))
756 return -1;
757
758#else
759 /* I give up - I hope you have the BSD ioctls. */
760 if (ioctl (fd, TIOCGETP, &settings->main) < 0)
761 return -1;
762
763#endif
764#endif
765#endif
766
767 /* Suivant - Do we have to get struct ltchars data? */
768#ifdef TIOCGLTC
769 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
770 return -1;
771#endif
772
773 /* How about a struct tchars and a wordful of lmode bits? */
774#ifdef TIOCGETC
775 if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
776 || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
777 return -1;
778#endif
779
780 /* We have survived the tempest. */
781 return 0;
782}
783
784
785/* Set the parameters of the tty on FD according to the contents of
786 *SETTINGS. If WAITP is non-zero, we wait for all queued output to
787 be written before making the change; otherwise, we forget any
788 queued input and make the change immediately.
789 Return 0 if all went well, and -1 if anything failed. */
790int
791emacs_set_tty (fd, settings, waitp)
792 int fd;
793 struct emacs_tty *settings;
794 int waitp;
795{
796 /* Set the primary parameters - baud rate, character size, etcetera. */
797#ifdef HAVE_TCATTR
798 /* We have those nifty POSIX tcmumbleattr functions.
799 William J. Smith <wjs@wiis.wang.com> writes:
800 "POSIX 1003.1 defines tcsetattr() to return success if it was
801 able to perform any of the requested actions, even if some
802 of the requested actions could not be performed.
803 We must read settings back to ensure tty setup properly.
804 AIX requires this to keep tty from hanging occasionally." */
805 for (;;)
806 if (tcsetattr (fd, waitp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
807 {
808 if (errno == EINTR)
809 continue;
810 else
811 return -1;
812 }
813 else
814 {
815 struct termios new;
816
817 /* Get the current settings, and see if they're what we asked for. */
818 tcgetattr (fd, &new);
819 if (memcmp (&new, &settings->main, sizeof (new)))
820 continue;
821 else
822 break;
823 }
824
825#else
826#ifdef HAVE_TERMIO
827 /* The SYSV-style interface? */
828 if (ioctl (fd, waitp ? TCSETAW : TCSETAF, &settings->main) < 0)
829 return -1;
830
831#else
832#ifdef VMS
833 /* Vehemently Monstrous System? :-) */
834 if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
835 &settings->main.class, 12, 0, 0, 0, 0)
836 & 1))
837 return -1;
838
839#else
840 /* I give up - I hope you have the BSD ioctls. */
841 if (ioctl (fd, (waitp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
842 return -1;
843
844#endif
845#endif
846#endif
847
848 /* Suivant - Do we have to get struct ltchars data? */
849#ifdef TIOCGLTC
850 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
851 return -1;
852#endif
853
854 /* How about a struct tchars and a wordful of lmode bits? */
855#ifdef TIOCGETC
856 if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
857 || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
858 return -1;
859#endif
860
861 /* We have survived the tempest. */
862 return 0;
863}
864
865\f
91bac16a
JB
866/* The initial tty mode bits */
867struct emacs_tty old_tty;
86a5659e
JB
868
869int term_initted; /* 1 if outer tty status has been recorded */
870
91bac16a
JB
871#ifdef BSD4_1
872/* BSD 4.1 needs to keep track of the lmode bits in order to start
873 sigio. */
874int lmode;
875#endif
876
86a5659e
JB
877#ifdef F_SETOWN
878int old_fcntl_owner;
879#endif /* F_SETOWN */
880
86a5659e
JB
881/* This may also be defined in stdio,
882 but if so, this does no harm,
883 and using the same name avoids wasting the other one's space. */
884
885#if defined (USG) || defined (DGUX)
886unsigned char _sobuf[BUFSIZ+8];
887#else
888char _sobuf[BUFSIZ];
889#endif
890
891#ifdef TIOCGLTC
892static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
893#endif
894#ifdef TIOCGETC
895 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
896#endif
897
898init_sys_modes ()
899{
91bac16a
JB
900 struct emacs_tty tty;
901
86a5659e
JB
902#ifdef VMS
903#if 0
904 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
905 extern int (*interrupt_signal) ();
906#endif
907#endif
908
909 if (noninteractive)
910 return;
911
912#ifdef VMS
913 if (!input_ef)
914 input_ef = get_kbd_event_flag ();
915 /* LIB$GET_EF (&input_ef); */
916 SYS$CLREF (input_ef);
917 waiting_for_ast = 0;
918 if (!timer_ef)
919 timer_ef = get_timer_event_flag ();
920 /* LIB$GET_EF (&timer_ef); */
921 SYS$CLREF (timer_ef);
210b2b4f 922#if 0
86a5659e
JB
923 if (!process_ef)
924 {
925 LIB$GET_EF (&process_ef);
926 SYS$CLREF (process_ef);
927 }
928 if (input_ef / 32 != process_ef / 32)
929 croak ("Input and process event flags in different clusters.");
210b2b4f 930#endif
86a5659e 931 if (input_ef / 32 != timer_ef / 32)
210b2b4f
JB
932 croak ("Input and timer event flags in different clusters.");
933#if 0
86a5659e
JB
934 input_eflist = ((unsigned) 1 << (input_ef % 32)) |
935 ((unsigned) 1 << (process_ef % 32));
210b2b4f 936#endif
86a5659e
JB
937 timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
938 ((unsigned) 1 << (timer_ef % 32));
86a5659e
JB
939#ifndef VMS4_4
940 sys_access_reinit ();
941#endif
86a5659e 942#endif /* not VMS */
91bac16a
JB
943
944 EMACS_GET_TTY (input_fd, &old_tty);
945
86a5659e
JB
946 if (!read_socket_hook && EQ (Vwindow_system, Qnil))
947 {
91bac16a 948 tty = old_tty;
86a5659e 949
31be8d24 950#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
91bac16a
JB
951 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
952 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
86a5659e 953#ifdef ISTRIP
91bac16a 954 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
86a5659e 955#endif
91bac16a
JB
956 tty.main.c_lflag &= ~ECHO; /* Disable echo */
957 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
e2b40c23
RS
958#ifdef IEXTEN
959 tty.main.c_iflag &= ~IEXTEN; /* Disable other editing characters. */
960#endif
91bac16a 961 tty.main.c_lflag |= ISIG; /* Enable signals */
86a5659e
JB
962 if (flow_control)
963 {
91bac16a 964 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
86a5659e 965#ifdef IXANY
91bac16a 966 tty.main.c_iflag &= ~IXANY;
86a5659e
JB
967#endif /* IXANY */
968 }
969 else
91bac16a
JB
970 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
971 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
972 on output */
973 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
86a5659e
JB
974#ifdef CS8
975 if (meta_key)
976 {
91bac16a
JB
977 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
978 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
86a5659e
JB
979 }
980#endif
91bac16a 981 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
86a5659e
JB
982 /* Set up C-g for both SIGQUIT and SIGINT.
983 We don't know which we will get, but we handle both alike
984 so which one it really gives us does not matter. */
91bac16a
JB
985 tty.main.c_cc[VQUIT] = quit_char;
986 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
987 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
86a5659e 988#ifdef VSWTCH
e2b40c23 989 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
91bac16a 990 of C-z */
86a5659e
JB
991#endif /* VSWTCH */
992#if defined (mips) || defined (HAVE_TCATTR)
86a5659e 993#ifdef VSUSP
e2b40c23 994 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
86a5659e
JB
995#endif /* VSUSP */
996#ifdef V_DSUSP
e2b40c23 997 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
86a5659e 998#endif /* V_DSUSP */
e2b40c23
RS
999#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
1000 tty.main.c_cc[VDSUSP] = CDISABLE;
1001#endif /* VDSUSP */
86a5659e
JB
1002#endif /* mips or HAVE_TCATTR */
1003#ifdef AIX
1004#ifndef IBMR2AIX
1005 /* AIX enhanced edit loses NULs, so disable it */
91bac16a
JB
1006 tty.main.c_line = 0;
1007 tty.main.c_iflag &= ~ASCEDIT;
86a5659e 1008#else
91bac16a
JB
1009 tty.main.c_cc[VSTRT] = 255;
1010 tty.main.c_cc[VSTOP] = 255;
1011 tty.main.c_cc[VSUSP] = 255;
1012 tty.main.c_cc[VDSUSP] = 255;
86a5659e
JB
1013#endif /* IBMR2AIX */
1014 /* Also, PTY overloads NUL and BREAK.
1015 don't ignore break, but don't signal either, so it looks like NUL.
1016 This really serves a purpose only if running in an XTERM window
1017 or via TELNET or the like, but does no harm elsewhere. */
91bac16a
JB
1018 tty.main.c_iflag &= ~IGNBRK;
1019 tty.main.c_iflag &= ~BRKINT;
86a5659e
JB
1020#endif
1021#else /* if not HAVE_TERMIO */
1022#ifdef VMS
91bac16a 1023 tty.main.tt_char |= TT$M_NOECHO;
86a5659e 1024 if (meta_key)
986ffb24 1025 tty.main.tt_char |= TT$M_EIGHTBIT;
86a5659e 1026 if (flow_control)
91bac16a 1027 tty.main.tt_char |= TT$M_TTSYNC;
86a5659e 1028 else
91bac16a
JB
1029 tty.main.tt_char &= ~TT$M_TTSYNC;
1030 tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
86a5659e 1031#else /* not VMS (BSD, that is) */
91bac16a 1032 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
86a5659e 1033 if (meta_key)
91bac16a
JB
1034 tty.main.sg_flags |= ANYP;
1035 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
86a5659e
JB
1036#endif /* not VMS (BSD, that is) */
1037#endif /* not HAVE_TERMIO */
1038
91bac16a
JB
1039 /* If going to use CBREAK mode, we must request C-g to interrupt
1040 and turn off start and stop chars, etc. If not going to use
1041 CBREAK mode, do this anyway so as to turn off local flow
1042 control for user coming over network on 4.2; in this case,
1043 only t_stopc and t_startc really matter. */
1044#ifndef HAVE_TERMIO
1045#ifdef TIOCGETC
1046 /* Note: if not using CBREAK mode, it makes no difference how we
1047 set this */
1048 tty.tchars = new_tchars;
1049 tty.tchars.t_intrc = quit_char;
1050 if (flow_control)
1051 {
1052 tty.tchars.t_startc = '\021';
1053 tty.tchars.t_stopc = '\023';
1054 }
1055
1056/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
1057#ifndef LPASS8
1058#define LPASS8 0
86a5659e 1059#endif
91bac16a
JB
1060
1061#ifdef BSD4_1
1062#define LNOFLSH 0100000
1063#endif
1064
1065 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
1066
1067#ifdef BSD4_1
1068 lmode = tty.lmode;
1069#endif
1070
1071#endif /* TIOCGETC */
1072#endif /* not HAVE_TERMIO */
1073
1074#ifdef TIOCGLTC
1075 tty.ltchars = new_ltchars;
1076#endif /* TIOCGLTC */
1077
1078 EMACS_SET_TTY (input_fd, &tty, 0);
86a5659e
JB
1079
1080 /* This code added to insure that, if flow-control is not to be used,
0137dbf7 1081 we have an unlocked terminal at the start. */
91bac16a 1082
86a5659e
JB
1083#ifdef TCXONC
1084 if (!flow_control) ioctl (0, TCXONC, 1);
1085#endif
1086#ifndef APOLLO
1087#ifdef TIOCSTART
1088 if (!flow_control) ioctl (0, TIOCSTART, 0);
1089#endif
1090#endif
1091
1092#ifdef AIX
1093 hft_init ();
1094#ifdef IBMR2AIX
1095 {
1096 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1097 to be only LF. This is the way that is done. */
1098 struct termio tty;
1099
1100 if (ioctl (1, HFTGETID, &tty) != -1)
1101 write (1, "\033[20l", 5);
1102 }
1103#endif
1104#endif
1105
86a5659e
JB
1106#ifdef VMS
1107/* Appears to do nothing when in PASTHRU mode.
91bac16a 1108 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
86a5659e
JB
1109 interrupt_signal, oob_chars, 0, 0, 0, 0);
1110*/
1111 queue_kbd_input (0);
1112#endif /* VMS */
1113 }
1114
1115#ifdef F_SETFL
1116#ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */
1117 if (interrupt_input)
1118 {
1119 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
1120 fcntl (0, F_SETOWN, getpid ());
1121 init_sigio ();
1122 }
1123#endif /* F_GETOWN */
1124#endif /* F_SETFL */
1125
1126#ifdef BSD4_1
1127 if (interrupt_input)
1128 init_sigio ();
1129#endif
1130
1131#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1132#undef _IOFBF
1133#endif
1134#ifdef _IOFBF
1135 /* This symbol is defined on recent USG systems.
1136 Someone says without this call USG won't really buffer the file
1137 even with a call to setbuf. */
1138 setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
1139#else
1140 setbuf (stdout, _sobuf);
1141#endif
1142 set_terminal_modes ();
1143 if (term_initted && no_redraw_on_reenter)
1144 {
1145 if (display_completed)
1146 direct_output_forward_char (0);
1147 }
1148 else
1149 {
0137dbf7
JB
1150 frame_garbaged = 1;
1151#ifdef MULTI_FRAME
1152 if (FRAMEP (Vterminal_frame))
1153 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
86a5659e
JB
1154#endif
1155 }
91bac16a 1156
86a5659e
JB
1157 term_initted = 1;
1158}
1159
1160/* Return nonzero if safe to use tabs in output.
1161 At the time this is called, init_sys_modes has not been done yet. */
1162
1163tabs_safe_p ()
1164{
91bac16a
JB
1165 struct emacs_tty tty;
1166
1167 EMACS_GET_TTY (input_fd, &tty);
1168 return EMACS_TTY_TABS_OK (&tty);
86a5659e
JB
1169}
1170
1171/* Get terminal size from system.
1172 Store number of lines into *heightp and width into *widthp.
1173 If zero or a negative number is stored, the value is not valid. */
1174
0137dbf7 1175get_frame_size (widthp, heightp)
86a5659e
JB
1176 int *widthp, *heightp;
1177{
86a5659e 1178
86a5659e 1179#ifdef TIOCGWINSZ
91bac16a
JB
1180
1181 /* BSD-style. */
86a5659e 1182 struct winsize size;
91bac16a
JB
1183
1184 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1185 *widthp = *heightp = 0;
1186 else
1187 {
1188 *widthp = size.ws_col;
1189 *heightp = size.ws_row;
1190 }
1191
1192#else
1193#ifdef TIOCGSIZE
1194
1195 /* SunOS - style. */
1196 struct ttysize size;
1197
1198 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1199 *widthp = *heightp = 0;
1200 else
1201 {
1202 *widthp = size.ts_cols;
1203 *heightp = size.ts_lines;
1204 }
1205
1206#else
86a5659e 1207#ifdef VMS
91bac16a
JB
1208
1209 struct sensemode tty;
1210
1211 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
86a5659e
JB
1212 &tty.class, 12, 0, 0, 0, 0);
1213 *widthp = tty.scr_wid;
1214 *heightp = tty.scr_len;
91bac16a 1215
86a5659e 1216#else /* system doesn't know size */
91bac16a 1217
86a5659e
JB
1218 *widthp = 0;
1219 *heightp = 0;
91bac16a
JB
1220
1221#endif /* not VMS */
1222#endif /* not SunOS-style */
1223#endif /* not BSD-style */
86a5659e 1224}
91bac16a 1225
86a5659e 1226\f
91bac16a 1227/* Prepare the terminal for exiting Emacs; move the cursor to the
0137dbf7 1228 bottom of the frame, turn off interrupt-driven I/O, etc. */
86a5659e
JB
1229reset_sys_modes ()
1230{
1231 if (noninteractive)
1232 {
1233 fflush (stdout);
1234 return;
1235 }
1236 if (!term_initted)
1237 return;
1238 if (read_socket_hook || !EQ (Vwindow_system, Qnil))
1239 return;
0137dbf7
JB
1240 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
1241 clear_end_of_line (FRAME_WIDTH (selected_frame));
86a5659e 1242 /* clear_end_of_line may move the cursor */
0137dbf7 1243 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
86a5659e
JB
1244#ifdef IBMR2AIX
1245 {
1246 /* HFT devices normally use ^J as a LF/CR. We forced it to
1247 do the LF only. Now, we need to reset it. */
1248 struct termio tty;
1249
1250 if (ioctl (1, HFTGETID, &tty) != -1)
1251 write (1, "\033[20h", 5);
1252 }
1253#endif
1254
1255 reset_terminal_modes ();
1256 fflush (stdout);
1257#ifdef BSD
1258#ifndef BSD4_1
1259 /* Avoid possible loss of output when changing terminal modes. */
1260 fsync (fileno (stdout));
1261#endif
1262#endif
91bac16a 1263
86a5659e
JB
1264#ifdef F_SETFL
1265#ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */
1266 if (interrupt_input)
1267 {
1268 reset_sigio ();
1269 fcntl (0, F_SETOWN, old_fcntl_owner);
1270 }
1271#endif /* F_SETOWN */
1272#endif /* F_SETFL */
1273#ifdef BSD4_1
1274 if (interrupt_input)
1275 reset_sigio ();
1276#endif /* BSD4_1 */
91bac16a 1277
1334b321 1278 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
91bac16a 1279 ;
86a5659e
JB
1280
1281#ifdef AIX
1282 hft_reset ();
1283#endif
1284}
1285\f
1286#ifdef HAVE_PTYS
1287
1288/* Set up the proper status flags for use of a pty. */
1289
1290setup_pty (fd)
1291 int fd;
1292{
1293 /* I'm told that TOICREMOTE does not mean control chars
1294 "can't be sent" but rather that they don't have
1295 input-editing or signaling effects.
1296 That should be good, because we have other ways
1297 to do those things in Emacs.
1298 However, telnet mode seems not to work on 4.2.
1299 So TIOCREMOTE is turned off now. */
1300
1301 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1302 will hang. In particular, the "timeout" feature (which
1303 causes a read to return if there is no data available)
1304 does this. Also it is known that telnet mode will hang
1305 in such a way that Emacs must be stopped (perhaps this
1306 is the same problem).
1307
1308 If TIOCREMOTE is turned off, then there is a bug in
1309 hp-ux which sometimes loses data. Apparently the
1310 code which blocks the master process when the internal
1311 buffer fills up does not work. Other than this,
1312 though, everything else seems to work fine.
1313
1314 Since the latter lossage is more benign, we may as well
1315 lose that way. -- cph */
1316#ifdef FIONBIO
1317#ifdef SYSV_PTYS
1318 {
1319 int on = 1;
1320 ioctl (fd, FIONBIO, &on);
1321 }
1322#endif
1323#endif
1324#ifdef IBMRTAIX
1325 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1326 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1327 /* cause EMACS not to die when it should, i.e., when its own controlling */
1328 /* tty goes away. I've complained to the AIX developers, and they may */
1329 /* change this behavior, but I'm not going to hold my breath. */
1330 signal (SIGHUP, SIG_IGN);
1331#endif
1332}
1333#endif /* HAVE_PTYS */
1334\f
1335#ifdef VMS
1336
1337/* Assigning an input channel is done at the start of Emacs execution.
1338 This is called each time Emacs is resumed, also, but does nothing
1339 because input_chain is no longer zero. */
1340
1341init_vms_input ()
1342{
1343 int status;
1344
91bac16a 1345 if (input_fd == 0)
86a5659e 1346 {
91bac16a 1347 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
86a5659e
JB
1348 if (! (status & 1))
1349 LIB$STOP (status);
1350 }
1351}
1352
1353/* Deassigning the input channel is done before exiting. */
1354
1355stop_vms_input ()
1356{
91bac16a 1357 return SYS$DASSGN (input_fd);
86a5659e
JB
1358}
1359
1360short input_buffer;
1361
1362/* Request reading one character into the keyboard buffer.
1363 This is done as soon as the buffer becomes empty. */
1364
1365queue_kbd_input ()
1366{
1367 int status;
210b2b4f
JB
1368 extern kbd_input_ast ();
1369
86a5659e
JB
1370 waiting_for_ast = 0;
1371 stop_input = 0;
91bac16a 1372 status = SYS$QIO (0, input_fd, IO$_READVBLK,
86a5659e
JB
1373 &input_iosb, kbd_input_ast, 1,
1374 &input_buffer, 1, 0, terminator_mask, 0, 0);
1375}
1376
1377int input_count;
1378
1379/* Ast routine that is called when keyboard input comes in
1380 in accord with the SYS$QIO above. */
1381
1382kbd_input_ast ()
1383{
1384 register int c = -1;
1385 int old_errno = errno;
ffd56f97 1386 extern EMACS_TIME *input_available_clear_time;
86a5659e
JB
1387
1388 if (waiting_for_ast)
1389 SYS$SETEF (input_ef);
1390 waiting_for_ast = 0;
1391 input_count++;
1392#ifdef ASTDEBUG
1393 if (input_count == 25)
1394 exit (1);
1395 printf ("Ast # %d,", input_count);
1396 printf (" iosb = %x, %x, %x, %x",
1397 input_iosb.offset, input_iosb.status, input_iosb.termlen,
1398 input_iosb.term);
1399#endif
1400 if (input_iosb.offset)
1401 {
1402 c = input_buffer;
1403#ifdef ASTDEBUG
1404 printf (", char = 0%o", c);
1405#endif
1406 }
1407#ifdef ASTDEBUG
1408 printf ("\n");
1409 fflush (stdout);
1410 sleep (1);
1411#endif
1412 if (! stop_input)
1413 queue_kbd_input ();
1414 if (c >= 0)
1415 {
1416 struct input_event e;
1417 e.kind = ascii_keystroke;
210b2b4f
JB
1418 XSET (e.code, Lisp_Int, c);
1419#ifdef MULTI_FRAME
1420 XSET(e.frame_or_window, Lisp_Frame, selected_frame);
1421#else
1422 e.frame_or_window = Qnil;
1423#endif
86a5659e
JB
1424 kbd_buffer_store_event (&e);
1425 }
ffd56f97
JB
1426 if (input_available_clear_time)
1427 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
86a5659e
JB
1428 errno = old_errno;
1429}
1430
1431/* Wait until there is something in kbd_buffer. */
1432
1433wait_for_kbd_input ()
1434{
1435 extern int have_process_input, process_exited;
1436
1437 /* If already something, avoid doing system calls. */
1438 if (detect_input_pending ())
1439 {
1440 return;
1441 }
1442 /* Clear a flag, and tell ast routine above to set it. */
1443 SYS$CLREF (input_ef);
1444 waiting_for_ast = 1;
1445 /* Check for timing error: ast happened while we were doing that. */
1446 if (!detect_input_pending ())
1447 {
1448 /* No timing error: wait for flag to be set. */
1449 set_waiting_for_input (0);
1450 SYS$WFLOR (input_ef, input_eflist);
1451 clear_waiting_for_input (0);
1452 if (!detect_input_pending ())
1453 /* Check for subprocess input availability */
1454 {
1455 int dsp = have_process_input || process_exited;
1456
1457 SYS$CLREF (process_ef);
1458 if (have_process_input)
1459 process_command_input ();
1460 if (process_exited)
1461 process_exit ();
1462 if (dsp)
1463 {
1464 update_mode_lines++;
1465 redisplay_preserve_echo_area ();
1466 }
1467 }
1468 }
1469 waiting_for_ast = 0;
1470}
1471
1472/* Get rid of any pending QIO, when we are about to suspend
1473 or when we want to throw away pending input.
1474 We wait for a positive sign that the AST routine has run
1475 and therefore there is no I/O request queued when we return.
1476 SYS$SETAST is used to avoid a timing error. */
1477
1478end_kbd_input ()
1479{
1480#ifdef ASTDEBUG
1481 printf ("At end_kbd_input.\n");
1482 fflush (stdout);
1483 sleep (1);
1484#endif
1485 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
1486 {
91bac16a 1487 SYS$CANCEL (input_fd);
86a5659e
JB
1488 return;
1489 }
1490
1491 SYS$SETAST (0);
1492 /* Clear a flag, and tell ast routine above to set it. */
1493 SYS$CLREF (input_ef);
1494 waiting_for_ast = 1;
1495 stop_input = 1;
91bac16a 1496 SYS$CANCEL (input_fd);
86a5659e
JB
1497 SYS$SETAST (1);
1498 SYS$WAITFR (input_ef);
1499 waiting_for_ast = 0;
1500}
1501
1502/* Wait for either input available or time interval expiry. */
1503
1504input_wait_timeout (timeval)
1505 int timeval; /* Time to wait, in seconds */
1506{
1507 int time [2];
1508 static int zero = 0;
1509 static int large = -10000000;
1510
1511 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1512
1513 /* If already something, avoid doing system calls. */
1514 if (detect_input_pending ())
1515 {
1516 return;
1517 }
1518 /* Clear a flag, and tell ast routine above to set it. */
1519 SYS$CLREF (input_ef);
1520 waiting_for_ast = 1;
1521 /* Check for timing error: ast happened while we were doing that. */
1522 if (!detect_input_pending ())
1523 {
1524 /* No timing error: wait for flag to be set. */
1525 SYS$CANTIM (1, 0);
1526 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1527 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
1528 }
1529 waiting_for_ast = 0;
1530}
1531
1532/* The standard `sleep' routine works some other way
1533 and it stops working if you have ever quit out of it.
1534 This one continues to work. */
1535
1536sys_sleep (timeval)
1537 int timeval;
1538{
1539 int time [2];
1540 static int zero = 0;
1541 static int large = -10000000;
1542
1543 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1544
1545 SYS$CANTIM (1, 0);
1546 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1547 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
1548}
1549
1550init_sigio ()
1551{
1552 request_sigio ();
1553}
1554
1555reset_sigio ()
1556{
1557 unrequest_sigio ();
1558}
1559
1560request_sigio ()
1561{
1562 croak ("request sigio");
1563}
1564
1565unrequest_sigio ()
1566{
1567 croak ("unrequest sigio");
1568}
1569
1570#endif /* VMS */
1571\f
1572/* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1573#ifndef CANNOT_DUMP
1574#define NEED_STARTS
1575#endif
1576
1577#ifndef SYSTEM_MALLOC
1578#ifndef NEED_STARTS
1579#define NEED_STARTS
1580#endif
1581#endif
1582
1583#ifdef NEED_STARTS
1584/* Some systems that cannot dump also cannot implement these. */
1585
1586/*
1587 * Return the address of the start of the text segment prior to
1588 * doing an unexec. After unexec the return value is undefined.
1589 * See crt0.c for further explanation and _start.
1590 *
1591 */
1592
1593#ifndef CANNOT_UNEXEC
1594char *
1595start_of_text ()
1596{
1597#ifdef TEXT_START
1598 return ((char *) TEXT_START);
1599#else
1600#ifdef GOULD
1601 extern csrt ();
1602 return ((char *) csrt);
1603#else /* not GOULD */
1604 extern int _start ();
1605 return ((char *) _start);
1606#endif /* GOULD */
1607#endif /* TEXT_START */
1608}
1609#endif /* not CANNOT_UNEXEC */
1610
1611/*
1612 * Return the address of the start of the data segment prior to
1613 * doing an unexec. After unexec the return value is undefined.
1614 * See crt0.c for further information and definition of data_start.
1615 *
1616 * Apparently, on BSD systems this is etext at startup. On
1617 * USG systems (swapping) this is highly mmu dependent and
1618 * is also dependent on whether or not the program is running
1619 * with shared text. Generally there is a (possibly large)
1620 * gap between end of text and start of data with shared text.
1621 *
1622 * On Uniplus+ systems with shared text, data starts at a
1623 * fixed address. Each port (from a given oem) is generally
1624 * different, and the specific value of the start of data can
1625 * be obtained via the UniPlus+ specific "uvar" system call,
1626 * however the method outlined in crt0.c seems to be more portable.
1627 *
1628 * Probably what will have to happen when a USG unexec is available,
1629 * at least on UniPlus, is temacs will have to be made unshared so
1630 * that text and data are contiguous. Then once loadup is complete,
1631 * unexec will produce a shared executable where the data can be
1632 * at the normal shared text boundry and the startofdata variable
1633 * will be patched by unexec to the correct value.
1634 *
1635 */
1636
1637char *
1638start_of_data ()
1639{
1640#ifdef DATA_START
1641 return ((char *) DATA_START);
6c65530f
JB
1642#else
1643#ifdef ORDINARY_LINK
1644 /*
1645 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
1646 * data_start isn't defined. We take the address of environ, which
1647 * is known to live at or near the start of the system crt0.c, and
1648 * we don't sweat the handful of bytes that might lose.
1649 */
1650 extern char **environ;
1651
1652 return((char *) &environ);
86a5659e
JB
1653#else
1654 extern int data_start;
1655 return ((char *) &data_start);
6c65530f
JB
1656#endif /* ORDINARY_LINK */
1657#endif /* DATA_START */
86a5659e
JB
1658}
1659#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1660
1661#ifndef CANNOT_DUMP
1662/* Some systems that cannot dump also cannot implement these. */
1663
1664/*
1665 * Return the address of the end of the text segment prior to
1666 * doing an unexec. After unexec the return value is undefined.
1667 */
1668
1669char *
1670end_of_text ()
1671{
1672#ifdef TEXT_END
1673 return ((char *) TEXT_END);
1674#else
1675 extern int etext;
1676 return ((char *) &etext);
1677#endif
1678}
1679
1680/*
1681 * Return the address of the end of the data segment prior to
1682 * doing an unexec. After unexec the return value is undefined.
1683 */
1684
1685char *
1686end_of_data ()
1687{
1688#ifdef DATA_END
1689 return ((char *) DATA_END);
1690#else
1691 extern int edata;
1692 return ((char *) &edata);
1693#endif
1694}
1695
1696#endif /* not CANNOT_DUMP */
1697\f
1698/* Get_system_name returns as its value
1699 a string for the Lisp function system-name to return. */
1700
1701#ifdef BSD4_1
1702#include <whoami.h>
1703#endif
1704
e36ba278
RS
1705/* Can't have this within the function since `static' is #defined to
1706 nothing for some USG systems. */
86a5659e 1707#ifdef USG
e36ba278
RS
1708#ifdef HAVE_GETHOSTNAME
1709static char get_system_name_name[256];
1710#else /* not HAVE_GETHOSTNAME */
86a5659e 1711static struct utsname get_system_name_name;
e36ba278
RS
1712#endif /* not HAVE_GETHOSTNAME */
1713#endif /* USG */
86a5659e
JB
1714
1715char *
1716get_system_name ()
1717{
1718#ifdef USG
e36ba278
RS
1719#ifdef HAVE_GETHOSTNAME
1720 gethostname (get_system_name_name, sizeof (get_system_name_name));
1721 return get_system_name_name;
1722#else /* not HAVE_GETHOSTNAME */
86a5659e
JB
1723 uname (&get_system_name_name);
1724 return (get_system_name_name.nodename);
e36ba278 1725#endif /* not HAVE_GETHOSTNAME */
86a5659e
JB
1726#else /* Not USG */
1727#ifdef BSD4_1
1728 return sysname;
1729#else /* not USG, not 4.1 */
1730 static char system_name_saved[32];
1731#ifdef VMS
1732 char *sp;
1733 if ((sp = egetenv ("SYS$NODE")) == 0)
1734 sp = "vax-vms";
1735 else
1736 {
1737 char *end;
1738
1739 if ((end = index (sp, ':')) != 0)
1740 *end = '\0';
1741 }
1742 strcpy (system_name_saved, sp);
1743#else /* not VMS */
1744 gethostname (system_name_saved, sizeof (system_name_saved));
1745#endif /* not VMS */
1746 return system_name_saved;
1747#endif /* not USG, not 4.1 */
1748#endif /* not USG */
1749}
210b2b4f
JB
1750
1751#ifdef VMS
1752#ifndef HAVE_GETHOSTNAME
1753void gethostname(buf, len)
1754 char *buf;
1755 int len;
1756{
1757 char *s;
1758 s = getenv ("SYS$NODE");
1759 if (s == NULL)
1760 buf[0] = '\0';
1761 else {
1762 strncpy (buf, s, len - 2);
1763 buf[len - 1] = '\0';
1764 } /* else */
1765} /* static void gethostname */
1766#endif /* ! HAVE_GETHOSTNAME */
1767#endif /* VMS */
1768
86a5659e
JB
1769\f
1770#ifndef VMS
1771#ifndef HAVE_SELECT
1772
1773#ifdef HAVE_X_WINDOWS
1774/* Cause explanatory error message at compile time,
1775 since the select emulation is not good enough for X. */
1776int *x = &x_windows_lose_if_no_select_system_call;
1777#endif
1778
1779/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1780 * Only checks read descriptors.
1781 */
1782/* How long to wait between checking fds in select */
1783#define SELECT_PAUSE 1
1784int select_alarmed;
1785
1786/* For longjmp'ing back to read_input_waiting. */
1787
1788jmp_buf read_alarm_throw;
1789
1790/* Nonzero if the alarm signal should throw back to read_input_waiting.
1791 The read_socket_hook function sets this to 1 while it is waiting. */
1792
1793int read_alarm_should_throw;
1794
1795SIGTYPE
1796select_alarm ()
1797{
1798 select_alarmed = 1;
1799#ifdef BSD4_1
1800 sigrelse (SIGALRM);
1801#else /* not BSD4_1 */
1802 signal (SIGALRM, SIG_IGN);
1803#endif /* not BSD4_1 */
1804 if (read_alarm_should_throw)
1805 longjmp (read_alarm_throw, 1);
1806}
1807
1808/* Only rfds are checked. */
1809int
1810select (nfds, rfds, wfds, efds, timeout)
1811 int nfds;
1812 int *rfds, *wfds, *efds, *timeout;
1813{
1814 int ravail = 0, orfds = 0, old_alarm;
1815 int timeoutval = timeout ? *timeout : 100000;
1816 int *local_timeout = &timeoutval;
1817 extern int proc_buffered_char[];
1818#ifndef subprocesses
1819 int process_tick = 0, update_tick = 0;
1820#else
1821 extern int process_tick, update_tick;
1822#endif
1823 SIGTYPE (*old_trap) ();
1824 unsigned char buf;
1825
1826 if (rfds)
1827 {
1828 orfds = *rfds;
1829 *rfds = 0;
1830 }
1831 if (wfds)
1832 *wfds = 0;
1833 if (efds)
1834 *efds = 0;
1835
1836 /* If we are looking only for the terminal, with no timeout,
1837 just read it and wait -- that's more efficient. */
1838 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
1839 {
1840 if (! detect_input_pending ())
1841 read_input_waiting ();
1842 *rfds = 1;
1843 return 1;
1844 }
1845
1846 /* Once a second, till the timer expires, check all the flagged read
1847 * descriptors to see if any input is available. If there is some then
1848 * set the corresponding bit in the return copy of rfds.
1849 */
1850 while (1)
1851 {
1852 register int to_check, bit, fd;
1853
1854 if (rfds)
1855 {
1856 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
1857 {
1858 if (orfds & bit)
1859 {
1860 int avail = 0, status = 0;
1861
1862 if (bit == 1)
1863 avail = detect_input_pending (); /* Special keyboard handler */
1864 else
1865 {
1866#ifdef FIONREAD
1867 status = ioctl (fd, FIONREAD, &avail);
1868#else /* no FIONREAD */
1869 /* Hoping it will return -1 if nothing available
1870 or 0 if all 0 chars requested are read. */
1871 if (proc_buffered_char[fd] >= 0)
1872 avail = 1;
1873 else
1874 {
1875 avail = read (fd, &buf, 1);
1876 if (avail > 0)
1877 proc_buffered_char[fd] = buf;
1878 }
1879#endif /* no FIONREAD */
1880 }
1881 if (status >= 0 && avail > 0)
1882 {
1883 (*rfds) |= bit;
1884 ravail++;
1885 }
1886 }
1887 }
1888 }
1889 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1890 break;
1891 old_alarm = alarm (0);
34567704 1892 old_trap = signal (SIGALRM, select_alarm);
86a5659e
JB
1893 select_alarmed = 0;
1894 alarm (SELECT_PAUSE);
1895 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1896 while (select_alarmed == 0 && *local_timeout != 0
1897 && process_tick == update_tick)
1898 {
1899 /* If we are interested in terminal input,
1900 wait by reading the terminal.
1901 That makes instant wakeup for terminal input at least. */
1902 if (orfds & 1)
1903 {
1904 read_input_waiting ();
1905 if (detect_input_pending ())
1906 select_alarmed = 1;
1907 }
1908 else
1909 pause ();
1910 }
1911 (*local_timeout) -= SELECT_PAUSE;
1912 /* Reset the old alarm if there was one */
1913 alarm (0);
1914 signal (SIGALRM, old_trap);
1915 if (old_alarm != 0)
1916 {
1917 /* Reset or forge an interrupt for the original handler. */
1918 old_alarm -= SELECT_PAUSE;
1919 if (old_alarm <= 0)
1920 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
1921 else
1922 alarm (old_alarm);
1923 }
1924 if (*local_timeout == 0) /* Stop on timer being cleared */
1925 break;
1926 }
1927 return ravail;
1928}
1929
1930/* Read keyboard input into the standard buffer,
1931 waiting for at least one character. */
1932
1933/* Make all keyboard buffers much bigger when using X windows. */
1934#ifdef HAVE_X_WINDOWS
1935#define BUFFER_SIZE_FACTOR 16
1936#else
1937#define BUFFER_SIZE_FACTOR 1
1938#endif
1939
1940read_input_waiting ()
1941{
1942 char buf[256 * BUFFER_SIZE_FACTOR];
1943 struct input_event e;
34567704
JB
1944 int nread, i;
1945 extern int quit_char;
86a5659e
JB
1946
1947 if (read_socket_hook)
1948 {
1949 read_alarm_should_throw = 0;
1950 if (! setjmp (read_alarm_throw))
1951 nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
1952 else
1953 nread = -1;
1954 }
1955 else
1956 nread = read (fileno (stdin), buf, 1);
1957
1958 /* Scan the chars for C-g and store them in kbd_buffer. */
1959 e.kind = ascii_keystroke;
6c65530f 1960 e.frame_or_window = selected_frame;
57ef1664 1961 e.modifiers = 0;
86a5659e
JB
1962 for (i = 0; i < nread; i++)
1963 {
1964 XSET (e.code, Lisp_Int, buf[i]);
1965 kbd_buffer_store_event (&e);
1966 /* Don't look at input that follows a C-g too closely.
1967 This reduces lossage due to autorepeat on C-g. */
34567704 1968 if (buf[i] == quit_char)
86a5659e
JB
1969 break;
1970 }
1971}
1972
1973#endif /* not HAVE_SELECT */
1974#endif /* not VMS */
1975\f
1976#ifdef BSD4_1
86a5659e
JB
1977/*
1978 * Partially emulate 4.2 open call.
1979 * open is defined as this in 4.1.
1980 *
1981 * - added by Michael Bloom @ Citicorp/TTI
1982 *
1983 */
1984
1985int
1986sys_open (path, oflag, mode)
1987 char *path;
1988 int oflag, mode;
1989{
1990 if (oflag & O_CREAT)
1991 return creat (path, mode);
1992 else
1993 return open (path, oflag);
1994}
1995
1996init_sigio ()
1997{
1998 if (noninteractive)
1999 return;
2000 lmode = LINTRUP | lmode;
2001 ioctl (0, TIOCLSET, &lmode);
2002}
2003
2004reset_sigio ()
2005{
2006 if (noninteractive)
2007 return;
2008 lmode = ~LINTRUP & lmode;
2009 ioctl (0, TIOCLSET, &lmode);
2010}
2011
2012request_sigio ()
2013{
2014 sigrelse (SIGTINT);
2015
2016 interrupts_deferred = 0;
2017}
2018
2019unrequest_sigio ()
2020{
2021 sighold (SIGTINT);
2022
2023 interrupts_deferred = 1;
2024}
2025
2026/* still inside #ifdef BSD4_1 */
2027#ifdef subprocesses
2028
2029int sigheld; /* Mask of held signals */
2030
2031sigholdx (signum)
2032 int signum;
2033{
2034 sigheld |= sigbit (signum);
2035 sighold (signum);
2036}
2037
2038sigisheld (signum)
2039 int signum;
2040{
2041 sigheld |= sigbit (signum);
2042}
2043
2044sigunhold (signum)
2045 int signum;
2046{
2047 sigheld &= ~sigbit (signum);
2048 sigrelse (signum);
2049}
2050
2051sigfree () /* Free all held signals */
2052{
2053 int i;
2054 for (i = 0; i < NSIG; i++)
2055 if (sigheld & sigbit (i))
2056 sigrelse (i);
2057 sigheld = 0;
2058}
2059
2060sigbit (i)
2061{
2062 return 1 << (i - 1);
2063}
2064#endif /* subprocesses */
2065#endif /* BSD4_1 */
2066\f
2067/* POSIX signals support - DJB */
2068/* Anyone with POSIX signals should have ANSI C declarations */
2069
2070#ifdef POSIX_SIGNALS
2071
2072sigset_t old_mask, empty_mask, full_mask, temp_mask;
2073static struct sigaction new_action, old_action;
2074
2075init_signals ()
2076{
00eaaa32
JB
2077 sigemptyset (&empty_mask);
2078 sigfillset (&full_mask);
86a5659e
JB
2079}
2080
86a5659e
JB
2081signal_handler_t
2082sys_signal (int signal_number, signal_handler_t action)
2083{
2084#ifdef DGUX
2085 /* This gets us restartable system calls for efficiency.
2086 The "else" code will works as well. */
2087 return (berk_signal (signal_number, action));
2088#else
2089 sigemptyset (&new_action.sa_mask);
2090 new_action.sa_handler = action;
2091 new_action.sa_flags = NULL;
d32b2f3c 2092 sigaction (signal_number, &new_action, &old_action);
86a5659e
JB
2093 return (old_action.sa_handler);
2094#endif /* DGUX */
2095}
2096
e065a56e
JB
2097#ifndef __GNUC__
2098/* If we're compiling with GCC, we don't need this function, since it
2099 can be written as a macro. */
2100sigset_t
2101sys_sigmask (int sig)
2102{
2103 sigset_t mask;
2104 sigemptyset (&mask);
2105 sigaddset (&mask, sig);
2106 return mask;
2107}
2108#endif
2109
86a5659e
JB
2110int
2111sys_sigpause (sigset_t new_mask)
2112{
2113 /* pause emulating berk sigpause... */
2114 sigsuspend (&new_mask);
2115 return (EINTR);
2116}
2117
2118/* I'd like to have these guys return pointers to the mask storage in here,
2119 but there'd be trouble if the code was saving multiple masks. I'll be
2120 safe and pass the structure. It normally won't be more than 2 bytes
2121 anyhow. - DJB */
2122
2123sigset_t
2124sys_sigblock (sigset_t new_mask)
2125{
2126 sigset_t old_mask;
2127 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2128 return (old_mask);
2129}
2130
2131sigset_t
2132sys_sigunblock (sigset_t new_mask)
2133{
2134 sigset_t old_mask;
2135 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2136 return (old_mask);
2137}
2138
2139sigset_t
2140sys_sigsetmask (sigset_t new_mask)
2141{
2142 sigset_t old_mask;
2143 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2144 return (old_mask);
2145}
2146
2147#endif /* POSIX_SIGNALS */
2148\f
2149#ifndef BSTRING
2150
2151void
2152bzero (b, length)
2153 register char *b;
2154 register int length;
2155{
2156#ifdef VMS
2157 short zero = 0;
2158 long max_str = 65535;
2159
2160 while (length > max_str) {
2161 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2162 length -= max_str;
2163 b += max_str;
2164 }
2165 max_str = length;
2166 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2167#else
2168 while (length-- > 0)
2169 *b++ = 0;
2170#endif /* not VMS */
2171}
2172
2173/* Saying `void' requires a declaration, above, where bcopy is used
2174 and that declaration causes pain for systems where bcopy is a macro. */
2175bcopy (b1, b2, length)
2176 register char *b1;
2177 register char *b2;
2178 register int length;
2179{
2180#ifdef VMS
2181 long max_str = 65535;
2182
2183 while (length > max_str) {
2184 (void) LIB$MOVC3 (&max_str, b1, b2);
2185 length -= max_str;
2186 b1 += max_str;
2187 b2 += max_str;
2188 }
2189 max_str = length;
2190 (void) LIB$MOVC3 (&length, b1, b2);
2191#else
2192 while (length-- > 0)
2193 *b2++ = *b1++;
2194#endif /* not VMS */
2195}
2196
2197int
2198bcmp (b1, b2, length) /* This could be a macro! */
2199 register char *b1;
2200 register char *b2;
2201 register int length;
2202{
2203#ifdef VMS
2204 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
2205 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
2206
2207 return STR$COMPARE (&src1, &src2);
2208#else
2209 while (length-- > 0)
2210 if (*b1++ != *b2++)
2211 return 1;
2212
2213 return 0;
2214#endif /* not VMS */
2215}
2216#endif /* not BSTRING */
2217\f
9927a7b1 2218#ifndef HAVE_RANDOM
86a5659e
JB
2219#ifdef USG
2220/*
2221 * The BSD random returns numbers in the range of
2222 * 0 to 2e31 - 1. The USG rand returns numbers in the
2223 * range of 0 to 2e15 - 1. This is probably not significant
2224 * in this usage.
2225 */
2226
2227long
2228random ()
2229{
2230 /* Arrange to return a range centered on zero. */
2231 return (rand () << 15) + rand () - (1 << 29);
2232}
2233
2234srandom (arg)
2235 int arg;
2236{
2237 srand (arg);
2238}
2239
2240#endif /* USG */
2241
2242#ifdef BSD4_1
2243long random ()
2244{
2245 /* Arrange to return a range centered on zero. */
2246 return (rand () << 15) + rand () - (1 << 29);
2247}
2248
2249srandom (arg)
2250 int arg;
2251{
2252 srand (arg);
2253}
2254#endif /* BSD4_1 */
9927a7b1 2255#endif
86a5659e
JB
2256\f
2257#ifdef WRONG_NAME_INSQUE
2258
2259insque (q,p)
2260 caddr_t q,p;
2261{
2262 _insque (q,p);
2263}
2264
2265#endif
2266\f
2267#ifdef VMS
2268
2269#ifdef getenv
2270/* If any place else asks for the TERM variable,
2271 allow it to be overridden with the EMACS_TERM variable
2272 before attempting to translate the logical name TERM. As a last
2273 resort, ask for VAX C's special idea of the TERM variable. */
2274#undef getenv
2275char *
2276sys_getenv (name)
2277 char *name;
2278{
2279 register char *val;
2280 static char buf[256];
2281 static struct dsc$descriptor_s equiv
2282 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2283 static struct dsc$descriptor_s d_name
2284 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2285 short eqlen;
2286
2287 if (!strcmp (name, "TERM"))
2288 {
2289 val = (char *) getenv ("EMACS_TERM");
2290 if (val)
2291 return val;
2292 }
2293
2294 d_name.dsc$w_length = strlen (name);
2295 d_name.dsc$a_pointer = name;
986ffb24 2296 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
86a5659e
JB
2297 {
2298 char *str = (char *) xmalloc (eqlen + 1);
2299 bcopy (buf, str, eqlen);
2300 str[eqlen] = '\0';
2301 /* This is a storage leak, but a pain to fix. With luck,
2302 no one will ever notice. */
2303 return str;
2304 }
2305 return (char *) getenv (name);
2306}
2307#endif /* getenv */
2308
2309#ifdef abort
2310/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2311 to force a call on the debugger from within the image. */
2312#undef abort
2313sys_abort ()
2314{
2315 reset_sys_modes ();
2316 LIB$SIGNAL (SS$_DEBUG);
2317}
2318#endif /* abort */
2319#endif /* VMS */
2320\f
2321#ifdef VMS
2322#ifdef LINK_CRTL_SHARE
2323#ifdef SHAREABLE_LIB_BUG
2324/* Variables declared noshare and initialized in shareable libraries
2325 cannot be shared. The VMS linker incorrectly forces you to use a private
2326 version which is uninitialized... If not for this "feature", we
2327 could use the C library definition of sys_nerr and sys_errlist. */
2328int sys_nerr = 35;
2329char *sys_errlist[] =
2330 {
2331 "error 0",
2332 "not owner",
2333 "no such file or directory",
2334 "no such process",
2335 "interrupted system call",
2336 "i/o error",
2337 "no such device or address",
2338 "argument list too long",
2339 "exec format error",
2340 "bad file number",
2341 "no child process",
2342 "no more processes",
2343 "not enough memory",
2344 "permission denied",
2345 "bad address",
2346 "block device required",
2347 "mount devices busy",
2348 "file exists",
2349 "cross-device link",
2350 "no such device",
2351 "not a directory",
2352 "is a directory",
2353 "invalid argument",
2354 "file table overflow",
2355 "too many open files",
2356 "not a typewriter",
2357 "text file busy",
2358 "file too big",
2359 "no space left on device",
2360 "illegal seek",
2361 "read-only file system",
2362 "too many links",
2363 "broken pipe",
2364 "math argument",
2365 "result too large",
2366 "I/O stream empty",
2367 "vax/vms specific error code nontranslatable error"
2368 };
2369#endif /* SHAREABLE_LIB_BUG */
2370#endif /* LINK_CRTL_SHARE */
2371#endif /* VMS */
2372\f
2373#ifdef INTERRUPTIBLE_OPEN
2374
2375int
2376/* VARARGS 2 */
2377sys_open (path, oflag, mode)
2378 char *path;
2379 int oflag, mode;
2380{
2381 register int rtnval;
2382
2383 while ((rtnval = open (path, oflag, mode)) == -1
2384 && (errno == EINTR));
2385 return (rtnval);
2386}
2387
2388#endif /* INTERRUPTIBLE_OPEN */
2389
2390#ifdef INTERRUPTIBLE_CLOSE
2391
2392sys_close (fd)
2393 int fd;
2394{
2395 register int rtnval;
2396
2397 while ((rtnval = close (fd)) == -1
2398 && (errno == EINTR));
2399 return rtnval;
2400}
2401
2402#endif /* INTERRUPTIBLE_CLOSE */
2403
2404#ifdef INTERRUPTIBLE_IO
2405
2406int
2407sys_read (fildes, buf, nbyte)
2408 int fildes;
2409 char *buf;
2410 unsigned int nbyte;
2411{
2412 register int rtnval;
2413
2414 while ((rtnval = read (fildes, buf, nbyte)) == -1
2415 && (errno == EINTR));
2416 return (rtnval);
2417}
2418
2419int
2420sys_write (fildes, buf, nbyte)
2421 int fildes;
2422 char *buf;
2423 unsigned int nbyte;
2424{
2425 register int rtnval;
2426
2427 while ((rtnval = write (fildes, buf, nbyte)) == -1
2428 && (errno == EINTR));
2429 return (rtnval);
2430}
2431
2432#endif /* INTERRUPTIBLE_IO */
2433\f
2434#ifdef USG
2435/*
2436 * All of the following are for USG.
2437 *
2438 * On USG systems the system calls are INTERRUPTIBLE by signals
2439 * that the user program has elected to catch. Thus the system call
2440 * must be retried in these cases. To handle this without massive
2441 * changes in the source code, we remap the standard system call names
2442 * to names for our own functions in sysdep.c that do the system call
2443 * with retries. Actually, for portability reasons, it is good
2444 * programming practice, as this example shows, to limit all actual
2445 * system calls to a single occurance in the source. Sure, this
2446 * adds an extra level of function call overhead but it is almost
2447 * always negligible. Fred Fish, Unisoft Systems Inc.
2448 */
2449
00eaaa32 2450#ifndef HAVE_SYS_SIGLIST
86a5659e
JB
2451char *sys_siglist[NSIG + 1] =
2452{
2453#ifdef AIX
2454/* AIX has changed the signals a bit */
2455 "bogus signal", /* 0 */
2456 "hangup", /* 1 SIGHUP */
2457 "interrupt", /* 2 SIGINT */
2458 "quit", /* 3 SIGQUIT */
2459 "illegal instruction", /* 4 SIGILL */
2460 "trace trap", /* 5 SIGTRAP */
2461 "IOT instruction", /* 6 SIGIOT */
2462 "crash likely", /* 7 SIGDANGER */
2463 "floating point exception", /* 8 SIGFPE */
2464 "kill", /* 9 SIGKILL */
2465 "bus error", /* 10 SIGBUS */
2466 "segmentation violation", /* 11 SIGSEGV */
2467 "bad argument to system call", /* 12 SIGSYS */
2468 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2469 "alarm clock", /* 14 SIGALRM */
2470 "software termination signum", /* 15 SIGTERM */
2471 "user defined signal 1", /* 16 SIGUSR1 */
2472 "user defined signal 2", /* 17 SIGUSR2 */
2473 "death of a child", /* 18 SIGCLD */
2474 "power-fail restart", /* 19 SIGPWR */
2475 "bogus signal", /* 20 */
2476 "bogus signal", /* 21 */
2477 "bogus signal", /* 22 */
2478 "bogus signal", /* 23 */
2479 "bogus signal", /* 24 */
2480 "LAN I/O interrupt", /* 25 SIGAIO */
2481 "PTY I/O interrupt", /* 26 SIGPTY */
2482 "I/O intervention required", /* 27 SIGIOINT */
2483 "HFT grant", /* 28 SIGGRANT */
2484 "HFT retract", /* 29 SIGRETRACT */
2485 "HFT sound done", /* 30 SIGSOUND */
2486 "HFT input ready", /* 31 SIGMSG */
2487#else /* not AIX */
2488 "bogus signal", /* 0 */
2489 "hangup", /* 1 SIGHUP */
2490 "interrupt", /* 2 SIGINT */
2491 "quit", /* 3 SIGQUIT */
2492 "illegal instruction", /* 4 SIGILL */
2493 "trace trap", /* 5 SIGTRAP */
2494 "IOT instruction", /* 6 SIGIOT */
2495 "EMT instruction", /* 7 SIGEMT */
2496 "floating point exception", /* 8 SIGFPE */
2497 "kill", /* 9 SIGKILL */
2498 "bus error", /* 10 SIGBUS */
2499 "segmentation violation", /* 11 SIGSEGV */
2500 "bad argument to system call", /* 12 SIGSYS */
2501 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2502 "alarm clock", /* 14 SIGALRM */
2503 "software termination signum", /* 15 SIGTERM */
2504 "user defined signal 1", /* 16 SIGUSR1 */
2505 "user defined signal 2", /* 17 SIGUSR2 */
2506 "death of a child", /* 18 SIGCLD */
2507 "power-fail restart", /* 19 SIGPWR */
2508#endif /* not AIX */
2509 0
2510 };
00eaaa32 2511#endif HAVE_SYS_SIGLIST
86a5659e
JB
2512
2513/*
2514 * Warning, this function may not duplicate 4.2 action properly
2515 * under error conditions.
2516 */
2517
2518#ifndef MAXPATHLEN
2519/* In 4.1, param.h fails to define this. */
2520#define MAXPATHLEN 1024
2521#endif
2522
2523#ifndef HAVE_GETWD
2524
2525char *
2526getwd (pathname)
2527 char *pathname;
2528{
2529 char *npath, *spath;
2530 extern char *getcwd ();
2531
9ac0d9e0 2532 BLOCK_INPUT; /* getcwd uses malloc */
86a5659e
JB
2533 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2534 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2535 up to first slash. Should be harmless on other systems. */
2536 while (*npath && *npath != '/')
2537 npath++;
2538 strcpy (pathname, npath);
2539 free (spath); /* getcwd uses malloc */
9ac0d9e0 2540 UNBLOCK_INPUT;
86a5659e
JB
2541 return pathname;
2542}
2543
2544#endif /* HAVE_GETWD */
2545
2546/*
2547 * Emulate rename using unlink/link. Note that this is
2548 * only partially correct. Also, doesn't enforce restriction
2549 * that files be of same type (regular->regular, dir->dir, etc).
2550 */
2551
4746118a
JB
2552#ifndef HAVE_RENAME
2553
86a5659e
JB
2554rename (from, to)
2555 char *from;
2556 char *to;
2557{
2558 if (access (from, 0) == 0)
2559 {
2560 unlink (to);
2561 if (link (from, to) == 0)
2562 if (unlink (from) == 0)
2563 return (0);
2564 }
2565 return (-1);
2566}
2567
4746118a
JB
2568#endif
2569
86a5659e
JB
2570#ifndef HAVE_VFORK
2571
2572/*
2573 * Substitute fork for vfork on USG flavors.
2574 */
2575
2576vfork ()
2577{
2578 return (fork ());
2579}
2580
2581#endif /* not HAVE_VFORK */
2582
2583#ifdef MISSING_UTIMES
2584
2585/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2586
2587utimes ()
2588{
2589}
2590#endif
2591
2592#ifdef IRIS_UTIME
2593
2594/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2595 utimbuf structure defined anywhere but in the man page. */
2596
2597struct utimbuf
2598 {
2599 long actime;
2600 long modtime;
2601 };
2602
2603utimes (name, tvp)
2604 char *name;
2605 struct timeval tvp[];
2606{
2607 struct utimbuf utb;
2608 utb.actime = tvp[0].tv_sec;
2609 utb.modtime = tvp[1].tv_sec;
2610 utime (name, &utb);
2611}
2612#endif /* IRIS_UTIME */
2613
2614
2615#ifdef HPUX
2616#ifndef HAVE_PERROR
2617
2618/* HPUX curses library references perror, but as far as we know
2619 it won't be called. Anyway this definition will do for now. */
2620
2621perror ()
2622{
2623}
2624
2625#endif /* not HAVE_PERROR */
2626#endif /* HPUX */
2627
2628#ifndef HAVE_DUP2
2629
2630/*
2631 * Emulate BSD dup2. First close newd if it already exists.
2632 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2633 * until we are, then close the unsuccessful ones.
2634 */
2635
2636dup2 (oldd, newd)
2637 int oldd;
2638 int newd;
2639{
2640 register int fd, ret;
2641
2642 sys_close (newd);
2643
2644#ifdef F_DUPFD
2645 fd = fcntl (oldd, F_DUPFD, newd);
2646 if (fd != newd)
2647 error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
2648#else
2649 fd = dup (old);
2650 if (fd == -1)
2651 return -1;
2652 if (fd == new)
2653 return new;
2654 ret = dup2 (old,new);
2655 sys_close (fd);
2656 return ret;
2657#endif
2658}
2659
2660#endif /* not HAVE_DUP2 */
2661
2662/*
2663 * Gettimeofday. Simulate as much as possible. Only accurate
2664 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2665 * Only needed when subprocesses are defined.
2666 */
2667
2668#ifdef subprocesses
2669#ifndef VMS
2670#ifndef HAVE_GETTIMEOFDAY
2671#ifdef HAVE_TIMEVAL
2672
2673/* ARGSUSED */
2674gettimeofday (tp, tzp)
2675 struct timeval *tp;
2676 struct timezone *tzp;
2677{
2678 extern long time ();
2679
2680 tp->tv_sec = time ((long *)0);
2681 tp->tv_usec = 0;
2682 tzp->tz_minuteswest = -1;
2683}
2684
2685#endif
2686#endif
2687#endif
2688#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
2689
2690/*
2691 * This function will go away as soon as all the stubs fixed. (fnf)
2692 */
2693
2694croak (badfunc)
2695 char *badfunc;
2696{
2697 printf ("%s not yet implemented\r\n", badfunc);
2698 reset_sys_modes ();
2699 exit (1);
2700}
2701
2702#endif /* USG */
2703\f
2704#ifdef DGUX
2705
2706char *sys_siglist[NSIG + 1] =
2707{
2708 "null signal", /* 0 SIGNULL */
2709 "hangup", /* 1 SIGHUP */
2710 "interrupt", /* 2 SIGINT */
2711 "quit", /* 3 SIGQUIT */
2712 "illegal instruction", /* 4 SIGILL */
2713 "trace trap", /* 5 SIGTRAP */
2714 "abort termination", /* 6 SIGABRT */
2715 "SIGEMT", /* 7 SIGEMT */
2716 "floating point exception", /* 8 SIGFPE */
2717 "kill", /* 9 SIGKILL */
2718 "bus error", /* 10 SIGBUS */
2719 "segmentation violation", /* 11 SIGSEGV */
2720 "bad argument to system call", /* 12 SIGSYS */
2721 "write on a pipe with no reader", /* 13 SIGPIPE */
2722 "alarm clock", /* 14 SIGALRM */
2723 "software termination signal", /* 15 SIGTERM */
2724 "user defined signal 1", /* 16 SIGUSR1 */
2725 "user defined signal 2", /* 17 SIGUSR2 */
2726 "child stopped or terminated", /* 18 SIGCLD */
2727 "power-fail restart", /* 19 SIGPWR */
2728 "window size changed", /* 20 SIGWINCH */
2729 "undefined", /* 21 */
2730 "pollable event occured", /* 22 SIGPOLL */
2731 "sendable stop signal not from tty", /* 23 SIGSTOP */
2732 "stop signal from tty", /* 24 SIGSTP */
2733 "continue a stopped process", /* 25 SIGCONT */
2734 "attempted background tty read", /* 26 SIGTTIN */
2735 "attempted background tty write", /* 27 SIGTTOU */
2736 "undefined", /* 28 */
2737 "undefined", /* 29 */
2738 "undefined", /* 30 */
2739 "undefined", /* 31 */
2740 "undefined", /* 32 */
2741 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
2742 "I/O is possible", /* 34 SIGIO */
2743 "exceeded cpu time limit", /* 35 SIGXCPU */
2744 "exceeded file size limit", /* 36 SIGXFSZ */
2745 "virtual time alarm", /* 37 SIGVTALRM */
2746 "profiling time alarm", /* 38 SIGPROF */
2747 "undefined", /* 39 */
2748 "file record locks revoked", /* 40 SIGLOST */
2749 "undefined", /* 41 */
2750 "undefined", /* 42 */
2751 "undefined", /* 43 */
2752 "undefined", /* 44 */
2753 "undefined", /* 45 */
2754 "undefined", /* 46 */
2755 "undefined", /* 47 */
2756 "undefined", /* 48 */
2757 "undefined", /* 49 */
2758 "undefined", /* 50 */
2759 "undefined", /* 51 */
2760 "undefined", /* 52 */
2761 "undefined", /* 53 */
2762 "undefined", /* 54 */
2763 "undefined", /* 55 */
2764 "undefined", /* 56 */
2765 "undefined", /* 57 */
2766 "undefined", /* 58 */
2767 "undefined", /* 59 */
2768 "undefined", /* 60 */
2769 "undefined", /* 61 */
2770 "undefined", /* 62 */
2771 "undefined", /* 63 */
2772 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
2773 0
2774};
2775
2776#endif /* DGUX */
2777\f
2778/* Directory routines for systems that don't have them. */
2779
2780#ifdef SYSV_SYSTEM_DIR
2781
2782#include <dirent.h>
2783
2784#ifndef AIX
2785int
2786closedir (dirp)
2787 register DIR *dirp; /* stream from opendir */
2788{
2789 sys_close (dirp->dd_fd);
9ac0d9e0
JB
2790 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
2791 xfree ((char *) dirp);
86a5659e
JB
2792}
2793#endif /* not AIX */
2794#endif /* SYSV_SYSTEM_DIR */
2795
2796#ifdef NONSYSTEM_DIR_LIBRARY
2797
2798DIR *
2799opendir (filename)
2800 char *filename; /* name of directory */
2801{
2802 register DIR *dirp; /* -> malloc'ed storage */
2803 register int fd; /* file descriptor for read */
2804 struct stat sbuf; /* result of fstat */
2805
2806 fd = sys_open (filename, 0);
2807 if (fd < 0)
2808 return 0;
2809
9ac0d9e0 2810 BLOCK_INPUT;
86a5659e
JB
2811 if (fstat (fd, &sbuf) < 0
2812 || (sbuf.st_mode & S_IFMT) != S_IFDIR
2813 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2814 {
2815 sys_close (fd);
9ac0d9e0 2816 UNBLOCK_INPUT;
86a5659e
JB
2817 return 0; /* bad luck today */
2818 }
9ac0d9e0 2819 UNBLOCK_INPUT;
86a5659e
JB
2820
2821 dirp->dd_fd = fd;
2822 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2823
2824 return dirp;
2825}
2826
2827void
2828closedir (dirp)
2829 register DIR *dirp; /* stream from opendir */
2830{
2831 sys_close (dirp->dd_fd);
9ac0d9e0 2832 xfree ((char *) dirp);
86a5659e
JB
2833}
2834
2835
2836#ifndef VMS
2837#define DIRSIZ 14
2838struct olddir
2839 {
2840 ino_t od_ino; /* inode */
2841 char od_name[DIRSIZ]; /* filename */
2842 };
2843#endif /* not VMS */
2844
2845struct direct dir_static; /* simulated directory contents */
2846
2847/* ARGUSED */
2848struct direct *
2849readdir (dirp)
2850 register DIR *dirp; /* stream from opendir */
2851{
2852#ifndef VMS
2853 register struct olddir *dp; /* -> directory data */
2854#else /* VMS */
2855 register struct dir$_name *dp; /* -> directory data */
2856 register struct dir$_version *dv; /* -> version data */
2857#endif /* VMS */
2858
2859 for (; ;)
2860 {
2861 if (dirp->dd_loc >= dirp->dd_size)
2862 dirp->dd_loc = dirp->dd_size = 0;
2863
2864 if (dirp->dd_size == 0 /* refill buffer */
2865 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2866 return 0;
2867
2868#ifndef VMS
2869 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
2870 dirp->dd_loc += sizeof (struct olddir);
2871
2872 if (dp->od_ino != 0) /* not deleted entry */
2873 {
2874 dir_static.d_ino = dp->od_ino;
2875 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
2876 dir_static.d_name[DIRSIZ] = '\0';
2877 dir_static.d_namlen = strlen (dir_static.d_name);
2878 dir_static.d_reclen = sizeof (struct direct)
2879 - MAXNAMLEN + 3
2880 + dir_static.d_namlen - dir_static.d_namlen % 4;
2881 return &dir_static; /* -> simulated structure */
2882 }
2883#else /* VMS */
2884 dp = (struct dir$_name *) dirp->dd_buf;
2885 if (dirp->dd_loc == 0)
2886 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
2887 : dp->dir$b_namecount;
2888 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
2889 dir_static.d_ino = dv->dir$w_fid_num;
2890 dir_static.d_namlen = dp->dir$b_namecount;
2891 dir_static.d_reclen = sizeof (struct direct)
2892 - MAXNAMLEN + 3
2893 + dir_static.d_namlen - dir_static.d_namlen % 4;
2894 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2895 dir_static.d_name[dir_static.d_namlen] = '\0';
2896 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
2897 return &dir_static;
2898#endif /* VMS */
2899 }
2900}
2901
2902#ifdef VMS
2903/* readdirver is just like readdir except it returns all versions of a file
2904 as separate entries. */
2905
2906/* ARGUSED */
2907struct direct *
2908readdirver (dirp)
2909 register DIR *dirp; /* stream from opendir */
2910{
2911 register struct dir$_name *dp; /* -> directory data */
2912 register struct dir$_version *dv; /* -> version data */
2913
2914 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
2915 dirp->dd_loc = dirp->dd_size = 0;
2916
2917 if (dirp->dd_size == 0 /* refill buffer */
2918 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2919 return 0;
2920
2921 dp = (struct dir$_name *) dirp->dd_buf;
2922 if (dirp->dd_loc == 0)
2923 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
2924 : dp->dir$b_namecount;
2925 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
2926 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2927 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
2928 dir_static.d_namlen = strlen (dir_static.d_name);
2929 dir_static.d_ino = dv->dir$w_fid_num;
2930 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
2931 + dir_static.d_namlen - dir_static.d_namlen % 4;
2932 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
2933 return &dir_static;
2934}
2935
2936#endif /* VMS */
2937
2938#endif /* NONSYSTEM_DIR_LIBRARY */
2939\f
2940/* Functions for VMS */
2941#ifdef VMS
91bac16a 2942#include "vms-pwd.h"
86a5659e
JB
2943#include <acldef.h>
2944#include <chpdef.h>
2945#include <jpidef.h>
2946
2947/* Return as a string the VMS error string pertaining to STATUS.
2948 Reuses the same static buffer each time it is called. */
2949
2950char *
2951vmserrstr (status)
2952 int status; /* VMS status code */
2953{
2954 int bufadr[2];
2955 short len;
2956 static char buf[257];
2957
2958 bufadr[0] = sizeof buf - 1;
2959 bufadr[1] = (int) buf;
2960 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
2961 return "untranslatable VMS error status";
2962 buf[len] = '\0';
2963 return buf;
2964}
2965
2966#ifdef access
2967#undef access
2968
2969/* The following is necessary because 'access' emulation by VMS C (2.0) does
2970 * not work correctly. (It also doesn't work well in version 2.3.)
2971 */
2972
2973#ifdef VMS4_4
2974
2975#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
2976 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
2977
2978typedef union {
2979 struct {
2980 unsigned short s_buflen;
2981 unsigned short s_code;
2982 char *s_bufadr;
2983 unsigned short *s_retlenadr;
2984 } s;
2985 int end;
2986} item;
2987#define buflen s.s_buflen
2988#define code s.s_code
2989#define bufadr s.s_bufadr
2990#define retlenadr s.s_retlenadr
2991
2992#define R_OK 4 /* test for read permission */
2993#define W_OK 2 /* test for write permission */
2994#define X_OK 1 /* test for execute (search) permission */
2995#define F_OK 0 /* test for presence of file */
2996
2997int
2998sys_access (path, mode)
2999 char *path;
3000 int mode;
3001{
3002 static char *user = NULL;
3003 char dir_fn[512];
3004
3005 /* translate possible directory spec into .DIR file name, so brain-dead
3006 * access can treat the directory like a file. */
3007 if (directory_file_name (path, dir_fn))
3008 path = dir_fn;
3009
3010 if (mode == F_OK)
3011 return access (path, mode);
3012 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3013 return -1;
3014 {
3015 int stat;
3016 int flags;
3017 int acces;
3018 unsigned short int dummy;
3019 item itemlst[3];
3020 static int constant = ACL$C_FILE;
3021 DESCRIPTOR (path_desc, path);
3022 DESCRIPTOR (user_desc, user);
3023
3024 flags = 0;
3025 acces = 0;
3026 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3027 return stat;
3028 if (mode & R_OK)
3029 acces |= CHP$M_READ;
3030 if (mode & W_OK)
3031 acces |= CHP$M_WRITE;
3032 itemlst[0].buflen = sizeof (int);
3033 itemlst[0].code = CHP$_FLAGS;
3034 itemlst[0].bufadr = (char *) &flags;
3035 itemlst[0].retlenadr = &dummy;
3036 itemlst[1].buflen = sizeof (int);
3037 itemlst[1].code = CHP$_ACCESS;
3038 itemlst[1].bufadr = (char *) &acces;
3039 itemlst[1].retlenadr = &dummy;
3040 itemlst[2].end = CHP$_END;
3041 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3042 return stat == SS$_NORMAL ? 0 : -1;
3043 }
3044}
3045
3046#else /* not VMS4_4 */
3047
3048#include <prvdef.h>
3049#define ACE$M_WRITE 2
3050#define ACE$C_KEYID 1
3051
3052static unsigned short memid, grpid;
3053static unsigned int uic;
3054
3055/* Called from init_sys_modes, so it happens not very often
3056 but at least each time Emacs is loaded. */
3057sys_access_reinit ()
3058{
3059 uic = 0;
3060}
3061
3062int
3063sys_access (filename, type)
3064 char * filename;
3065 int type;
3066{
3067 struct FAB fab;
3068 struct XABPRO xab;
3069 int status, size, i, typecode, acl_controlled;
3070 unsigned int *aclptr, *aclend, aclbuf[60];
3071 union prvdef prvmask;
3072
3073 /* Get UIC and GRP values for protection checking. */
3074 if (uic == 0)
3075 {
3076 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3077 if (! (status & 1))
3078 return -1;
3079 memid = uic & 0xFFFF;
3080 grpid = uic >> 16;
3081 }
3082
3083 if (type != 2) /* not checking write access */
3084 return access (filename, type);
3085
3086 /* Check write protection. */
3087
3088#define CHECKPRIV(bit) (prvmask.bit)
3089#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3090
3091 /* Find privilege bits */
986ffb24 3092 status = SYS$SETPRV (0, 0, 0, prvmask);
86a5659e
JB
3093 if (! (status & 1))
3094 error ("Unable to find privileges: %s", vmserrstr (status));
3095 if (CHECKPRIV (PRV$V_BYPASS))
3096 return 0; /* BYPASS enabled */
3097 fab = cc$rms_fab;
3098 fab.fab$b_fac = FAB$M_GET;
3099 fab.fab$l_fna = filename;
3100 fab.fab$b_fns = strlen (filename);
3101 fab.fab$l_xab = &xab;
3102 xab = cc$rms_xabpro;
3103 xab.xab$l_aclbuf = aclbuf;
3104 xab.xab$w_aclsiz = sizeof (aclbuf);
986ffb24 3105 status = SYS$OPEN (&fab, 0, 0);
86a5659e
JB
3106 if (! (status & 1))
3107 return -1;
986ffb24 3108 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3109 /* Check system access */
3110 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
3111 return 0;
3112 /* Check ACL entries, if any */
3113 acl_controlled = 0;
3114 if (xab.xab$w_acllen > 0)
3115 {
3116 aclptr = aclbuf;
3117 aclend = &aclbuf[xab.xab$w_acllen / 4];
3118 while (*aclptr && aclptr < aclend)
3119 {
3120 size = (*aclptr & 0xff) / 4;
3121 typecode = (*aclptr >> 8) & 0xff;
3122 if (typecode == ACE$C_KEYID)
3123 for (i = size - 1; i > 1; i--)
3124 if (aclptr[i] == uic)
3125 {
3126 acl_controlled = 1;
3127 if (aclptr[1] & ACE$M_WRITE)
3128 return 0; /* Write access through ACL */
3129 }
3130 aclptr = &aclptr[size];
3131 }
3132 if (acl_controlled) /* ACL specified, prohibits write access */
3133 return -1;
3134 }
3135 /* No ACL entries specified, check normal protection */
3136 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
3137 return 0;
3138 if (WRITEABLE (XAB$V_GRP) &&
3139 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3140 return 0; /* Group writeable */
3141 if (WRITEABLE (XAB$V_OWN) &&
3142 (xab.xab$l_uic & 0xFFFF) == memid)
3143 return 0; /* Owner writeable */
3144
3145 return -1; /* Not writeable */
3146}
3147#endif /* not VMS4_4 */
3148#endif /* access */
3149
3150static char vtbuf[NAM$C_MAXRSS+1];
3151
3152/* translate a vms file spec to a unix path */
3153char *
3154sys_translate_vms (vfile)
3155 char * vfile;
3156{
3157 char * p;
3158 char * targ;
3159
3160 if (!vfile)
3161 return 0;
3162
3163 targ = vtbuf;
3164
3165 /* leading device or logical name is a root directory */
3166 if (p = strchr (vfile, ':'))
3167 {
3168 *targ++ = '/';
3169 while (vfile < p)
3170 *targ++ = *vfile++;
3171 vfile++;
3172 *targ++ = '/';
3173 }
3174 p = vfile;
3175 if (*p == '[' || *p == '<')
3176 {
3177 while (*++vfile != *p + 2)
3178 switch (*vfile)
3179 {
3180 case '.':
3181 if (vfile[-1] == *p)
3182 *targ++ = '.';
3183 *targ++ = '/';
3184 break;
3185
3186 case '-':
3187 *targ++ = '.';
3188 *targ++ = '.';
3189 break;
3190
3191 default:
3192 *targ++ = *vfile;
3193 break;
3194 }
3195 vfile++;
3196 *targ++ = '/';
3197 }
3198 while (*vfile)
3199 *targ++ = *vfile++;
3200
3201 return vtbuf;
3202}
3203
3204static char utbuf[NAM$C_MAXRSS+1];
3205
3206/* translate a unix path to a VMS file spec */
3207char *
3208sys_translate_unix (ufile)
3209 char * ufile;
3210{
3211 int slash_seen = 0;
3212 char *p;
3213 char * targ;
3214
3215 if (!ufile)
3216 return 0;
3217
3218 targ = utbuf;
3219
3220 if (*ufile == '/')
3221 {
3222 ufile++;
3223 }
3224
3225 while (*ufile)
3226 {
3227 switch (*ufile)
3228 {
3229 case '/':
3230 if (slash_seen)
3231 if (index (&ufile[1], '/'))
3232 *targ++ = '.';
3233 else
3234 *targ++ = ']';
3235 else
3236 {
3237 *targ++ = ':';
3238 if (index (&ufile[1], '/'))
3239 *targ++ = '[';
3240 slash_seen = 1;
3241 }
3242 break;
3243
3244 case '.':
3245 if (strncmp (ufile, "./", 2) == 0)
3246 {
3247 if (!slash_seen)
3248 {
3249 *targ++ = '[';
3250 slash_seen = 1;
3251 }
3252 ufile++; /* skip the dot */
3253 if (index (&ufile[1], '/'))
3254 *targ++ = '.';
3255 else
3256 *targ++ = ']';
3257 }
3258 else if (strncmp (ufile, "../", 3) == 0)
3259 {
3260 if (!slash_seen)
3261 {
3262 *targ++ = '[';
3263 slash_seen = 1;
3264 }
3265 *targ++ = '-';
3266 ufile += 2; /* skip the dots */
3267 if (index (&ufile[1], '/'))
3268 *targ++ = '.';
3269 else
3270 *targ++ = ']';
3271 }
3272 else
3273 *targ++ = *ufile;
3274 break;
3275
3276 default:
3277 *targ++ = *ufile;
3278 break;
3279 }
3280 ufile++;
3281 }
3282 *targ = '\0';
3283
3284 return utbuf;
3285}
3286
3287char *
3288getwd (pathname)
3289 char *pathname;
3290{
3291 char *ptr;
210b2b4f 3292 extern char *getcwd ();
86a5659e 3293
210b2b4f
JB
3294#define MAXPATHLEN 1024
3295
9ac0d9e0 3296 ptr = xmalloc (MAXPATHLEN);
210b2b4f
JB
3297 getcwd (ptr, MAXPATHLEN);
3298 strcpy (pathname, ptr);
9ac0d9e0 3299 xfree (ptr);
210b2b4f
JB
3300
3301 return pathname;
86a5659e
JB
3302}
3303
3304getppid ()
3305{
3306 long item_code = JPI$_OWNER;
3307 unsigned long parent_id;
3308 int status;
3309
3310 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3311 {
3312 errno = EVMSERR;
3313 vaxc$errno = status;
3314 return -1;
3315 }
3316 return parent_id;
3317}
3318
3319#undef getuid
3320unsigned
3321sys_getuid ()
3322{
3323 return (getgid () << 16) | getuid ();
3324}
3325
3326int
3327sys_read (fildes, buf, nbyte)
3328 int fildes;
3329 char *buf;
3330 unsigned int nbyte;
3331{
3332 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3333}
3334
3335#if 0
3336int
3337sys_write (fildes, buf, nbyte)
3338 int fildes;
3339 char *buf;
3340 unsigned int nbyte;
3341{
3342 register int nwrote, rtnval = 0;
3343
3344 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3345 nbyte -= nwrote;
3346 buf += nwrote;
3347 rtnval += nwrote;
3348 }
3349 if (nwrote < 0)
3350 return rtnval ? rtnval : -1;
3351 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3352 return rtnval ? rtnval : -1;
3353 return (rtnval + nwrote);
3354}
3355#endif /* 0 */
3356
3357/*
3358 * VAX/VMS VAX C RTL really loses. It insists that records
3359 * end with a newline (carriage return) character, and if they
3360 * don't it adds one (nice of it isn't it!)
3361 *
3362 * Thus we do this stupidity below.
3363 */
3364
3365int
3366sys_write (fildes, buf, nbytes)
3367 int fildes;
3368 char *buf;
3369 unsigned int nbytes;
3370{
3371 register char *p;
3372 register char *e;
23b0668c
JB
3373 int sum = 0;
3374 struct stat st;
3375
3376 fstat (fildes, &st);
86a5659e 3377 p = buf;
86a5659e
JB
3378 while (nbytes > 0)
3379 {
23b0668c
JB
3380 int len, retval;
3381
3382 /* Handle fixed-length files with carriage control. */
3383 if (st.st_fab_rfm == FAB$C_FIX
3384 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3385 {
3386 len = st.st_fab_mrs;
3387 retval = write (fildes, p, min (len, nbytes));
3388 if (retval != len)
3389 return -1;
3390 retval++; /* This skips the implied carriage control */
3391 }
3392 else
3393 {
3394 e = p + min (MAXIOSIZE, nbytes) - 1;
3395 while (*e != '\n' && e > p) e--;
3396 if (p == e) /* Ok.. so here we add a newline... sigh. */
3397 e = p + min (MAXIOSIZE, nbytes) - 1;
3398 len = e + 1 - p;
3399 retval = write (fildes, p, len);
3400 if (retval != len)
3401 return -1;
3402 }
3403 p += retval;
3404 sum += retval;
86a5659e
JB
3405 nbytes -= retval;
3406 }
3407 return sum;
3408}
3409
3410/* Create file NEW copying its attributes from file OLD. If
3411 OLD is 0 or does not exist, create based on the value of
3412 vms_stmlf_recfm. */
3413
3414/* Protection value the file should ultimately have.
3415 Set by create_copy_attrs, and use by rename_sansversions. */
3416static unsigned short int fab_final_pro;
3417
3418int
3419creat_copy_attrs (old, new)
3420 char *old, *new;
3421{
3422 struct FAB fab = cc$rms_fab;
3423 struct XABPRO xabpro;
3424 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3425 extern int vms_stmlf_recfm;
3426
3427 if (old)
3428 {
3429 fab.fab$b_fac = FAB$M_GET;
3430 fab.fab$l_fna = old;
3431 fab.fab$b_fns = strlen (old);
3432 fab.fab$l_xab = (char *) &xabpro;
3433 xabpro = cc$rms_xabpro;
3434 xabpro.xab$l_aclbuf = aclbuf;
3435 xabpro.xab$w_aclsiz = sizeof aclbuf;
3436 /* Call $OPEN to fill in the fab & xabpro fields. */
986ffb24 3437 if (SYS$OPEN (&fab, 0, 0) & 1)
86a5659e 3438 {
986ffb24 3439 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3440 fab.fab$l_alq = 0; /* zero the allocation quantity */
3441 if (xabpro.xab$w_acllen > 0)
3442 {
3443 if (xabpro.xab$w_acllen > sizeof aclbuf)
3444 /* If the acl buffer was too short, redo open with longer one.
3445 Wouldn't need to do this if there were some system imposed
3446 limit on the size of an ACL, but I can't find any such. */
3447 {
3448 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
3449 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
986ffb24
JB
3450 if (SYS$OPEN (&fab, 0, 0) & 1)
3451 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3452 else
3453 old = 0;
3454 }
3455 }
3456 else
3457 xabpro.xab$l_aclbuf = 0;
3458 }
3459 else
3460 old = 0;
3461 }
3462 fab.fab$l_fna = new;
3463 fab.fab$b_fns = strlen (new);
3464 if (!old)
3465 {
3466 fab.fab$l_xab = 0;
3467 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
3468 fab.fab$b_rat = FAB$M_CR;
3469 }
3470
3471 /* Set the file protections such that we will be able to manipulate
3472 this file. Once we are done writing and renaming it, we will set
3473 the protections back. */
3474 if (old)
3475 fab_final_pro = xabpro.xab$w_pro;
3476 else
986ffb24 3477 SYS$SETDFPROT (0, &fab_final_pro);
86a5659e
JB
3478 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
3479
3480 /* Create the new file with either default attrs or attrs copied
3481 from old file. */
3482 if (!(SYS$CREATE (&fab, 0, 0) & 1))
3483 return -1;
986ffb24 3484 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3485 /* As this is a "replacement" for creat, return a file descriptor
3486 opened for writing. */
3487 return open (new, O_WRONLY);
3488}
3489
3490#ifdef creat
3491#undef creat
3492#include <varargs.h>
3493#ifdef __GNUC__
3494#ifndef va_count
3495#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3496#endif
3497#endif
3498
3499sys_creat (va_alist)
3500 va_dcl
3501{
3502 va_list list_incrementor;
3503 char *name;
3504 int mode;
3505 int rfd; /* related file descriptor */
3506 int fd; /* Our new file descriptor */
3507 int count;
3508 struct stat st_buf;
3509 char rfm[12];
3510 char rat[15];
3511 char mrs[13];
3512 char fsz[13];
3513 extern int vms_stmlf_recfm;
3514
3515 va_count (count);
3516 va_start (list_incrementor);
3517 name = va_arg (list_incrementor, char *);
3518 mode = va_arg (list_incrementor, int);
3519 if (count > 2)
3520 rfd = va_arg (list_incrementor, int);
3521 va_end (list_incrementor);
3522 if (count > 2)
3523 {
3524 /* Use information from the related file descriptor to set record
3525 format of the newly created file. */
3526 fstat (rfd, &st_buf);
3527 switch (st_buf.st_fab_rfm)
3528 {
3529 case FAB$C_FIX:
3530 strcpy (rfm, "rfm = fix");
3531 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
3532 strcpy (rat, "rat = ");
3533 if (st_buf.st_fab_rat & FAB$M_CR)
3534 strcat (rat, "cr");
3535 else if (st_buf.st_fab_rat & FAB$M_FTN)
3536 strcat (rat, "ftn");
3537 else if (st_buf.st_fab_rat & FAB$M_PRN)
3538 strcat (rat, "prn");
3539 if (st_buf.st_fab_rat & FAB$M_BLK)
3540 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3541 strcat (rat, ", blk");
3542 else
3543 strcat (rat, "blk");
3544 return creat (name, 0, rfm, rat, mrs);
3545
3546 case FAB$C_VFC:
3547 strcpy (rfm, "rfm = vfc");
3548 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
3549 strcpy (rat, "rat = ");
3550 if (st_buf.st_fab_rat & FAB$M_CR)
3551 strcat (rat, "cr");
3552 else if (st_buf.st_fab_rat & FAB$M_FTN)
3553 strcat (rat, "ftn");
3554 else if (st_buf.st_fab_rat & FAB$M_PRN)
3555 strcat (rat, "prn");
3556 if (st_buf.st_fab_rat & FAB$M_BLK)
3557 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3558 strcat (rat, ", blk");
3559 else
3560 strcat (rat, "blk");
3561 return creat (name, 0, rfm, rat, fsz);
3562
3563 case FAB$C_STM:
3564 strcpy (rfm, "rfm = stm");
3565 break;
3566
3567 case FAB$C_STMCR:
3568 strcpy (rfm, "rfm = stmcr");
3569 break;
3570
3571 case FAB$C_STMLF:
3572 strcpy (rfm, "rfm = stmlf");
3573 break;
3574
3575 case FAB$C_UDF:
3576 strcpy (rfm, "rfm = udf");
3577 break;
3578
3579 case FAB$C_VAR:
3580 strcpy (rfm, "rfm = var");
3581 break;
3582 }
3583 strcpy (rat, "rat = ");
3584 if (st_buf.st_fab_rat & FAB$M_CR)
3585 strcat (rat, "cr");
3586 else if (st_buf.st_fab_rat & FAB$M_FTN)
3587 strcat (rat, "ftn");
3588 else if (st_buf.st_fab_rat & FAB$M_PRN)
3589 strcat (rat, "prn");
3590 if (st_buf.st_fab_rat & FAB$M_BLK)
3591 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3592 strcat (rat, ", blk");
3593 else
3594 strcat (rat, "blk");
3595 }
3596 else
3597 {
3598 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3599 strcpy (rat, "rat=cr");
3600 }
3601 /* Until the VAX C RTL fixes the many bugs with modes, always use
3602 mode 0 to get the user's default protection. */
3603 fd = creat (name, 0, rfm, rat);
3604 if (fd < 0 && errno == EEXIST)
3605 {
3606 if (unlink (name) < 0)
3607 report_file_error ("delete", build_string (name));
3608 fd = creat (name, 0, rfm, rat);
3609 }
3610 return fd;
3611}
3612#endif /* creat */
3613
3614/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3615sys_fwrite (ptr, size, num, fp)
3616 register char * ptr;
3617 FILE * fp;
3618{
3619 register int tot = num * size;
3620
3621 while (tot--)
3622 fputc (*ptr++, fp);
3623}
3624
3625/*
3626 * The VMS C library routine creat actually creates a new version of an
3627 * existing file rather than truncating the old version. There are times
3628 * when this is not the desired behavior, for instance, when writing an
3629 * auto save file (you only want one version), or when you don't have
3630 * write permission in the directory containing the file (but the file
3631 * itself is writable). Hence this routine, which is equivalent to
3632 * "close (creat (fn, 0));" on Unix if fn already exists.
3633 */
3634int
3635vms_truncate (fn)
3636 char *fn;
3637{
3638 struct FAB xfab = cc$rms_fab;
3639 struct RAB xrab = cc$rms_rab;
3640 int status;
3641
3642 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3643 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3644 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3645 xfab.fab$l_fna = fn;
3646 xfab.fab$b_fns = strlen (fn);
3647 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3648 xfab.fab$b_dns = 2;
3649 xrab.rab$l_fab = &xfab;
3650
3651 /* This gibberish opens the file, positions to the first record, and
3652 deletes all records from there until the end of file. */
986ffb24 3653 if ((SYS$OPEN (&xfab) & 01) == 01)
86a5659e 3654 {
986ffb24
JB
3655 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
3656 (SYS$FIND (&xrab) & 01) == 01 &&
3657 (SYS$TRUNCATE (&xrab) & 01) == 01)
86a5659e
JB
3658 status = 0;
3659 else
3660 status = -1;
3661 }
3662 else
3663 status = -1;
986ffb24 3664 SYS$CLOSE (&xfab);
86a5659e
JB
3665 return status;
3666}
3667
3668/* Define this symbol to actually read SYSUAF.DAT. This requires either
3669 SYSPRV or a readable SYSUAF.DAT. */
3670
3671#ifdef READ_SYSUAF
3672/*
3673 * getuaf.c
3674 *
3675 * Routine to read the VMS User Authorization File and return
3676 * a specific user's record.
3677 */
3678
3679static struct UAF retuaf;
3680
3681struct UAF *
3682get_uaf_name (uname)
3683 char * uname;
3684{
3685 register status;
3686 struct FAB uaf_fab;
3687 struct RAB uaf_rab;
3688
3689 uaf_fab = cc$rms_fab;
3690 uaf_rab = cc$rms_rab;
3691 /* initialize fab fields */
3692 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3693 uaf_fab.fab$b_fns = 21;
3694 uaf_fab.fab$b_fac = FAB$M_GET;
3695 uaf_fab.fab$b_org = FAB$C_IDX;
3696 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3697 /* initialize rab fields */
3698 uaf_rab.rab$l_fab = &uaf_fab;
3699 /* open the User Authorization File */
986ffb24 3700 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3701 if (!(status&1))
3702 {
3703 errno = EVMSERR;
3704 vaxc$errno = status;
3705 return 0;
3706 }
986ffb24 3707 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3708 if (!(status&1))
3709 {
3710 errno = EVMSERR;
3711 vaxc$errno = status;
3712 return 0;
3713 }
3714 /* read the requested record - index is in uname */
3715 uaf_rab.rab$l_kbf = uname;
3716 uaf_rab.rab$b_ksz = strlen (uname);
3717 uaf_rab.rab$b_rac = RAB$C_KEY;
3718 uaf_rab.rab$l_ubf = (char *)&retuaf;
3719 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3720 status = SYS$GET (&uaf_rab);
86a5659e
JB
3721 if (!(status&1))
3722 {
3723 errno = EVMSERR;
3724 vaxc$errno = status;
3725 return 0;
3726 }
3727 /* close the User Authorization File */
986ffb24 3728 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3729 if (!(status&1))
3730 {
3731 errno = EVMSERR;
3732 vaxc$errno = status;
3733 return 0;
3734 }
986ffb24 3735 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3736 if (!(status&1))
3737 {
3738 errno = EVMSERR;
3739 vaxc$errno = status;
3740 return 0;
3741 }
3742 return &retuaf;
3743}
3744
3745struct UAF *
3746get_uaf_uic (uic)
3747 unsigned long uic;
3748{
3749 register status;
3750 struct FAB uaf_fab;
3751 struct RAB uaf_rab;
3752
3753 uaf_fab = cc$rms_fab;
3754 uaf_rab = cc$rms_rab;
3755 /* initialize fab fields */
3756 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3757 uaf_fab.fab$b_fns = 21;
3758 uaf_fab.fab$b_fac = FAB$M_GET;
3759 uaf_fab.fab$b_org = FAB$C_IDX;
3760 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3761 /* initialize rab fields */
3762 uaf_rab.rab$l_fab = &uaf_fab;
3763 /* open the User Authorization File */
986ffb24 3764 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3765 if (!(status&1))
3766 {
3767 errno = EVMSERR;
3768 vaxc$errno = status;
3769 return 0;
3770 }
986ffb24 3771 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3772 if (!(status&1))
3773 {
3774 errno = EVMSERR;
3775 vaxc$errno = status;
3776 return 0;
3777 }
3778 /* read the requested record - index is in uic */
3779 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3780 uaf_rab.rab$l_kbf = (char *) &uic;
3781 uaf_rab.rab$b_ksz = sizeof uic;
3782 uaf_rab.rab$b_rac = RAB$C_KEY;
3783 uaf_rab.rab$l_ubf = (char *)&retuaf;
3784 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3785 status = SYS$GET (&uaf_rab);
86a5659e
JB
3786 if (!(status&1))
3787 {
3788 errno = EVMSERR;
3789 vaxc$errno = status;
3790 return 0;
3791 }
3792 /* close the User Authorization File */
986ffb24 3793 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3794 if (!(status&1))
3795 {
3796 errno = EVMSERR;
3797 vaxc$errno = status;
3798 return 0;
3799 }
986ffb24 3800 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3801 if (!(status&1))
3802 {
3803 errno = EVMSERR;
3804 vaxc$errno = status;
3805 return 0;
3806 }
3807 return &retuaf;
3808}
3809
3810static struct passwd retpw;
3811
3812struct passwd *
3813cnv_uaf_pw (up)
3814 struct UAF * up;
3815{
3816 char * ptr;
3817
3818 /* copy these out first because if the username is 32 chars, the next
3819 section will overwrite the first byte of the UIC */
3820 retpw.pw_uid = up->uaf$w_mem;
3821 retpw.pw_gid = up->uaf$w_grp;
3822
3823 /* I suppose this is not the best sytle, to possibly overwrite one
3824 byte beyond the end of the field, but what the heck... */
3825 ptr = &up->uaf$t_username[UAF$S_USERNAME];
3826 while (ptr[-1] == ' ')
3827 ptr--;
3828 *ptr = '\0';
3829 strcpy (retpw.pw_name, up->uaf$t_username);
3830
3831 /* the rest of these are counted ascii strings */
3832 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3833 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3834 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3835 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3836 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3837 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3838 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3839 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3840
3841 return &retpw;
3842}
3843#else /* not READ_SYSUAF */
3844static struct passwd retpw;
3845#endif /* not READ_SYSUAF */
3846
3847struct passwd *
3848getpwnam (name)
3849 char * name;
3850{
3851#ifdef READ_SYSUAF
3852 struct UAF *up;
3853#else
3854 char * user;
3855 char * dir;
3856 unsigned char * full;
3857#endif /* READ_SYSUAF */
3858 char *ptr = name;
3859
3860 while (*ptr)
3861 {
3862 if ('a' <= *ptr && *ptr <= 'z')
3863 *ptr -= 040;
3864 ptr++;
3865 }
3866#ifdef READ_SYSUAF
3867 if (!(up = get_uaf_name (name)))
3868 return 0;
3869 return cnv_uaf_pw (up);
3870#else
3871 if (strcmp (name, getenv ("USER")) == 0)
3872 {
3873 retpw.pw_uid = getuid ();
3874 retpw.pw_gid = getgid ();
3875 strcpy (retpw.pw_name, name);
3876 if (full = egetenv ("FULLNAME"))
3877 strcpy (retpw.pw_gecos, full);
3878 else
3879 *retpw.pw_gecos = '\0';
3880 strcpy (retpw.pw_dir, egetenv ("HOME"));
3881 *retpw.pw_shell = '\0';
3882 return &retpw;
3883 }
3884 else
3885 return 0;
3886#endif /* not READ_SYSUAF */
3887}
3888
3889struct passwd *
3890getpwuid (uid)
3891 unsigned long uid;
3892{
3893#ifdef READ_SYSUAF
3894 struct UAF * up;
3895
3896 if (!(up = get_uaf_uic (uid)))
3897 return 0;
3898 return cnv_uaf_pw (up);
3899#else
3900 if (uid == sys_getuid ())
3901 return getpwnam (egetenv ("USER"));
3902 else
3903 return 0;
3904#endif /* not READ_SYSUAF */
3905}
3906
3907/* return total address space available to the current process. This is
3908 the sum of the current p0 size, p1 size and free page table entries
3909 available. */
3910vlimit ()
3911{
3912 int item_code;
3913 unsigned long free_pages;
3914 unsigned long frep0va;
3915 unsigned long frep1va;
3916 register status;
3917
3918 item_code = JPI$_FREPTECNT;
3919 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
3920 {
3921 errno = EVMSERR;
3922 vaxc$errno = status;
3923 return -1;
3924 }
3925 free_pages *= 512;
3926
3927 item_code = JPI$_FREP0VA;
3928 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
3929 {
3930 errno = EVMSERR;
3931 vaxc$errno = status;
3932 return -1;
3933 }
3934 item_code = JPI$_FREP1VA;
3935 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
3936 {
3937 errno = EVMSERR;
3938 vaxc$errno = status;
3939 return -1;
3940 }
3941
3942 return free_pages + frep0va + (0x7fffffff - frep1va);
3943}
3944
3945define_logical_name (varname, string)
3946 char *varname;
3947 char *string;
3948{
3949 struct dsc$descriptor_s strdsc =
3950 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
3951 struct dsc$descriptor_s envdsc =
3952 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3953 struct dsc$descriptor_s lnmdsc =
3954 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3955
3956 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
3957}
3958
3959delete_logical_name (varname)
3960 char *varname;
3961{
3962 struct dsc$descriptor_s envdsc =
3963 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3964 struct dsc$descriptor_s lnmdsc =
3965 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3966
3967 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
3968}
3969
3970ulimit ()
3971{}
3972
86a5659e
JB
3973setpgrp ()
3974{}
3975
3976execvp ()
3977{
3978 error ("execvp system call not implemented");
3979}
3980
3981int
3982rename (from, to)
3983 char *from, *to;
3984{
3985 int status;
3986 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
3987 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
3988 char from_esn[NAM$C_MAXRSS];
3989 char to_esn[NAM$C_MAXRSS];
3990
3991 from_fab.fab$l_fna = from;
3992 from_fab.fab$b_fns = strlen (from);
3993 from_fab.fab$l_nam = &from_nam;
3994 from_fab.fab$l_fop = FAB$M_NAM;
3995
3996 from_nam.nam$l_esa = from_esn;
3997 from_nam.nam$b_ess = sizeof from_esn;
3998
3999 to_fab.fab$l_fna = to;
4000 to_fab.fab$b_fns = strlen (to);
4001 to_fab.fab$l_nam = &to_nam;
4002 to_fab.fab$l_fop = FAB$M_NAM;
4003
4004 to_nam.nam$l_esa = to_esn;
4005 to_nam.nam$b_ess = sizeof to_esn;
4006
4007 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4008
4009 if (status & 1)
4010 return 0;
4011 else
4012 {
4013 if (status == RMS$_DEV)
4014 errno = EXDEV;
4015 else
4016 errno = EVMSERR;
4017 vaxc$errno = status;
4018 return -1;
4019 }
4020}
4021
4022/* This function renames a file like `rename', but it strips
4023 the version number from the "to" filename, such that the "to" file is
4024 will always be a new version. It also sets the file protection once it is
4025 finished. The protection that we will use is stored in fab_final_pro,
4026 and was set when we did a creat_copy_attrs to create the file that we
4027 are renaming.
4028
4029 We could use the chmod function, but Eunichs uses 3 bits per user category
4030 to describe the protection, and VMS uses 4 (write and delete are seperate
4031 bits). To maintain portability, the VMS implementation of `chmod' wires
4032 the W and D bits together. */
4033
4034
4035static struct fibdef fib; /* We need this initialized to zero */
4036char vms_file_written[NAM$C_MAXRSS];
4037
4038int
4039rename_sans_version (from,to)
4040 char *from, *to;
4041{
4042 short int chan;
4043 int stat;
4044 short int iosb[4];
4045 int status;
4046 struct FAB to_fab = cc$rms_fab;
4047 struct NAM to_nam = cc$rms_nam;
4048 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4049 struct dsc$descriptor fib_attr[2]
4050 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4051 char to_esn[NAM$C_MAXRSS];
4052
4053 $DESCRIPTOR (disk,to_esn);
4054
4055 to_fab.fab$l_fna = to;
4056 to_fab.fab$b_fns = strlen (to);
4057 to_fab.fab$l_nam = &to_nam;
4058 to_fab.fab$l_fop = FAB$M_NAM;
4059
4060 to_nam.nam$l_esa = to_esn;
4061 to_nam.nam$b_ess = sizeof to_esn;
4062
4063 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4064
4065 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4066 *(to_nam.nam$l_ver) = '\0';
4067
4068 stat = rename (from, to_esn);
4069 if (stat < 0)
4070 return stat;
4071
4072 strcpy (vms_file_written, to_esn);
4073
4074 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4075 to_fab.fab$b_fns = strlen (vms_file_written);
4076
4077 /* Now set the file protection to the correct value */
986ffb24 4078 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
86a5659e
JB
4079
4080 /* Copy these fields into the fib */
4081 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4082 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4083 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4084
986ffb24 4085 SYS$CLOSE (&to_fab, 0, 0);
86a5659e 4086
986ffb24 4087 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
86a5659e 4088 if (!stat)
986ffb24
JB
4089 LIB$SIGNAL (stat);
4090 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
86a5659e
JB
4091 0, 0, 0, &fib_attr, 0);
4092 if (!stat)
986ffb24
JB
4093 LIB$SIGNAL (stat);
4094 stat = SYS$DASSGN (chan);
86a5659e 4095 if (!stat)
986ffb24 4096 LIB$SIGNAL (stat);
0137dbf7 4097 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
4098 return 0;
4099}
4100
4101link (file, new)
4102 char * file, * new;
4103{
4104 register status;
4105 struct FAB fab;
4106 struct NAM nam;
4107 unsigned short fid[3];
4108 char esa[NAM$C_MAXRSS];
4109
4110 fab = cc$rms_fab;
4111 fab.fab$l_fop = FAB$M_OFP;
4112 fab.fab$l_fna = file;
4113 fab.fab$b_fns = strlen (file);
4114 fab.fab$l_nam = &nam;
4115
4116 nam = cc$rms_nam;
4117 nam.nam$l_esa = esa;
4118 nam.nam$b_ess = NAM$C_MAXRSS;
4119
4120 status = SYS$PARSE (&fab);
4121 if ((status & 1) == 0)
4122 {
4123 errno = EVMSERR;
4124 vaxc$errno = status;
4125 return -1;
4126 }
4127 status = SYS$SEARCH (&fab);
4128 if ((status & 1) == 0)
4129 {
4130 errno = EVMSERR;
4131 vaxc$errno = status;
4132 return -1;
4133 }
4134
4135 fid[0] = nam.nam$w_fid[0];
4136 fid[1] = nam.nam$w_fid[1];
4137 fid[2] = nam.nam$w_fid[2];
4138
4139 fab.fab$l_fna = new;
4140 fab.fab$b_fns = strlen (new);
4141
4142 status = SYS$PARSE (&fab);
4143 if ((status & 1) == 0)
4144 {
4145 errno = EVMSERR;
4146 vaxc$errno = status;
4147 return -1;
4148 }
4149
4150 nam.nam$w_fid[0] = fid[0];
4151 nam.nam$w_fid[1] = fid[1];
4152 nam.nam$w_fid[2] = fid[2];
4153
4154 nam.nam$l_esa = nam.nam$l_name;
4155 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
4156
4157 status = SYS$ENTER (&fab);
4158 if ((status & 1) == 0)
4159 {
4160 errno = EVMSERR;
4161 vaxc$errno = status;
4162 return -1;
4163 }
4164
4165 return 0;
4166}
4167
4168croak (badfunc)
4169 char *badfunc;
4170{
4171 printf ("%s not yet implemented\r\n", badfunc);
4172 reset_sys_modes ();
4173 exit (1);
4174}
4175
4176long
4177random ()
4178{
4179 /* Arrange to return a range centered on zero. */
4180 return rand () - (1 << 30);
4181}
4182
4183srandom (seed)
4184{
4185 srand (seed);
4186}
4187#endif /* VMS */
4188\f
4189#ifdef AIX
4190
4191/* Called from init_sys_modes. */
4192hft_init ()
4193{
4194 int junk;
4195
4196 /* If we're not on an HFT we shouldn't do any of this. We determine
4197 if we are on an HFT by trying to get an HFT error code. If this
4198 call fails, we're not on an HFT. */
4199#ifdef IBMR2AIX
4200 if (ioctl (0, HFQERROR, &junk) < 0)
4201 return;
4202#else /* not IBMR2AIX */
4203 if (ioctl (0, HFQEIO, 0) < 0)
4204 return;
4205#endif /* not IBMR2AIX */
4206
4207 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4208 as the rubout key's ASCII code. Here this is changed. The bug is that
4209 there's no way to determine the old mapping, so in reset_sys_modes
4210 we need to assume that the normal map had been present. Of course, this
4211 code also doesn't help if on a terminal emulator which doesn't understand
4212 HFT VTD's. */
4213 {
4214 struct hfbuf buf;
4215 struct hfkeymap keymap;
4216
4217 buf.hf_bufp = (char *)&keymap;
4218 buf.hf_buflen = sizeof (keymap);
4219 keymap.hf_nkeys = 2;
4220 keymap.hfkey[0].hf_kpos = 15;
4221 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4222#ifdef IBMR2AIX
4223 keymap.hfkey[0].hf_keyidh = '<';
4224#else /* not IBMR2AIX */
4225 keymap.hfkey[0].hf_page = '<';
4226#endif /* not IBMR2AIX */
4227 keymap.hfkey[0].hf_char = 127;
4228 keymap.hfkey[1].hf_kpos = 15;
4229 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4230#ifdef IBMR2AIX
4231 keymap.hfkey[1].hf_keyidh = '<';
4232#else /* not IBMR2AIX */
4233 keymap.hfkey[1].hf_page = '<';
4234#endif /* not IBMR2AIX */
4235 keymap.hfkey[1].hf_char = 127;
4236 hftctl (0, HFSKBD, &buf);
4237 }
4238 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4239 at times. */
4240 line_ins_del_ok = char_ins_del_ok = 0;
4241}
4242
4243/* Reset the rubout key to backspace. */
4244
4245hft_reset ()
4246{
4247 struct hfbuf buf;
4248 struct hfkeymap keymap;
4249 int junk;
4250
4251#ifdef IBMR2AIX
4252 if (ioctl (0, HFQERROR, &junk) < 0)
4253 return;
4254#else /* not IBMR2AIX */
4255 if (ioctl (0, HFQEIO, 0) < 0)
4256 return;
4257#endif /* not IBMR2AIX */
4258
4259 buf.hf_bufp = (char *)&keymap;
4260 buf.hf_buflen = sizeof (keymap);
4261 keymap.hf_nkeys = 2;
4262 keymap.hfkey[0].hf_kpos = 15;
4263 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4264#ifdef IBMR2AIX
4265 keymap.hfkey[0].hf_keyidh = '<';
4266#else /* not IBMR2AIX */
4267 keymap.hfkey[0].hf_page = '<';
4268#endif /* not IBMR2AIX */
4269 keymap.hfkey[0].hf_char = 8;
4270 keymap.hfkey[1].hf_kpos = 15;
4271 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4272#ifdef IBMR2AIX
4273 keymap.hfkey[1].hf_keyidh = '<';
4274#else /* not IBMR2AIX */
4275 keymap.hfkey[1].hf_page = '<';
4276#endif /* not IBMR2AIX */
4277 keymap.hfkey[1].hf_char = 8;
4278 hftctl (0, HFSKBD, &buf);
4279}
4280
4281#endif /* AIX */