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