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