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