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