(random, srandom): Obey HAVE_RAND48 flag.
[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
86a5659e
JB
2615 /* Arrange to return a range centered on zero. */
2616 return (rand () << 15) + rand () - (1 << 29);
2e46c7c6 2617#endif
86a5659e
JB
2618}
2619
2620srandom (arg)
2621 int arg;
2622{
2e46c7c6
RS
2623#ifdef HAVE_RAND48
2624 return srand48 ();
2625#else
86a5659e 2626 srand (arg);
2e46c7c6 2627#endif
86a5659e
JB
2628}
2629
2e46c7c6
RS
2630#endif /* no random */
2631#endif /* not HAVE_RANDOM */
86a5659e
JB
2632\f
2633#ifdef WRONG_NAME_INSQUE
2634
2635insque (q,p)
2636 caddr_t q,p;
2637{
2638 _insque (q,p);
2639}
2640
2641#endif
2642\f
2643#ifdef VMS
2644
2645#ifdef getenv
2646/* If any place else asks for the TERM variable,
2647 allow it to be overridden with the EMACS_TERM variable
2648 before attempting to translate the logical name TERM. As a last
2649 resort, ask for VAX C's special idea of the TERM variable. */
2650#undef getenv
2651char *
2652sys_getenv (name)
2653 char *name;
2654{
2655 register char *val;
2656 static char buf[256];
2657 static struct dsc$descriptor_s equiv
2658 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2659 static struct dsc$descriptor_s d_name
2660 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2661 short eqlen;
2662
2663 if (!strcmp (name, "TERM"))
2664 {
2665 val = (char *) getenv ("EMACS_TERM");
2666 if (val)
2667 return val;
2668 }
2669
2670 d_name.dsc$w_length = strlen (name);
2671 d_name.dsc$a_pointer = name;
986ffb24 2672 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
86a5659e
JB
2673 {
2674 char *str = (char *) xmalloc (eqlen + 1);
2675 bcopy (buf, str, eqlen);
2676 str[eqlen] = '\0';
2677 /* This is a storage leak, but a pain to fix. With luck,
2678 no one will ever notice. */
2679 return str;
2680 }
2681 return (char *) getenv (name);
2682}
2683#endif /* getenv */
2684
2685#ifdef abort
2686/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2687 to force a call on the debugger from within the image. */
2688#undef abort
2689sys_abort ()
2690{
2691 reset_sys_modes ();
2692 LIB$SIGNAL (SS$_DEBUG);
2693}
2694#endif /* abort */
2695#endif /* VMS */
2696\f
2697#ifdef VMS
2698#ifdef LINK_CRTL_SHARE
2699#ifdef SHAREABLE_LIB_BUG
eb8c3be9 2700/* Variables declared noshare and initialized in sharable libraries
86a5659e
JB
2701 cannot be shared. The VMS linker incorrectly forces you to use a private
2702 version which is uninitialized... If not for this "feature", we
2703 could use the C library definition of sys_nerr and sys_errlist. */
2704int sys_nerr = 35;
2705char *sys_errlist[] =
2706 {
2707 "error 0",
2708 "not owner",
2709 "no such file or directory",
2710 "no such process",
2711 "interrupted system call",
2712 "i/o error",
2713 "no such device or address",
2714 "argument list too long",
2715 "exec format error",
2716 "bad file number",
2717 "no child process",
2718 "no more processes",
2719 "not enough memory",
2720 "permission denied",
2721 "bad address",
2722 "block device required",
2723 "mount devices busy",
2724 "file exists",
2725 "cross-device link",
2726 "no such device",
2727 "not a directory",
2728 "is a directory",
2729 "invalid argument",
2730 "file table overflow",
2731 "too many open files",
2732 "not a typewriter",
2733 "text file busy",
2734 "file too big",
2735 "no space left on device",
2736 "illegal seek",
2737 "read-only file system",
2738 "too many links",
2739 "broken pipe",
2740 "math argument",
2741 "result too large",
2742 "I/O stream empty",
2743 "vax/vms specific error code nontranslatable error"
2744 };
2745#endif /* SHAREABLE_LIB_BUG */
2746#endif /* LINK_CRTL_SHARE */
2747#endif /* VMS */
7088d1ca
RM
2748
2749#ifndef HAVE_STRERROR
2750char *
2751strerror (errnum)
2752 int errnum;
2753{
2754 extern char *sys_errlist[];
2755 extern int sys_nerr;
2756
2757 if (errnum >= 0 && errnum < sys_nerr)
2758 return sys_errlist[errnum];
2759 return (char *) "Unknown error";
2760}
2761
2762#endif /* ! HAVE_STRERROR */
86a5659e
JB
2763\f
2764#ifdef INTERRUPTIBLE_OPEN
2765
2766int
2767/* VARARGS 2 */
2768sys_open (path, oflag, mode)
2769 char *path;
2770 int oflag, mode;
2771{
2772 register int rtnval;
2773
2774 while ((rtnval = open (path, oflag, mode)) == -1
2775 && (errno == EINTR));
2776 return (rtnval);
2777}
2778
2779#endif /* INTERRUPTIBLE_OPEN */
2780
2781#ifdef INTERRUPTIBLE_CLOSE
2782
2783sys_close (fd)
2784 int fd;
2785{
2786 register int rtnval;
2787
2788 while ((rtnval = close (fd)) == -1
2789 && (errno == EINTR));
2790 return rtnval;
2791}
2792
2793#endif /* INTERRUPTIBLE_CLOSE */
2794
2795#ifdef INTERRUPTIBLE_IO
2796
2797int
2798sys_read (fildes, buf, nbyte)
2799 int fildes;
2800 char *buf;
2801 unsigned int nbyte;
2802{
2803 register int rtnval;
2804
2805 while ((rtnval = read (fildes, buf, nbyte)) == -1
2806 && (errno == EINTR));
2807 return (rtnval);
2808}
2809
2810int
2811sys_write (fildes, buf, nbyte)
2812 int fildes;
2813 char *buf;
2814 unsigned int nbyte;
2815{
b95520f5 2816 register int rtnval, bytes_written;
86a5659e 2817
b95520f5
BF
2818 bytes_written = 0;
2819
2820 while (nbyte > 0)
2821 {
2822 rtnval = write (fildes, buf, nbyte);
2823
2824 if (rtnval == -1)
2825 {
2826 if (errno == EINTR)
2827 continue;
2828 else
aa670904 2829 return (bytes_written ? bytes_written : -1);
b95520f5
BF
2830 }
2831
2832 buf += rtnval;
2833 nbyte -= rtnval;
2834 bytes_written += rtnval;
2835 }
2836 return (bytes_written);
86a5659e
JB
2837}
2838
2839#endif /* INTERRUPTIBLE_IO */
2840\f
0e18d8ef
RS
2841#ifndef HAVE_VFORK
2842
2843/*
2844 * Substitute fork for vfork on USG flavors.
2845 */
2846
2847vfork ()
2848{
2849 return (fork ());
2850}
2851
2852#endif /* not HAVE_VFORK */
2853\f
86a5659e
JB
2854#ifdef USG
2855/*
2856 * All of the following are for USG.
2857 *
2858 * On USG systems the system calls are INTERRUPTIBLE by signals
2859 * that the user program has elected to catch. Thus the system call
2860 * must be retried in these cases. To handle this without massive
2861 * changes in the source code, we remap the standard system call names
2862 * to names for our own functions in sysdep.c that do the system call
2863 * with retries. Actually, for portability reasons, it is good
2864 * programming practice, as this example shows, to limit all actual
eb8c3be9 2865 * system calls to a single occurrence in the source. Sure, this
86a5659e
JB
2866 * adds an extra level of function call overhead but it is almost
2867 * always negligible. Fred Fish, Unisoft Systems Inc.
2868 */
2869
00eaaa32 2870#ifndef HAVE_SYS_SIGLIST
86a5659e
JB
2871char *sys_siglist[NSIG + 1] =
2872{
2873#ifdef AIX
2874/* AIX has changed the signals a bit */
2875 "bogus signal", /* 0 */
2876 "hangup", /* 1 SIGHUP */
2877 "interrupt", /* 2 SIGINT */
2878 "quit", /* 3 SIGQUIT */
2879 "illegal instruction", /* 4 SIGILL */
2880 "trace trap", /* 5 SIGTRAP */
2881 "IOT instruction", /* 6 SIGIOT */
2882 "crash likely", /* 7 SIGDANGER */
2883 "floating point exception", /* 8 SIGFPE */
2884 "kill", /* 9 SIGKILL */
2885 "bus error", /* 10 SIGBUS */
2886 "segmentation violation", /* 11 SIGSEGV */
2887 "bad argument to system call", /* 12 SIGSYS */
2888 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2889 "alarm clock", /* 14 SIGALRM */
2890 "software termination signum", /* 15 SIGTERM */
2891 "user defined signal 1", /* 16 SIGUSR1 */
2892 "user defined signal 2", /* 17 SIGUSR2 */
2893 "death of a child", /* 18 SIGCLD */
2894 "power-fail restart", /* 19 SIGPWR */
2895 "bogus signal", /* 20 */
2896 "bogus signal", /* 21 */
2897 "bogus signal", /* 22 */
2898 "bogus signal", /* 23 */
2899 "bogus signal", /* 24 */
2900 "LAN I/O interrupt", /* 25 SIGAIO */
2901 "PTY I/O interrupt", /* 26 SIGPTY */
2902 "I/O intervention required", /* 27 SIGIOINT */
2903 "HFT grant", /* 28 SIGGRANT */
2904 "HFT retract", /* 29 SIGRETRACT */
2905 "HFT sound done", /* 30 SIGSOUND */
2906 "HFT input ready", /* 31 SIGMSG */
2907#else /* not AIX */
2908 "bogus signal", /* 0 */
2909 "hangup", /* 1 SIGHUP */
2910 "interrupt", /* 2 SIGINT */
2911 "quit", /* 3 SIGQUIT */
2912 "illegal instruction", /* 4 SIGILL */
2913 "trace trap", /* 5 SIGTRAP */
2914 "IOT instruction", /* 6 SIGIOT */
2915 "EMT instruction", /* 7 SIGEMT */
2916 "floating point exception", /* 8 SIGFPE */
2917 "kill", /* 9 SIGKILL */
2918 "bus error", /* 10 SIGBUS */
2919 "segmentation violation", /* 11 SIGSEGV */
2920 "bad argument to system call", /* 12 SIGSYS */
2921 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2922 "alarm clock", /* 14 SIGALRM */
2923 "software termination signum", /* 15 SIGTERM */
2924 "user defined signal 1", /* 16 SIGUSR1 */
2925 "user defined signal 2", /* 17 SIGUSR2 */
2926 "death of a child", /* 18 SIGCLD */
2927 "power-fail restart", /* 19 SIGPWR */
0f0ea229
RS
2928#ifdef sun
2929 "window size change", /* 20 SIGWINCH */
2930 "urgent socket condition", /* 21 SIGURG */
2931 "pollable event occured", /* 22 SIGPOLL */
2932 "stop (cannot be caught or ignored)", /* 23 SIGSTOP */
2933 "user stop requested from tty", /* 24 SIGTSTP */
2934 "stopped process has been continued", /* 25 SIGCONT */
2935 "background tty read attempted", /* 26 SIGTTIN */
2936 "background tty write attempted", /* 27 SIGTTOU */
2937 "virtual timer expired", /* 28 SIGVTALRM */
2938 "profiling timer expired", /* 29 SIGPROF */
2939 "exceeded cpu limit", /* 30 SIGXCPU */
2940 "exceeded file size limit", /* 31 SIGXFSZ */
2941 "process's lwps are blocked", /* 32 SIGWAITING */
2942 "special signal used by thread library", /* 33 SIGLWP */
2da0df4d 2943#ifdef SIGFREEZE
0f0ea229 2944 "Special Signal Used By CPR", /* 34 SIGFREEZE */
2da0df4d
RS
2945#endif
2946#ifdef SIGTHAW
0f0ea229 2947 "Special Signal Used By CPR", /* 35 SIGTHAW */
2da0df4d 2948#endif
0f0ea229 2949#endif /* sun */
86a5659e
JB
2950#endif /* not AIX */
2951 0
2952 };
70080de1 2953#endif /* HAVE_SYS_SIGLIST */
86a5659e
JB
2954
2955/*
2956 * Warning, this function may not duplicate 4.2 action properly
2957 * under error conditions.
2958 */
2959
2960#ifndef MAXPATHLEN
2961/* In 4.1, param.h fails to define this. */
2962#define MAXPATHLEN 1024
2963#endif
2964
2965#ifndef HAVE_GETWD
2966
2967char *
2968getwd (pathname)
2969 char *pathname;
2970{
2971 char *npath, *spath;
2972 extern char *getcwd ();
2973
9ac0d9e0 2974 BLOCK_INPUT; /* getcwd uses malloc */
86a5659e 2975 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
f4a7e5bd
RS
2976 if (spath == 0)
2977 return spath;
86a5659e
JB
2978 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2979 up to first slash. Should be harmless on other systems. */
2980 while (*npath && *npath != '/')
2981 npath++;
2982 strcpy (pathname, npath);
2983 free (spath); /* getcwd uses malloc */
9ac0d9e0 2984 UNBLOCK_INPUT;
86a5659e
JB
2985 return pathname;
2986}
2987
2988#endif /* HAVE_GETWD */
2989
2990/*
2991 * Emulate rename using unlink/link. Note that this is
2992 * only partially correct. Also, doesn't enforce restriction
2993 * that files be of same type (regular->regular, dir->dir, etc).
2994 */
2995
4746118a
JB
2996#ifndef HAVE_RENAME
2997
86a5659e 2998rename (from, to)
19c7afdf
JB
2999 const char *from;
3000 const char *to;
86a5659e
JB
3001{
3002 if (access (from, 0) == 0)
3003 {
3004 unlink (to);
3005 if (link (from, to) == 0)
3006 if (unlink (from) == 0)
3007 return (0);
3008 }
3009 return (-1);
3010}
3011
4746118a
JB
3012#endif
3013
86a5659e
JB
3014#ifdef MISSING_UTIMES
3015
3016/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
3017
3018utimes ()
3019{
3020}
3021#endif
3022
3023#ifdef IRIS_UTIME
3024
3025/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
3026 utimbuf structure defined anywhere but in the man page. */
3027
3028struct utimbuf
3029 {
3030 long actime;
3031 long modtime;
3032 };
3033
3034utimes (name, tvp)
3035 char *name;
3036 struct timeval tvp[];
3037{
3038 struct utimbuf utb;
3039 utb.actime = tvp[0].tv_sec;
3040 utb.modtime = tvp[1].tv_sec;
3041 utime (name, &utb);
3042}
3043#endif /* IRIS_UTIME */
3044
3045
3046#ifdef HPUX
3047#ifndef HAVE_PERROR
3048
3049/* HPUX curses library references perror, but as far as we know
3050 it won't be called. Anyway this definition will do for now. */
3051
3052perror ()
3053{
3054}
3055
3056#endif /* not HAVE_PERROR */
3057#endif /* HPUX */
3058
3059#ifndef HAVE_DUP2
3060
3061/*
3062 * Emulate BSD dup2. First close newd if it already exists.
3063 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3064 * until we are, then close the unsuccessful ones.
3065 */
3066
3067dup2 (oldd, newd)
3068 int oldd;
3069 int newd;
3070{
3071 register int fd, ret;
3072
3073 sys_close (newd);
3074
3075#ifdef F_DUPFD
3076 fd = fcntl (oldd, F_DUPFD, newd);
3077 if (fd != newd)
7088d1ca 3078 error ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (errno));
86a5659e
JB
3079#else
3080 fd = dup (old);
3081 if (fd == -1)
3082 return -1;
3083 if (fd == new)
3084 return new;
3085 ret = dup2 (old,new);
3086 sys_close (fd);
3087 return ret;
3088#endif
3089}
3090
3091#endif /* not HAVE_DUP2 */
3092
3093/*
3094 * Gettimeofday. Simulate as much as possible. Only accurate
3095 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3096 * Only needed when subprocesses are defined.
3097 */
3098
3099#ifdef subprocesses
3100#ifndef VMS
3101#ifndef HAVE_GETTIMEOFDAY
3102#ifdef HAVE_TIMEVAL
3103
3104/* ARGSUSED */
3105gettimeofday (tp, tzp)
3106 struct timeval *tp;
3107 struct timezone *tzp;
3108{
3109 extern long time ();
3110
3111 tp->tv_sec = time ((long *)0);
3112 tp->tv_usec = 0;
4ca7594f
RS
3113 if (tzp != 0)
3114 tzp->tz_minuteswest = -1;
86a5659e
JB
3115}
3116
3117#endif
3118#endif
3119#endif
3120#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
3121
3122/*
3123 * This function will go away as soon as all the stubs fixed. (fnf)
3124 */
3125
3126croak (badfunc)
3127 char *badfunc;
3128{
3129 printf ("%s not yet implemented\r\n", badfunc);
3130 reset_sys_modes ();
3131 exit (1);
3132}
3133
3134#endif /* USG */
3135\f
3136#ifdef DGUX
3137
3138char *sys_siglist[NSIG + 1] =
3139{
3140 "null signal", /* 0 SIGNULL */
3141 "hangup", /* 1 SIGHUP */
3142 "interrupt", /* 2 SIGINT */
3143 "quit", /* 3 SIGQUIT */
3144 "illegal instruction", /* 4 SIGILL */
3145 "trace trap", /* 5 SIGTRAP */
3146 "abort termination", /* 6 SIGABRT */
3147 "SIGEMT", /* 7 SIGEMT */
3148 "floating point exception", /* 8 SIGFPE */
3149 "kill", /* 9 SIGKILL */
3150 "bus error", /* 10 SIGBUS */
3151 "segmentation violation", /* 11 SIGSEGV */
3152 "bad argument to system call", /* 12 SIGSYS */
3153 "write on a pipe with no reader", /* 13 SIGPIPE */
3154 "alarm clock", /* 14 SIGALRM */
3155 "software termination signal", /* 15 SIGTERM */
3156 "user defined signal 1", /* 16 SIGUSR1 */
3157 "user defined signal 2", /* 17 SIGUSR2 */
3158 "child stopped or terminated", /* 18 SIGCLD */
3159 "power-fail restart", /* 19 SIGPWR */
3160 "window size changed", /* 20 SIGWINCH */
3161 "undefined", /* 21 */
eb8c3be9 3162 "pollable event occurred", /* 22 SIGPOLL */
86a5659e
JB
3163 "sendable stop signal not from tty", /* 23 SIGSTOP */
3164 "stop signal from tty", /* 24 SIGSTP */
3165 "continue a stopped process", /* 25 SIGCONT */
3166 "attempted background tty read", /* 26 SIGTTIN */
3167 "attempted background tty write", /* 27 SIGTTOU */
3168 "undefined", /* 28 */
3169 "undefined", /* 29 */
3170 "undefined", /* 30 */
3171 "undefined", /* 31 */
3172 "undefined", /* 32 */
3173 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
3174 "I/O is possible", /* 34 SIGIO */
3175 "exceeded cpu time limit", /* 35 SIGXCPU */
3176 "exceeded file size limit", /* 36 SIGXFSZ */
3177 "virtual time alarm", /* 37 SIGVTALRM */
3178 "profiling time alarm", /* 38 SIGPROF */
3179 "undefined", /* 39 */
3180 "file record locks revoked", /* 40 SIGLOST */
3181 "undefined", /* 41 */
3182 "undefined", /* 42 */
3183 "undefined", /* 43 */
3184 "undefined", /* 44 */
3185 "undefined", /* 45 */
3186 "undefined", /* 46 */
3187 "undefined", /* 47 */
3188 "undefined", /* 48 */
3189 "undefined", /* 49 */
3190 "undefined", /* 50 */
3191 "undefined", /* 51 */
3192 "undefined", /* 52 */
3193 "undefined", /* 53 */
3194 "undefined", /* 54 */
3195 "undefined", /* 55 */
3196 "undefined", /* 56 */
3197 "undefined", /* 57 */
3198 "undefined", /* 58 */
3199 "undefined", /* 59 */
3200 "undefined", /* 60 */
3201 "undefined", /* 61 */
3202 "undefined", /* 62 */
3203 "undefined", /* 63 */
3204 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
3205 0
3206};
3207
3208#endif /* DGUX */
3209\f
3210/* Directory routines for systems that don't have them. */
3211
3212#ifdef SYSV_SYSTEM_DIR
3213
3214#include <dirent.h>
3215
1db6401c 3216#if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
cfdc57af 3217
86a5659e
JB
3218int
3219closedir (dirp)
3220 register DIR *dirp; /* stream from opendir */
3221{
cfdc57af
RS
3222 int rtnval;
3223
3224 rtnval = sys_close (dirp->dd_fd);
1b929d25 3225
65aa44ac
JB
3226 /* Some systems (like Solaris) allocate the buffer and the DIR all
3227 in one block. Why in the world are we freeing this ourselves
3228 anyway? */
3229#if ! (defined (sun) && defined (USG5_4))
3230 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3231#endif
9ac0d9e0 3232 xfree ((char *) dirp);
cfdc57af
RS
3233
3234 return rtnval;
86a5659e 3235}
1db6401c 3236#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
86a5659e
JB
3237#endif /* SYSV_SYSTEM_DIR */
3238
3239#ifdef NONSYSTEM_DIR_LIBRARY
3240
3241DIR *
3242opendir (filename)
3243 char *filename; /* name of directory */
3244{
3245 register DIR *dirp; /* -> malloc'ed storage */
3246 register int fd; /* file descriptor for read */
3247 struct stat sbuf; /* result of fstat */
3248
3249 fd = sys_open (filename, 0);
3250 if (fd < 0)
3251 return 0;
3252
9ac0d9e0 3253 BLOCK_INPUT;
86a5659e
JB
3254 if (fstat (fd, &sbuf) < 0
3255 || (sbuf.st_mode & S_IFMT) != S_IFDIR
3256 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
3257 {
3258 sys_close (fd);
9ac0d9e0 3259 UNBLOCK_INPUT;
86a5659e
JB
3260 return 0; /* bad luck today */
3261 }
9ac0d9e0 3262 UNBLOCK_INPUT;
86a5659e
JB
3263
3264 dirp->dd_fd = fd;
3265 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
3266
3267 return dirp;
3268}
3269
3270void
3271closedir (dirp)
3272 register DIR *dirp; /* stream from opendir */
3273{
3274 sys_close (dirp->dd_fd);
9ac0d9e0 3275 xfree ((char *) dirp);
86a5659e
JB
3276}
3277
3278
3279#ifndef VMS
3280#define DIRSIZ 14
3281struct olddir
3282 {
3283 ino_t od_ino; /* inode */
3284 char od_name[DIRSIZ]; /* filename */
3285 };
3286#endif /* not VMS */
3287
3288struct direct dir_static; /* simulated directory contents */
3289
3290/* ARGUSED */
3291struct direct *
3292readdir (dirp)
3293 register DIR *dirp; /* stream from opendir */
3294{
3295#ifndef VMS
3296 register struct olddir *dp; /* -> directory data */
3297#else /* VMS */
3298 register struct dir$_name *dp; /* -> directory data */
3299 register struct dir$_version *dv; /* -> version data */
3300#endif /* VMS */
3301
3302 for (; ;)
3303 {
3304 if (dirp->dd_loc >= dirp->dd_size)
3305 dirp->dd_loc = dirp->dd_size = 0;
3306
3307 if (dirp->dd_size == 0 /* refill buffer */
3308 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3309 return 0;
3310
3311#ifndef VMS
3312 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3313 dirp->dd_loc += sizeof (struct olddir);
3314
3315 if (dp->od_ino != 0) /* not deleted entry */
3316 {
3317 dir_static.d_ino = dp->od_ino;
3318 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3319 dir_static.d_name[DIRSIZ] = '\0';
3320 dir_static.d_namlen = strlen (dir_static.d_name);
3321 dir_static.d_reclen = sizeof (struct direct)
3322 - MAXNAMLEN + 3
3323 + dir_static.d_namlen - dir_static.d_namlen % 4;
3324 return &dir_static; /* -> simulated structure */
3325 }
3326#else /* VMS */
3327 dp = (struct dir$_name *) dirp->dd_buf;
3328 if (dirp->dd_loc == 0)
3329 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3330 : dp->dir$b_namecount;
3331 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3332 dir_static.d_ino = dv->dir$w_fid_num;
3333 dir_static.d_namlen = dp->dir$b_namecount;
3334 dir_static.d_reclen = sizeof (struct direct)
3335 - MAXNAMLEN + 3
3336 + dir_static.d_namlen - dir_static.d_namlen % 4;
3337 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3338 dir_static.d_name[dir_static.d_namlen] = '\0';
3339 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3340 return &dir_static;
3341#endif /* VMS */
3342 }
3343}
3344
3345#ifdef VMS
3346/* readdirver is just like readdir except it returns all versions of a file
3347 as separate entries. */
3348
3349/* ARGUSED */
3350struct direct *
3351readdirver (dirp)
3352 register DIR *dirp; /* stream from opendir */
3353{
3354 register struct dir$_name *dp; /* -> directory data */
3355 register struct dir$_version *dv; /* -> version data */
3356
3357 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3358 dirp->dd_loc = dirp->dd_size = 0;
3359
3360 if (dirp->dd_size == 0 /* refill buffer */
3361 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3362 return 0;
3363
3364 dp = (struct dir$_name *) dirp->dd_buf;
3365 if (dirp->dd_loc == 0)
3366 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3367 : dp->dir$b_namecount;
3368 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3369 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3370 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3371 dir_static.d_namlen = strlen (dir_static.d_name);
3372 dir_static.d_ino = dv->dir$w_fid_num;
3373 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3374 + dir_static.d_namlen - dir_static.d_namlen % 4;
3375 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3376 return &dir_static;
3377}
3378
3379#endif /* VMS */
3380
3381#endif /* NONSYSTEM_DIR_LIBRARY */
23524fb9
JB
3382
3383\f
3384/* mkdir and rmdir functions, for systems which don't have them. */
3385
3386#ifndef HAVE_MKDIR
3387/*
3388 * Written by Robert Rother, Mariah Corporation, August 1985.
3389 *
3390 * If you want it, it's yours. All I ask in return is that if you
3391 * figure out how to do this in a Bourne Shell script you send me
3392 * a copy.
3393 * sdcsvax!rmr or rmr@uscd
3394 *
3395 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3396 * subroutine. 11Mar86; hoptoad!gnu
3397 *
3398 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3399 * subroutine didn't return EEXIST. It does now.
3400 */
3401
3402/*
3403 * Make a directory.
3404 */
f3892946
RS
3405#ifdef MKDIR_PROTOTYPE
3406MKDIR_PROTOTYPE
3407#else
23524fb9
JB
3408int
3409mkdir (dpath, dmode)
3410 char *dpath;
3411 int dmode;
f3892946 3412#endif
23524fb9 3413{
039f26a4 3414 int cpid, status, fd;
23524fb9
JB
3415 struct stat statbuf;
3416
3417 if (stat (dpath, &statbuf) == 0)
3418 {
3419 errno = EEXIST; /* Stat worked, so it already exists */
3420 return -1;
3421 }
3422
3423 /* If stat fails for a reason other than non-existence, return error */
3424 if (errno != ENOENT)
3425 return -1;
3426
039f26a4 3427 synch_process_alive = 1;
23524fb9
JB
3428 switch (cpid = fork ())
3429 {
3430
039f26a4 3431 case -1: /* Error in fork */
23524fb9
JB
3432 return (-1); /* Errno is set already */
3433
3434 case 0: /* Child process */
3435 /*
3436 * Cheap hack to set mode of new directory. Since this
3437 * child process is going away anyway, we zap its umask.
3438 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3439 * directory. Does anybody care?
3440 */
3441 status = umask (0); /* Get current umask */
3442 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
039f26a4
RS
3443 fd = sys_open("/dev/null", 2);
3444 if (fd >= 0)
3445 {
3446 dup2 (fd, 0);
3447 dup2 (fd, 1);
3448 dup2 (fd, 2);
3449 }
23524fb9
JB
3450 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3451 _exit (-1); /* Can't exec /bin/mkdir */
3452
3453 default: /* Parent process */
039f26a4 3454 wait_for_termination (cpid);
23524fb9
JB
3455 }
3456
039f26a4 3457 if (synch_process_death != 0 || synch_process_retcode != 0)
23524fb9
JB
3458 {
3459 errno = EIO; /* We don't know why, but */
3460 return -1; /* /bin/mkdir failed */
3461 }
3462
3463 return 0;
3464}
3465#endif /* not HAVE_MKDIR */
3466
3467#ifndef HAVE_RMDIR
3468int
3469rmdir (dpath)
3470 char *dpath;
3471{
039f26a4 3472 int cpid, status, fd;
23524fb9
JB
3473 struct stat statbuf;
3474
3475 if (stat (dpath, &statbuf) != 0)
3476 {
3477 /* Stat just set errno. We don't have to */
3478 return -1;
3479 }
3480
039f26a4 3481 synch_process_alive = 1;
23524fb9
JB
3482 switch (cpid = fork ())
3483 {
3484
039f26a4 3485 case -1: /* Error in fork */
23524fb9
JB
3486 return (-1); /* Errno is set already */
3487
3488 case 0: /* Child process */
039f26a4
RS
3489 fd = sys_open("/dev/null", 2);
3490 if (fd >= 0)
3491 {
3492 dup2 (fd, 0);
3493 dup2 (fd, 1);
3494 dup2 (fd, 2);
3495 }
039f26a4 3496 wait_for_termination (cpid);
207bdbdb
RS
3497 if (synch_process_death != 0 || synch_process_retcode != 0)
3498 return -1; /* /bin/rmdir failed */
3499 default: /* Parent process */
3500 while (cpid != wait (&status)); /* Wait for kid to finish */
23524fb9
JB
3501 }
3502
207bdbdb 3503 if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
23524fb9
JB
3504 {
3505 errno = EIO; /* We don't know why, but */
207bdbdb 3506 return -1; /* /bin/mkdir failed */
23524fb9
JB
3507 }
3508
3509 return 0;
3510}
3511#endif /* !HAVE_RMDIR */
3512
3513
86a5659e
JB
3514\f
3515/* Functions for VMS */
3516#ifdef VMS
91bac16a 3517#include "vms-pwd.h"
86a5659e
JB
3518#include <acldef.h>
3519#include <chpdef.h>
3520#include <jpidef.h>
3521
3522/* Return as a string the VMS error string pertaining to STATUS.
3523 Reuses the same static buffer each time it is called. */
3524
3525char *
3526vmserrstr (status)
3527 int status; /* VMS status code */
3528{
3529 int bufadr[2];
3530 short len;
3531 static char buf[257];
3532
3533 bufadr[0] = sizeof buf - 1;
3534 bufadr[1] = (int) buf;
3535 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3536 return "untranslatable VMS error status";
3537 buf[len] = '\0';
3538 return buf;
3539}
3540
3541#ifdef access
3542#undef access
3543
3544/* The following is necessary because 'access' emulation by VMS C (2.0) does
3545 * not work correctly. (It also doesn't work well in version 2.3.)
3546 */
3547
3548#ifdef VMS4_4
3549
3550#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3551 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3552
3553typedef union {
3554 struct {
3555 unsigned short s_buflen;
3556 unsigned short s_code;
3557 char *s_bufadr;
3558 unsigned short *s_retlenadr;
3559 } s;
3560 int end;
3561} item;
3562#define buflen s.s_buflen
3563#define code s.s_code
3564#define bufadr s.s_bufadr
3565#define retlenadr s.s_retlenadr
3566
3567#define R_OK 4 /* test for read permission */
3568#define W_OK 2 /* test for write permission */
3569#define X_OK 1 /* test for execute (search) permission */
3570#define F_OK 0 /* test for presence of file */
3571
3572int
3573sys_access (path, mode)
3574 char *path;
3575 int mode;
3576{
3577 static char *user = NULL;
3578 char dir_fn[512];
3579
3580 /* translate possible directory spec into .DIR file name, so brain-dead
3581 * access can treat the directory like a file. */
3582 if (directory_file_name (path, dir_fn))
3583 path = dir_fn;
3584
3585 if (mode == F_OK)
3586 return access (path, mode);
3587 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3588 return -1;
3589 {
3590 int stat;
3591 int flags;
3592 int acces;
3593 unsigned short int dummy;
3594 item itemlst[3];
3595 static int constant = ACL$C_FILE;
3596 DESCRIPTOR (path_desc, path);
3597 DESCRIPTOR (user_desc, user);
3598
3599 flags = 0;
3600 acces = 0;
3601 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3602 return stat;
3603 if (mode & R_OK)
3604 acces |= CHP$M_READ;
3605 if (mode & W_OK)
3606 acces |= CHP$M_WRITE;
3607 itemlst[0].buflen = sizeof (int);
3608 itemlst[0].code = CHP$_FLAGS;
3609 itemlst[0].bufadr = (char *) &flags;
3610 itemlst[0].retlenadr = &dummy;
3611 itemlst[1].buflen = sizeof (int);
3612 itemlst[1].code = CHP$_ACCESS;
3613 itemlst[1].bufadr = (char *) &acces;
3614 itemlst[1].retlenadr = &dummy;
3615 itemlst[2].end = CHP$_END;
3616 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3617 return stat == SS$_NORMAL ? 0 : -1;
3618 }
3619}
3620
3621#else /* not VMS4_4 */
3622
3623#include <prvdef.h>
3624#define ACE$M_WRITE 2
3625#define ACE$C_KEYID 1
3626
3627static unsigned short memid, grpid;
3628static unsigned int uic;
3629
3630/* Called from init_sys_modes, so it happens not very often
3631 but at least each time Emacs is loaded. */
3632sys_access_reinit ()
3633{
3634 uic = 0;
3635}
3636
3637int
3638sys_access (filename, type)
3639 char * filename;
3640 int type;
3641{
3642 struct FAB fab;
3643 struct XABPRO xab;
3644 int status, size, i, typecode, acl_controlled;
3645 unsigned int *aclptr, *aclend, aclbuf[60];
3646 union prvdef prvmask;
3647
3648 /* Get UIC and GRP values for protection checking. */
3649 if (uic == 0)
3650 {
3651 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3652 if (! (status & 1))
3653 return -1;
3654 memid = uic & 0xFFFF;
3655 grpid = uic >> 16;
3656 }
3657
3658 if (type != 2) /* not checking write access */
3659 return access (filename, type);
3660
3661 /* Check write protection. */
3662
3663#define CHECKPRIV(bit) (prvmask.bit)
3664#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3665
3666 /* Find privilege bits */
986ffb24 3667 status = SYS$SETPRV (0, 0, 0, prvmask);
86a5659e
JB
3668 if (! (status & 1))
3669 error ("Unable to find privileges: %s", vmserrstr (status));
3670 if (CHECKPRIV (PRV$V_BYPASS))
3671 return 0; /* BYPASS enabled */
3672 fab = cc$rms_fab;
3673 fab.fab$b_fac = FAB$M_GET;
3674 fab.fab$l_fna = filename;
3675 fab.fab$b_fns = strlen (filename);
3676 fab.fab$l_xab = &xab;
3677 xab = cc$rms_xabpro;
3678 xab.xab$l_aclbuf = aclbuf;
3679 xab.xab$w_aclsiz = sizeof (aclbuf);
986ffb24 3680 status = SYS$OPEN (&fab, 0, 0);
86a5659e
JB
3681 if (! (status & 1))
3682 return -1;
986ffb24 3683 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3684 /* Check system access */
3685 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
3686 return 0;
3687 /* Check ACL entries, if any */
3688 acl_controlled = 0;
3689 if (xab.xab$w_acllen > 0)
3690 {
3691 aclptr = aclbuf;
3692 aclend = &aclbuf[xab.xab$w_acllen / 4];
3693 while (*aclptr && aclptr < aclend)
3694 {
3695 size = (*aclptr & 0xff) / 4;
3696 typecode = (*aclptr >> 8) & 0xff;
3697 if (typecode == ACE$C_KEYID)
3698 for (i = size - 1; i > 1; i--)
3699 if (aclptr[i] == uic)
3700 {
3701 acl_controlled = 1;
3702 if (aclptr[1] & ACE$M_WRITE)
3703 return 0; /* Write access through ACL */
3704 }
3705 aclptr = &aclptr[size];
3706 }
3707 if (acl_controlled) /* ACL specified, prohibits write access */
3708 return -1;
3709 }
3710 /* No ACL entries specified, check normal protection */
3711 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
3712 return 0;
3713 if (WRITEABLE (XAB$V_GRP) &&
3714 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3715 return 0; /* Group writeable */
3716 if (WRITEABLE (XAB$V_OWN) &&
3717 (xab.xab$l_uic & 0xFFFF) == memid)
3718 return 0; /* Owner writeable */
3719
3720 return -1; /* Not writeable */
3721}
3722#endif /* not VMS4_4 */
3723#endif /* access */
3724
3725static char vtbuf[NAM$C_MAXRSS+1];
3726
3727/* translate a vms file spec to a unix path */
3728char *
3729sys_translate_vms (vfile)
3730 char * vfile;
3731{
3732 char * p;
3733 char * targ;
3734
3735 if (!vfile)
3736 return 0;
3737
3738 targ = vtbuf;
3739
3740 /* leading device or logical name is a root directory */
3741 if (p = strchr (vfile, ':'))
3742 {
3743 *targ++ = '/';
3744 while (vfile < p)
3745 *targ++ = *vfile++;
3746 vfile++;
3747 *targ++ = '/';
3748 }
3749 p = vfile;
3750 if (*p == '[' || *p == '<')
3751 {
3752 while (*++vfile != *p + 2)
3753 switch (*vfile)
3754 {
3755 case '.':
3756 if (vfile[-1] == *p)
3757 *targ++ = '.';
3758 *targ++ = '/';
3759 break;
3760
3761 case '-':
3762 *targ++ = '.';
3763 *targ++ = '.';
3764 break;
3765
3766 default:
3767 *targ++ = *vfile;
3768 break;
3769 }
3770 vfile++;
3771 *targ++ = '/';
3772 }
3773 while (*vfile)
3774 *targ++ = *vfile++;
3775
3776 return vtbuf;
3777}
3778
3779static char utbuf[NAM$C_MAXRSS+1];
3780
3781/* translate a unix path to a VMS file spec */
3782char *
3783sys_translate_unix (ufile)
3784 char * ufile;
3785{
3786 int slash_seen = 0;
3787 char *p;
3788 char * targ;
3789
3790 if (!ufile)
3791 return 0;
3792
3793 targ = utbuf;
3794
3795 if (*ufile == '/')
3796 {
3797 ufile++;
3798 }
3799
3800 while (*ufile)
3801 {
3802 switch (*ufile)
3803 {
3804 case '/':
3805 if (slash_seen)
3806 if (index (&ufile[1], '/'))
3807 *targ++ = '.';
3808 else
3809 *targ++ = ']';
3810 else
3811 {
3812 *targ++ = ':';
3813 if (index (&ufile[1], '/'))
3814 *targ++ = '[';
3815 slash_seen = 1;
3816 }
3817 break;
3818
3819 case '.':
3820 if (strncmp (ufile, "./", 2) == 0)
3821 {
3822 if (!slash_seen)
3823 {
3824 *targ++ = '[';
3825 slash_seen = 1;
3826 }
3827 ufile++; /* skip the dot */
3828 if (index (&ufile[1], '/'))
3829 *targ++ = '.';
3830 else
3831 *targ++ = ']';
3832 }
3833 else if (strncmp (ufile, "../", 3) == 0)
3834 {
3835 if (!slash_seen)
3836 {
3837 *targ++ = '[';
3838 slash_seen = 1;
3839 }
3840 *targ++ = '-';
3841 ufile += 2; /* skip the dots */
3842 if (index (&ufile[1], '/'))
3843 *targ++ = '.';
3844 else
3845 *targ++ = ']';
3846 }
3847 else
3848 *targ++ = *ufile;
3849 break;
3850
3851 default:
3852 *targ++ = *ufile;
3853 break;
3854 }
3855 ufile++;
3856 }
3857 *targ = '\0';
3858
3859 return utbuf;
3860}
3861
3862char *
3863getwd (pathname)
3864 char *pathname;
3865{
f4a7e5bd 3866 char *ptr, *val;
210b2b4f 3867 extern char *getcwd ();
86a5659e 3868
210b2b4f
JB
3869#define MAXPATHLEN 1024
3870
9ac0d9e0 3871 ptr = xmalloc (MAXPATHLEN);
f4a7e5bd
RS
3872 val = getcwd (ptr, MAXPATHLEN);
3873 if (val == 0)
3874 {
3875 xfree (ptr);
3876 return val;
3877 }
210b2b4f 3878 strcpy (pathname, ptr);
9ac0d9e0 3879 xfree (ptr);
210b2b4f
JB
3880
3881 return pathname;
86a5659e
JB
3882}
3883
3884getppid ()
3885{
3886 long item_code = JPI$_OWNER;
3887 unsigned long parent_id;
3888 int status;
3889
3890 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3891 {
3892 errno = EVMSERR;
3893 vaxc$errno = status;
3894 return -1;
3895 }
3896 return parent_id;
3897}
3898
3899#undef getuid
3900unsigned
3901sys_getuid ()
3902{
3903 return (getgid () << 16) | getuid ();
3904}
3905
3906int
3907sys_read (fildes, buf, nbyte)
3908 int fildes;
3909 char *buf;
3910 unsigned int nbyte;
3911{
3912 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3913}
3914
3915#if 0
3916int
3917sys_write (fildes, buf, nbyte)
3918 int fildes;
3919 char *buf;
3920 unsigned int nbyte;
3921{
3922 register int nwrote, rtnval = 0;
3923
3924 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3925 nbyte -= nwrote;
3926 buf += nwrote;
3927 rtnval += nwrote;
3928 }
3929 if (nwrote < 0)
3930 return rtnval ? rtnval : -1;
3931 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3932 return rtnval ? rtnval : -1;
3933 return (rtnval + nwrote);
3934}
3935#endif /* 0 */
3936
3937/*
3938 * VAX/VMS VAX C RTL really loses. It insists that records
3939 * end with a newline (carriage return) character, and if they
3940 * don't it adds one (nice of it isn't it!)
3941 *
3942 * Thus we do this stupidity below.
3943 */
3944
3945int
3946sys_write (fildes, buf, nbytes)
3947 int fildes;
3948 char *buf;
3949 unsigned int nbytes;
3950{
3951 register char *p;
3952 register char *e;
23b0668c
JB
3953 int sum = 0;
3954 struct stat st;
3955
3956 fstat (fildes, &st);
86a5659e 3957 p = buf;
86a5659e
JB
3958 while (nbytes > 0)
3959 {
23b0668c
JB
3960 int len, retval;
3961
3962 /* Handle fixed-length files with carriage control. */
3963 if (st.st_fab_rfm == FAB$C_FIX
3964 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3965 {
3966 len = st.st_fab_mrs;
3967 retval = write (fildes, p, min (len, nbytes));
3968 if (retval != len)
3969 return -1;
3970 retval++; /* This skips the implied carriage control */
3971 }
3972 else
3973 {
3974 e = p + min (MAXIOSIZE, nbytes) - 1;
3975 while (*e != '\n' && e > p) e--;
3976 if (p == e) /* Ok.. so here we add a newline... sigh. */
3977 e = p + min (MAXIOSIZE, nbytes) - 1;
3978 len = e + 1 - p;
3979 retval = write (fildes, p, len);
3980 if (retval != len)
3981 return -1;
3982 }
3983 p += retval;
3984 sum += retval;
86a5659e
JB
3985 nbytes -= retval;
3986 }
3987 return sum;
3988}
3989
3990/* Create file NEW copying its attributes from file OLD. If
3991 OLD is 0 or does not exist, create based on the value of
3992 vms_stmlf_recfm. */
3993
3994/* Protection value the file should ultimately have.
3995 Set by create_copy_attrs, and use by rename_sansversions. */
3996static unsigned short int fab_final_pro;
3997
3998int
3999creat_copy_attrs (old, new)
4000 char *old, *new;
4001{
4002 struct FAB fab = cc$rms_fab;
4003 struct XABPRO xabpro;
4004 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
4005 extern int vms_stmlf_recfm;
4006
4007 if (old)
4008 {
4009 fab.fab$b_fac = FAB$M_GET;
4010 fab.fab$l_fna = old;
4011 fab.fab$b_fns = strlen (old);
4012 fab.fab$l_xab = (char *) &xabpro;
4013 xabpro = cc$rms_xabpro;
4014 xabpro.xab$l_aclbuf = aclbuf;
4015 xabpro.xab$w_aclsiz = sizeof aclbuf;
4016 /* Call $OPEN to fill in the fab & xabpro fields. */
986ffb24 4017 if (SYS$OPEN (&fab, 0, 0) & 1)
86a5659e 4018 {
986ffb24 4019 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
4020 fab.fab$l_alq = 0; /* zero the allocation quantity */
4021 if (xabpro.xab$w_acllen > 0)
4022 {
4023 if (xabpro.xab$w_acllen > sizeof aclbuf)
4024 /* If the acl buffer was too short, redo open with longer one.
4025 Wouldn't need to do this if there were some system imposed
4026 limit on the size of an ACL, but I can't find any such. */
4027 {
4028 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4029 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
986ffb24
JB
4030 if (SYS$OPEN (&fab, 0, 0) & 1)
4031 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
4032 else
4033 old = 0;
4034 }
4035 }
4036 else
4037 xabpro.xab$l_aclbuf = 0;
4038 }
4039 else
4040 old = 0;
4041 }
4042 fab.fab$l_fna = new;
4043 fab.fab$b_fns = strlen (new);
4044 if (!old)
4045 {
4046 fab.fab$l_xab = 0;
4047 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4048 fab.fab$b_rat = FAB$M_CR;
4049 }
4050
4051 /* Set the file protections such that we will be able to manipulate
4052 this file. Once we are done writing and renaming it, we will set
4053 the protections back. */
4054 if (old)
4055 fab_final_pro = xabpro.xab$w_pro;
4056 else
986ffb24 4057 SYS$SETDFPROT (0, &fab_final_pro);
86a5659e
JB
4058 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4059
4060 /* Create the new file with either default attrs or attrs copied
4061 from old file. */
4062 if (!(SYS$CREATE (&fab, 0, 0) & 1))
4063 return -1;
986ffb24 4064 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
4065 /* As this is a "replacement" for creat, return a file descriptor
4066 opened for writing. */
4067 return open (new, O_WRONLY);
4068}
4069
4070#ifdef creat
4071#undef creat
4072#include <varargs.h>
4073#ifdef __GNUC__
4074#ifndef va_count
4075#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4076#endif
4077#endif
4078
4079sys_creat (va_alist)
4080 va_dcl
4081{
eb8c3be9 4082 va_list list_incrementer;
86a5659e
JB
4083 char *name;
4084 int mode;
4085 int rfd; /* related file descriptor */
4086 int fd; /* Our new file descriptor */
4087 int count;
4088 struct stat st_buf;
4089 char rfm[12];
4090 char rat[15];
4091 char mrs[13];
4092 char fsz[13];
4093 extern int vms_stmlf_recfm;
4094
4095 va_count (count);
eb8c3be9
JB
4096 va_start (list_incrementer);
4097 name = va_arg (list_incrementer, char *);
4098 mode = va_arg (list_incrementer, int);
86a5659e 4099 if (count > 2)
eb8c3be9
JB
4100 rfd = va_arg (list_incrementer, int);
4101 va_end (list_incrementer);
86a5659e
JB
4102 if (count > 2)
4103 {
4104 /* Use information from the related file descriptor to set record
4105 format of the newly created file. */
4106 fstat (rfd, &st_buf);
4107 switch (st_buf.st_fab_rfm)
4108 {
4109 case FAB$C_FIX:
4110 strcpy (rfm, "rfm = fix");
4111 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4112 strcpy (rat, "rat = ");
4113 if (st_buf.st_fab_rat & FAB$M_CR)
4114 strcat (rat, "cr");
4115 else if (st_buf.st_fab_rat & FAB$M_FTN)
4116 strcat (rat, "ftn");
4117 else if (st_buf.st_fab_rat & FAB$M_PRN)
4118 strcat (rat, "prn");
4119 if (st_buf.st_fab_rat & FAB$M_BLK)
4120 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4121 strcat (rat, ", blk");
4122 else
4123 strcat (rat, "blk");
4124 return creat (name, 0, rfm, rat, mrs);
4125
4126 case FAB$C_VFC:
4127 strcpy (rfm, "rfm = vfc");
4128 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4129 strcpy (rat, "rat = ");
4130 if (st_buf.st_fab_rat & FAB$M_CR)
4131 strcat (rat, "cr");
4132 else if (st_buf.st_fab_rat & FAB$M_FTN)
4133 strcat (rat, "ftn");
4134 else if (st_buf.st_fab_rat & FAB$M_PRN)
4135 strcat (rat, "prn");
4136 if (st_buf.st_fab_rat & FAB$M_BLK)
4137 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4138 strcat (rat, ", blk");
4139 else
4140 strcat (rat, "blk");
4141 return creat (name, 0, rfm, rat, fsz);
4142
4143 case FAB$C_STM:
4144 strcpy (rfm, "rfm = stm");
4145 break;
4146
4147 case FAB$C_STMCR:
4148 strcpy (rfm, "rfm = stmcr");
4149 break;
4150
4151 case FAB$C_STMLF:
4152 strcpy (rfm, "rfm = stmlf");
4153 break;
4154
4155 case FAB$C_UDF:
4156 strcpy (rfm, "rfm = udf");
4157 break;
4158
4159 case FAB$C_VAR:
4160 strcpy (rfm, "rfm = var");
4161 break;
4162 }
4163 strcpy (rat, "rat = ");
4164 if (st_buf.st_fab_rat & FAB$M_CR)
4165 strcat (rat, "cr");
4166 else if (st_buf.st_fab_rat & FAB$M_FTN)
4167 strcat (rat, "ftn");
4168 else if (st_buf.st_fab_rat & FAB$M_PRN)
4169 strcat (rat, "prn");
4170 if (st_buf.st_fab_rat & FAB$M_BLK)
4171 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4172 strcat (rat, ", blk");
4173 else
4174 strcat (rat, "blk");
4175 }
4176 else
4177 {
4178 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4179 strcpy (rat, "rat=cr");
4180 }
4181 /* Until the VAX C RTL fixes the many bugs with modes, always use
4182 mode 0 to get the user's default protection. */
4183 fd = creat (name, 0, rfm, rat);
4184 if (fd < 0 && errno == EEXIST)
4185 {
4186 if (unlink (name) < 0)
4187 report_file_error ("delete", build_string (name));
4188 fd = creat (name, 0, rfm, rat);
4189 }
4190 return fd;
4191}
4192#endif /* creat */
4193
4194/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4195sys_fwrite (ptr, size, num, fp)
4196 register char * ptr;
4197 FILE * fp;
4198{
4199 register int tot = num * size;
4200
4201 while (tot--)
4202 fputc (*ptr++, fp);
4203}
4204
4205/*
4206 * The VMS C library routine creat actually creates a new version of an
4207 * existing file rather than truncating the old version. There are times
4208 * when this is not the desired behavior, for instance, when writing an
4209 * auto save file (you only want one version), or when you don't have
4210 * write permission in the directory containing the file (but the file
4211 * itself is writable). Hence this routine, which is equivalent to
4212 * "close (creat (fn, 0));" on Unix if fn already exists.
4213 */
4214int
4215vms_truncate (fn)
4216 char *fn;
4217{
4218 struct FAB xfab = cc$rms_fab;
4219 struct RAB xrab = cc$rms_rab;
4220 int status;
4221
4222 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
4223 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4224 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
4225 xfab.fab$l_fna = fn;
4226 xfab.fab$b_fns = strlen (fn);
4227 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
4228 xfab.fab$b_dns = 2;
4229 xrab.rab$l_fab = &xfab;
4230
4231 /* This gibberish opens the file, positions to the first record, and
4232 deletes all records from there until the end of file. */
986ffb24 4233 if ((SYS$OPEN (&xfab) & 01) == 01)
86a5659e 4234 {
986ffb24
JB
4235 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4236 (SYS$FIND (&xrab) & 01) == 01 &&
4237 (SYS$TRUNCATE (&xrab) & 01) == 01)
86a5659e
JB
4238 status = 0;
4239 else
4240 status = -1;
4241 }
4242 else
4243 status = -1;
986ffb24 4244 SYS$CLOSE (&xfab);
86a5659e
JB
4245 return status;
4246}
4247
4248/* Define this symbol to actually read SYSUAF.DAT. This requires either
4249 SYSPRV or a readable SYSUAF.DAT. */
4250
4251#ifdef READ_SYSUAF
4252/*
4253 * getuaf.c
4254 *
4255 * Routine to read the VMS User Authorization File and return
4256 * a specific user's record.
4257 */
4258
4259static struct UAF retuaf;
4260
4261struct UAF *
4262get_uaf_name (uname)
4263 char * uname;
4264{
4265 register status;
4266 struct FAB uaf_fab;
4267 struct RAB uaf_rab;
4268
4269 uaf_fab = cc$rms_fab;
4270 uaf_rab = cc$rms_rab;
4271 /* initialize fab fields */
4272 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4273 uaf_fab.fab$b_fns = 21;
4274 uaf_fab.fab$b_fac = FAB$M_GET;
4275 uaf_fab.fab$b_org = FAB$C_IDX;
4276 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4277 /* initialize rab fields */
4278 uaf_rab.rab$l_fab = &uaf_fab;
4279 /* open the User Authorization File */
986ffb24 4280 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
4281 if (!(status&1))
4282 {
4283 errno = EVMSERR;
4284 vaxc$errno = status;
4285 return 0;
4286 }
986ffb24 4287 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
4288 if (!(status&1))
4289 {
4290 errno = EVMSERR;
4291 vaxc$errno = status;
4292 return 0;
4293 }
4294 /* read the requested record - index is in uname */
4295 uaf_rab.rab$l_kbf = uname;
4296 uaf_rab.rab$b_ksz = strlen (uname);
4297 uaf_rab.rab$b_rac = RAB$C_KEY;
4298 uaf_rab.rab$l_ubf = (char *)&retuaf;
4299 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 4300 status = SYS$GET (&uaf_rab);
86a5659e
JB
4301 if (!(status&1))
4302 {
4303 errno = EVMSERR;
4304 vaxc$errno = status;
4305 return 0;
4306 }
4307 /* close the User Authorization File */
986ffb24 4308 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
4309 if (!(status&1))
4310 {
4311 errno = EVMSERR;
4312 vaxc$errno = status;
4313 return 0;
4314 }
986ffb24 4315 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
4316 if (!(status&1))
4317 {
4318 errno = EVMSERR;
4319 vaxc$errno = status;
4320 return 0;
4321 }
4322 return &retuaf;
4323}
4324
4325struct UAF *
4326get_uaf_uic (uic)
4327 unsigned long uic;
4328{
4329 register status;
4330 struct FAB uaf_fab;
4331 struct RAB uaf_rab;
4332
4333 uaf_fab = cc$rms_fab;
4334 uaf_rab = cc$rms_rab;
4335 /* initialize fab fields */
4336 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4337 uaf_fab.fab$b_fns = 21;
4338 uaf_fab.fab$b_fac = FAB$M_GET;
4339 uaf_fab.fab$b_org = FAB$C_IDX;
4340 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4341 /* initialize rab fields */
4342 uaf_rab.rab$l_fab = &uaf_fab;
4343 /* open the User Authorization File */
986ffb24 4344 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
4345 if (!(status&1))
4346 {
4347 errno = EVMSERR;
4348 vaxc$errno = status;
4349 return 0;
4350 }
986ffb24 4351 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
4352 if (!(status&1))
4353 {
4354 errno = EVMSERR;
4355 vaxc$errno = status;
4356 return 0;
4357 }
4358 /* read the requested record - index is in uic */
4359 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
4360 uaf_rab.rab$l_kbf = (char *) &uic;
4361 uaf_rab.rab$b_ksz = sizeof uic;
4362 uaf_rab.rab$b_rac = RAB$C_KEY;
4363 uaf_rab.rab$l_ubf = (char *)&retuaf;
4364 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 4365 status = SYS$GET (&uaf_rab);
86a5659e
JB
4366 if (!(status&1))
4367 {
4368 errno = EVMSERR;
4369 vaxc$errno = status;
4370 return 0;
4371 }
4372 /* close the User Authorization File */
986ffb24 4373 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
4374 if (!(status&1))
4375 {
4376 errno = EVMSERR;
4377 vaxc$errno = status;
4378 return 0;
4379 }
986ffb24 4380 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
4381 if (!(status&1))
4382 {
4383 errno = EVMSERR;
4384 vaxc$errno = status;
4385 return 0;
4386 }
4387 return &retuaf;
4388}
4389
4390static struct passwd retpw;
4391
4392struct passwd *
4393cnv_uaf_pw (up)
4394 struct UAF * up;
4395{
4396 char * ptr;
4397
4398 /* copy these out first because if the username is 32 chars, the next
4399 section will overwrite the first byte of the UIC */
4400 retpw.pw_uid = up->uaf$w_mem;
4401 retpw.pw_gid = up->uaf$w_grp;
4402
4403 /* I suppose this is not the best sytle, to possibly overwrite one
4404 byte beyond the end of the field, but what the heck... */
4405 ptr = &up->uaf$t_username[UAF$S_USERNAME];
4406 while (ptr[-1] == ' ')
4407 ptr--;
4408 *ptr = '\0';
4409 strcpy (retpw.pw_name, up->uaf$t_username);
4410
4411 /* the rest of these are counted ascii strings */
4412 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
4413 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
4414 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
4415 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
4416 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
4417 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
4418 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
4419 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
4420
4421 return &retpw;
4422}
4423#else /* not READ_SYSUAF */
4424static struct passwd retpw;
4425#endif /* not READ_SYSUAF */
4426
4427struct passwd *
4428getpwnam (name)
4429 char * name;
4430{
4431#ifdef READ_SYSUAF
4432 struct UAF *up;
4433#else
4434 char * user;
4435 char * dir;
4436 unsigned char * full;
4437#endif /* READ_SYSUAF */
4438 char *ptr = name;
4439
4440 while (*ptr)
4441 {
4442 if ('a' <= *ptr && *ptr <= 'z')
4443 *ptr -= 040;
4444 ptr++;
4445 }
4446#ifdef READ_SYSUAF
4447 if (!(up = get_uaf_name (name)))
4448 return 0;
4449 return cnv_uaf_pw (up);
4450#else
4451 if (strcmp (name, getenv ("USER")) == 0)
4452 {
4453 retpw.pw_uid = getuid ();
4454 retpw.pw_gid = getgid ();
4455 strcpy (retpw.pw_name, name);
4456 if (full = egetenv ("FULLNAME"))
4457 strcpy (retpw.pw_gecos, full);
4458 else
4459 *retpw.pw_gecos = '\0';
4460 strcpy (retpw.pw_dir, egetenv ("HOME"));
4461 *retpw.pw_shell = '\0';
4462 return &retpw;
4463 }
4464 else
4465 return 0;
4466#endif /* not READ_SYSUAF */
4467}
4468
4469struct passwd *
4470getpwuid (uid)
4471 unsigned long uid;
4472{
4473#ifdef READ_SYSUAF
4474 struct UAF * up;
4475
4476 if (!(up = get_uaf_uic (uid)))
4477 return 0;
4478 return cnv_uaf_pw (up);
4479#else
4480 if (uid == sys_getuid ())
4481 return getpwnam (egetenv ("USER"));
4482 else
4483 return 0;
4484#endif /* not READ_SYSUAF */
4485}
4486
4487/* return total address space available to the current process. This is
4488 the sum of the current p0 size, p1 size and free page table entries
4489 available. */
4490vlimit ()
4491{
4492 int item_code;
4493 unsigned long free_pages;
4494 unsigned long frep0va;
4495 unsigned long frep1va;
4496 register status;
4497
4498 item_code = JPI$_FREPTECNT;
4499 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4500 {
4501 errno = EVMSERR;
4502 vaxc$errno = status;
4503 return -1;
4504 }
4505 free_pages *= 512;
4506
4507 item_code = JPI$_FREP0VA;
4508 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4509 {
4510 errno = EVMSERR;
4511 vaxc$errno = status;
4512 return -1;
4513 }
4514 item_code = JPI$_FREP1VA;
4515 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4516 {
4517 errno = EVMSERR;
4518 vaxc$errno = status;
4519 return -1;
4520 }
4521
4522 return free_pages + frep0va + (0x7fffffff - frep1va);
4523}
4524
4525define_logical_name (varname, string)
4526 char *varname;
4527 char *string;
4528{
4529 struct dsc$descriptor_s strdsc =
4530 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4531 struct dsc$descriptor_s envdsc =
4532 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4533 struct dsc$descriptor_s lnmdsc =
4534 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4535
4536 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4537}
4538
4539delete_logical_name (varname)
4540 char *varname;
4541{
4542 struct dsc$descriptor_s envdsc =
4543 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4544 struct dsc$descriptor_s lnmdsc =
4545 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4546
4547 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4548}
4549
4550ulimit ()
4551{}
4552
86a5659e
JB
4553setpgrp ()
4554{}
4555
4556execvp ()
4557{
4558 error ("execvp system call not implemented");
4559}
4560
4561int
4562rename (from, to)
4563 char *from, *to;
4564{
4565 int status;
4566 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4567 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4568 char from_esn[NAM$C_MAXRSS];
4569 char to_esn[NAM$C_MAXRSS];
4570
4571 from_fab.fab$l_fna = from;
4572 from_fab.fab$b_fns = strlen (from);
4573 from_fab.fab$l_nam = &from_nam;
4574 from_fab.fab$l_fop = FAB$M_NAM;
4575
4576 from_nam.nam$l_esa = from_esn;
4577 from_nam.nam$b_ess = sizeof from_esn;
4578
4579 to_fab.fab$l_fna = to;
4580 to_fab.fab$b_fns = strlen (to);
4581 to_fab.fab$l_nam = &to_nam;
4582 to_fab.fab$l_fop = FAB$M_NAM;
4583
4584 to_nam.nam$l_esa = to_esn;
4585 to_nam.nam$b_ess = sizeof to_esn;
4586
4587 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4588
4589 if (status & 1)
4590 return 0;
4591 else
4592 {
4593 if (status == RMS$_DEV)
4594 errno = EXDEV;
4595 else
4596 errno = EVMSERR;
4597 vaxc$errno = status;
4598 return -1;
4599 }
4600}
4601
4602/* This function renames a file like `rename', but it strips
4603 the version number from the "to" filename, such that the "to" file is
4604 will always be a new version. It also sets the file protection once it is
4605 finished. The protection that we will use is stored in fab_final_pro,
4606 and was set when we did a creat_copy_attrs to create the file that we
4607 are renaming.
4608
4609 We could use the chmod function, but Eunichs uses 3 bits per user category
eb8c3be9 4610 to describe the protection, and VMS uses 4 (write and delete are separate
86a5659e
JB
4611 bits). To maintain portability, the VMS implementation of `chmod' wires
4612 the W and D bits together. */
4613
4614
4615static struct fibdef fib; /* We need this initialized to zero */
4616char vms_file_written[NAM$C_MAXRSS];
4617
4618int
4619rename_sans_version (from,to)
4620 char *from, *to;
4621{
4622 short int chan;
4623 int stat;
4624 short int iosb[4];
4625 int status;
4626 struct FAB to_fab = cc$rms_fab;
4627 struct NAM to_nam = cc$rms_nam;
4628 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4629 struct dsc$descriptor fib_attr[2]
4630 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4631 char to_esn[NAM$C_MAXRSS];
4632
4633 $DESCRIPTOR (disk,to_esn);
4634
4635 to_fab.fab$l_fna = to;
4636 to_fab.fab$b_fns = strlen (to);
4637 to_fab.fab$l_nam = &to_nam;
4638 to_fab.fab$l_fop = FAB$M_NAM;
4639
4640 to_nam.nam$l_esa = to_esn;
4641 to_nam.nam$b_ess = sizeof to_esn;
4642
4643 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4644
4645 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4646 *(to_nam.nam$l_ver) = '\0';
4647
4648 stat = rename (from, to_esn);
4649 if (stat < 0)
4650 return stat;
4651
4652 strcpy (vms_file_written, to_esn);
4653
4654 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4655 to_fab.fab$b_fns = strlen (vms_file_written);
4656
4657 /* Now set the file protection to the correct value */
986ffb24 4658 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
86a5659e
JB
4659
4660 /* Copy these fields into the fib */
4661 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4662 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4663 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4664
986ffb24 4665 SYS$CLOSE (&to_fab, 0, 0);
86a5659e 4666
986ffb24 4667 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
86a5659e 4668 if (!stat)
986ffb24
JB
4669 LIB$SIGNAL (stat);
4670 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
86a5659e
JB
4671 0, 0, 0, &fib_attr, 0);
4672 if (!stat)
986ffb24
JB
4673 LIB$SIGNAL (stat);
4674 stat = SYS$DASSGN (chan);
86a5659e 4675 if (!stat)
986ffb24 4676 LIB$SIGNAL (stat);
0137dbf7 4677 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
4678 return 0;
4679}
4680
4681link (file, new)
4682 char * file, * new;
4683{
4684 register status;
4685 struct FAB fab;
4686 struct NAM nam;
4687 unsigned short fid[3];
4688 char esa[NAM$C_MAXRSS];
4689
4690 fab = cc$rms_fab;
4691 fab.fab$l_fop = FAB$M_OFP;
4692 fab.fab$l_fna = file;
4693 fab.fab$b_fns = strlen (file);
4694 fab.fab$l_nam = &nam;
4695
4696 nam = cc$rms_nam;
4697 nam.nam$l_esa = esa;
4698 nam.nam$b_ess = NAM$C_MAXRSS;
4699
4700 status = SYS$PARSE (&fab);
4701 if ((status & 1) == 0)
4702 {
4703 errno = EVMSERR;
4704 vaxc$errno = status;
4705 return -1;
4706 }
4707 status = SYS$SEARCH (&fab);
4708 if ((status & 1) == 0)
4709 {
4710 errno = EVMSERR;
4711 vaxc$errno = status;
4712 return -1;
4713 }
4714
4715 fid[0] = nam.nam$w_fid[0];
4716 fid[1] = nam.nam$w_fid[1];
4717 fid[2] = nam.nam$w_fid[2];
4718
4719 fab.fab$l_fna = new;
4720 fab.fab$b_fns = strlen (new);
4721
4722 status = SYS$PARSE (&fab);
4723 if ((status & 1) == 0)
4724 {
4725 errno = EVMSERR;
4726 vaxc$errno = status;
4727 return -1;
4728 }
4729
4730 nam.nam$w_fid[0] = fid[0];
4731 nam.nam$w_fid[1] = fid[1];
4732 nam.nam$w_fid[2] = fid[2];
4733
4734 nam.nam$l_esa = nam.nam$l_name;
4735 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
4736
4737 status = SYS$ENTER (&fab);
4738 if ((status & 1) == 0)
4739 {
4740 errno = EVMSERR;
4741 vaxc$errno = status;
4742 return -1;
4743 }
4744
4745 return 0;
4746}
4747
4748croak (badfunc)
4749 char *badfunc;
4750{
4751 printf ("%s not yet implemented\r\n", badfunc);
4752 reset_sys_modes ();
4753 exit (1);
4754}
4755
4756long
4757random ()
4758{
4759 /* Arrange to return a range centered on zero. */
4760 return rand () - (1 << 30);
4761}
4762
4763srandom (seed)
4764{
4765 srand (seed);
4766}
4767#endif /* VMS */
4768\f
4769#ifdef AIX
4770
4771/* Called from init_sys_modes. */
4772hft_init ()
4773{
4774 int junk;
4775
4776 /* If we're not on an HFT we shouldn't do any of this. We determine
4777 if we are on an HFT by trying to get an HFT error code. If this
4778 call fails, we're not on an HFT. */
4779#ifdef IBMR2AIX
4780 if (ioctl (0, HFQERROR, &junk) < 0)
4781 return;
4782#else /* not IBMR2AIX */
4783 if (ioctl (0, HFQEIO, 0) < 0)
4784 return;
4785#endif /* not IBMR2AIX */
4786
4787 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4788 as the rubout key's ASCII code. Here this is changed. The bug is that
4789 there's no way to determine the old mapping, so in reset_sys_modes
4790 we need to assume that the normal map had been present. Of course, this
4791 code also doesn't help if on a terminal emulator which doesn't understand
4792 HFT VTD's. */
4793 {
4794 struct hfbuf buf;
4795 struct hfkeymap keymap;
4796
4797 buf.hf_bufp = (char *)&keymap;
4798 buf.hf_buflen = sizeof (keymap);
4799 keymap.hf_nkeys = 2;
4800 keymap.hfkey[0].hf_kpos = 15;
4801 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4802#ifdef IBMR2AIX
4803 keymap.hfkey[0].hf_keyidh = '<';
4804#else /* not IBMR2AIX */
4805 keymap.hfkey[0].hf_page = '<';
4806#endif /* not IBMR2AIX */
4807 keymap.hfkey[0].hf_char = 127;
4808 keymap.hfkey[1].hf_kpos = 15;
4809 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4810#ifdef IBMR2AIX
4811 keymap.hfkey[1].hf_keyidh = '<';
4812#else /* not IBMR2AIX */
4813 keymap.hfkey[1].hf_page = '<';
4814#endif /* not IBMR2AIX */
4815 keymap.hfkey[1].hf_char = 127;
4816 hftctl (0, HFSKBD, &buf);
4817 }
4818 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4819 at times. */
4820 line_ins_del_ok = char_ins_del_ok = 0;
4821}
4822
4823/* Reset the rubout key to backspace. */
4824
4825hft_reset ()
4826{
4827 struct hfbuf buf;
4828 struct hfkeymap keymap;
4829 int junk;
4830
4831#ifdef IBMR2AIX
4832 if (ioctl (0, HFQERROR, &junk) < 0)
4833 return;
4834#else /* not IBMR2AIX */
4835 if (ioctl (0, HFQEIO, 0) < 0)
4836 return;
4837#endif /* not IBMR2AIX */
4838
4839 buf.hf_bufp = (char *)&keymap;
4840 buf.hf_buflen = sizeof (keymap);
4841 keymap.hf_nkeys = 2;
4842 keymap.hfkey[0].hf_kpos = 15;
4843 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4844#ifdef IBMR2AIX
4845 keymap.hfkey[0].hf_keyidh = '<';
4846#else /* not IBMR2AIX */
4847 keymap.hfkey[0].hf_page = '<';
4848#endif /* not IBMR2AIX */
4849 keymap.hfkey[0].hf_char = 8;
4850 keymap.hfkey[1].hf_kpos = 15;
4851 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4852#ifdef IBMR2AIX
4853 keymap.hfkey[1].hf_keyidh = '<';
4854#else /* not IBMR2AIX */
4855 keymap.hfkey[1].hf_page = '<';
4856#endif /* not IBMR2AIX */
4857 keymap.hfkey[1].hf_char = 8;
4858 hftctl (0, HFSKBD, &buf);
4859}
4860
4861#endif /* AIX */