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