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