* s/aix3-2.h (C_SWITCH_SYSTEM): Don't define this to be "-ma" if
[bpt/emacs.git] / src / sysdep.c
CommitLineData
86a5659e 1/* Interfaces to system-dependent kernel and library entries.
c6c5df7f 2 Copyright (C) 1985, 1986, 1987, 1988, 1993 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 */
280073d7 317#if (defined (BSD) && !defined (LINUX)) || (defined (HPUX) && !defined (HPUX_5))
4c8975ad
RS
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);
280073d7 336#else /* not BSD, not LINUX, and not HPUX version >= 6 */
5f3461a5 337#if defined (UNIPLUS) || defined (LINUX)
4c8975ad
RS
338 if (0 > kill (pid, 0))
339 break;
340 wait (0);
5f3461a5 341#else /* neither BSD nor UNIPLUS nor LINUX: random sysV */
4c8975ad
RS
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 1714
f8a80313
RS
1715#ifndef BSD4_1
1716#ifndef USG
1717#ifndef VMS
1718#ifdef HAVE_SOCKETS
1719#include <sys/socket.h>
1720#include <netdb.h>
1721#endif /* HAVE_SOCKETS */
1722#endif /* not VMS */
1723#endif /* not USG */
1724#endif /* not BSD4_1 */
1725
86a5659e
JB
1726char *
1727get_system_name ()
1728{
1729#ifdef USG
e36ba278
RS
1730#ifdef HAVE_GETHOSTNAME
1731 gethostname (get_system_name_name, sizeof (get_system_name_name));
1732 return get_system_name_name;
1733#else /* not HAVE_GETHOSTNAME */
86a5659e
JB
1734 uname (&get_system_name_name);
1735 return (get_system_name_name.nodename);
e36ba278 1736#endif /* not HAVE_GETHOSTNAME */
86a5659e
JB
1737#else /* Not USG */
1738#ifdef BSD4_1
1739 return sysname;
1740#else /* not USG, not 4.1 */
1741 static char system_name_saved[32];
1742#ifdef VMS
1743 char *sp;
1744 if ((sp = egetenv ("SYS$NODE")) == 0)
1745 sp = "vax-vms";
1746 else
1747 {
1748 char *end;
1749
1750 if ((end = index (sp, ':')) != 0)
1751 *end = '\0';
1752 }
1753 strcpy (system_name_saved, sp);
1754#else /* not VMS */
1755 gethostname (system_name_saved, sizeof (system_name_saved));
f8a80313
RS
1756#ifdef HAVE_SOCKETS
1757 /* Turn the hostname into the official, fully-qualified hostname.
1758 Don't do this if we're going to dump; this can confuse system
1759 libraries on some machines and make the dumped emacs core dump. */
1760#ifndef CANNOT_DUMP
1761 if (initialized)
1762#endif /* not CANNOT_DUMP */
1763 {
1764 struct hostent *hp;
1765 hp = gethostbyname (system_name_saved);
1766 if (hp && strlen (hp->h_name) < sizeof(system_name_saved))
1767 strcpy (system_name_saved, hp->h_name);
1768 }
1769#endif /* HAVE_SOCKETS */
86a5659e
JB
1770#endif /* not VMS */
1771 return system_name_saved;
1772#endif /* not USG, not 4.1 */
1773#endif /* not USG */
1774}
210b2b4f
JB
1775
1776#ifdef VMS
1777#ifndef HAVE_GETHOSTNAME
1778void gethostname(buf, len)
1779 char *buf;
1780 int len;
1781{
1782 char *s;
1783 s = getenv ("SYS$NODE");
1784 if (s == NULL)
1785 buf[0] = '\0';
1786 else {
1787 strncpy (buf, s, len - 2);
1788 buf[len - 1] = '\0';
1789 } /* else */
1790} /* static void gethostname */
1791#endif /* ! HAVE_GETHOSTNAME */
1792#endif /* VMS */
1793
86a5659e
JB
1794\f
1795#ifndef VMS
1796#ifndef HAVE_SELECT
1797
1798#ifdef HAVE_X_WINDOWS
1799/* Cause explanatory error message at compile time,
1800 since the select emulation is not good enough for X. */
1801int *x = &x_windows_lose_if_no_select_system_call;
1802#endif
1803
1804/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1805 * Only checks read descriptors.
1806 */
1807/* How long to wait between checking fds in select */
1808#define SELECT_PAUSE 1
1809int select_alarmed;
1810
1811/* For longjmp'ing back to read_input_waiting. */
1812
1813jmp_buf read_alarm_throw;
1814
1815/* Nonzero if the alarm signal should throw back to read_input_waiting.
1816 The read_socket_hook function sets this to 1 while it is waiting. */
1817
1818int read_alarm_should_throw;
1819
1820SIGTYPE
1821select_alarm ()
1822{
1823 select_alarmed = 1;
1824#ifdef BSD4_1
1825 sigrelse (SIGALRM);
1826#else /* not BSD4_1 */
1827 signal (SIGALRM, SIG_IGN);
1828#endif /* not BSD4_1 */
1829 if (read_alarm_should_throw)
1830 longjmp (read_alarm_throw, 1);
1831}
1832
1833/* Only rfds are checked. */
1834int
1835select (nfds, rfds, wfds, efds, timeout)
1836 int nfds;
1837 int *rfds, *wfds, *efds, *timeout;
1838{
1839 int ravail = 0, orfds = 0, old_alarm;
1840 int timeoutval = timeout ? *timeout : 100000;
1841 int *local_timeout = &timeoutval;
1842 extern int proc_buffered_char[];
1843#ifndef subprocesses
1844 int process_tick = 0, update_tick = 0;
1845#else
1846 extern int process_tick, update_tick;
1847#endif
1848 SIGTYPE (*old_trap) ();
1849 unsigned char buf;
1850
1851 if (rfds)
1852 {
1853 orfds = *rfds;
1854 *rfds = 0;
1855 }
1856 if (wfds)
1857 *wfds = 0;
1858 if (efds)
1859 *efds = 0;
1860
1861 /* If we are looking only for the terminal, with no timeout,
1862 just read it and wait -- that's more efficient. */
1863 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
1864 {
1865 if (! detect_input_pending ())
1866 read_input_waiting ();
1867 *rfds = 1;
1868 return 1;
1869 }
1870
1871 /* Once a second, till the timer expires, check all the flagged read
1872 * descriptors to see if any input is available. If there is some then
1873 * set the corresponding bit in the return copy of rfds.
1874 */
1875 while (1)
1876 {
1877 register int to_check, bit, fd;
1878
1879 if (rfds)
1880 {
1881 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
1882 {
1883 if (orfds & bit)
1884 {
1885 int avail = 0, status = 0;
1886
1887 if (bit == 1)
1888 avail = detect_input_pending (); /* Special keyboard handler */
1889 else
1890 {
1891#ifdef FIONREAD
1892 status = ioctl (fd, FIONREAD, &avail);
1893#else /* no FIONREAD */
1894 /* Hoping it will return -1 if nothing available
1895 or 0 if all 0 chars requested are read. */
1896 if (proc_buffered_char[fd] >= 0)
1897 avail = 1;
1898 else
1899 {
1900 avail = read (fd, &buf, 1);
1901 if (avail > 0)
1902 proc_buffered_char[fd] = buf;
1903 }
1904#endif /* no FIONREAD */
1905 }
1906 if (status >= 0 && avail > 0)
1907 {
1908 (*rfds) |= bit;
1909 ravail++;
1910 }
1911 }
1912 }
1913 }
1914 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1915 break;
1916 old_alarm = alarm (0);
34567704 1917 old_trap = signal (SIGALRM, select_alarm);
86a5659e
JB
1918 select_alarmed = 0;
1919 alarm (SELECT_PAUSE);
1920 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1921 while (select_alarmed == 0 && *local_timeout != 0
1922 && process_tick == update_tick)
1923 {
1924 /* If we are interested in terminal input,
1925 wait by reading the terminal.
1926 That makes instant wakeup for terminal input at least. */
1927 if (orfds & 1)
1928 {
1929 read_input_waiting ();
1930 if (detect_input_pending ())
1931 select_alarmed = 1;
1932 }
1933 else
1934 pause ();
1935 }
1936 (*local_timeout) -= SELECT_PAUSE;
1937 /* Reset the old alarm if there was one */
1938 alarm (0);
1939 signal (SIGALRM, old_trap);
1940 if (old_alarm != 0)
1941 {
1942 /* Reset or forge an interrupt for the original handler. */
1943 old_alarm -= SELECT_PAUSE;
1944 if (old_alarm <= 0)
1945 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
1946 else
1947 alarm (old_alarm);
1948 }
1949 if (*local_timeout == 0) /* Stop on timer being cleared */
1950 break;
1951 }
1952 return ravail;
1953}
1954
1955/* Read keyboard input into the standard buffer,
1956 waiting for at least one character. */
1957
1958/* Make all keyboard buffers much bigger when using X windows. */
1959#ifdef HAVE_X_WINDOWS
1960#define BUFFER_SIZE_FACTOR 16
1961#else
1962#define BUFFER_SIZE_FACTOR 1
1963#endif
1964
1965read_input_waiting ()
1966{
1967 char buf[256 * BUFFER_SIZE_FACTOR];
1968 struct input_event e;
34567704
JB
1969 int nread, i;
1970 extern int quit_char;
86a5659e
JB
1971
1972 if (read_socket_hook)
1973 {
1974 read_alarm_should_throw = 0;
1975 if (! setjmp (read_alarm_throw))
1976 nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
1977 else
1978 nread = -1;
1979 }
1980 else
1981 nread = read (fileno (stdin), buf, 1);
1982
1983 /* Scan the chars for C-g and store them in kbd_buffer. */
1984 e.kind = ascii_keystroke;
6c65530f 1985 e.frame_or_window = selected_frame;
57ef1664 1986 e.modifiers = 0;
86a5659e
JB
1987 for (i = 0; i < nread; i++)
1988 {
1989 XSET (e.code, Lisp_Int, buf[i]);
1990 kbd_buffer_store_event (&e);
1991 /* Don't look at input that follows a C-g too closely.
1992 This reduces lossage due to autorepeat on C-g. */
34567704 1993 if (buf[i] == quit_char)
86a5659e
JB
1994 break;
1995 }
1996}
1997
1998#endif /* not HAVE_SELECT */
1999#endif /* not VMS */
2000\f
2001#ifdef BSD4_1
86a5659e
JB
2002/*
2003 * Partially emulate 4.2 open call.
2004 * open is defined as this in 4.1.
2005 *
2006 * - added by Michael Bloom @ Citicorp/TTI
2007 *
2008 */
2009
2010int
2011sys_open (path, oflag, mode)
2012 char *path;
2013 int oflag, mode;
2014{
2015 if (oflag & O_CREAT)
2016 return creat (path, mode);
2017 else
2018 return open (path, oflag);
2019}
2020
2021init_sigio ()
2022{
2023 if (noninteractive)
2024 return;
2025 lmode = LINTRUP | lmode;
2026 ioctl (0, TIOCLSET, &lmode);
2027}
2028
2029reset_sigio ()
2030{
2031 if (noninteractive)
2032 return;
2033 lmode = ~LINTRUP & lmode;
2034 ioctl (0, TIOCLSET, &lmode);
2035}
2036
2037request_sigio ()
2038{
2039 sigrelse (SIGTINT);
2040
2041 interrupts_deferred = 0;
2042}
2043
2044unrequest_sigio ()
2045{
2046 sighold (SIGTINT);
2047
2048 interrupts_deferred = 1;
2049}
2050
2051/* still inside #ifdef BSD4_1 */
2052#ifdef subprocesses
2053
2054int sigheld; /* Mask of held signals */
2055
2056sigholdx (signum)
2057 int signum;
2058{
2059 sigheld |= sigbit (signum);
2060 sighold (signum);
2061}
2062
2063sigisheld (signum)
2064 int signum;
2065{
2066 sigheld |= sigbit (signum);
2067}
2068
2069sigunhold (signum)
2070 int signum;
2071{
2072 sigheld &= ~sigbit (signum);
2073 sigrelse (signum);
2074}
2075
2076sigfree () /* Free all held signals */
2077{
2078 int i;
2079 for (i = 0; i < NSIG; i++)
2080 if (sigheld & sigbit (i))
2081 sigrelse (i);
2082 sigheld = 0;
2083}
2084
2085sigbit (i)
2086{
2087 return 1 << (i - 1);
2088}
2089#endif /* subprocesses */
2090#endif /* BSD4_1 */
2091\f
2092/* POSIX signals support - DJB */
2093/* Anyone with POSIX signals should have ANSI C declarations */
2094
2095#ifdef POSIX_SIGNALS
2096
2097sigset_t old_mask, empty_mask, full_mask, temp_mask;
2098static struct sigaction new_action, old_action;
2099
2100init_signals ()
2101{
00eaaa32
JB
2102 sigemptyset (&empty_mask);
2103 sigfillset (&full_mask);
86a5659e
JB
2104}
2105
86a5659e
JB
2106signal_handler_t
2107sys_signal (int signal_number, signal_handler_t action)
2108{
2109#ifdef DGUX
2110 /* This gets us restartable system calls for efficiency.
2111 The "else" code will works as well. */
2112 return (berk_signal (signal_number, action));
2113#else
2114 sigemptyset (&new_action.sa_mask);
2115 new_action.sa_handler = action;
2116 new_action.sa_flags = NULL;
d32b2f3c 2117 sigaction (signal_number, &new_action, &old_action);
86a5659e
JB
2118 return (old_action.sa_handler);
2119#endif /* DGUX */
2120}
2121
e065a56e
JB
2122#ifndef __GNUC__
2123/* If we're compiling with GCC, we don't need this function, since it
2124 can be written as a macro. */
2125sigset_t
2126sys_sigmask (int sig)
2127{
2128 sigset_t mask;
2129 sigemptyset (&mask);
2130 sigaddset (&mask, sig);
2131 return mask;
2132}
2133#endif
2134
86a5659e
JB
2135int
2136sys_sigpause (sigset_t new_mask)
2137{
2138 /* pause emulating berk sigpause... */
2139 sigsuspend (&new_mask);
2140 return (EINTR);
2141}
2142
2143/* I'd like to have these guys return pointers to the mask storage in here,
2144 but there'd be trouble if the code was saving multiple masks. I'll be
2145 safe and pass the structure. It normally won't be more than 2 bytes
2146 anyhow. - DJB */
2147
2148sigset_t
2149sys_sigblock (sigset_t new_mask)
2150{
2151 sigset_t old_mask;
2152 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2153 return (old_mask);
2154}
2155
2156sigset_t
2157sys_sigunblock (sigset_t new_mask)
2158{
2159 sigset_t old_mask;
2160 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2161 return (old_mask);
2162}
2163
2164sigset_t
2165sys_sigsetmask (sigset_t new_mask)
2166{
2167 sigset_t old_mask;
2168 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2169 return (old_mask);
2170}
2171
2172#endif /* POSIX_SIGNALS */
2173\f
2174#ifndef BSTRING
2175
2176void
2177bzero (b, length)
2178 register char *b;
2179 register int length;
2180{
2181#ifdef VMS
2182 short zero = 0;
2183 long max_str = 65535;
2184
2185 while (length > max_str) {
2186 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2187 length -= max_str;
2188 b += max_str;
2189 }
2190 max_str = length;
2191 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2192#else
2193 while (length-- > 0)
2194 *b++ = 0;
2195#endif /* not VMS */
2196}
2197
2198/* Saying `void' requires a declaration, above, where bcopy is used
2199 and that declaration causes pain for systems where bcopy is a macro. */
2200bcopy (b1, b2, length)
2201 register char *b1;
2202 register char *b2;
2203 register int length;
2204{
2205#ifdef VMS
2206 long max_str = 65535;
2207
2208 while (length > max_str) {
2209 (void) LIB$MOVC3 (&max_str, b1, b2);
2210 length -= max_str;
2211 b1 += max_str;
2212 b2 += max_str;
2213 }
2214 max_str = length;
2215 (void) LIB$MOVC3 (&length, b1, b2);
2216#else
2217 while (length-- > 0)
2218 *b2++ = *b1++;
2219#endif /* not VMS */
2220}
2221
2222int
2223bcmp (b1, b2, length) /* This could be a macro! */
2224 register char *b1;
2225 register char *b2;
2226 register int length;
2227{
2228#ifdef VMS
2229 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
2230 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
2231
2232 return STR$COMPARE (&src1, &src2);
2233#else
2234 while (length-- > 0)
2235 if (*b1++ != *b2++)
2236 return 1;
2237
2238 return 0;
2239#endif /* not VMS */
2240}
2241#endif /* not BSTRING */
2242\f
9927a7b1 2243#ifndef HAVE_RANDOM
86a5659e
JB
2244#ifdef USG
2245/*
2246 * The BSD random returns numbers in the range of
2247 * 0 to 2e31 - 1. The USG rand returns numbers in the
2248 * range of 0 to 2e15 - 1. This is probably not significant
2249 * in this usage.
2250 */
2251
2252long
2253random ()
2254{
2255 /* Arrange to return a range centered on zero. */
2256 return (rand () << 15) + rand () - (1 << 29);
2257}
2258
2259srandom (arg)
2260 int arg;
2261{
2262 srand (arg);
2263}
2264
2265#endif /* USG */
2266
2267#ifdef BSD4_1
2268long random ()
2269{
2270 /* Arrange to return a range centered on zero. */
2271 return (rand () << 15) + rand () - (1 << 29);
2272}
2273
2274srandom (arg)
2275 int arg;
2276{
2277 srand (arg);
2278}
2279#endif /* BSD4_1 */
9927a7b1 2280#endif
86a5659e
JB
2281\f
2282#ifdef WRONG_NAME_INSQUE
2283
2284insque (q,p)
2285 caddr_t q,p;
2286{
2287 _insque (q,p);
2288}
2289
2290#endif
2291\f
2292#ifdef VMS
2293
2294#ifdef getenv
2295/* If any place else asks for the TERM variable,
2296 allow it to be overridden with the EMACS_TERM variable
2297 before attempting to translate the logical name TERM. As a last
2298 resort, ask for VAX C's special idea of the TERM variable. */
2299#undef getenv
2300char *
2301sys_getenv (name)
2302 char *name;
2303{
2304 register char *val;
2305 static char buf[256];
2306 static struct dsc$descriptor_s equiv
2307 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2308 static struct dsc$descriptor_s d_name
2309 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2310 short eqlen;
2311
2312 if (!strcmp (name, "TERM"))
2313 {
2314 val = (char *) getenv ("EMACS_TERM");
2315 if (val)
2316 return val;
2317 }
2318
2319 d_name.dsc$w_length = strlen (name);
2320 d_name.dsc$a_pointer = name;
986ffb24 2321 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
86a5659e
JB
2322 {
2323 char *str = (char *) xmalloc (eqlen + 1);
2324 bcopy (buf, str, eqlen);
2325 str[eqlen] = '\0';
2326 /* This is a storage leak, but a pain to fix. With luck,
2327 no one will ever notice. */
2328 return str;
2329 }
2330 return (char *) getenv (name);
2331}
2332#endif /* getenv */
2333
2334#ifdef abort
2335/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2336 to force a call on the debugger from within the image. */
2337#undef abort
2338sys_abort ()
2339{
2340 reset_sys_modes ();
2341 LIB$SIGNAL (SS$_DEBUG);
2342}
2343#endif /* abort */
2344#endif /* VMS */
2345\f
2346#ifdef VMS
2347#ifdef LINK_CRTL_SHARE
2348#ifdef SHAREABLE_LIB_BUG
2349/* Variables declared noshare and initialized in shareable libraries
2350 cannot be shared. The VMS linker incorrectly forces you to use a private
2351 version which is uninitialized... If not for this "feature", we
2352 could use the C library definition of sys_nerr and sys_errlist. */
2353int sys_nerr = 35;
2354char *sys_errlist[] =
2355 {
2356 "error 0",
2357 "not owner",
2358 "no such file or directory",
2359 "no such process",
2360 "interrupted system call",
2361 "i/o error",
2362 "no such device or address",
2363 "argument list too long",
2364 "exec format error",
2365 "bad file number",
2366 "no child process",
2367 "no more processes",
2368 "not enough memory",
2369 "permission denied",
2370 "bad address",
2371 "block device required",
2372 "mount devices busy",
2373 "file exists",
2374 "cross-device link",
2375 "no such device",
2376 "not a directory",
2377 "is a directory",
2378 "invalid argument",
2379 "file table overflow",
2380 "too many open files",
2381 "not a typewriter",
2382 "text file busy",
2383 "file too big",
2384 "no space left on device",
2385 "illegal seek",
2386 "read-only file system",
2387 "too many links",
2388 "broken pipe",
2389 "math argument",
2390 "result too large",
2391 "I/O stream empty",
2392 "vax/vms specific error code nontranslatable error"
2393 };
2394#endif /* SHAREABLE_LIB_BUG */
2395#endif /* LINK_CRTL_SHARE */
2396#endif /* VMS */
2397\f
2398#ifdef INTERRUPTIBLE_OPEN
2399
2400int
2401/* VARARGS 2 */
2402sys_open (path, oflag, mode)
2403 char *path;
2404 int oflag, mode;
2405{
2406 register int rtnval;
2407
2408 while ((rtnval = open (path, oflag, mode)) == -1
2409 && (errno == EINTR));
2410 return (rtnval);
2411}
2412
2413#endif /* INTERRUPTIBLE_OPEN */
2414
2415#ifdef INTERRUPTIBLE_CLOSE
2416
2417sys_close (fd)
2418 int fd;
2419{
2420 register int rtnval;
2421
2422 while ((rtnval = close (fd)) == -1
2423 && (errno == EINTR));
2424 return rtnval;
2425}
2426
2427#endif /* INTERRUPTIBLE_CLOSE */
2428
2429#ifdef INTERRUPTIBLE_IO
2430
2431int
2432sys_read (fildes, buf, nbyte)
2433 int fildes;
2434 char *buf;
2435 unsigned int nbyte;
2436{
2437 register int rtnval;
2438
2439 while ((rtnval = read (fildes, buf, nbyte)) == -1
2440 && (errno == EINTR));
2441 return (rtnval);
2442}
2443
2444int
2445sys_write (fildes, buf, nbyte)
2446 int fildes;
2447 char *buf;
2448 unsigned int nbyte;
2449{
2450 register int rtnval;
2451
2452 while ((rtnval = write (fildes, buf, nbyte)) == -1
2453 && (errno == EINTR));
2454 return (rtnval);
2455}
2456
2457#endif /* INTERRUPTIBLE_IO */
2458\f
2459#ifdef USG
2460/*
2461 * All of the following are for USG.
2462 *
2463 * On USG systems the system calls are INTERRUPTIBLE by signals
2464 * that the user program has elected to catch. Thus the system call
2465 * must be retried in these cases. To handle this without massive
2466 * changes in the source code, we remap the standard system call names
2467 * to names for our own functions in sysdep.c that do the system call
2468 * with retries. Actually, for portability reasons, it is good
2469 * programming practice, as this example shows, to limit all actual
2470 * system calls to a single occurance in the source. Sure, this
2471 * adds an extra level of function call overhead but it is almost
2472 * always negligible. Fred Fish, Unisoft Systems Inc.
2473 */
2474
00eaaa32 2475#ifndef HAVE_SYS_SIGLIST
86a5659e
JB
2476char *sys_siglist[NSIG + 1] =
2477{
2478#ifdef AIX
2479/* AIX has changed the signals a bit */
2480 "bogus signal", /* 0 */
2481 "hangup", /* 1 SIGHUP */
2482 "interrupt", /* 2 SIGINT */
2483 "quit", /* 3 SIGQUIT */
2484 "illegal instruction", /* 4 SIGILL */
2485 "trace trap", /* 5 SIGTRAP */
2486 "IOT instruction", /* 6 SIGIOT */
2487 "crash likely", /* 7 SIGDANGER */
2488 "floating point exception", /* 8 SIGFPE */
2489 "kill", /* 9 SIGKILL */
2490 "bus error", /* 10 SIGBUS */
2491 "segmentation violation", /* 11 SIGSEGV */
2492 "bad argument to system call", /* 12 SIGSYS */
2493 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2494 "alarm clock", /* 14 SIGALRM */
2495 "software termination signum", /* 15 SIGTERM */
2496 "user defined signal 1", /* 16 SIGUSR1 */
2497 "user defined signal 2", /* 17 SIGUSR2 */
2498 "death of a child", /* 18 SIGCLD */
2499 "power-fail restart", /* 19 SIGPWR */
2500 "bogus signal", /* 20 */
2501 "bogus signal", /* 21 */
2502 "bogus signal", /* 22 */
2503 "bogus signal", /* 23 */
2504 "bogus signal", /* 24 */
2505 "LAN I/O interrupt", /* 25 SIGAIO */
2506 "PTY I/O interrupt", /* 26 SIGPTY */
2507 "I/O intervention required", /* 27 SIGIOINT */
2508 "HFT grant", /* 28 SIGGRANT */
2509 "HFT retract", /* 29 SIGRETRACT */
2510 "HFT sound done", /* 30 SIGSOUND */
2511 "HFT input ready", /* 31 SIGMSG */
2512#else /* not AIX */
2513 "bogus signal", /* 0 */
2514 "hangup", /* 1 SIGHUP */
2515 "interrupt", /* 2 SIGINT */
2516 "quit", /* 3 SIGQUIT */
2517 "illegal instruction", /* 4 SIGILL */
2518 "trace trap", /* 5 SIGTRAP */
2519 "IOT instruction", /* 6 SIGIOT */
2520 "EMT instruction", /* 7 SIGEMT */
2521 "floating point exception", /* 8 SIGFPE */
2522 "kill", /* 9 SIGKILL */
2523 "bus error", /* 10 SIGBUS */
2524 "segmentation violation", /* 11 SIGSEGV */
2525 "bad argument to system call", /* 12 SIGSYS */
2526 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2527 "alarm clock", /* 14 SIGALRM */
2528 "software termination signum", /* 15 SIGTERM */
2529 "user defined signal 1", /* 16 SIGUSR1 */
2530 "user defined signal 2", /* 17 SIGUSR2 */
2531 "death of a child", /* 18 SIGCLD */
2532 "power-fail restart", /* 19 SIGPWR */
2533#endif /* not AIX */
2534 0
2535 };
00eaaa32 2536#endif HAVE_SYS_SIGLIST
86a5659e
JB
2537
2538/*
2539 * Warning, this function may not duplicate 4.2 action properly
2540 * under error conditions.
2541 */
2542
2543#ifndef MAXPATHLEN
2544/* In 4.1, param.h fails to define this. */
2545#define MAXPATHLEN 1024
2546#endif
2547
2548#ifndef HAVE_GETWD
2549
2550char *
2551getwd (pathname)
2552 char *pathname;
2553{
2554 char *npath, *spath;
2555 extern char *getcwd ();
2556
9ac0d9e0 2557 BLOCK_INPUT; /* getcwd uses malloc */
86a5659e
JB
2558 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2559 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2560 up to first slash. Should be harmless on other systems. */
2561 while (*npath && *npath != '/')
2562 npath++;
2563 strcpy (pathname, npath);
2564 free (spath); /* getcwd uses malloc */
9ac0d9e0 2565 UNBLOCK_INPUT;
86a5659e
JB
2566 return pathname;
2567}
2568
2569#endif /* HAVE_GETWD */
2570
2571/*
2572 * Emulate rename using unlink/link. Note that this is
2573 * only partially correct. Also, doesn't enforce restriction
2574 * that files be of same type (regular->regular, dir->dir, etc).
2575 */
2576
4746118a
JB
2577#ifndef HAVE_RENAME
2578
86a5659e
JB
2579rename (from, to)
2580 char *from;
2581 char *to;
2582{
2583 if (access (from, 0) == 0)
2584 {
2585 unlink (to);
2586 if (link (from, to) == 0)
2587 if (unlink (from) == 0)
2588 return (0);
2589 }
2590 return (-1);
2591}
2592
4746118a
JB
2593#endif
2594
86a5659e
JB
2595#ifndef HAVE_VFORK
2596
2597/*
2598 * Substitute fork for vfork on USG flavors.
2599 */
2600
2601vfork ()
2602{
2603 return (fork ());
2604}
2605
2606#endif /* not HAVE_VFORK */
2607
2608#ifdef MISSING_UTIMES
2609
2610/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2611
2612utimes ()
2613{
2614}
2615#endif
2616
2617#ifdef IRIS_UTIME
2618
2619/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2620 utimbuf structure defined anywhere but in the man page. */
2621
2622struct utimbuf
2623 {
2624 long actime;
2625 long modtime;
2626 };
2627
2628utimes (name, tvp)
2629 char *name;
2630 struct timeval tvp[];
2631{
2632 struct utimbuf utb;
2633 utb.actime = tvp[0].tv_sec;
2634 utb.modtime = tvp[1].tv_sec;
2635 utime (name, &utb);
2636}
2637#endif /* IRIS_UTIME */
2638
2639
2640#ifdef HPUX
2641#ifndef HAVE_PERROR
2642
2643/* HPUX curses library references perror, but as far as we know
2644 it won't be called. Anyway this definition will do for now. */
2645
2646perror ()
2647{
2648}
2649
2650#endif /* not HAVE_PERROR */
2651#endif /* HPUX */
2652
2653#ifndef HAVE_DUP2
2654
2655/*
2656 * Emulate BSD dup2. First close newd if it already exists.
2657 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2658 * until we are, then close the unsuccessful ones.
2659 */
2660
2661dup2 (oldd, newd)
2662 int oldd;
2663 int newd;
2664{
2665 register int fd, ret;
2666
2667 sys_close (newd);
2668
2669#ifdef F_DUPFD
2670 fd = fcntl (oldd, F_DUPFD, newd);
2671 if (fd != newd)
2672 error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
2673#else
2674 fd = dup (old);
2675 if (fd == -1)
2676 return -1;
2677 if (fd == new)
2678 return new;
2679 ret = dup2 (old,new);
2680 sys_close (fd);
2681 return ret;
2682#endif
2683}
2684
2685#endif /* not HAVE_DUP2 */
2686
2687/*
2688 * Gettimeofday. Simulate as much as possible. Only accurate
2689 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2690 * Only needed when subprocesses are defined.
2691 */
2692
2693#ifdef subprocesses
2694#ifndef VMS
2695#ifndef HAVE_GETTIMEOFDAY
2696#ifdef HAVE_TIMEVAL
2697
2698/* ARGSUSED */
2699gettimeofday (tp, tzp)
2700 struct timeval *tp;
2701 struct timezone *tzp;
2702{
2703 extern long time ();
2704
2705 tp->tv_sec = time ((long *)0);
2706 tp->tv_usec = 0;
2707 tzp->tz_minuteswest = -1;
2708}
2709
2710#endif
2711#endif
2712#endif
2713#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
2714
2715/*
2716 * This function will go away as soon as all the stubs fixed. (fnf)
2717 */
2718
2719croak (badfunc)
2720 char *badfunc;
2721{
2722 printf ("%s not yet implemented\r\n", badfunc);
2723 reset_sys_modes ();
2724 exit (1);
2725}
2726
2727#endif /* USG */
2728\f
2729#ifdef DGUX
2730
2731char *sys_siglist[NSIG + 1] =
2732{
2733 "null signal", /* 0 SIGNULL */
2734 "hangup", /* 1 SIGHUP */
2735 "interrupt", /* 2 SIGINT */
2736 "quit", /* 3 SIGQUIT */
2737 "illegal instruction", /* 4 SIGILL */
2738 "trace trap", /* 5 SIGTRAP */
2739 "abort termination", /* 6 SIGABRT */
2740 "SIGEMT", /* 7 SIGEMT */
2741 "floating point exception", /* 8 SIGFPE */
2742 "kill", /* 9 SIGKILL */
2743 "bus error", /* 10 SIGBUS */
2744 "segmentation violation", /* 11 SIGSEGV */
2745 "bad argument to system call", /* 12 SIGSYS */
2746 "write on a pipe with no reader", /* 13 SIGPIPE */
2747 "alarm clock", /* 14 SIGALRM */
2748 "software termination signal", /* 15 SIGTERM */
2749 "user defined signal 1", /* 16 SIGUSR1 */
2750 "user defined signal 2", /* 17 SIGUSR2 */
2751 "child stopped or terminated", /* 18 SIGCLD */
2752 "power-fail restart", /* 19 SIGPWR */
2753 "window size changed", /* 20 SIGWINCH */
2754 "undefined", /* 21 */
2755 "pollable event occured", /* 22 SIGPOLL */
2756 "sendable stop signal not from tty", /* 23 SIGSTOP */
2757 "stop signal from tty", /* 24 SIGSTP */
2758 "continue a stopped process", /* 25 SIGCONT */
2759 "attempted background tty read", /* 26 SIGTTIN */
2760 "attempted background tty write", /* 27 SIGTTOU */
2761 "undefined", /* 28 */
2762 "undefined", /* 29 */
2763 "undefined", /* 30 */
2764 "undefined", /* 31 */
2765 "undefined", /* 32 */
2766 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
2767 "I/O is possible", /* 34 SIGIO */
2768 "exceeded cpu time limit", /* 35 SIGXCPU */
2769 "exceeded file size limit", /* 36 SIGXFSZ */
2770 "virtual time alarm", /* 37 SIGVTALRM */
2771 "profiling time alarm", /* 38 SIGPROF */
2772 "undefined", /* 39 */
2773 "file record locks revoked", /* 40 SIGLOST */
2774 "undefined", /* 41 */
2775 "undefined", /* 42 */
2776 "undefined", /* 43 */
2777 "undefined", /* 44 */
2778 "undefined", /* 45 */
2779 "undefined", /* 46 */
2780 "undefined", /* 47 */
2781 "undefined", /* 48 */
2782 "undefined", /* 49 */
2783 "undefined", /* 50 */
2784 "undefined", /* 51 */
2785 "undefined", /* 52 */
2786 "undefined", /* 53 */
2787 "undefined", /* 54 */
2788 "undefined", /* 55 */
2789 "undefined", /* 56 */
2790 "undefined", /* 57 */
2791 "undefined", /* 58 */
2792 "undefined", /* 59 */
2793 "undefined", /* 60 */
2794 "undefined", /* 61 */
2795 "undefined", /* 62 */
2796 "undefined", /* 63 */
2797 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
2798 0
2799};
2800
2801#endif /* DGUX */
2802\f
2803/* Directory routines for systems that don't have them. */
2804
2805#ifdef SYSV_SYSTEM_DIR
2806
2807#include <dirent.h>
2808
2809#ifndef AIX
2810int
2811closedir (dirp)
2812 register DIR *dirp; /* stream from opendir */
2813{
2814 sys_close (dirp->dd_fd);
9ac0d9e0
JB
2815 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
2816 xfree ((char *) dirp);
86a5659e
JB
2817}
2818#endif /* not AIX */
2819#endif /* SYSV_SYSTEM_DIR */
2820
2821#ifdef NONSYSTEM_DIR_LIBRARY
2822
2823DIR *
2824opendir (filename)
2825 char *filename; /* name of directory */
2826{
2827 register DIR *dirp; /* -> malloc'ed storage */
2828 register int fd; /* file descriptor for read */
2829 struct stat sbuf; /* result of fstat */
2830
2831 fd = sys_open (filename, 0);
2832 if (fd < 0)
2833 return 0;
2834
9ac0d9e0 2835 BLOCK_INPUT;
86a5659e
JB
2836 if (fstat (fd, &sbuf) < 0
2837 || (sbuf.st_mode & S_IFMT) != S_IFDIR
2838 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2839 {
2840 sys_close (fd);
9ac0d9e0 2841 UNBLOCK_INPUT;
86a5659e
JB
2842 return 0; /* bad luck today */
2843 }
9ac0d9e0 2844 UNBLOCK_INPUT;
86a5659e
JB
2845
2846 dirp->dd_fd = fd;
2847 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2848
2849 return dirp;
2850}
2851
2852void
2853closedir (dirp)
2854 register DIR *dirp; /* stream from opendir */
2855{
2856 sys_close (dirp->dd_fd);
9ac0d9e0 2857 xfree ((char *) dirp);
86a5659e
JB
2858}
2859
2860
2861#ifndef VMS
2862#define DIRSIZ 14
2863struct olddir
2864 {
2865 ino_t od_ino; /* inode */
2866 char od_name[DIRSIZ]; /* filename */
2867 };
2868#endif /* not VMS */
2869
2870struct direct dir_static; /* simulated directory contents */
2871
2872/* ARGUSED */
2873struct direct *
2874readdir (dirp)
2875 register DIR *dirp; /* stream from opendir */
2876{
2877#ifndef VMS
2878 register struct olddir *dp; /* -> directory data */
2879#else /* VMS */
2880 register struct dir$_name *dp; /* -> directory data */
2881 register struct dir$_version *dv; /* -> version data */
2882#endif /* VMS */
2883
2884 for (; ;)
2885 {
2886 if (dirp->dd_loc >= dirp->dd_size)
2887 dirp->dd_loc = dirp->dd_size = 0;
2888
2889 if (dirp->dd_size == 0 /* refill buffer */
2890 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2891 return 0;
2892
2893#ifndef VMS
2894 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
2895 dirp->dd_loc += sizeof (struct olddir);
2896
2897 if (dp->od_ino != 0) /* not deleted entry */
2898 {
2899 dir_static.d_ino = dp->od_ino;
2900 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
2901 dir_static.d_name[DIRSIZ] = '\0';
2902 dir_static.d_namlen = strlen (dir_static.d_name);
2903 dir_static.d_reclen = sizeof (struct direct)
2904 - MAXNAMLEN + 3
2905 + dir_static.d_namlen - dir_static.d_namlen % 4;
2906 return &dir_static; /* -> simulated structure */
2907 }
2908#else /* VMS */
2909 dp = (struct dir$_name *) dirp->dd_buf;
2910 if (dirp->dd_loc == 0)
2911 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
2912 : dp->dir$b_namecount;
2913 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
2914 dir_static.d_ino = dv->dir$w_fid_num;
2915 dir_static.d_namlen = dp->dir$b_namecount;
2916 dir_static.d_reclen = sizeof (struct direct)
2917 - MAXNAMLEN + 3
2918 + dir_static.d_namlen - dir_static.d_namlen % 4;
2919 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2920 dir_static.d_name[dir_static.d_namlen] = '\0';
2921 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
2922 return &dir_static;
2923#endif /* VMS */
2924 }
2925}
2926
2927#ifdef VMS
2928/* readdirver is just like readdir except it returns all versions of a file
2929 as separate entries. */
2930
2931/* ARGUSED */
2932struct direct *
2933readdirver (dirp)
2934 register DIR *dirp; /* stream from opendir */
2935{
2936 register struct dir$_name *dp; /* -> directory data */
2937 register struct dir$_version *dv; /* -> version data */
2938
2939 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
2940 dirp->dd_loc = dirp->dd_size = 0;
2941
2942 if (dirp->dd_size == 0 /* refill buffer */
2943 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2944 return 0;
2945
2946 dp = (struct dir$_name *) dirp->dd_buf;
2947 if (dirp->dd_loc == 0)
2948 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
2949 : dp->dir$b_namecount;
2950 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
2951 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2952 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
2953 dir_static.d_namlen = strlen (dir_static.d_name);
2954 dir_static.d_ino = dv->dir$w_fid_num;
2955 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
2956 + dir_static.d_namlen - dir_static.d_namlen % 4;
2957 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
2958 return &dir_static;
2959}
2960
2961#endif /* VMS */
2962
2963#endif /* NONSYSTEM_DIR_LIBRARY */
2964\f
2965/* Functions for VMS */
2966#ifdef VMS
91bac16a 2967#include "vms-pwd.h"
86a5659e
JB
2968#include <acldef.h>
2969#include <chpdef.h>
2970#include <jpidef.h>
2971
2972/* Return as a string the VMS error string pertaining to STATUS.
2973 Reuses the same static buffer each time it is called. */
2974
2975char *
2976vmserrstr (status)
2977 int status; /* VMS status code */
2978{
2979 int bufadr[2];
2980 short len;
2981 static char buf[257];
2982
2983 bufadr[0] = sizeof buf - 1;
2984 bufadr[1] = (int) buf;
2985 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
2986 return "untranslatable VMS error status";
2987 buf[len] = '\0';
2988 return buf;
2989}
2990
2991#ifdef access
2992#undef access
2993
2994/* The following is necessary because 'access' emulation by VMS C (2.0) does
2995 * not work correctly. (It also doesn't work well in version 2.3.)
2996 */
2997
2998#ifdef VMS4_4
2999
3000#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3001 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3002
3003typedef union {
3004 struct {
3005 unsigned short s_buflen;
3006 unsigned short s_code;
3007 char *s_bufadr;
3008 unsigned short *s_retlenadr;
3009 } s;
3010 int end;
3011} item;
3012#define buflen s.s_buflen
3013#define code s.s_code
3014#define bufadr s.s_bufadr
3015#define retlenadr s.s_retlenadr
3016
3017#define R_OK 4 /* test for read permission */
3018#define W_OK 2 /* test for write permission */
3019#define X_OK 1 /* test for execute (search) permission */
3020#define F_OK 0 /* test for presence of file */
3021
3022int
3023sys_access (path, mode)
3024 char *path;
3025 int mode;
3026{
3027 static char *user = NULL;
3028 char dir_fn[512];
3029
3030 /* translate possible directory spec into .DIR file name, so brain-dead
3031 * access can treat the directory like a file. */
3032 if (directory_file_name (path, dir_fn))
3033 path = dir_fn;
3034
3035 if (mode == F_OK)
3036 return access (path, mode);
3037 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3038 return -1;
3039 {
3040 int stat;
3041 int flags;
3042 int acces;
3043 unsigned short int dummy;
3044 item itemlst[3];
3045 static int constant = ACL$C_FILE;
3046 DESCRIPTOR (path_desc, path);
3047 DESCRIPTOR (user_desc, user);
3048
3049 flags = 0;
3050 acces = 0;
3051 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3052 return stat;
3053 if (mode & R_OK)
3054 acces |= CHP$M_READ;
3055 if (mode & W_OK)
3056 acces |= CHP$M_WRITE;
3057 itemlst[0].buflen = sizeof (int);
3058 itemlst[0].code = CHP$_FLAGS;
3059 itemlst[0].bufadr = (char *) &flags;
3060 itemlst[0].retlenadr = &dummy;
3061 itemlst[1].buflen = sizeof (int);
3062 itemlst[1].code = CHP$_ACCESS;
3063 itemlst[1].bufadr = (char *) &acces;
3064 itemlst[1].retlenadr = &dummy;
3065 itemlst[2].end = CHP$_END;
3066 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3067 return stat == SS$_NORMAL ? 0 : -1;
3068 }
3069}
3070
3071#else /* not VMS4_4 */
3072
3073#include <prvdef.h>
3074#define ACE$M_WRITE 2
3075#define ACE$C_KEYID 1
3076
3077static unsigned short memid, grpid;
3078static unsigned int uic;
3079
3080/* Called from init_sys_modes, so it happens not very often
3081 but at least each time Emacs is loaded. */
3082sys_access_reinit ()
3083{
3084 uic = 0;
3085}
3086
3087int
3088sys_access (filename, type)
3089 char * filename;
3090 int type;
3091{
3092 struct FAB fab;
3093 struct XABPRO xab;
3094 int status, size, i, typecode, acl_controlled;
3095 unsigned int *aclptr, *aclend, aclbuf[60];
3096 union prvdef prvmask;
3097
3098 /* Get UIC and GRP values for protection checking. */
3099 if (uic == 0)
3100 {
3101 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3102 if (! (status & 1))
3103 return -1;
3104 memid = uic & 0xFFFF;
3105 grpid = uic >> 16;
3106 }
3107
3108 if (type != 2) /* not checking write access */
3109 return access (filename, type);
3110
3111 /* Check write protection. */
3112
3113#define CHECKPRIV(bit) (prvmask.bit)
3114#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3115
3116 /* Find privilege bits */
986ffb24 3117 status = SYS$SETPRV (0, 0, 0, prvmask);
86a5659e
JB
3118 if (! (status & 1))
3119 error ("Unable to find privileges: %s", vmserrstr (status));
3120 if (CHECKPRIV (PRV$V_BYPASS))
3121 return 0; /* BYPASS enabled */
3122 fab = cc$rms_fab;
3123 fab.fab$b_fac = FAB$M_GET;
3124 fab.fab$l_fna = filename;
3125 fab.fab$b_fns = strlen (filename);
3126 fab.fab$l_xab = &xab;
3127 xab = cc$rms_xabpro;
3128 xab.xab$l_aclbuf = aclbuf;
3129 xab.xab$w_aclsiz = sizeof (aclbuf);
986ffb24 3130 status = SYS$OPEN (&fab, 0, 0);
86a5659e
JB
3131 if (! (status & 1))
3132 return -1;
986ffb24 3133 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3134 /* Check system access */
3135 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
3136 return 0;
3137 /* Check ACL entries, if any */
3138 acl_controlled = 0;
3139 if (xab.xab$w_acllen > 0)
3140 {
3141 aclptr = aclbuf;
3142 aclend = &aclbuf[xab.xab$w_acllen / 4];
3143 while (*aclptr && aclptr < aclend)
3144 {
3145 size = (*aclptr & 0xff) / 4;
3146 typecode = (*aclptr >> 8) & 0xff;
3147 if (typecode == ACE$C_KEYID)
3148 for (i = size - 1; i > 1; i--)
3149 if (aclptr[i] == uic)
3150 {
3151 acl_controlled = 1;
3152 if (aclptr[1] & ACE$M_WRITE)
3153 return 0; /* Write access through ACL */
3154 }
3155 aclptr = &aclptr[size];
3156 }
3157 if (acl_controlled) /* ACL specified, prohibits write access */
3158 return -1;
3159 }
3160 /* No ACL entries specified, check normal protection */
3161 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
3162 return 0;
3163 if (WRITEABLE (XAB$V_GRP) &&
3164 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3165 return 0; /* Group writeable */
3166 if (WRITEABLE (XAB$V_OWN) &&
3167 (xab.xab$l_uic & 0xFFFF) == memid)
3168 return 0; /* Owner writeable */
3169
3170 return -1; /* Not writeable */
3171}
3172#endif /* not VMS4_4 */
3173#endif /* access */
3174
3175static char vtbuf[NAM$C_MAXRSS+1];
3176
3177/* translate a vms file spec to a unix path */
3178char *
3179sys_translate_vms (vfile)
3180 char * vfile;
3181{
3182 char * p;
3183 char * targ;
3184
3185 if (!vfile)
3186 return 0;
3187
3188 targ = vtbuf;
3189
3190 /* leading device or logical name is a root directory */
3191 if (p = strchr (vfile, ':'))
3192 {
3193 *targ++ = '/';
3194 while (vfile < p)
3195 *targ++ = *vfile++;
3196 vfile++;
3197 *targ++ = '/';
3198 }
3199 p = vfile;
3200 if (*p == '[' || *p == '<')
3201 {
3202 while (*++vfile != *p + 2)
3203 switch (*vfile)
3204 {
3205 case '.':
3206 if (vfile[-1] == *p)
3207 *targ++ = '.';
3208 *targ++ = '/';
3209 break;
3210
3211 case '-':
3212 *targ++ = '.';
3213 *targ++ = '.';
3214 break;
3215
3216 default:
3217 *targ++ = *vfile;
3218 break;
3219 }
3220 vfile++;
3221 *targ++ = '/';
3222 }
3223 while (*vfile)
3224 *targ++ = *vfile++;
3225
3226 return vtbuf;
3227}
3228
3229static char utbuf[NAM$C_MAXRSS+1];
3230
3231/* translate a unix path to a VMS file spec */
3232char *
3233sys_translate_unix (ufile)
3234 char * ufile;
3235{
3236 int slash_seen = 0;
3237 char *p;
3238 char * targ;
3239
3240 if (!ufile)
3241 return 0;
3242
3243 targ = utbuf;
3244
3245 if (*ufile == '/')
3246 {
3247 ufile++;
3248 }
3249
3250 while (*ufile)
3251 {
3252 switch (*ufile)
3253 {
3254 case '/':
3255 if (slash_seen)
3256 if (index (&ufile[1], '/'))
3257 *targ++ = '.';
3258 else
3259 *targ++ = ']';
3260 else
3261 {
3262 *targ++ = ':';
3263 if (index (&ufile[1], '/'))
3264 *targ++ = '[';
3265 slash_seen = 1;
3266 }
3267 break;
3268
3269 case '.':
3270 if (strncmp (ufile, "./", 2) == 0)
3271 {
3272 if (!slash_seen)
3273 {
3274 *targ++ = '[';
3275 slash_seen = 1;
3276 }
3277 ufile++; /* skip the dot */
3278 if (index (&ufile[1], '/'))
3279 *targ++ = '.';
3280 else
3281 *targ++ = ']';
3282 }
3283 else if (strncmp (ufile, "../", 3) == 0)
3284 {
3285 if (!slash_seen)
3286 {
3287 *targ++ = '[';
3288 slash_seen = 1;
3289 }
3290 *targ++ = '-';
3291 ufile += 2; /* skip the dots */
3292 if (index (&ufile[1], '/'))
3293 *targ++ = '.';
3294 else
3295 *targ++ = ']';
3296 }
3297 else
3298 *targ++ = *ufile;
3299 break;
3300
3301 default:
3302 *targ++ = *ufile;
3303 break;
3304 }
3305 ufile++;
3306 }
3307 *targ = '\0';
3308
3309 return utbuf;
3310}
3311
3312char *
3313getwd (pathname)
3314 char *pathname;
3315{
3316 char *ptr;
210b2b4f 3317 extern char *getcwd ();
86a5659e 3318
210b2b4f
JB
3319#define MAXPATHLEN 1024
3320
9ac0d9e0 3321 ptr = xmalloc (MAXPATHLEN);
210b2b4f
JB
3322 getcwd (ptr, MAXPATHLEN);
3323 strcpy (pathname, ptr);
9ac0d9e0 3324 xfree (ptr);
210b2b4f
JB
3325
3326 return pathname;
86a5659e
JB
3327}
3328
3329getppid ()
3330{
3331 long item_code = JPI$_OWNER;
3332 unsigned long parent_id;
3333 int status;
3334
3335 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3336 {
3337 errno = EVMSERR;
3338 vaxc$errno = status;
3339 return -1;
3340 }
3341 return parent_id;
3342}
3343
3344#undef getuid
3345unsigned
3346sys_getuid ()
3347{
3348 return (getgid () << 16) | getuid ();
3349}
3350
3351int
3352sys_read (fildes, buf, nbyte)
3353 int fildes;
3354 char *buf;
3355 unsigned int nbyte;
3356{
3357 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3358}
3359
3360#if 0
3361int
3362sys_write (fildes, buf, nbyte)
3363 int fildes;
3364 char *buf;
3365 unsigned int nbyte;
3366{
3367 register int nwrote, rtnval = 0;
3368
3369 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3370 nbyte -= nwrote;
3371 buf += nwrote;
3372 rtnval += nwrote;
3373 }
3374 if (nwrote < 0)
3375 return rtnval ? rtnval : -1;
3376 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3377 return rtnval ? rtnval : -1;
3378 return (rtnval + nwrote);
3379}
3380#endif /* 0 */
3381
3382/*
3383 * VAX/VMS VAX C RTL really loses. It insists that records
3384 * end with a newline (carriage return) character, and if they
3385 * don't it adds one (nice of it isn't it!)
3386 *
3387 * Thus we do this stupidity below.
3388 */
3389
3390int
3391sys_write (fildes, buf, nbytes)
3392 int fildes;
3393 char *buf;
3394 unsigned int nbytes;
3395{
3396 register char *p;
3397 register char *e;
23b0668c
JB
3398 int sum = 0;
3399 struct stat st;
3400
3401 fstat (fildes, &st);
86a5659e 3402 p = buf;
86a5659e
JB
3403 while (nbytes > 0)
3404 {
23b0668c
JB
3405 int len, retval;
3406
3407 /* Handle fixed-length files with carriage control. */
3408 if (st.st_fab_rfm == FAB$C_FIX
3409 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3410 {
3411 len = st.st_fab_mrs;
3412 retval = write (fildes, p, min (len, nbytes));
3413 if (retval != len)
3414 return -1;
3415 retval++; /* This skips the implied carriage control */
3416 }
3417 else
3418 {
3419 e = p + min (MAXIOSIZE, nbytes) - 1;
3420 while (*e != '\n' && e > p) e--;
3421 if (p == e) /* Ok.. so here we add a newline... sigh. */
3422 e = p + min (MAXIOSIZE, nbytes) - 1;
3423 len = e + 1 - p;
3424 retval = write (fildes, p, len);
3425 if (retval != len)
3426 return -1;
3427 }
3428 p += retval;
3429 sum += retval;
86a5659e
JB
3430 nbytes -= retval;
3431 }
3432 return sum;
3433}
3434
3435/* Create file NEW copying its attributes from file OLD. If
3436 OLD is 0 or does not exist, create based on the value of
3437 vms_stmlf_recfm. */
3438
3439/* Protection value the file should ultimately have.
3440 Set by create_copy_attrs, and use by rename_sansversions. */
3441static unsigned short int fab_final_pro;
3442
3443int
3444creat_copy_attrs (old, new)
3445 char *old, *new;
3446{
3447 struct FAB fab = cc$rms_fab;
3448 struct XABPRO xabpro;
3449 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3450 extern int vms_stmlf_recfm;
3451
3452 if (old)
3453 {
3454 fab.fab$b_fac = FAB$M_GET;
3455 fab.fab$l_fna = old;
3456 fab.fab$b_fns = strlen (old);
3457 fab.fab$l_xab = (char *) &xabpro;
3458 xabpro = cc$rms_xabpro;
3459 xabpro.xab$l_aclbuf = aclbuf;
3460 xabpro.xab$w_aclsiz = sizeof aclbuf;
3461 /* Call $OPEN to fill in the fab & xabpro fields. */
986ffb24 3462 if (SYS$OPEN (&fab, 0, 0) & 1)
86a5659e 3463 {
986ffb24 3464 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3465 fab.fab$l_alq = 0; /* zero the allocation quantity */
3466 if (xabpro.xab$w_acllen > 0)
3467 {
3468 if (xabpro.xab$w_acllen > sizeof aclbuf)
3469 /* If the acl buffer was too short, redo open with longer one.
3470 Wouldn't need to do this if there were some system imposed
3471 limit on the size of an ACL, but I can't find any such. */
3472 {
3473 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
3474 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
986ffb24
JB
3475 if (SYS$OPEN (&fab, 0, 0) & 1)
3476 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3477 else
3478 old = 0;
3479 }
3480 }
3481 else
3482 xabpro.xab$l_aclbuf = 0;
3483 }
3484 else
3485 old = 0;
3486 }
3487 fab.fab$l_fna = new;
3488 fab.fab$b_fns = strlen (new);
3489 if (!old)
3490 {
3491 fab.fab$l_xab = 0;
3492 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
3493 fab.fab$b_rat = FAB$M_CR;
3494 }
3495
3496 /* Set the file protections such that we will be able to manipulate
3497 this file. Once we are done writing and renaming it, we will set
3498 the protections back. */
3499 if (old)
3500 fab_final_pro = xabpro.xab$w_pro;
3501 else
986ffb24 3502 SYS$SETDFPROT (0, &fab_final_pro);
86a5659e
JB
3503 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
3504
3505 /* Create the new file with either default attrs or attrs copied
3506 from old file. */
3507 if (!(SYS$CREATE (&fab, 0, 0) & 1))
3508 return -1;
986ffb24 3509 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3510 /* As this is a "replacement" for creat, return a file descriptor
3511 opened for writing. */
3512 return open (new, O_WRONLY);
3513}
3514
3515#ifdef creat
3516#undef creat
3517#include <varargs.h>
3518#ifdef __GNUC__
3519#ifndef va_count
3520#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3521#endif
3522#endif
3523
3524sys_creat (va_alist)
3525 va_dcl
3526{
3527 va_list list_incrementor;
3528 char *name;
3529 int mode;
3530 int rfd; /* related file descriptor */
3531 int fd; /* Our new file descriptor */
3532 int count;
3533 struct stat st_buf;
3534 char rfm[12];
3535 char rat[15];
3536 char mrs[13];
3537 char fsz[13];
3538 extern int vms_stmlf_recfm;
3539
3540 va_count (count);
3541 va_start (list_incrementor);
3542 name = va_arg (list_incrementor, char *);
3543 mode = va_arg (list_incrementor, int);
3544 if (count > 2)
3545 rfd = va_arg (list_incrementor, int);
3546 va_end (list_incrementor);
3547 if (count > 2)
3548 {
3549 /* Use information from the related file descriptor to set record
3550 format of the newly created file. */
3551 fstat (rfd, &st_buf);
3552 switch (st_buf.st_fab_rfm)
3553 {
3554 case FAB$C_FIX:
3555 strcpy (rfm, "rfm = fix");
3556 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
3557 strcpy (rat, "rat = ");
3558 if (st_buf.st_fab_rat & FAB$M_CR)
3559 strcat (rat, "cr");
3560 else if (st_buf.st_fab_rat & FAB$M_FTN)
3561 strcat (rat, "ftn");
3562 else if (st_buf.st_fab_rat & FAB$M_PRN)
3563 strcat (rat, "prn");
3564 if (st_buf.st_fab_rat & FAB$M_BLK)
3565 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3566 strcat (rat, ", blk");
3567 else
3568 strcat (rat, "blk");
3569 return creat (name, 0, rfm, rat, mrs);
3570
3571 case FAB$C_VFC:
3572 strcpy (rfm, "rfm = vfc");
3573 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
3574 strcpy (rat, "rat = ");
3575 if (st_buf.st_fab_rat & FAB$M_CR)
3576 strcat (rat, "cr");
3577 else if (st_buf.st_fab_rat & FAB$M_FTN)
3578 strcat (rat, "ftn");
3579 else if (st_buf.st_fab_rat & FAB$M_PRN)
3580 strcat (rat, "prn");
3581 if (st_buf.st_fab_rat & FAB$M_BLK)
3582 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3583 strcat (rat, ", blk");
3584 else
3585 strcat (rat, "blk");
3586 return creat (name, 0, rfm, rat, fsz);
3587
3588 case FAB$C_STM:
3589 strcpy (rfm, "rfm = stm");
3590 break;
3591
3592 case FAB$C_STMCR:
3593 strcpy (rfm, "rfm = stmcr");
3594 break;
3595
3596 case FAB$C_STMLF:
3597 strcpy (rfm, "rfm = stmlf");
3598 break;
3599
3600 case FAB$C_UDF:
3601 strcpy (rfm, "rfm = udf");
3602 break;
3603
3604 case FAB$C_VAR:
3605 strcpy (rfm, "rfm = var");
3606 break;
3607 }
3608 strcpy (rat, "rat = ");
3609 if (st_buf.st_fab_rat & FAB$M_CR)
3610 strcat (rat, "cr");
3611 else if (st_buf.st_fab_rat & FAB$M_FTN)
3612 strcat (rat, "ftn");
3613 else if (st_buf.st_fab_rat & FAB$M_PRN)
3614 strcat (rat, "prn");
3615 if (st_buf.st_fab_rat & FAB$M_BLK)
3616 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3617 strcat (rat, ", blk");
3618 else
3619 strcat (rat, "blk");
3620 }
3621 else
3622 {
3623 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3624 strcpy (rat, "rat=cr");
3625 }
3626 /* Until the VAX C RTL fixes the many bugs with modes, always use
3627 mode 0 to get the user's default protection. */
3628 fd = creat (name, 0, rfm, rat);
3629 if (fd < 0 && errno == EEXIST)
3630 {
3631 if (unlink (name) < 0)
3632 report_file_error ("delete", build_string (name));
3633 fd = creat (name, 0, rfm, rat);
3634 }
3635 return fd;
3636}
3637#endif /* creat */
3638
3639/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3640sys_fwrite (ptr, size, num, fp)
3641 register char * ptr;
3642 FILE * fp;
3643{
3644 register int tot = num * size;
3645
3646 while (tot--)
3647 fputc (*ptr++, fp);
3648}
3649
3650/*
3651 * The VMS C library routine creat actually creates a new version of an
3652 * existing file rather than truncating the old version. There are times
3653 * when this is not the desired behavior, for instance, when writing an
3654 * auto save file (you only want one version), or when you don't have
3655 * write permission in the directory containing the file (but the file
3656 * itself is writable). Hence this routine, which is equivalent to
3657 * "close (creat (fn, 0));" on Unix if fn already exists.
3658 */
3659int
3660vms_truncate (fn)
3661 char *fn;
3662{
3663 struct FAB xfab = cc$rms_fab;
3664 struct RAB xrab = cc$rms_rab;
3665 int status;
3666
3667 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3668 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3669 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3670 xfab.fab$l_fna = fn;
3671 xfab.fab$b_fns = strlen (fn);
3672 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3673 xfab.fab$b_dns = 2;
3674 xrab.rab$l_fab = &xfab;
3675
3676 /* This gibberish opens the file, positions to the first record, and
3677 deletes all records from there until the end of file. */
986ffb24 3678 if ((SYS$OPEN (&xfab) & 01) == 01)
86a5659e 3679 {
986ffb24
JB
3680 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
3681 (SYS$FIND (&xrab) & 01) == 01 &&
3682 (SYS$TRUNCATE (&xrab) & 01) == 01)
86a5659e
JB
3683 status = 0;
3684 else
3685 status = -1;
3686 }
3687 else
3688 status = -1;
986ffb24 3689 SYS$CLOSE (&xfab);
86a5659e
JB
3690 return status;
3691}
3692
3693/* Define this symbol to actually read SYSUAF.DAT. This requires either
3694 SYSPRV or a readable SYSUAF.DAT. */
3695
3696#ifdef READ_SYSUAF
3697/*
3698 * getuaf.c
3699 *
3700 * Routine to read the VMS User Authorization File and return
3701 * a specific user's record.
3702 */
3703
3704static struct UAF retuaf;
3705
3706struct UAF *
3707get_uaf_name (uname)
3708 char * uname;
3709{
3710 register status;
3711 struct FAB uaf_fab;
3712 struct RAB uaf_rab;
3713
3714 uaf_fab = cc$rms_fab;
3715 uaf_rab = cc$rms_rab;
3716 /* initialize fab fields */
3717 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3718 uaf_fab.fab$b_fns = 21;
3719 uaf_fab.fab$b_fac = FAB$M_GET;
3720 uaf_fab.fab$b_org = FAB$C_IDX;
3721 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3722 /* initialize rab fields */
3723 uaf_rab.rab$l_fab = &uaf_fab;
3724 /* open the User Authorization File */
986ffb24 3725 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3726 if (!(status&1))
3727 {
3728 errno = EVMSERR;
3729 vaxc$errno = status;
3730 return 0;
3731 }
986ffb24 3732 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3733 if (!(status&1))
3734 {
3735 errno = EVMSERR;
3736 vaxc$errno = status;
3737 return 0;
3738 }
3739 /* read the requested record - index is in uname */
3740 uaf_rab.rab$l_kbf = uname;
3741 uaf_rab.rab$b_ksz = strlen (uname);
3742 uaf_rab.rab$b_rac = RAB$C_KEY;
3743 uaf_rab.rab$l_ubf = (char *)&retuaf;
3744 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3745 status = SYS$GET (&uaf_rab);
86a5659e
JB
3746 if (!(status&1))
3747 {
3748 errno = EVMSERR;
3749 vaxc$errno = status;
3750 return 0;
3751 }
3752 /* close the User Authorization File */
986ffb24 3753 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3754 if (!(status&1))
3755 {
3756 errno = EVMSERR;
3757 vaxc$errno = status;
3758 return 0;
3759 }
986ffb24 3760 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3761 if (!(status&1))
3762 {
3763 errno = EVMSERR;
3764 vaxc$errno = status;
3765 return 0;
3766 }
3767 return &retuaf;
3768}
3769
3770struct UAF *
3771get_uaf_uic (uic)
3772 unsigned long uic;
3773{
3774 register status;
3775 struct FAB uaf_fab;
3776 struct RAB uaf_rab;
3777
3778 uaf_fab = cc$rms_fab;
3779 uaf_rab = cc$rms_rab;
3780 /* initialize fab fields */
3781 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3782 uaf_fab.fab$b_fns = 21;
3783 uaf_fab.fab$b_fac = FAB$M_GET;
3784 uaf_fab.fab$b_org = FAB$C_IDX;
3785 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3786 /* initialize rab fields */
3787 uaf_rab.rab$l_fab = &uaf_fab;
3788 /* open the User Authorization File */
986ffb24 3789 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3790 if (!(status&1))
3791 {
3792 errno = EVMSERR;
3793 vaxc$errno = status;
3794 return 0;
3795 }
986ffb24 3796 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3797 if (!(status&1))
3798 {
3799 errno = EVMSERR;
3800 vaxc$errno = status;
3801 return 0;
3802 }
3803 /* read the requested record - index is in uic */
3804 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3805 uaf_rab.rab$l_kbf = (char *) &uic;
3806 uaf_rab.rab$b_ksz = sizeof uic;
3807 uaf_rab.rab$b_rac = RAB$C_KEY;
3808 uaf_rab.rab$l_ubf = (char *)&retuaf;
3809 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3810 status = SYS$GET (&uaf_rab);
86a5659e
JB
3811 if (!(status&1))
3812 {
3813 errno = EVMSERR;
3814 vaxc$errno = status;
3815 return 0;
3816 }
3817 /* close the User Authorization File */
986ffb24 3818 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3819 if (!(status&1))
3820 {
3821 errno = EVMSERR;
3822 vaxc$errno = status;
3823 return 0;
3824 }
986ffb24 3825 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3826 if (!(status&1))
3827 {
3828 errno = EVMSERR;
3829 vaxc$errno = status;
3830 return 0;
3831 }
3832 return &retuaf;
3833}
3834
3835static struct passwd retpw;
3836
3837struct passwd *
3838cnv_uaf_pw (up)
3839 struct UAF * up;
3840{
3841 char * ptr;
3842
3843 /* copy these out first because if the username is 32 chars, the next
3844 section will overwrite the first byte of the UIC */
3845 retpw.pw_uid = up->uaf$w_mem;
3846 retpw.pw_gid = up->uaf$w_grp;
3847
3848 /* I suppose this is not the best sytle, to possibly overwrite one
3849 byte beyond the end of the field, but what the heck... */
3850 ptr = &up->uaf$t_username[UAF$S_USERNAME];
3851 while (ptr[-1] == ' ')
3852 ptr--;
3853 *ptr = '\0';
3854 strcpy (retpw.pw_name, up->uaf$t_username);
3855
3856 /* the rest of these are counted ascii strings */
3857 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3858 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3859 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3860 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3861 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3862 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3863 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3864 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3865
3866 return &retpw;
3867}
3868#else /* not READ_SYSUAF */
3869static struct passwd retpw;
3870#endif /* not READ_SYSUAF */
3871
3872struct passwd *
3873getpwnam (name)
3874 char * name;
3875{
3876#ifdef READ_SYSUAF
3877 struct UAF *up;
3878#else
3879 char * user;
3880 char * dir;
3881 unsigned char * full;
3882#endif /* READ_SYSUAF */
3883 char *ptr = name;
3884
3885 while (*ptr)
3886 {
3887 if ('a' <= *ptr && *ptr <= 'z')
3888 *ptr -= 040;
3889 ptr++;
3890 }
3891#ifdef READ_SYSUAF
3892 if (!(up = get_uaf_name (name)))
3893 return 0;
3894 return cnv_uaf_pw (up);
3895#else
3896 if (strcmp (name, getenv ("USER")) == 0)
3897 {
3898 retpw.pw_uid = getuid ();
3899 retpw.pw_gid = getgid ();
3900 strcpy (retpw.pw_name, name);
3901 if (full = egetenv ("FULLNAME"))
3902 strcpy (retpw.pw_gecos, full);
3903 else
3904 *retpw.pw_gecos = '\0';
3905 strcpy (retpw.pw_dir, egetenv ("HOME"));
3906 *retpw.pw_shell = '\0';
3907 return &retpw;
3908 }
3909 else
3910 return 0;
3911#endif /* not READ_SYSUAF */
3912}
3913
3914struct passwd *
3915getpwuid (uid)
3916 unsigned long uid;
3917{
3918#ifdef READ_SYSUAF
3919 struct UAF * up;
3920
3921 if (!(up = get_uaf_uic (uid)))
3922 return 0;
3923 return cnv_uaf_pw (up);
3924#else
3925 if (uid == sys_getuid ())
3926 return getpwnam (egetenv ("USER"));
3927 else
3928 return 0;
3929#endif /* not READ_SYSUAF */
3930}
3931
3932/* return total address space available to the current process. This is
3933 the sum of the current p0 size, p1 size and free page table entries
3934 available. */
3935vlimit ()
3936{
3937 int item_code;
3938 unsigned long free_pages;
3939 unsigned long frep0va;
3940 unsigned long frep1va;
3941 register status;
3942
3943 item_code = JPI$_FREPTECNT;
3944 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
3945 {
3946 errno = EVMSERR;
3947 vaxc$errno = status;
3948 return -1;
3949 }
3950 free_pages *= 512;
3951
3952 item_code = JPI$_FREP0VA;
3953 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
3954 {
3955 errno = EVMSERR;
3956 vaxc$errno = status;
3957 return -1;
3958 }
3959 item_code = JPI$_FREP1VA;
3960 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
3961 {
3962 errno = EVMSERR;
3963 vaxc$errno = status;
3964 return -1;
3965 }
3966
3967 return free_pages + frep0va + (0x7fffffff - frep1va);
3968}
3969
3970define_logical_name (varname, string)
3971 char *varname;
3972 char *string;
3973{
3974 struct dsc$descriptor_s strdsc =
3975 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
3976 struct dsc$descriptor_s envdsc =
3977 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3978 struct dsc$descriptor_s lnmdsc =
3979 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3980
3981 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
3982}
3983
3984delete_logical_name (varname)
3985 char *varname;
3986{
3987 struct dsc$descriptor_s envdsc =
3988 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3989 struct dsc$descriptor_s lnmdsc =
3990 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3991
3992 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
3993}
3994
3995ulimit ()
3996{}
3997
86a5659e
JB
3998setpgrp ()
3999{}
4000
4001execvp ()
4002{
4003 error ("execvp system call not implemented");
4004}
4005
4006int
4007rename (from, to)
4008 char *from, *to;
4009{
4010 int status;
4011 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4012 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4013 char from_esn[NAM$C_MAXRSS];
4014 char to_esn[NAM$C_MAXRSS];
4015
4016 from_fab.fab$l_fna = from;
4017 from_fab.fab$b_fns = strlen (from);
4018 from_fab.fab$l_nam = &from_nam;
4019 from_fab.fab$l_fop = FAB$M_NAM;
4020
4021 from_nam.nam$l_esa = from_esn;
4022 from_nam.nam$b_ess = sizeof from_esn;
4023
4024 to_fab.fab$l_fna = to;
4025 to_fab.fab$b_fns = strlen (to);
4026 to_fab.fab$l_nam = &to_nam;
4027 to_fab.fab$l_fop = FAB$M_NAM;
4028
4029 to_nam.nam$l_esa = to_esn;
4030 to_nam.nam$b_ess = sizeof to_esn;
4031
4032 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4033
4034 if (status & 1)
4035 return 0;
4036 else
4037 {
4038 if (status == RMS$_DEV)
4039 errno = EXDEV;
4040 else
4041 errno = EVMSERR;
4042 vaxc$errno = status;
4043 return -1;
4044 }
4045}
4046
4047/* This function renames a file like `rename', but it strips
4048 the version number from the "to" filename, such that the "to" file is
4049 will always be a new version. It also sets the file protection once it is
4050 finished. The protection that we will use is stored in fab_final_pro,
4051 and was set when we did a creat_copy_attrs to create the file that we
4052 are renaming.
4053
4054 We could use the chmod function, but Eunichs uses 3 bits per user category
4055 to describe the protection, and VMS uses 4 (write and delete are seperate
4056 bits). To maintain portability, the VMS implementation of `chmod' wires
4057 the W and D bits together. */
4058
4059
4060static struct fibdef fib; /* We need this initialized to zero */
4061char vms_file_written[NAM$C_MAXRSS];
4062
4063int
4064rename_sans_version (from,to)
4065 char *from, *to;
4066{
4067 short int chan;
4068 int stat;
4069 short int iosb[4];
4070 int status;
4071 struct FAB to_fab = cc$rms_fab;
4072 struct NAM to_nam = cc$rms_nam;
4073 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4074 struct dsc$descriptor fib_attr[2]
4075 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4076 char to_esn[NAM$C_MAXRSS];
4077
4078 $DESCRIPTOR (disk,to_esn);
4079
4080 to_fab.fab$l_fna = to;
4081 to_fab.fab$b_fns = strlen (to);
4082 to_fab.fab$l_nam = &to_nam;
4083 to_fab.fab$l_fop = FAB$M_NAM;
4084
4085 to_nam.nam$l_esa = to_esn;
4086 to_nam.nam$b_ess = sizeof to_esn;
4087
4088 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4089
4090 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4091 *(to_nam.nam$l_ver) = '\0';
4092
4093 stat = rename (from, to_esn);
4094 if (stat < 0)
4095 return stat;
4096
4097 strcpy (vms_file_written, to_esn);
4098
4099 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4100 to_fab.fab$b_fns = strlen (vms_file_written);
4101
4102 /* Now set the file protection to the correct value */
986ffb24 4103 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
86a5659e
JB
4104
4105 /* Copy these fields into the fib */
4106 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4107 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4108 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4109
986ffb24 4110 SYS$CLOSE (&to_fab, 0, 0);
86a5659e 4111
986ffb24 4112 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
86a5659e 4113 if (!stat)
986ffb24
JB
4114 LIB$SIGNAL (stat);
4115 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
86a5659e
JB
4116 0, 0, 0, &fib_attr, 0);
4117 if (!stat)
986ffb24
JB
4118 LIB$SIGNAL (stat);
4119 stat = SYS$DASSGN (chan);
86a5659e 4120 if (!stat)
986ffb24 4121 LIB$SIGNAL (stat);
0137dbf7 4122 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
4123 return 0;
4124}
4125
4126link (file, new)
4127 char * file, * new;
4128{
4129 register status;
4130 struct FAB fab;
4131 struct NAM nam;
4132 unsigned short fid[3];
4133 char esa[NAM$C_MAXRSS];
4134
4135 fab = cc$rms_fab;
4136 fab.fab$l_fop = FAB$M_OFP;
4137 fab.fab$l_fna = file;
4138 fab.fab$b_fns = strlen (file);
4139 fab.fab$l_nam = &nam;
4140
4141 nam = cc$rms_nam;
4142 nam.nam$l_esa = esa;
4143 nam.nam$b_ess = NAM$C_MAXRSS;
4144
4145 status = SYS$PARSE (&fab);
4146 if ((status & 1) == 0)
4147 {
4148 errno = EVMSERR;
4149 vaxc$errno = status;
4150 return -1;
4151 }
4152 status = SYS$SEARCH (&fab);
4153 if ((status & 1) == 0)
4154 {
4155 errno = EVMSERR;
4156 vaxc$errno = status;
4157 return -1;
4158 }
4159
4160 fid[0] = nam.nam$w_fid[0];
4161 fid[1] = nam.nam$w_fid[1];
4162 fid[2] = nam.nam$w_fid[2];
4163
4164 fab.fab$l_fna = new;
4165 fab.fab$b_fns = strlen (new);
4166
4167 status = SYS$PARSE (&fab);
4168 if ((status & 1) == 0)
4169 {
4170 errno = EVMSERR;
4171 vaxc$errno = status;
4172 return -1;
4173 }
4174
4175 nam.nam$w_fid[0] = fid[0];
4176 nam.nam$w_fid[1] = fid[1];
4177 nam.nam$w_fid[2] = fid[2];
4178
4179 nam.nam$l_esa = nam.nam$l_name;
4180 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
4181
4182 status = SYS$ENTER (&fab);
4183 if ((status & 1) == 0)
4184 {
4185 errno = EVMSERR;
4186 vaxc$errno = status;
4187 return -1;
4188 }
4189
4190 return 0;
4191}
4192
4193croak (badfunc)
4194 char *badfunc;
4195{
4196 printf ("%s not yet implemented\r\n", badfunc);
4197 reset_sys_modes ();
4198 exit (1);
4199}
4200
4201long
4202random ()
4203{
4204 /* Arrange to return a range centered on zero. */
4205 return rand () - (1 << 30);
4206}
4207
4208srandom (seed)
4209{
4210 srand (seed);
4211}
4212#endif /* VMS */
4213\f
4214#ifdef AIX
4215
4216/* Called from init_sys_modes. */
4217hft_init ()
4218{
4219 int junk;
4220
4221 /* If we're not on an HFT we shouldn't do any of this. We determine
4222 if we are on an HFT by trying to get an HFT error code. If this
4223 call fails, we're not on an HFT. */
4224#ifdef IBMR2AIX
4225 if (ioctl (0, HFQERROR, &junk) < 0)
4226 return;
4227#else /* not IBMR2AIX */
4228 if (ioctl (0, HFQEIO, 0) < 0)
4229 return;
4230#endif /* not IBMR2AIX */
4231
4232 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4233 as the rubout key's ASCII code. Here this is changed. The bug is that
4234 there's no way to determine the old mapping, so in reset_sys_modes
4235 we need to assume that the normal map had been present. Of course, this
4236 code also doesn't help if on a terminal emulator which doesn't understand
4237 HFT VTD's. */
4238 {
4239 struct hfbuf buf;
4240 struct hfkeymap keymap;
4241
4242 buf.hf_bufp = (char *)&keymap;
4243 buf.hf_buflen = sizeof (keymap);
4244 keymap.hf_nkeys = 2;
4245 keymap.hfkey[0].hf_kpos = 15;
4246 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4247#ifdef IBMR2AIX
4248 keymap.hfkey[0].hf_keyidh = '<';
4249#else /* not IBMR2AIX */
4250 keymap.hfkey[0].hf_page = '<';
4251#endif /* not IBMR2AIX */
4252 keymap.hfkey[0].hf_char = 127;
4253 keymap.hfkey[1].hf_kpos = 15;
4254 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4255#ifdef IBMR2AIX
4256 keymap.hfkey[1].hf_keyidh = '<';
4257#else /* not IBMR2AIX */
4258 keymap.hfkey[1].hf_page = '<';
4259#endif /* not IBMR2AIX */
4260 keymap.hfkey[1].hf_char = 127;
4261 hftctl (0, HFSKBD, &buf);
4262 }
4263 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4264 at times. */
4265 line_ins_del_ok = char_ins_del_ok = 0;
4266}
4267
4268/* Reset the rubout key to backspace. */
4269
4270hft_reset ()
4271{
4272 struct hfbuf buf;
4273 struct hfkeymap keymap;
4274 int junk;
4275
4276#ifdef IBMR2AIX
4277 if (ioctl (0, HFQERROR, &junk) < 0)
4278 return;
4279#else /* not IBMR2AIX */
4280 if (ioctl (0, HFQEIO, 0) < 0)
4281 return;
4282#endif /* not IBMR2AIX */
4283
4284 buf.hf_bufp = (char *)&keymap;
4285 buf.hf_buflen = sizeof (keymap);
4286 keymap.hf_nkeys = 2;
4287 keymap.hfkey[0].hf_kpos = 15;
4288 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4289#ifdef IBMR2AIX
4290 keymap.hfkey[0].hf_keyidh = '<';
4291#else /* not IBMR2AIX */
4292 keymap.hfkey[0].hf_page = '<';
4293#endif /* not IBMR2AIX */
4294 keymap.hfkey[0].hf_char = 8;
4295 keymap.hfkey[1].hf_kpos = 15;
4296 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4297#ifdef IBMR2AIX
4298 keymap.hfkey[1].hf_keyidh = '<';
4299#else /* not IBMR2AIX */
4300 keymap.hfkey[1].hf_page = '<';
4301#endif /* not IBMR2AIX */
4302 keymap.hfkey[1].hf_char = 8;
4303 hftctl (0, HFSKBD, &buf);
4304}
4305
4306#endif /* AIX */