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