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