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