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