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