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