(latexenc-find-file-coding-system): Fix regular expressions.
[bpt/emacs.git] / src / sysdep.c
CommitLineData
86a5659e 1/* Interfaces to system-dependent kernel and library entries.
275464e7 2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
e120ea40 3 2003, 2004, 2005 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 */
e120ea40 872 execlp (sh, sh, (char *) 0);
86a5659e
JB
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 */
333f1b6f 2475 SIGNAL_THREAD_CHECK (SIGALRM);
86a5659e
JB
2476 if (read_alarm_should_throw)
2477 longjmp (read_alarm_throw, 1);
2478}
2479
fe03522b 2480#ifndef WINDOWSNT
86a5659e
JB
2481/* Only rfds are checked. */
2482int
86d1f23a 2483sys_select (nfds, rfds, wfds, efds, timeout)
86a5659e 2484 int nfds;
86d1f23a
KH
2485 SELECT_TYPE *rfds, *wfds, *efds;
2486 EMACS_TIME *timeout;
86a5659e 2487{
ffdcc91d 2488 int ravail = 0;
86d1f23a
KH
2489 SELECT_TYPE orfds;
2490 int timeoutval;
2491 int *local_timeout;
86a5659e
JB
2492 extern int proc_buffered_char[];
2493#ifndef subprocesses
2494 int process_tick = 0, update_tick = 0;
2495#else
2496 extern int process_tick, update_tick;
2497#endif
86a5659e
JB
2498 unsigned char buf;
2499
86d1f23a
KH
2500#if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
2501 /* If we're using X, then the native select will work; we only need the
2502 emulation for non-X usage. */
2503 if (!NILP (Vwindow_system))
2504 return select (nfds, rfds, wfds, efds, timeout);
2505#endif
2506 timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
2507 local_timeout = &timeoutval;
2508 FD_ZERO (&orfds);
86a5659e
JB
2509 if (rfds)
2510 {
2511 orfds = *rfds;
86d1f23a 2512 FD_ZERO (rfds);
86a5659e
JB
2513 }
2514 if (wfds)
86d1f23a 2515 FD_ZERO (wfds);
86a5659e 2516 if (efds)
86d1f23a 2517 FD_ZERO (efds);
86a5659e
JB
2518
2519 /* If we are looking only for the terminal, with no timeout,
2520 just read it and wait -- that's more efficient. */
86d1f23a
KH
2521 if (*local_timeout == 100000 && process_tick == update_tick
2522 && FD_ISSET (0, &orfds))
86a5659e 2523 {
86d1f23a
KH
2524 int fd;
2525 for (fd = 1; fd < nfds; ++fd)
2526 if (FD_ISSET (fd, &orfds))
2527 goto hardway;
86a5659e
JB
2528 if (! detect_input_pending ())
2529 read_input_waiting ();
86d1f23a 2530 FD_SET (0, rfds);
86a5659e
JB
2531 return 1;
2532 }
2533
86d1f23a 2534 hardway:
86a5659e
JB
2535 /* Once a second, till the timer expires, check all the flagged read
2536 * descriptors to see if any input is available. If there is some then
2537 * set the corresponding bit in the return copy of rfds.
177c0ea7 2538 */
86a5659e
JB
2539 while (1)
2540 {
86d1f23a 2541 register int to_check, fd;
86a5659e
JB
2542
2543 if (rfds)
2544 {
86d1f23a 2545 for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
86a5659e 2546 {
86d1f23a 2547 if (FD_ISSET (fd, &orfds))
86a5659e
JB
2548 {
2549 int avail = 0, status = 0;
2550
86d1f23a 2551 if (fd == 0)
86a5659e
JB
2552 avail = detect_input_pending (); /* Special keyboard handler */
2553 else
2554 {
2555#ifdef FIONREAD
2556 status = ioctl (fd, FIONREAD, &avail);
2557#else /* no FIONREAD */
2558 /* Hoping it will return -1 if nothing available
2559 or 0 if all 0 chars requested are read. */
2560 if (proc_buffered_char[fd] >= 0)
2561 avail = 1;
2562 else
2563 {
2564 avail = read (fd, &buf, 1);
2565 if (avail > 0)
2566 proc_buffered_char[fd] = buf;
2567 }
2568#endif /* no FIONREAD */
2569 }
2570 if (status >= 0 && avail > 0)
2571 {
86d1f23a 2572 FD_SET (fd, rfds);
86a5659e
JB
2573 ravail++;
2574 }
2575 }
2576 }
2577 }
2578 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
2579 break;
ffdcc91d
GM
2580
2581 turn_on_atimers (0);
2582 signal (SIGALRM, select_alarm);
86a5659e
JB
2583 select_alarmed = 0;
2584 alarm (SELECT_PAUSE);
177c0ea7 2585
86a5659e
JB
2586 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2587 while (select_alarmed == 0 && *local_timeout != 0
2588 && process_tick == update_tick)
2589 {
2590 /* If we are interested in terminal input,
2591 wait by reading the terminal.
2592 That makes instant wakeup for terminal input at least. */
86d1f23a 2593 if (FD_ISSET (0, &orfds))
86a5659e
JB
2594 {
2595 read_input_waiting ();
2596 if (detect_input_pending ())
2597 select_alarmed = 1;
2598 }
2599 else
2600 pause ();
2601 }
2602 (*local_timeout) -= SELECT_PAUSE;
177c0ea7 2603
ffdcc91d
GM
2604 /* Reset the old alarm if there was one. */
2605 turn_on_atimers (1);
177c0ea7 2606
86a5659e
JB
2607 if (*local_timeout == 0) /* Stop on timer being cleared */
2608 break;
2609 }
2610 return ravail;
2611}
fe03522b 2612#endif /* not WINDOWSNT */
86a5659e
JB
2613
2614/* Read keyboard input into the standard buffer,
2615 waiting for at least one character. */
2616
dfcf069d 2617void
86a5659e
JB
2618read_input_waiting ()
2619{
34567704
JB
2620 int nread, i;
2621 extern int quit_char;
86a5659e
JB
2622
2623 if (read_socket_hook)
2624 {
9f893fc6
KS
2625 struct input_event hold_quit;
2626
2627 EVENT_INIT (hold_quit);
2628 hold_quit.kind = NO_EVENT;
2629
86a5659e
JB
2630 read_alarm_should_throw = 0;
2631 if (! setjmp (read_alarm_throw))
9f893fc6 2632 nread = (*read_socket_hook) (0, 1, &hold_quit);
86a5659e
JB
2633 else
2634 nread = -1;
f4a7e5bd 2635
9f893fc6
KS
2636 if (hold_quit.kind != NO_EVENT)
2637 kbd_buffer_store_event (&hold_quit);
86a5659e
JB
2638 }
2639 else
86a5659e 2640 {
50acda85 2641 struct input_event e;
f4a7e5bd
RS
2642 char buf[3];
2643 nread = read (fileno (stdin), buf, 1);
50acda85 2644 EVENT_INIT (e);
f4a7e5bd
RS
2645
2646 /* Scan the chars for C-g and store them in kbd_buffer. */
e43bd4f5 2647 e.kind = ASCII_KEYSTROKE_EVENT;
2d064114 2648 e.frame_or_window = selected_frame;
f4a7e5bd
RS
2649 e.modifiers = 0;
2650 for (i = 0; i < nread; i++)
a00d5589 2651 {
f4a7e5bd
RS
2652 /* Convert chars > 0177 to meta events if desired.
2653 We do this under the same conditions that read_avail_input does. */
2654 if (read_socket_hook == 0)
2655 {
2656 /* If the user says she has a meta key, then believe her. */
2657 if (meta_key == 1 && (buf[i] & 0x80))
2658 e.modifiers = meta_modifier;
2659 if (meta_key != 2)
2660 buf[i] &= ~0x80;
2661 }
b95520f5 2662
c81d47b4 2663 XSETINT (e.code, buf[i]);
f4a7e5bd
RS
2664 kbd_buffer_store_event (&e);
2665 /* Don't look at input that follows a C-g too closely.
2666 This reduces lossage due to autorepeat on C-g. */
2667 if (buf[i] == quit_char)
2668 break;
2669 }
86a5659e
JB
2670 }
2671}
2672
2673#endif /* not HAVE_SELECT */
2674#endif /* not VMS */
7964ba9e 2675#endif /* not MSDOS */
86a5659e
JB
2676\f
2677#ifdef BSD4_1
08633194 2678void
23dab951
RS
2679init_sigio (fd)
2680 int fd;
86a5659e
JB
2681{
2682 if (noninteractive)
2683 return;
2684 lmode = LINTRUP | lmode;
23dab951 2685 ioctl (fd, TIOCLSET, &lmode);
86a5659e
JB
2686}
2687
dfcf069d 2688void
86a5659e
JB
2689reset_sigio ()
2690{
2691 if (noninteractive)
2692 return;
2693 lmode = ~LINTRUP & lmode;
2694 ioctl (0, TIOCLSET, &lmode);
2695}
2696
08633194 2697void
86a5659e
JB
2698request_sigio ()
2699{
2700 sigrelse (SIGTINT);
2701
2702 interrupts_deferred = 0;
2703}
2704
08633194 2705void
86a5659e
JB
2706unrequest_sigio ()
2707{
2708 sighold (SIGTINT);
2709
2710 interrupts_deferred = 1;
2711}
2712
2713/* still inside #ifdef BSD4_1 */
2714#ifdef subprocesses
2715
2716int sigheld; /* Mask of held signals */
2717
dfcf069d 2718void
86a5659e
JB
2719sigholdx (signum)
2720 int signum;
2721{
2722 sigheld |= sigbit (signum);
2723 sighold (signum);
2724}
2725
dfcf069d 2726void
86a5659e
JB
2727sigisheld (signum)
2728 int signum;
2729{
2730 sigheld |= sigbit (signum);
2731}
2732
dfcf069d 2733void
86a5659e
JB
2734sigunhold (signum)
2735 int signum;
2736{
2737 sigheld &= ~sigbit (signum);
2738 sigrelse (signum);
2739}
2740
dfcf069d 2741void
86a5659e
JB
2742sigfree () /* Free all held signals */
2743{
2744 int i;
2745 for (i = 0; i < NSIG; i++)
2746 if (sigheld & sigbit (i))
2747 sigrelse (i);
2748 sigheld = 0;
2749}
2750
dfcf069d 2751int
86a5659e
JB
2752sigbit (i)
2753{
2754 return 1 << (i - 1);
2755}
2756#endif /* subprocesses */
2757#endif /* BSD4_1 */
2758\f
2759/* POSIX signals support - DJB */
2760/* Anyone with POSIX signals should have ANSI C declarations */
2761
2762#ifdef POSIX_SIGNALS
2763
c639b0e3 2764sigset_t empty_mask, full_mask;
86a5659e 2765
86a5659e
JB
2766signal_handler_t
2767sys_signal (int signal_number, signal_handler_t action)
2768{
c639b0e3 2769 struct sigaction new_action, old_action;
86a5659e 2770 sigemptyset (&new_action.sa_mask);
e5c99298 2771 new_action.sa_handler = action;
275464e7 2772#if defined (SA_RESTART) && ! defined (BROKEN_SA_RESTART) && !defined(SYNC_INPUT)
25ab68af 2773 /* Emacs mostly works better with restartable system services. If this
55fafcf0
RS
2774 flag exists, we probably want to turn it on here.
2775 However, on some systems this resets the timeout of `select'
2776 which means that `select' never finishes if it keeps getting signals.
2777 BROKEN_SA_RESTART is defined on those systems. */
275464e7
SM
2778 /* It's not clear why the comment above says "mostly works better". --Stef
2779 When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
2780 for pending input so we need long-running syscalls to be interrupted
2781 after a signal that sets the interrupt_input_pending flag. */
25ab68af
RS
2782 new_action.sa_flags = SA_RESTART;
2783#else
4a785b6e 2784 new_action.sa_flags = 0;
25ab68af 2785#endif
d32b2f3c 2786 sigaction (signal_number, &new_action, &old_action);
e5c99298 2787 return (old_action.sa_handler);
86a5659e
JB
2788}
2789
e065a56e
JB
2790#ifndef __GNUC__
2791/* If we're compiling with GCC, we don't need this function, since it
2792 can be written as a macro. */
2793sigset_t
2794sys_sigmask (int sig)
2795{
2796 sigset_t mask;
2797 sigemptyset (&mask);
2798 sigaddset (&mask, sig);
2799 return mask;
2800}
2801#endif
2802
86a5659e
JB
2803/* I'd like to have these guys return pointers to the mask storage in here,
2804 but there'd be trouble if the code was saving multiple masks. I'll be
2805 safe and pass the structure. It normally won't be more than 2 bytes
2806 anyhow. - DJB */
2807
2808sigset_t
2809sys_sigblock (sigset_t new_mask)
2810{
2811 sigset_t old_mask;
2812 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2813 return (old_mask);
2814}
2815
2816sigset_t
2817sys_sigunblock (sigset_t new_mask)
2818{
2819 sigset_t old_mask;
2820 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2821 return (old_mask);
2822}
2823
2824sigset_t
2825sys_sigsetmask (sigset_t new_mask)
2826{
2827 sigset_t old_mask;
2828 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2829 return (old_mask);
2830}
2831
2832#endif /* POSIX_SIGNALS */
2833\f
b80263be 2834#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
ca9c0567
PE
2835static char *my_sys_siglist[NSIG];
2836# ifdef sys_siglist
2837# undef sys_siglist
2838# endif
2839# define sys_siglist my_sys_siglist
2840#endif
2841
2842void
2843init_signals ()
2844{
2845#ifdef POSIX_SIGNALS
2846 sigemptyset (&empty_mask);
2847 sigfillset (&full_mask);
2848#endif
2849
b80263be 2850#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
ca9c0567
PE
2851 if (! initialized)
2852 {
2853# ifdef SIGABRT
2854 sys_siglist[SIGABRT] = "Aborted";
2855# endif
2856# ifdef SIGAIO
2857 sys_siglist[SIGAIO] = "LAN I/O interrupt";
2858# endif
2859# ifdef SIGALRM
2860 sys_siglist[SIGALRM] = "Alarm clock";
2861# endif
2862# ifdef SIGBUS
2863 sys_siglist[SIGBUS] = "Bus error";
2864# endif
2865# ifdef SIGCLD
2866 sys_siglist[SIGCLD] = "Child status changed";
2867# endif
2868# ifdef SIGCHLD
2869 sys_siglist[SIGCHLD] = "Child status changed";
2870# endif
2871# ifdef SIGCONT
2872 sys_siglist[SIGCONT] = "Continued";
2873# endif
2874# ifdef SIGDANGER
2875 sys_siglist[SIGDANGER] = "Swap space dangerously low";
2876# endif
2877# ifdef SIGDGNOTIFY
2878 sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
2879# endif
2880# ifdef SIGEMT
2881 sys_siglist[SIGEMT] = "Emulation trap";
2882# endif
2883# ifdef SIGFPE
2884 sys_siglist[SIGFPE] = "Arithmetic exception";
2885# endif
2886# ifdef SIGFREEZE
2887 sys_siglist[SIGFREEZE] = "SIGFREEZE";
2888# endif
2889# ifdef SIGGRANT
2890 sys_siglist[SIGGRANT] = "Monitor mode granted";
2891# endif
2892# ifdef SIGHUP
2893 sys_siglist[SIGHUP] = "Hangup";
2894# endif
2895# ifdef SIGILL
2896 sys_siglist[SIGILL] = "Illegal instruction";
2897# endif
2898# ifdef SIGINT
2899 sys_siglist[SIGINT] = "Interrupt";
2900# endif
2901# ifdef SIGIO
2902 sys_siglist[SIGIO] = "I/O possible";
2903# endif
2904# ifdef SIGIOINT
2905 sys_siglist[SIGIOINT] = "I/O intervention required";
2906# endif
2907# ifdef SIGIOT
2908 sys_siglist[SIGIOT] = "IOT trap";
2909# endif
2910# ifdef SIGKILL
2911 sys_siglist[SIGKILL] = "Killed";
2912# endif
2913# ifdef SIGLOST
2914 sys_siglist[SIGLOST] = "Resource lost";
2915# endif
2916# ifdef SIGLWP
2917 sys_siglist[SIGLWP] = "SIGLWP";
2918# endif
2919# ifdef SIGMSG
2920 sys_siglist[SIGMSG] = "Monitor mode data available";
2921# endif
2922# ifdef SIGPHONE
2923 sys_siglist[SIGWIND] = "SIGPHONE";
2924# endif
2925# ifdef SIGPIPE
2926 sys_siglist[SIGPIPE] = "Broken pipe";
2927# endif
2928# ifdef SIGPOLL
2929 sys_siglist[SIGPOLL] = "Pollable event occurred";
2930# endif
2931# ifdef SIGPROF
2932 sys_siglist[SIGPROF] = "Profiling timer expired";
2933# endif
2934# ifdef SIGPTY
2935 sys_siglist[SIGPTY] = "PTY I/O interrupt";
2936# endif
2937# ifdef SIGPWR
2938 sys_siglist[SIGPWR] = "Power-fail restart";
2939# endif
2940# ifdef SIGQUIT
2941 sys_siglist[SIGQUIT] = "Quit";
2942# endif
2943# ifdef SIGRETRACT
2944 sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
2945# endif
2946# ifdef SIGSAK
2947 sys_siglist[SIGSAK] = "Secure attention";
2948# endif
2949# ifdef SIGSEGV
2950 sys_siglist[SIGSEGV] = "Segmentation violation";
2951# endif
2952# ifdef SIGSOUND
2953 sys_siglist[SIGSOUND] = "Sound completed";
2954# endif
2955# ifdef SIGSTOP
2956 sys_siglist[SIGSTOP] = "Stopped (signal)";
2957# endif
2958# ifdef SIGSTP
2959 sys_siglist[SIGSTP] = "Stopped (user)";
2960# endif
2961# ifdef SIGSYS
2962 sys_siglist[SIGSYS] = "Bad argument to system call";
2963# endif
2964# ifdef SIGTERM
2965 sys_siglist[SIGTERM] = "Terminated";
2966# endif
2967# ifdef SIGTHAW
2968 sys_siglist[SIGTHAW] = "SIGTHAW";
2969# endif
2970# ifdef SIGTRAP
2971 sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
2972# endif
2973# ifdef SIGTSTP
2974 sys_siglist[SIGTSTP] = "Stopped (user)";
2975# endif
2976# ifdef SIGTTIN
2977 sys_siglist[SIGTTIN] = "Stopped (tty input)";
2978# endif
2979# ifdef SIGTTOU
2980 sys_siglist[SIGTTOU] = "Stopped (tty output)";
2981# endif
2982# ifdef SIGURG
2983 sys_siglist[SIGURG] = "Urgent I/O condition";
2984# endif
2985# ifdef SIGUSR1
2986 sys_siglist[SIGUSR1] = "User defined signal 1";
2987# endif
2988# ifdef SIGUSR2
2989 sys_siglist[SIGUSR2] = "User defined signal 2";
2990# endif
2991# ifdef SIGVTALRM
2992 sys_siglist[SIGVTALRM] = "Virtual timer expired";
2993# endif
2994# ifdef SIGWAITING
2995 sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
2996# endif
2997# ifdef SIGWINCH
2998 sys_siglist[SIGWINCH] = "Window size changed";
2999# endif
3000# ifdef SIGWIND
3001 sys_siglist[SIGWIND] = "SIGWIND";
3002# endif
3003# ifdef SIGXCPU
3004 sys_siglist[SIGXCPU] = "CPU time limit exceeded";
3005# endif
3006# ifdef SIGXFSZ
3007 sys_siglist[SIGXFSZ] = "File size limit exceeded";
3008# endif
3009 }
b80263be 3010#endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
ca9c0567
PE
3011}
3012\f
9927a7b1 3013#ifndef HAVE_RANDOM
4bb8c8b7
KH
3014#ifdef random
3015#define HAVE_RANDOM
3016#endif
3017#endif
3018
3019/* Figure out how many bits the system's random number generator uses.
3020 `random' and `lrand48' are assumed to return 31 usable bits.
3021 BSD `rand' returns a 31 bit value but the low order bits are unusable;
3022 so we'll shift it and treat it like the 15-bit USG `rand'. */
3023
3024#ifndef RAND_BITS
3025# ifdef HAVE_RANDOM
3026# define RAND_BITS 31
3027# else /* !HAVE_RANDOM */
3028# ifdef HAVE_LRAND48
3029# define RAND_BITS 31
3030# define random lrand48
3031# else /* !HAVE_LRAND48 */
3032# define RAND_BITS 15
3033# if RAND_MAX == 32767
3034# define random rand
3035# else /* RAND_MAX != 32767 */
3036# if RAND_MAX == 2147483647
3037# define random() (rand () >> 16)
3038# else /* RAND_MAX != 2147483647 */
3039# ifdef USG
3040# define random rand
3041# else
3042# define random() (rand () >> 16)
2a633456 3043# endif /* !USG */
4bb8c8b7
KH
3044# endif /* RAND_MAX != 2147483647 */
3045# endif /* RAND_MAX != 32767 */
3046# endif /* !HAVE_LRAND48 */
3047# endif /* !HAVE_RANDOM */
3048#endif /* !RAND_BITS */
2e46c7c6 3049
4bb8c8b7
KH
3050void
3051seed_random (arg)
3052 long arg;
86a5659e 3053{
4bb8c8b7
KH
3054#ifdef HAVE_RANDOM
3055 srandom ((unsigned int)arg);
f8b53a82 3056#else
4bb8c8b7 3057# ifdef HAVE_LRAND48
76425a49 3058 srand48 (arg);
4bb8c8b7
KH
3059# else
3060 srand ((unsigned int)arg);
3061# endif
2e46c7c6 3062#endif
86a5659e
JB
3063}
3064
4bb8c8b7
KH
3065/*
3066 * Build a full Emacs-sized word out of whatever we've got.
3067 * This suffices even for a 64-bit architecture with a 15-bit rand.
3068 */
3069long
3070get_random ()
3071{
3072 long val = random ();
3073#if VALBITS > RAND_BITS
3074 val = (val << RAND_BITS) ^ random ();
3075#if VALBITS > 2*RAND_BITS
3076 val = (val << RAND_BITS) ^ random ();
3077#if VALBITS > 3*RAND_BITS
3078 val = (val << RAND_BITS) ^ random ();
3079#if VALBITS > 4*RAND_BITS
3080 val = (val << RAND_BITS) ^ random ();
3081#endif /* need at least 5 */
3082#endif /* need at least 4 */
3083#endif /* need at least 3 */
3084#endif /* need at least 2 */
3085 return val & ((1L << VALBITS) - 1);
3086}
86a5659e
JB
3087\f
3088#ifdef WRONG_NAME_INSQUE
3089
3090insque (q,p)
3091 caddr_t q,p;
3092{
3093 _insque (q,p);
3094}
3095
3096#endif
3097\f
3098#ifdef VMS
3099
3100#ifdef getenv
3101/* If any place else asks for the TERM variable,
3102 allow it to be overridden with the EMACS_TERM variable
3103 before attempting to translate the logical name TERM. As a last
3104 resort, ask for VAX C's special idea of the TERM variable. */
3105#undef getenv
3106char *
3107sys_getenv (name)
3108 char *name;
3109{
3110 register char *val;
3111 static char buf[256];
3112 static struct dsc$descriptor_s equiv
3113 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
3114 static struct dsc$descriptor_s d_name
3115 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
3116 short eqlen;
3117
3118 if (!strcmp (name, "TERM"))
3119 {
3120 val = (char *) getenv ("EMACS_TERM");
3121 if (val)
3122 return val;
3123 }
3124
3125 d_name.dsc$w_length = strlen (name);
3126 d_name.dsc$a_pointer = name;
986ffb24 3127 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
86a5659e
JB
3128 {
3129 char *str = (char *) xmalloc (eqlen + 1);
3130 bcopy (buf, str, eqlen);
3131 str[eqlen] = '\0';
3132 /* This is a storage leak, but a pain to fix. With luck,
3133 no one will ever notice. */
3134 return str;
3135 }
3136 return (char *) getenv (name);
3137}
3138#endif /* getenv */
3139
3140#ifdef abort
3141/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
3142 to force a call on the debugger from within the image. */
3143#undef abort
3144sys_abort ()
3145{
3146 reset_sys_modes ();
3147 LIB$SIGNAL (SS$_DEBUG);
3148}
3149#endif /* abort */
3150#endif /* VMS */
3151\f
3152#ifdef VMS
3153#ifdef LINK_CRTL_SHARE
ea5a0917 3154#ifdef SHARABLE_LIB_BUG
eb8c3be9 3155/* Variables declared noshare and initialized in sharable libraries
86a5659e
JB
3156 cannot be shared. The VMS linker incorrectly forces you to use a private
3157 version which is uninitialized... If not for this "feature", we
3158 could use the C library definition of sys_nerr and sys_errlist. */
3159int sys_nerr = 35;
3160char *sys_errlist[] =
3161 {
3162 "error 0",
3163 "not owner",
3164 "no such file or directory",
3165 "no such process",
3166 "interrupted system call",
3167 "i/o error",
3168 "no such device or address",
3169 "argument list too long",
3170 "exec format error",
3171 "bad file number",
3172 "no child process",
3173 "no more processes",
3174 "not enough memory",
3175 "permission denied",
3176 "bad address",
3177 "block device required",
3178 "mount devices busy",
3179 "file exists",
3180 "cross-device link",
3181 "no such device",
3182 "not a directory",
3183 "is a directory",
3184 "invalid argument",
3185 "file table overflow",
3186 "too many open files",
3187 "not a typewriter",
3188 "text file busy",
3189 "file too big",
3190 "no space left on device",
3191 "illegal seek",
3192 "read-only file system",
3193 "too many links",
3194 "broken pipe",
3195 "math argument",
3196 "result too large",
3197 "I/O stream empty",
3198 "vax/vms specific error code nontranslatable error"
3199 };
ea5a0917 3200#endif /* SHARABLE_LIB_BUG */
86a5659e
JB
3201#endif /* LINK_CRTL_SHARE */
3202#endif /* VMS */
7088d1ca
RM
3203
3204#ifndef HAVE_STRERROR
fe03522b 3205#ifndef WINDOWSNT
7088d1ca
RM
3206char *
3207strerror (errnum)
3208 int errnum;
3209{
3210 extern char *sys_errlist[];
3211 extern int sys_nerr;
3212
3213 if (errnum >= 0 && errnum < sys_nerr)
3214 return sys_errlist[errnum];
3215 return (char *) "Unknown error";
3216}
fe03522b 3217#endif /* not WINDOWSNT */
7088d1ca 3218#endif /* ! HAVE_STRERROR */
86a5659e 3219\f
86a5659e 3220int
68c45bf0 3221emacs_open (path, oflag, mode)
8c2ba7de 3222 const char *path;
86a5659e
JB
3223 int oflag, mode;
3224{
3225 register int rtnval;
68c45bf0
PE
3226
3227#ifdef BSD4_1
177c0ea7 3228 if (oflag & O_CREAT)
68c45bf0
PE
3229 return creat (path, mode);
3230#endif
177c0ea7 3231
86a5659e 3232 while ((rtnval = open (path, oflag, mode)) == -1
275464e7
SM
3233 && (errno == EINTR))
3234 QUIT;
86a5659e
JB
3235 return (rtnval);
3236}
3237
dfcf069d 3238int
68c45bf0 3239emacs_close (fd)
86a5659e
JB
3240 int fd;
3241{
fe111daf 3242 int did_retry = 0;
86a5659e
JB
3243 register int rtnval;
3244
3245 while ((rtnval = close (fd)) == -1
fe111daf
KH
3246 && (errno == EINTR))
3247 did_retry = 1;
3248
3249 /* If close is interrupted SunOS 4.1 may or may not have closed the
3250 file descriptor. If it did the second close will fail with
3251 errno = EBADF. That means we have succeeded. */
3252 if (rtnval == -1 && did_retry && errno == EBADF)
3253 return 0;
3254
86a5659e
JB
3255 return rtnval;
3256}
3257
86a5659e 3258int
68c45bf0 3259emacs_read (fildes, buf, nbyte)
86a5659e
JB
3260 int fildes;
3261 char *buf;
3262 unsigned int nbyte;
3263{
3264 register int rtnval;
177c0ea7 3265
86a5659e 3266 while ((rtnval = read (fildes, buf, nbyte)) == -1
275464e7
SM
3267 && (errno == EINTR))
3268 QUIT;
86a5659e
JB
3269 return (rtnval);
3270}
3271
3272int
68c45bf0 3273emacs_write (fildes, buf, nbyte)
86a5659e 3274 int fildes;
7b1cc119 3275 const char *buf;
86a5659e
JB
3276 unsigned int nbyte;
3277{
b95520f5 3278 register int rtnval, bytes_written;
86a5659e 3279
b95520f5
BF
3280 bytes_written = 0;
3281
3282 while (nbyte > 0)
3283 {
3284 rtnval = write (fildes, buf, nbyte);
3285
3286 if (rtnval == -1)
3287 {
3288 if (errno == EINTR)
77220eeb
SM
3289 {
3290#ifdef SYNC_INPUT
3291 /* I originally used `QUIT' but that might causes files to
3292 be truncated if you hit C-g in the middle of it. --Stef */
3293 if (interrupt_input_pending)
3294 handle_async_input ();
3295#endif
3296 continue;
3297 }
b95520f5 3298 else
aa670904 3299 return (bytes_written ? bytes_written : -1);
b95520f5
BF
3300 }
3301
3302 buf += rtnval;
3303 nbyte -= rtnval;
3304 bytes_written += rtnval;
3305 }
3306 return (bytes_written);
86a5659e 3307}
86a5659e
JB
3308\f
3309#ifdef USG
3310/*
3311 * All of the following are for USG.
3312 *
3313 * On USG systems the system calls are INTERRUPTIBLE by signals
3314 * that the user program has elected to catch. Thus the system call
3315 * must be retried in these cases. To handle this without massive
3316 * changes in the source code, we remap the standard system call names
3317 * to names for our own functions in sysdep.c that do the system call
3318 * with retries. Actually, for portability reasons, it is good
3319 * programming practice, as this example shows, to limit all actual
eb8c3be9 3320 * system calls to a single occurrence in the source. Sure, this
86a5659e
JB
3321 * adds an extra level of function call overhead but it is almost
3322 * always negligible. Fred Fish, Unisoft Systems Inc.
3323 */
3324
86a5659e
JB
3325/*
3326 * Warning, this function may not duplicate 4.2 action properly
3327 * under error conditions.
3328 */
3329
3330#ifndef MAXPATHLEN
3331/* In 4.1, param.h fails to define this. */
3332#define MAXPATHLEN 1024
3333#endif
3334
3335#ifndef HAVE_GETWD
3336
3337char *
3338getwd (pathname)
3339 char *pathname;
3340{
3341 char *npath, *spath;
3342 extern char *getcwd ();
3343
9ac0d9e0 3344 BLOCK_INPUT; /* getcwd uses malloc */
86a5659e 3345 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
f4a7e5bd 3346 if (spath == 0)
18b6bc73
GM
3347 {
3348 UNBLOCK_INPUT;
3349 return spath;
3350 }
86a5659e
JB
3351 /* On Altos 3068, getcwd can return @hostname/dir, so discard
3352 up to first slash. Should be harmless on other systems. */
3353 while (*npath && *npath != '/')
3354 npath++;
3355 strcpy (pathname, npath);
3356 free (spath); /* getcwd uses malloc */
9ac0d9e0 3357 UNBLOCK_INPUT;
86a5659e
JB
3358 return pathname;
3359}
3360
3361#endif /* HAVE_GETWD */
3362
3363/*
3364 * Emulate rename using unlink/link. Note that this is
3365 * only partially correct. Also, doesn't enforce restriction
3366 * that files be of same type (regular->regular, dir->dir, etc).
3367 */
3368
4746118a
JB
3369#ifndef HAVE_RENAME
3370
86a5659e 3371rename (from, to)
19c7afdf
JB
3372 const char *from;
3373 const char *to;
86a5659e
JB
3374{
3375 if (access (from, 0) == 0)
3376 {
3377 unlink (to);
3378 if (link (from, to) == 0)
3379 if (unlink (from) == 0)
3380 return (0);
3381 }
3382 return (-1);
3383}
3384
4746118a
JB
3385#endif
3386
86a5659e
JB
3387
3388#ifdef HPUX
3389#ifndef HAVE_PERROR
3390
3391/* HPUX curses library references perror, but as far as we know
3392 it won't be called. Anyway this definition will do for now. */
3393
3394perror ()
3395{
3396}
3397
3398#endif /* not HAVE_PERROR */
3399#endif /* HPUX */
3400
3401#ifndef HAVE_DUP2
3402
3403/*
3404 * Emulate BSD dup2. First close newd if it already exists.
3405 * Then, attempt to dup oldd. If not successful, call dup2 recursively
3406 * until we are, then close the unsuccessful ones.
3407 */
3408
3409dup2 (oldd, newd)
3410 int oldd;
3411 int newd;
3412{
3413 register int fd, ret;
177c0ea7 3414
68c45bf0 3415 emacs_close (newd);
86a5659e
JB
3416
3417#ifdef F_DUPFD
68c45bf0 3418 return fcntl (oldd, F_DUPFD, newd);
86a5659e
JB
3419#else
3420 fd = dup (old);
3421 if (fd == -1)
3422 return -1;
3423 if (fd == new)
3424 return new;
3425 ret = dup2 (old,new);
68c45bf0 3426 emacs_close (fd);
86a5659e
JB
3427 return ret;
3428#endif
3429}
3430
3431#endif /* not HAVE_DUP2 */
3432
3433/*
3434 * Gettimeofday. Simulate as much as possible. Only accurate
3435 * to nearest second. Emacs doesn't use tzp so ignore it for now.
3436 * Only needed when subprocesses are defined.
3437 */
3438
3439#ifdef subprocesses
3440#ifndef VMS
3441#ifndef HAVE_GETTIMEOFDAY
3442#ifdef HAVE_TIMEVAL
177c0ea7 3443
86a5659e 3444/* ARGSUSED */
dfcf069d 3445int
86a5659e
JB
3446gettimeofday (tp, tzp)
3447 struct timeval *tp;
3448 struct timezone *tzp;
3449{
3450 extern long time ();
3451
177c0ea7 3452 tp->tv_sec = time ((long *)0);
86a5659e 3453 tp->tv_usec = 0;
4ca7594f
RS
3454 if (tzp != 0)
3455 tzp->tz_minuteswest = -1;
dfcf069d 3456 return 0;
86a5659e 3457}
177c0ea7 3458
86a5659e
JB
3459#endif
3460#endif
3461#endif
3462#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
177c0ea7 3463
86a5659e
JB
3464/*
3465 * This function will go away as soon as all the stubs fixed. (fnf)
3466 */
3467
dfcf069d 3468void
86a5659e
JB
3469croak (badfunc)
3470 char *badfunc;
3471{
3472 printf ("%s not yet implemented\r\n", badfunc);
3473 reset_sys_modes ();
3474 exit (1);
3475}
3476
3477#endif /* USG */
3478\f
86a5659e
JB
3479/* Directory routines for systems that don't have them. */
3480
3481#ifdef SYSV_SYSTEM_DIR
3482
3483#include <dirent.h>
3484
c4ea52a6 3485#if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
cfdc57af 3486
86a5659e
JB
3487int
3488closedir (dirp)
3489 register DIR *dirp; /* stream from opendir */
3490{
cfdc57af
RS
3491 int rtnval;
3492
68c45bf0 3493 rtnval = emacs_close (dirp->dd_fd);
1b929d25 3494
65aa44ac
JB
3495 /* Some systems (like Solaris) allocate the buffer and the DIR all
3496 in one block. Why in the world are we freeing this ourselves
3497 anyway? */
3498#if ! (defined (sun) && defined (USG5_4))
3499 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
3500#endif
9ac0d9e0 3501 xfree ((char *) dirp);
cfdc57af
RS
3502
3503 return rtnval;
86a5659e 3504}
1db6401c 3505#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
86a5659e
JB
3506#endif /* SYSV_SYSTEM_DIR */
3507
3508#ifdef NONSYSTEM_DIR_LIBRARY
3509
3510DIR *
3511opendir (filename)
3512 char *filename; /* name of directory */
3513{
3514 register DIR *dirp; /* -> malloc'ed storage */
3515 register int fd; /* file descriptor for read */
3516 struct stat sbuf; /* result of fstat */
3517
68c45bf0 3518 fd = emacs_open (filename, O_RDONLY, 0);
86a5659e
JB
3519 if (fd < 0)
3520 return 0;
3521
9ac0d9e0 3522 BLOCK_INPUT;
86a5659e
JB
3523 if (fstat (fd, &sbuf) < 0
3524 || (sbuf.st_mode & S_IFMT) != S_IFDIR
7f77dbe3 3525 || (dirp = (DIR *) xmalloc (sizeof (DIR))) == 0)
86a5659e 3526 {
68c45bf0 3527 emacs_close (fd);
9ac0d9e0 3528 UNBLOCK_INPUT;
86a5659e
JB
3529 return 0; /* bad luck today */
3530 }
9ac0d9e0 3531 UNBLOCK_INPUT;
86a5659e
JB
3532
3533 dirp->dd_fd = fd;
3534 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
3535
3536 return dirp;
3537}
3538
3539void
3540closedir (dirp)
3541 register DIR *dirp; /* stream from opendir */
3542{
68c45bf0 3543 emacs_close (dirp->dd_fd);
9ac0d9e0 3544 xfree ((char *) dirp);
86a5659e
JB
3545}
3546
3547
3548#ifndef VMS
3549#define DIRSIZ 14
3550struct olddir
3551 {
3552 ino_t od_ino; /* inode */
3553 char od_name[DIRSIZ]; /* filename */
3554 };
3555#endif /* not VMS */
3556
3557struct direct dir_static; /* simulated directory contents */
3558
3559/* ARGUSED */
3560struct direct *
3561readdir (dirp)
3562 register DIR *dirp; /* stream from opendir */
3563{
3564#ifndef VMS
3565 register struct olddir *dp; /* -> directory data */
3566#else /* VMS */
3567 register struct dir$_name *dp; /* -> directory data */
3568 register struct dir$_version *dv; /* -> version data */
3569#endif /* VMS */
3570
3571 for (; ;)
3572 {
3573 if (dirp->dd_loc >= dirp->dd_size)
3574 dirp->dd_loc = dirp->dd_size = 0;
3575
3576 if (dirp->dd_size == 0 /* refill buffer */
68c45bf0 3577 && (dirp->dd_size = emacs_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
86a5659e
JB
3578 return 0;
3579
3580#ifndef VMS
3581 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3582 dirp->dd_loc += sizeof (struct olddir);
3583
3584 if (dp->od_ino != 0) /* not deleted entry */
3585 {
3586 dir_static.d_ino = dp->od_ino;
3587 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3588 dir_static.d_name[DIRSIZ] = '\0';
3589 dir_static.d_namlen = strlen (dir_static.d_name);
3590 dir_static.d_reclen = sizeof (struct direct)
3591 - MAXNAMLEN + 3
3592 + dir_static.d_namlen - dir_static.d_namlen % 4;
3593 return &dir_static; /* -> simulated structure */
3594 }
3595#else /* VMS */
3596 dp = (struct dir$_name *) dirp->dd_buf;
3597 if (dirp->dd_loc == 0)
3598 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3599 : dp->dir$b_namecount;
3600 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3601 dir_static.d_ino = dv->dir$w_fid_num;
3602 dir_static.d_namlen = dp->dir$b_namecount;
3603 dir_static.d_reclen = sizeof (struct direct)
3604 - MAXNAMLEN + 3
3605 + dir_static.d_namlen - dir_static.d_namlen % 4;
3606 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3607 dir_static.d_name[dir_static.d_namlen] = '\0';
3608 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3609 return &dir_static;
3610#endif /* VMS */
3611 }
3612}
3613
3614#ifdef VMS
3615/* readdirver is just like readdir except it returns all versions of a file
3616 as separate entries. */
3617
3618/* ARGUSED */
3619struct direct *
3620readdirver (dirp)
3621 register DIR *dirp; /* stream from opendir */
3622{
3623 register struct dir$_name *dp; /* -> directory data */
3624 register struct dir$_version *dv; /* -> version data */
3625
3626 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3627 dirp->dd_loc = dirp->dd_size = 0;
3628
3629 if (dirp->dd_size == 0 /* refill buffer */
3630 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3631 return 0;
3632
3633 dp = (struct dir$_name *) dirp->dd_buf;
3634 if (dirp->dd_loc == 0)
3635 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3636 : dp->dir$b_namecount;
3637 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3638 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3639 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3640 dir_static.d_namlen = strlen (dir_static.d_name);
3641 dir_static.d_ino = dv->dir$w_fid_num;
3642 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3643 + dir_static.d_namlen - dir_static.d_namlen % 4;
3644 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3645 return &dir_static;
3646}
3647
3648#endif /* VMS */
3649
3650#endif /* NONSYSTEM_DIR_LIBRARY */
23524fb9
JB
3651
3652\f
53ea491a 3653int
061ea326 3654set_file_times (filename, atime, mtime)
8c2ba7de 3655 const char *filename;
53ea491a
KH
3656 EMACS_TIME atime, mtime;
3657{
3658#ifdef HAVE_UTIMES
3659 struct timeval tv[2];
3660 tv[0] = atime;
3661 tv[1] = mtime;
8334eb21
RS
3662 return utimes (filename, tv);
3663#else /* not HAVE_UTIMES */
53ea491a
KH
3664 struct utimbuf utb;
3665 utb.actime = EMACS_SECS (atime);
3666 utb.modtime = EMACS_SECS (mtime);
8334eb21
RS
3667 return utime (filename, &utb);
3668#endif /* not HAVE_UTIMES */
53ea491a
KH
3669}
3670\f
23524fb9
JB
3671/* mkdir and rmdir functions, for systems which don't have them. */
3672
3673#ifndef HAVE_MKDIR
3674/*
3675 * Written by Robert Rother, Mariah Corporation, August 1985.
3676 *
3677 * If you want it, it's yours. All I ask in return is that if you
3678 * figure out how to do this in a Bourne Shell script you send me
3679 * a copy.
3680 * sdcsvax!rmr or rmr@uscd
3681 *
3682 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
3683 * subroutine. 11Mar86; hoptoad!gnu
3684 *
3685 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
3686 * subroutine didn't return EEXIST. It does now.
3687 */
3688
3689/*
3690 * Make a directory.
3691 */
f3892946
RS
3692#ifdef MKDIR_PROTOTYPE
3693MKDIR_PROTOTYPE
3694#else
23524fb9
JB
3695int
3696mkdir (dpath, dmode)
3697 char *dpath;
3698 int dmode;
f3892946 3699#endif
23524fb9 3700{
039f26a4 3701 int cpid, status, fd;
23524fb9
JB
3702 struct stat statbuf;
3703
3704 if (stat (dpath, &statbuf) == 0)
3705 {
3706 errno = EEXIST; /* Stat worked, so it already exists */
3707 return -1;
3708 }
3709
3710 /* If stat fails for a reason other than non-existence, return error */
3711 if (errno != ENOENT)
3712 return -1;
3713
039f26a4 3714 synch_process_alive = 1;
23524fb9
JB
3715 switch (cpid = fork ())
3716 {
3717
039f26a4 3718 case -1: /* Error in fork */
23524fb9
JB
3719 return (-1); /* Errno is set already */
3720
3721 case 0: /* Child process */
3722 /*
3723 * Cheap hack to set mode of new directory. Since this
3724 * child process is going away anyway, we zap its umask.
3725 * FIXME, this won't suffice to set SUID, SGID, etc. on this
3726 * directory. Does anybody care?
3727 */
3728 status = umask (0); /* Get current umask */
3729 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
68c45bf0 3730 fd = emacs_open ("/dev/null", O_RDWR, 0);
039f26a4
RS
3731 if (fd >= 0)
3732 {
3733 dup2 (fd, 0);
3734 dup2 (fd, 1);
3735 dup2 (fd, 2);
3736 }
23524fb9
JB
3737 execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
3738 _exit (-1); /* Can't exec /bin/mkdir */
3739
3740 default: /* Parent process */
039f26a4 3741 wait_for_termination (cpid);
23524fb9
JB
3742 }
3743
6b0824c9
JD
3744 if (synch_process_death != 0 || synch_process_retcode != 0
3745 || synch_process_termsig != 0)
23524fb9
JB
3746 {
3747 errno = EIO; /* We don't know why, but */
3748 return -1; /* /bin/mkdir failed */
3749 }
3750
3751 return 0;
3752}
3753#endif /* not HAVE_MKDIR */
3754
3755#ifndef HAVE_RMDIR
3756int
3757rmdir (dpath)
3758 char *dpath;
3759{
039f26a4 3760 int cpid, status, fd;
23524fb9
JB
3761 struct stat statbuf;
3762
3763 if (stat (dpath, &statbuf) != 0)
3764 {
3765 /* Stat just set errno. We don't have to */
3766 return -1;
3767 }
3768
039f26a4 3769 synch_process_alive = 1;
23524fb9
JB
3770 switch (cpid = fork ())
3771 {
3772
039f26a4 3773 case -1: /* Error in fork */
23524fb9
JB
3774 return (-1); /* Errno is set already */
3775
3776 case 0: /* Child process */
68c45bf0 3777 fd = emacs_open ("/dev/null", O_RDWR, 0);
039f26a4
RS
3778 if (fd >= 0)
3779 {
3780 dup2 (fd, 0);
3781 dup2 (fd, 1);
3782 dup2 (fd, 2);
3783 }
f560db78
RS
3784 execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
3785 _exit (-1); /* Can't exec /bin/rmdir */
3786
207bdbdb 3787 default: /* Parent process */
f560db78 3788 wait_for_termination (cpid);
23524fb9
JB
3789 }
3790
6b0824c9
JD
3791 if (synch_process_death != 0 || synch_process_retcode != 0
3792 || synch_process_termsig != 0)
23524fb9
JB
3793 {
3794 errno = EIO; /* We don't know why, but */
f560db78 3795 return -1; /* /bin/rmdir failed */
23524fb9
JB
3796 }
3797
3798 return 0;
3799}
3800#endif /* !HAVE_RMDIR */
3801
3802
86a5659e
JB
3803\f
3804/* Functions for VMS */
3805#ifdef VMS
86a5659e
JB
3806#include <acldef.h>
3807#include <chpdef.h>
3808#include <jpidef.h>
3809
3810/* Return as a string the VMS error string pertaining to STATUS.
3811 Reuses the same static buffer each time it is called. */
3812
3813char *
3814vmserrstr (status)
3815 int status; /* VMS status code */
3816{
3817 int bufadr[2];
3818 short len;
3819 static char buf[257];
3820
3821 bufadr[0] = sizeof buf - 1;
3822 bufadr[1] = (int) buf;
3823 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3824 return "untranslatable VMS error status";
3825 buf[len] = '\0';
3826 return buf;
3827}
3828
3829#ifdef access
3830#undef access
177c0ea7 3831
86a5659e
JB
3832/* The following is necessary because 'access' emulation by VMS C (2.0) does
3833 * not work correctly. (It also doesn't work well in version 2.3.)
3834 */
3835
3836#ifdef VMS4_4
3837
3838#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3839 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3840
3841typedef union {
3842 struct {
3843 unsigned short s_buflen;
3844 unsigned short s_code;
3845 char *s_bufadr;
3846 unsigned short *s_retlenadr;
3847 } s;
3848 int end;
3849} item;
3850#define buflen s.s_buflen
3851#define code s.s_code
3852#define bufadr s.s_bufadr
3853#define retlenadr s.s_retlenadr
3854
3855#define R_OK 4 /* test for read permission */
3856#define W_OK 2 /* test for write permission */
3857#define X_OK 1 /* test for execute (search) permission */
3858#define F_OK 0 /* test for presence of file */
3859
3860int
3861sys_access (path, mode)
3862 char *path;
3863 int mode;
3864{
3865 static char *user = NULL;
3866 char dir_fn[512];
3867
3868 /* translate possible directory spec into .DIR file name, so brain-dead
3869 * access can treat the directory like a file. */
3870 if (directory_file_name (path, dir_fn))
3871 path = dir_fn;
177c0ea7 3872
86a5659e
JB
3873 if (mode == F_OK)
3874 return access (path, mode);
3875 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3876 return -1;
3877 {
3878 int stat;
3879 int flags;
3880 int acces;
3881 unsigned short int dummy;
3882 item itemlst[3];
3883 static int constant = ACL$C_FILE;
3884 DESCRIPTOR (path_desc, path);
3885 DESCRIPTOR (user_desc, user);
177c0ea7 3886
86a5659e
JB
3887 flags = 0;
3888 acces = 0;
3889 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3890 return stat;
3891 if (mode & R_OK)
3892 acces |= CHP$M_READ;
3893 if (mode & W_OK)
3894 acces |= CHP$M_WRITE;
3895 itemlst[0].buflen = sizeof (int);
3896 itemlst[0].code = CHP$_FLAGS;
3897 itemlst[0].bufadr = (char *) &flags;
3898 itemlst[0].retlenadr = &dummy;
3899 itemlst[1].buflen = sizeof (int);
3900 itemlst[1].code = CHP$_ACCESS;
3901 itemlst[1].bufadr = (char *) &acces;
3902 itemlst[1].retlenadr = &dummy;
3903 itemlst[2].end = CHP$_END;
3904 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3905 return stat == SS$_NORMAL ? 0 : -1;
3906 }
3907}
3908
3909#else /* not VMS4_4 */
3910
3911#include <prvdef.h>
fe03522b
RS
3912#define ACE$M_WRITE 2
3913#define ACE$C_KEYID 1
86a5659e
JB
3914
3915static unsigned short memid, grpid;
3916static unsigned int uic;
3917
3918/* Called from init_sys_modes, so it happens not very often
3919 but at least each time Emacs is loaded. */
dfcf069d 3920void
86a5659e
JB
3921sys_access_reinit ()
3922{
3923 uic = 0;
3924}
3925
3926int
3927sys_access (filename, type)
3928 char * filename;
3929 int type;
3930{
3931 struct FAB fab;
3932 struct XABPRO xab;
3933 int status, size, i, typecode, acl_controlled;
3934 unsigned int *aclptr, *aclend, aclbuf[60];
3935 union prvdef prvmask;
3936
3937 /* Get UIC and GRP values for protection checking. */
3938 if (uic == 0)
3939 {
3940 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3941 if (! (status & 1))
3942 return -1;
3943 memid = uic & 0xFFFF;
3944 grpid = uic >> 16;
3945 }
3946
fe03522b 3947 if (type != 2) /* not checking write access */
86a5659e
JB
3948 return access (filename, type);
3949
3950 /* Check write protection. */
177c0ea7 3951
fe03522b 3952#define CHECKPRIV(bit) (prvmask.bit)
ea5a0917 3953#define WRITABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
86a5659e
JB
3954
3955 /* Find privilege bits */
986ffb24 3956 status = SYS$SETPRV (0, 0, 0, prvmask);
86a5659e
JB
3957 if (! (status & 1))
3958 error ("Unable to find privileges: %s", vmserrstr (status));
3959 if (CHECKPRIV (PRV$V_BYPASS))
3960 return 0; /* BYPASS enabled */
3961 fab = cc$rms_fab;
3962 fab.fab$b_fac = FAB$M_GET;
3963 fab.fab$l_fna = filename;
3964 fab.fab$b_fns = strlen (filename);
3965 fab.fab$l_xab = &xab;
3966 xab = cc$rms_xabpro;
3967 xab.xab$l_aclbuf = aclbuf;
3968 xab.xab$w_aclsiz = sizeof (aclbuf);
986ffb24 3969 status = SYS$OPEN (&fab, 0, 0);
86a5659e
JB
3970 if (! (status & 1))
3971 return -1;
986ffb24 3972 SYS$CLOSE (&fab, 0, 0);
86a5659e 3973 /* Check system access */
ea5a0917 3974 if (CHECKPRIV (PRV$V_SYSPRV) && WRITABLE (XAB$V_SYS))
86a5659e
JB
3975 return 0;
3976 /* Check ACL entries, if any */
3977 acl_controlled = 0;
3978 if (xab.xab$w_acllen > 0)
3979 {
3980 aclptr = aclbuf;
3981 aclend = &aclbuf[xab.xab$w_acllen / 4];
3982 while (*aclptr && aclptr < aclend)
3983 {
3984 size = (*aclptr & 0xff) / 4;
3985 typecode = (*aclptr >> 8) & 0xff;
3986 if (typecode == ACE$C_KEYID)
3987 for (i = size - 1; i > 1; i--)
3988 if (aclptr[i] == uic)
3989 {
3990 acl_controlled = 1;
3991 if (aclptr[1] & ACE$M_WRITE)
3992 return 0; /* Write access through ACL */
3993 }
3994 aclptr = &aclptr[size];
3995 }
3996 if (acl_controlled) /* ACL specified, prohibits write access */
3997 return -1;
3998 }
3999 /* No ACL entries specified, check normal protection */
ea5a0917 4000 if (WRITABLE (XAB$V_WLD)) /* World writable */
86a5659e 4001 return 0;
ea5a0917 4002 if (WRITABLE (XAB$V_GRP) &&
86a5659e 4003 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
ea5a0917
KH
4004 return 0; /* Group writable */
4005 if (WRITABLE (XAB$V_OWN) &&
86a5659e 4006 (xab.xab$l_uic & 0xFFFF) == memid)
ea5a0917 4007 return 0; /* Owner writable */
86a5659e 4008
ea5a0917 4009 return -1; /* Not writable */
86a5659e
JB
4010}
4011#endif /* not VMS4_4 */
4012#endif /* access */
177c0ea7 4013
86a5659e
JB
4014static char vtbuf[NAM$C_MAXRSS+1];
4015
4016/* translate a vms file spec to a unix path */
4017char *
4018sys_translate_vms (vfile)
4019 char * vfile;
4020{
4021 char * p;
4022 char * targ;
4023
4024 if (!vfile)
4025 return 0;
4026
4027 targ = vtbuf;
4028
4029 /* leading device or logical name is a root directory */
4030 if (p = strchr (vfile, ':'))
4031 {
4032 *targ++ = '/';
4033 while (vfile < p)
4034 *targ++ = *vfile++;
4035 vfile++;
4036 *targ++ = '/';
4037 }
4038 p = vfile;
4039 if (*p == '[' || *p == '<')
4040 {
4041 while (*++vfile != *p + 2)
4042 switch (*vfile)
4043 {
4044 case '.':
4045 if (vfile[-1] == *p)
4046 *targ++ = '.';
4047 *targ++ = '/';
4048 break;
4049
4050 case '-':
4051 *targ++ = '.';
4052 *targ++ = '.';
4053 break;
177c0ea7 4054
86a5659e
JB
4055 default:
4056 *targ++ = *vfile;
4057 break;
4058 }
4059 vfile++;
4060 *targ++ = '/';
4061 }
4062 while (*vfile)
4063 *targ++ = *vfile++;
4064
4065 return vtbuf;
4066}
4067
4068static char utbuf[NAM$C_MAXRSS+1];
4069
4070/* translate a unix path to a VMS file spec */
4071char *
4072sys_translate_unix (ufile)
4073 char * ufile;
4074{
4075 int slash_seen = 0;
4076 char *p;
4077 char * targ;
4078
4079 if (!ufile)
4080 return 0;
4081
4082 targ = utbuf;
4083
4084 if (*ufile == '/')
4085 {
4086 ufile++;
4087 }
4088
4089 while (*ufile)
4090 {
4091 switch (*ufile)
4092 {
4093 case '/':
4094 if (slash_seen)
4095 if (index (&ufile[1], '/'))
4096 *targ++ = '.';
4097 else
4098 *targ++ = ']';
4099 else
4100 {
4101 *targ++ = ':';
4102 if (index (&ufile[1], '/'))
4103 *targ++ = '[';
4104 slash_seen = 1;
4105 }
4106 break;
4107
4108 case '.':
4109 if (strncmp (ufile, "./", 2) == 0)
4110 {
4111 if (!slash_seen)
4112 {
4113 *targ++ = '[';
4114 slash_seen = 1;
4115 }
4116 ufile++; /* skip the dot */
4117 if (index (&ufile[1], '/'))
4118 *targ++ = '.';
4119 else
4120 *targ++ = ']';
4121 }
4122 else if (strncmp (ufile, "../", 3) == 0)
4123 {
4124 if (!slash_seen)
4125 {
4126 *targ++ = '[';
4127 slash_seen = 1;
4128 }
4129 *targ++ = '-';
4130 ufile += 2; /* skip the dots */
4131 if (index (&ufile[1], '/'))
4132 *targ++ = '.';
4133 else
4134 *targ++ = ']';
4135 }
4136 else
4137 *targ++ = *ufile;
4138 break;
4139
4140 default:
4141 *targ++ = *ufile;
4142 break;
4143 }
4144 ufile++;
4145 }
4146 *targ = '\0';
177c0ea7 4147
86a5659e
JB
4148 return utbuf;
4149}
4150
4151char *
4152getwd (pathname)
4153 char *pathname;
4154{
f4a7e5bd 4155 char *ptr, *val;
210b2b4f 4156 extern char *getcwd ();
86a5659e 4157
210b2b4f
JB
4158#define MAXPATHLEN 1024
4159
9ac0d9e0 4160 ptr = xmalloc (MAXPATHLEN);
f4a7e5bd
RS
4161 val = getcwd (ptr, MAXPATHLEN);
4162 if (val == 0)
4163 {
4164 xfree (ptr);
4165 return val;
4166 }
210b2b4f 4167 strcpy (pathname, ptr);
9ac0d9e0 4168 xfree (ptr);
177c0ea7 4169
210b2b4f 4170 return pathname;
86a5659e
JB
4171}
4172
dfcf069d 4173int
86a5659e
JB
4174getppid ()
4175{
4176 long item_code = JPI$_OWNER;
4177 unsigned long parent_id;
4178 int status;
4179
4180 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
4181 {
4182 errno = EVMSERR;
4183 vaxc$errno = status;
4184 return -1;
4185 }
4186 return parent_id;
4187}
4188
4189#undef getuid
4190unsigned
4191sys_getuid ()
4192{
4193 return (getgid () << 16) | getuid ();
4194}
4195
68c45bf0 4196#undef read
86a5659e
JB
4197int
4198sys_read (fildes, buf, nbyte)
4199 int fildes;
4200 char *buf;
4201 unsigned int nbyte;
4202{
4203 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
4204}
4205
4206#if 0
4207int
4208sys_write (fildes, buf, nbyte)
4209 int fildes;
4210 char *buf;
4211 unsigned int nbyte;
4212{
4213 register int nwrote, rtnval = 0;
4214
4215 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
4216 nbyte -= nwrote;
4217 buf += nwrote;
4218 rtnval += nwrote;
4219 }
4220 if (nwrote < 0)
4221 return rtnval ? rtnval : -1;
4222 if ((nwrote = write (fildes, buf, nbyte)) < 0)
4223 return rtnval ? rtnval : -1;
4224 return (rtnval + nwrote);
4225}
4226#endif /* 0 */
4227
4228/*
4229 * VAX/VMS VAX C RTL really loses. It insists that records
4230 * end with a newline (carriage return) character, and if they
4231 * don't it adds one (nice of it isn't it!)
4232 *
4233 * Thus we do this stupidity below.
4234 */
4235
68c45bf0 4236#undef write
86a5659e
JB
4237int
4238sys_write (fildes, buf, nbytes)
4239 int fildes;
4240 char *buf;
4241 unsigned int nbytes;
4242{
4243 register char *p;
4244 register char *e;
23b0668c
JB
4245 int sum = 0;
4246 struct stat st;
4247
4248 fstat (fildes, &st);
86a5659e 4249 p = buf;
86a5659e
JB
4250 while (nbytes > 0)
4251 {
23b0668c
JB
4252 int len, retval;
4253
4254 /* Handle fixed-length files with carriage control. */
4255 if (st.st_fab_rfm == FAB$C_FIX
4256 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4257 {
4258 len = st.st_fab_mrs;
4259 retval = write (fildes, p, min (len, nbytes));
4260 if (retval != len)
4261 return -1;
4262 retval++; /* This skips the implied carriage control */
4263 }
4264 else
4265 {
4266 e = p + min (MAXIOSIZE, nbytes) - 1;
4267 while (*e != '\n' && e > p) e--;
4268 if (p == e) /* Ok.. so here we add a newline... sigh. */
4269 e = p + min (MAXIOSIZE, nbytes) - 1;
4270 len = e + 1 - p;
4271 retval = write (fildes, p, len);
4272 if (retval != len)
4273 return -1;
4274 }
4275 p += retval;
4276 sum += retval;
86a5659e
JB
4277 nbytes -= retval;
4278 }
4279 return sum;
4280}
4281
4282/* Create file NEW copying its attributes from file OLD. If
4283 OLD is 0 or does not exist, create based on the value of
4284 vms_stmlf_recfm. */
4285
4286/* Protection value the file should ultimately have.
4287 Set by create_copy_attrs, and use by rename_sansversions. */
4288static unsigned short int fab_final_pro;
4289
4290int
4291creat_copy_attrs (old, new)
4292 char *old, *new;
4293{
4294 struct FAB fab = cc$rms_fab;
4295 struct XABPRO xabpro;
4296 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
4297 extern int vms_stmlf_recfm;
4298
4299 if (old)
4300 {
4301 fab.fab$b_fac = FAB$M_GET;
4302 fab.fab$l_fna = old;
4303 fab.fab$b_fns = strlen (old);
4304 fab.fab$l_xab = (char *) &xabpro;
4305 xabpro = cc$rms_xabpro;
4306 xabpro.xab$l_aclbuf = aclbuf;
4307 xabpro.xab$w_aclsiz = sizeof aclbuf;
4308 /* Call $OPEN to fill in the fab & xabpro fields. */
986ffb24 4309 if (SYS$OPEN (&fab, 0, 0) & 1)
86a5659e 4310 {
986ffb24 4311 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
4312 fab.fab$l_alq = 0; /* zero the allocation quantity */
4313 if (xabpro.xab$w_acllen > 0)
4314 {
4315 if (xabpro.xab$w_acllen > sizeof aclbuf)
4316 /* If the acl buffer was too short, redo open with longer one.
4317 Wouldn't need to do this if there were some system imposed
4318 limit on the size of an ACL, but I can't find any such. */
4319 {
4320 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4321 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
986ffb24
JB
4322 if (SYS$OPEN (&fab, 0, 0) & 1)
4323 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
4324 else
4325 old = 0;
4326 }
4327 }
4328 else
4329 xabpro.xab$l_aclbuf = 0;
4330 }
4331 else
4332 old = 0;
4333 }
4334 fab.fab$l_fna = new;
4335 fab.fab$b_fns = strlen (new);
4336 if (!old)
4337 {
4338 fab.fab$l_xab = 0;
4339 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4340 fab.fab$b_rat = FAB$M_CR;
4341 }
4342
4343 /* Set the file protections such that we will be able to manipulate
4344 this file. Once we are done writing and renaming it, we will set
4345 the protections back. */
4346 if (old)
4347 fab_final_pro = xabpro.xab$w_pro;
4348 else
986ffb24 4349 SYS$SETDFPROT (0, &fab_final_pro);
86a5659e
JB
4350 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4351
4352 /* Create the new file with either default attrs or attrs copied
4353 from old file. */
4354 if (!(SYS$CREATE (&fab, 0, 0) & 1))
4355 return -1;
986ffb24 4356 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
4357 /* As this is a "replacement" for creat, return a file descriptor
4358 opened for writing. */
4359 return open (new, O_WRONLY);
4360}
4361
4362#ifdef creat
4363#undef creat
4364#include <varargs.h>
4365#ifdef __GNUC__
4366#ifndef va_count
4367#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
4368#endif
4369#endif
4370
dfcf069d 4371int
86a5659e
JB
4372sys_creat (va_alist)
4373 va_dcl
4374{
eb8c3be9 4375 va_list list_incrementer;
86a5659e
JB
4376 char *name;
4377 int mode;
4378 int rfd; /* related file descriptor */
4379 int fd; /* Our new file descriptor */
4380 int count;
4381 struct stat st_buf;
4382 char rfm[12];
4383 char rat[15];
4384 char mrs[13];
4385 char fsz[13];
4386 extern int vms_stmlf_recfm;
4387
4388 va_count (count);
eb8c3be9
JB
4389 va_start (list_incrementer);
4390 name = va_arg (list_incrementer, char *);
4391 mode = va_arg (list_incrementer, int);
86a5659e 4392 if (count > 2)
eb8c3be9
JB
4393 rfd = va_arg (list_incrementer, int);
4394 va_end (list_incrementer);
86a5659e
JB
4395 if (count > 2)
4396 {
4397 /* Use information from the related file descriptor to set record
4398 format of the newly created file. */
4399 fstat (rfd, &st_buf);
4400 switch (st_buf.st_fab_rfm)
4401 {
4402 case FAB$C_FIX:
4403 strcpy (rfm, "rfm = fix");
4404 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4405 strcpy (rat, "rat = ");
4406 if (st_buf.st_fab_rat & FAB$M_CR)
4407 strcat (rat, "cr");
4408 else if (st_buf.st_fab_rat & FAB$M_FTN)
4409 strcat (rat, "ftn");
4410 else if (st_buf.st_fab_rat & FAB$M_PRN)
4411 strcat (rat, "prn");
4412 if (st_buf.st_fab_rat & FAB$M_BLK)
4413 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4414 strcat (rat, ", blk");
4415 else
4416 strcat (rat, "blk");
4417 return creat (name, 0, rfm, rat, mrs);
4418
4419 case FAB$C_VFC:
4420 strcpy (rfm, "rfm = vfc");
4421 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4422 strcpy (rat, "rat = ");
4423 if (st_buf.st_fab_rat & FAB$M_CR)
4424 strcat (rat, "cr");
4425 else if (st_buf.st_fab_rat & FAB$M_FTN)
4426 strcat (rat, "ftn");
4427 else if (st_buf.st_fab_rat & FAB$M_PRN)
4428 strcat (rat, "prn");
4429 if (st_buf.st_fab_rat & FAB$M_BLK)
4430 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4431 strcat (rat, ", blk");
4432 else
4433 strcat (rat, "blk");
4434 return creat (name, 0, rfm, rat, fsz);
4435
4436 case FAB$C_STM:
4437 strcpy (rfm, "rfm = stm");
4438 break;
4439
4440 case FAB$C_STMCR:
4441 strcpy (rfm, "rfm = stmcr");
4442 break;
4443
4444 case FAB$C_STMLF:
4445 strcpy (rfm, "rfm = stmlf");
4446 break;
4447
4448 case FAB$C_UDF:
4449 strcpy (rfm, "rfm = udf");
4450 break;
4451
4452 case FAB$C_VAR:
4453 strcpy (rfm, "rfm = var");
4454 break;
4455 }
4456 strcpy (rat, "rat = ");
4457 if (st_buf.st_fab_rat & FAB$M_CR)
4458 strcat (rat, "cr");
4459 else if (st_buf.st_fab_rat & FAB$M_FTN)
4460 strcat (rat, "ftn");
4461 else if (st_buf.st_fab_rat & FAB$M_PRN)
4462 strcat (rat, "prn");
4463 if (st_buf.st_fab_rat & FAB$M_BLK)
4464 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4465 strcat (rat, ", blk");
4466 else
4467 strcat (rat, "blk");
4468 }
4469 else
4470 {
4471 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4472 strcpy (rat, "rat=cr");
4473 }
4474 /* Until the VAX C RTL fixes the many bugs with modes, always use
4475 mode 0 to get the user's default protection. */
4476 fd = creat (name, 0, rfm, rat);
4477 if (fd < 0 && errno == EEXIST)
4478 {
4479 if (unlink (name) < 0)
4480 report_file_error ("delete", build_string (name));
4481 fd = creat (name, 0, rfm, rat);
4482 }
4483 return fd;
4484}
4485#endif /* creat */
4486
4487/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
dfcf069d 4488int
86a5659e
JB
4489sys_fwrite (ptr, size, num, fp)
4490 register char * ptr;
4491 FILE * fp;
4492{
4493 register int tot = num * size;
4494
4495 while (tot--)
4496 fputc (*ptr++, fp);
dfcf069d 4497 return num;
86a5659e
JB
4498}
4499
4500/*
4501 * The VMS C library routine creat actually creates a new version of an
4502 * existing file rather than truncating the old version. There are times
4503 * when this is not the desired behavior, for instance, when writing an
4504 * auto save file (you only want one version), or when you don't have
4505 * write permission in the directory containing the file (but the file
177c0ea7 4506 * itself is writable). Hence this routine, which is equivalent to
86a5659e
JB
4507 * "close (creat (fn, 0));" on Unix if fn already exists.
4508 */
4509int
4510vms_truncate (fn)
4511 char *fn;
4512{
4513 struct FAB xfab = cc$rms_fab;
4514 struct RAB xrab = cc$rms_rab;
4515 int status;
4516
4517 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
4518 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4519 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
4520 xfab.fab$l_fna = fn;
4521 xfab.fab$b_fns = strlen (fn);
4522 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
4523 xfab.fab$b_dns = 2;
4524 xrab.rab$l_fab = &xfab;
4525
4526 /* This gibberish opens the file, positions to the first record, and
4527 deletes all records from there until the end of file. */
986ffb24 4528 if ((SYS$OPEN (&xfab) & 01) == 01)
86a5659e 4529 {
986ffb24
JB
4530 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4531 (SYS$FIND (&xrab) & 01) == 01 &&
4532 (SYS$TRUNCATE (&xrab) & 01) == 01)
86a5659e
JB
4533 status = 0;
4534 else
4535 status = -1;
4536 }
4537 else
4538 status = -1;
986ffb24 4539 SYS$CLOSE (&xfab);
86a5659e
JB
4540 return status;
4541}
4542
4543/* Define this symbol to actually read SYSUAF.DAT. This requires either
4544 SYSPRV or a readable SYSUAF.DAT. */
4545
4546#ifdef READ_SYSUAF
4547/*
4548 * getuaf.c
4549 *
4550 * Routine to read the VMS User Authorization File and return
4551 * a specific user's record.
4552 */
4553
4554static struct UAF retuaf;
4555
4556struct UAF *
4557get_uaf_name (uname)
4558 char * uname;
4559{
4560 register status;
4561 struct FAB uaf_fab;
4562 struct RAB uaf_rab;
177c0ea7 4563
86a5659e
JB
4564 uaf_fab = cc$rms_fab;
4565 uaf_rab = cc$rms_rab;
4566 /* initialize fab fields */
4567 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4568 uaf_fab.fab$b_fns = 21;
4569 uaf_fab.fab$b_fac = FAB$M_GET;
4570 uaf_fab.fab$b_org = FAB$C_IDX;
4571 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4572 /* initialize rab fields */
4573 uaf_rab.rab$l_fab = &uaf_fab;
4574 /* open the User Authorization File */
986ffb24 4575 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
4576 if (!(status&1))
4577 {
4578 errno = EVMSERR;
4579 vaxc$errno = status;
4580 return 0;
4581 }
986ffb24 4582 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
4583 if (!(status&1))
4584 {
4585 errno = EVMSERR;
4586 vaxc$errno = status;
4587 return 0;
4588 }
4589 /* read the requested record - index is in uname */
4590 uaf_rab.rab$l_kbf = uname;
4591 uaf_rab.rab$b_ksz = strlen (uname);
4592 uaf_rab.rab$b_rac = RAB$C_KEY;
4593 uaf_rab.rab$l_ubf = (char *)&retuaf;
4594 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 4595 status = SYS$GET (&uaf_rab);
86a5659e
JB
4596 if (!(status&1))
4597 {
4598 errno = EVMSERR;
4599 vaxc$errno = status;
4600 return 0;
4601 }
4602 /* close the User Authorization File */
986ffb24 4603 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
4604 if (!(status&1))
4605 {
4606 errno = EVMSERR;
4607 vaxc$errno = status;
4608 return 0;
4609 }
986ffb24 4610 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
4611 if (!(status&1))
4612 {
4613 errno = EVMSERR;
4614 vaxc$errno = status;
4615 return 0;
4616 }
4617 return &retuaf;
4618}
4619
4620struct UAF *
4621get_uaf_uic (uic)
4622 unsigned long uic;
4623{
4624 register status;
4625 struct FAB uaf_fab;
4626 struct RAB uaf_rab;
177c0ea7 4627
86a5659e
JB
4628 uaf_fab = cc$rms_fab;
4629 uaf_rab = cc$rms_rab;
4630 /* initialize fab fields */
4631 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4632 uaf_fab.fab$b_fns = 21;
4633 uaf_fab.fab$b_fac = FAB$M_GET;
4634 uaf_fab.fab$b_org = FAB$C_IDX;
4635 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4636 /* initialize rab fields */
4637 uaf_rab.rab$l_fab = &uaf_fab;
4638 /* open the User Authorization File */
986ffb24 4639 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
4640 if (!(status&1))
4641 {
4642 errno = EVMSERR;
4643 vaxc$errno = status;
4644 return 0;
4645 }
986ffb24 4646 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
4647 if (!(status&1))
4648 {
4649 errno = EVMSERR;
4650 vaxc$errno = status;
4651 return 0;
4652 }
4653 /* read the requested record - index is in uic */
4654 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
4655 uaf_rab.rab$l_kbf = (char *) &uic;
4656 uaf_rab.rab$b_ksz = sizeof uic;
4657 uaf_rab.rab$b_rac = RAB$C_KEY;
4658 uaf_rab.rab$l_ubf = (char *)&retuaf;
4659 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 4660 status = SYS$GET (&uaf_rab);
86a5659e
JB
4661 if (!(status&1))
4662 {
4663 errno = EVMSERR;
4664 vaxc$errno = status;
4665 return 0;
4666 }
4667 /* close the User Authorization File */
986ffb24 4668 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
4669 if (!(status&1))
4670 {
4671 errno = EVMSERR;
4672 vaxc$errno = status;
4673 return 0;
4674 }
986ffb24 4675 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
4676 if (!(status&1))
4677 {
4678 errno = EVMSERR;
4679 vaxc$errno = status;
4680 return 0;
4681 }
4682 return &retuaf;
4683}
4684
4685static struct passwd retpw;
4686
4687struct passwd *
4688cnv_uaf_pw (up)
4689 struct UAF * up;
4690{
4691 char * ptr;
4692
4693 /* copy these out first because if the username is 32 chars, the next
4694 section will overwrite the first byte of the UIC */
4695 retpw.pw_uid = up->uaf$w_mem;
4696 retpw.pw_gid = up->uaf$w_grp;
4697
ea5a0917 4698 /* I suppose this is not the best style, to possibly overwrite one
86a5659e
JB
4699 byte beyond the end of the field, but what the heck... */
4700 ptr = &up->uaf$t_username[UAF$S_USERNAME];
4701 while (ptr[-1] == ' ')
4702 ptr--;
4703 *ptr = '\0';
4704 strcpy (retpw.pw_name, up->uaf$t_username);
4705
4706 /* the rest of these are counted ascii strings */
4707 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
4708 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
4709 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
4710 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
4711 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
4712 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
4713 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
4714 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
4715
4716 return &retpw;
4717}
4718#else /* not READ_SYSUAF */
4719static struct passwd retpw;
4720#endif /* not READ_SYSUAF */
4721
4722struct passwd *
4723getpwnam (name)
4724 char * name;
4725{
4726#ifdef READ_SYSUAF
4727 struct UAF *up;
4728#else
4729 char * user;
4730 char * dir;
4731 unsigned char * full;
4732#endif /* READ_SYSUAF */
4733 char *ptr = name;
4734
4735 while (*ptr)
4736 {
4737 if ('a' <= *ptr && *ptr <= 'z')
4738 *ptr -= 040;
4739 ptr++;
4740 }
4741#ifdef READ_SYSUAF
4742 if (!(up = get_uaf_name (name)))
4743 return 0;
4744 return cnv_uaf_pw (up);
4745#else
4746 if (strcmp (name, getenv ("USER")) == 0)
4747 {
4748 retpw.pw_uid = getuid ();
4749 retpw.pw_gid = getgid ();
4750 strcpy (retpw.pw_name, name);
4751 if (full = egetenv ("FULLNAME"))
4752 strcpy (retpw.pw_gecos, full);
4753 else
4754 *retpw.pw_gecos = '\0';
4755 strcpy (retpw.pw_dir, egetenv ("HOME"));
4756 *retpw.pw_shell = '\0';
4757 return &retpw;
4758 }
4759 else
4760 return 0;
4761#endif /* not READ_SYSUAF */
4762}
4763
4764struct passwd *
4765getpwuid (uid)
4766 unsigned long uid;
4767{
4768#ifdef READ_SYSUAF
4769 struct UAF * up;
4770
4771 if (!(up = get_uaf_uic (uid)))
4772 return 0;
4773 return cnv_uaf_pw (up);
4774#else
4775 if (uid == sys_getuid ())
4776 return getpwnam (egetenv ("USER"));
4777 else
4778 return 0;
4779#endif /* not READ_SYSUAF */
4780}
4781
4782/* return total address space available to the current process. This is
4783 the sum of the current p0 size, p1 size and free page table entries
4784 available. */
dfcf069d 4785int
86a5659e
JB
4786vlimit ()
4787{
4788 int item_code;
4789 unsigned long free_pages;
4790 unsigned long frep0va;
4791 unsigned long frep1va;
4792 register status;
4793
4794 item_code = JPI$_FREPTECNT;
4795 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4796 {
4797 errno = EVMSERR;
4798 vaxc$errno = status;
4799 return -1;
4800 }
4801 free_pages *= 512;
4802
4803 item_code = JPI$_FREP0VA;
4804 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4805 {
4806 errno = EVMSERR;
4807 vaxc$errno = status;
4808 return -1;
4809 }
4810 item_code = JPI$_FREP1VA;
4811 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4812 {
4813 errno = EVMSERR;
4814 vaxc$errno = status;
4815 return -1;
4816 }
4817
4818 return free_pages + frep0va + (0x7fffffff - frep1va);
4819}
4820
dfcf069d 4821int
86a5659e
JB
4822define_logical_name (varname, string)
4823 char *varname;
4824 char *string;
4825{
4826 struct dsc$descriptor_s strdsc =
4827 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4828 struct dsc$descriptor_s envdsc =
4829 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4830 struct dsc$descriptor_s lnmdsc =
4831 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4832
4833 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4834}
4835
dfcf069d 4836int
86a5659e
JB
4837delete_logical_name (varname)
4838 char *varname;
4839{
4840 struct dsc$descriptor_s envdsc =
4841 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4842 struct dsc$descriptor_s lnmdsc =
4843 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4844
4845 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4846}
4847
dfcf069d 4848int
86a5659e 4849ulimit ()
dfcf069d
AS
4850{
4851 return 0;
4852}
86a5659e 4853
dfcf069d 4854int
86a5659e 4855setpgrp ()
dfcf069d
AS
4856{
4857 return 0;
4858}
86a5659e 4859
dfcf069d 4860int
86a5659e
JB
4861execvp ()
4862{
4863 error ("execvp system call not implemented");
dfcf069d 4864 return -1;
86a5659e
JB
4865}
4866
4867int
4868rename (from, to)
4869 char *from, *to;
4870{
4871 int status;
4872 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4873 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4874 char from_esn[NAM$C_MAXRSS];
4875 char to_esn[NAM$C_MAXRSS];
4876
4877 from_fab.fab$l_fna = from;
4878 from_fab.fab$b_fns = strlen (from);
4879 from_fab.fab$l_nam = &from_nam;
4880 from_fab.fab$l_fop = FAB$M_NAM;
4881
4882 from_nam.nam$l_esa = from_esn;
4883 from_nam.nam$b_ess = sizeof from_esn;
4884
4885 to_fab.fab$l_fna = to;
4886 to_fab.fab$b_fns = strlen (to);
4887 to_fab.fab$l_nam = &to_nam;
4888 to_fab.fab$l_fop = FAB$M_NAM;
4889
4890 to_nam.nam$l_esa = to_esn;
4891 to_nam.nam$b_ess = sizeof to_esn;
4892
4893 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4894
4895 if (status & 1)
4896 return 0;
4897 else
4898 {
4899 if (status == RMS$_DEV)
4900 errno = EXDEV;
4901 else
4902 errno = EVMSERR;
4903 vaxc$errno = status;
4904 return -1;
4905 }
4906}
4907
4908/* This function renames a file like `rename', but it strips
4909 the version number from the "to" filename, such that the "to" file is
4910 will always be a new version. It also sets the file protection once it is
4911 finished. The protection that we will use is stored in fab_final_pro,
4912 and was set when we did a creat_copy_attrs to create the file that we
4913 are renaming.
4914
4915 We could use the chmod function, but Eunichs uses 3 bits per user category
eb8c3be9 4916 to describe the protection, and VMS uses 4 (write and delete are separate
86a5659e
JB
4917 bits). To maintain portability, the VMS implementation of `chmod' wires
4918 the W and D bits together. */
4919
177c0ea7 4920
86a5659e
JB
4921static struct fibdef fib; /* We need this initialized to zero */
4922char vms_file_written[NAM$C_MAXRSS];
4923
4924int
4925rename_sans_version (from,to)
4926 char *from, *to;
4927{
4928 short int chan;
4929 int stat;
4930 short int iosb[4];
4931 int status;
4932 struct FAB to_fab = cc$rms_fab;
4933 struct NAM to_nam = cc$rms_nam;
4934 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4935 struct dsc$descriptor fib_attr[2]
4936 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4937 char to_esn[NAM$C_MAXRSS];
4938
4939 $DESCRIPTOR (disk,to_esn);
4940
4941 to_fab.fab$l_fna = to;
4942 to_fab.fab$b_fns = strlen (to);
4943 to_fab.fab$l_nam = &to_nam;
4944 to_fab.fab$l_fop = FAB$M_NAM;
4945
4946 to_nam.nam$l_esa = to_esn;
4947 to_nam.nam$b_ess = sizeof to_esn;
4948
4949 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4950
4951 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4952 *(to_nam.nam$l_ver) = '\0';
4953
4954 stat = rename (from, to_esn);
4955 if (stat < 0)
4956 return stat;
4957
4958 strcpy (vms_file_written, to_esn);
4959
4960 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4961 to_fab.fab$b_fns = strlen (vms_file_written);
4962
4963 /* Now set the file protection to the correct value */
986ffb24 4964 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
86a5659e
JB
4965
4966 /* Copy these fields into the fib */
4967 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4968 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4969 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4970
986ffb24 4971 SYS$CLOSE (&to_fab, 0, 0);
86a5659e 4972
986ffb24 4973 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
86a5659e 4974 if (!stat)
986ffb24
JB
4975 LIB$SIGNAL (stat);
4976 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
86a5659e
JB
4977 0, 0, 0, &fib_attr, 0);
4978 if (!stat)
986ffb24
JB
4979 LIB$SIGNAL (stat);
4980 stat = SYS$DASSGN (chan);
86a5659e 4981 if (!stat)
986ffb24 4982 LIB$SIGNAL (stat);
0137dbf7 4983 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
4984 return 0;
4985}
4986
dfcf069d 4987int
86a5659e
JB
4988link (file, new)
4989 char * file, * new;
4990{
4991 register status;
4992 struct FAB fab;
4993 struct NAM nam;
4994 unsigned short fid[3];
4995 char esa[NAM$C_MAXRSS];
4996
4997 fab = cc$rms_fab;
4998 fab.fab$l_fop = FAB$M_OFP;
4999 fab.fab$l_fna = file;
5000 fab.fab$b_fns = strlen (file);
5001 fab.fab$l_nam = &nam;
5002
5003 nam = cc$rms_nam;
5004 nam.nam$l_esa = esa;
5005 nam.nam$b_ess = NAM$C_MAXRSS;
5006
5007 status = SYS$PARSE (&fab);
5008 if ((status & 1) == 0)
5009 {
5010 errno = EVMSERR;
5011 vaxc$errno = status;
5012 return -1;
5013 }
5014 status = SYS$SEARCH (&fab);
5015 if ((status & 1) == 0)
5016 {
5017 errno = EVMSERR;
5018 vaxc$errno = status;
5019 return -1;
5020 }
5021
5022 fid[0] = nam.nam$w_fid[0];
5023 fid[1] = nam.nam$w_fid[1];
5024 fid[2] = nam.nam$w_fid[2];
5025
5026 fab.fab$l_fna = new;
5027 fab.fab$b_fns = strlen (new);
5028
5029 status = SYS$PARSE (&fab);
5030 if ((status & 1) == 0)
5031 {
5032 errno = EVMSERR;
5033 vaxc$errno = status;
5034 return -1;
5035 }
5036
5037 nam.nam$w_fid[0] = fid[0];
5038 nam.nam$w_fid[1] = fid[1];
5039 nam.nam$w_fid[2] = fid[2];
5040
5041 nam.nam$l_esa = nam.nam$l_name;
5042 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
5043
5044 status = SYS$ENTER (&fab);
5045 if ((status & 1) == 0)
5046 {
5047 errno = EVMSERR;
5048 vaxc$errno = status;
5049 return -1;
5050 }
5051
5052 return 0;
5053}
5054
dfcf069d 5055void
86a5659e
JB
5056croak (badfunc)
5057 char *badfunc;
5058{
5059 printf ("%s not yet implemented\r\n", badfunc);
5060 reset_sys_modes ();
5061 exit (1);
5062}
5063
5064long
5065random ()
5066{
5067 /* Arrange to return a range centered on zero. */
5068 return rand () - (1 << 30);
5069}
5070
dfcf069d 5071void
86a5659e
JB
5072srandom (seed)
5073{
5074 srand (seed);
5075}
5076#endif /* VMS */
5077\f
b97ab886 5078#ifdef AIXHFT
86a5659e
JB
5079
5080/* Called from init_sys_modes. */
dfcf069d 5081void
86a5659e
JB
5082hft_init ()
5083{
5084 int junk;
5085
5086 /* If we're not on an HFT we shouldn't do any of this. We determine
5087 if we are on an HFT by trying to get an HFT error code. If this
177c0ea7 5088 call fails, we're not on an HFT. */
86a5659e
JB
5089#ifdef IBMR2AIX
5090 if (ioctl (0, HFQERROR, &junk) < 0)
5091 return;
5092#else /* not IBMR2AIX */
5093 if (ioctl (0, HFQEIO, 0) < 0)
5094 return;
5095#endif /* not IBMR2AIX */
5096
5097 /* On AIX the default hft keyboard mapping uses backspace rather than delete
5098 as the rubout key's ASCII code. Here this is changed. The bug is that
5099 there's no way to determine the old mapping, so in reset_sys_modes
5100 we need to assume that the normal map had been present. Of course, this
5101 code also doesn't help if on a terminal emulator which doesn't understand
c4ea52a6 5102 HFT VTD's. */
86a5659e
JB
5103 {
5104 struct hfbuf buf;
5105 struct hfkeymap keymap;
5106
5107 buf.hf_bufp = (char *)&keymap;
5108 buf.hf_buflen = sizeof (keymap);
5109 keymap.hf_nkeys = 2;
5110 keymap.hfkey[0].hf_kpos = 15;
5111 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5112#ifdef IBMR2AIX
5113 keymap.hfkey[0].hf_keyidh = '<';
5114#else /* not IBMR2AIX */
5115 keymap.hfkey[0].hf_page = '<';
5116#endif /* not IBMR2AIX */
5117 keymap.hfkey[0].hf_char = 127;
5118 keymap.hfkey[1].hf_kpos = 15;
5119 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5120#ifdef IBMR2AIX
5121 keymap.hfkey[1].hf_keyidh = '<';
5122#else /* not IBMR2AIX */
5123 keymap.hfkey[1].hf_page = '<';
5124#endif /* not IBMR2AIX */
5125 keymap.hfkey[1].hf_char = 127;
5126 hftctl (0, HFSKBD, &buf);
5127 }
5128 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
5129 at times. */
5130 line_ins_del_ok = char_ins_del_ok = 0;
5131}
5132
c4ea52a6 5133/* Reset the rubout key to backspace. */
86a5659e 5134
dfcf069d 5135void
86a5659e
JB
5136hft_reset ()
5137{
5138 struct hfbuf buf;
5139 struct hfkeymap keymap;
5140 int junk;
5141
5142#ifdef IBMR2AIX
5143 if (ioctl (0, HFQERROR, &junk) < 0)
5144 return;
5145#else /* not IBMR2AIX */
5146 if (ioctl (0, HFQEIO, 0) < 0)
5147 return;
5148#endif /* not IBMR2AIX */
5149
5150 buf.hf_bufp = (char *)&keymap;
5151 buf.hf_buflen = sizeof (keymap);
5152 keymap.hf_nkeys = 2;
5153 keymap.hfkey[0].hf_kpos = 15;
5154 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
5155#ifdef IBMR2AIX
5156 keymap.hfkey[0].hf_keyidh = '<';
5157#else /* not IBMR2AIX */
5158 keymap.hfkey[0].hf_page = '<';
5159#endif /* not IBMR2AIX */
5160 keymap.hfkey[0].hf_char = 8;
5161 keymap.hfkey[1].hf_kpos = 15;
5162 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
5163#ifdef IBMR2AIX
5164 keymap.hfkey[1].hf_keyidh = '<';
5165#else /* not IBMR2AIX */
5166 keymap.hfkey[1].hf_page = '<';
5167#endif /* not IBMR2AIX */
5168 keymap.hfkey[1].hf_char = 8;
5169 hftctl (0, HFSKBD, &buf);
5170}
5171
b97ab886 5172#endif /* AIXHFT */
c238be24
RS
5173
5174#ifdef USE_DL_STUBS
5175
5176/* These are included on Sunos 4.1 when we do not use shared libraries.
5177 X11 libraries may refer to these functions but (we hope) do not
5178 actually call them. */
5179
5180void *
5181dlopen ()
5182{
5183 return 0;
5184}
5185
5186void *
5187dlsym ()
5188{
5189 return 0;
5190}
5191
5192int
5193dlclose ()
5194{
5195 return -1;
5196}
5197
5198#endif /* USE_DL_STUBS */
51417996
RS
5199\f
5200#ifndef BSTRING
5201
5202#ifndef bzero
5203
5204void
5205bzero (b, length)
5206 register char *b;
5207 register int length;
5208{
5209#ifdef VMS
5210 short zero = 0;
5211 long max_str = 65535;
5212
5213 while (length > max_str) {
5214 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5215 length -= max_str;
5216 b += max_str;
5217 }
5218 max_str = length;
5219 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5220#else
5221 while (length-- > 0)
5222 *b++ = 0;
5223#endif /* not VMS */
5224}
5225
5226#endif /* no bzero */
5227#endif /* BSTRING */
5228
c7f93f28 5229#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
51417996
RS
5230#undef bcopy
5231
5232/* Saying `void' requires a declaration, above, where bcopy is used
5233 and that declaration causes pain for systems where bcopy is a macro. */
5234bcopy (b1, b2, length)
5235 register char *b1;
5236 register char *b2;
5237 register int length;
5238{
5239#ifdef VMS
5240 long max_str = 65535;
5241
5242 while (length > max_str) {
5243 (void) LIB$MOVC3 (&max_str, b1, b2);
5244 length -= max_str;
5245 b1 += max_str;
5246 b2 += max_str;
5247 }
5248 max_str = length;
5249 (void) LIB$MOVC3 (&length, b1, b2);
5250#else
5251 while (length-- > 0)
5252 *b2++ = *b1++;
5253#endif /* not VMS */
5254}
dfcf069d 5255#endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
51417996 5256
c7f93f28 5257#ifndef BSTRING
51417996
RS
5258#ifndef bcmp
5259int
5260bcmp (b1, b2, length) /* This could be a macro! */
5261 register char *b1;
5262 register char *b2;
5263 register int length;
5264{
5265#ifdef VMS
5266 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
5267 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
5268
5269 return STR$COMPARE (&src1, &src2);
5270#else
5271 while (length-- > 0)
5272 if (*b1++ != *b2++)
5273 return 1;
5274
5275 return 0;
5276#endif /* not VMS */
5277}
5278#endif /* no bcmp */
5279#endif /* not BSTRING */
68c45bf0
PE
5280\f
5281#ifndef HAVE_STRSIGNAL
5282char *
5283strsignal (code)
5284 int code;
5285{
5286 char *signame = 0;
5287
5288 if (0 <= code && code < NSIG)
5289 {
5290#ifdef VMS
5291 signame = sys_errlist[code];
5292#else
5293 /* Cast to suppress warning if the table has const char *. */
5294 signame = (char *) sys_siglist[code];
5295#endif
5296 }
c4ea52a6 5297
68c45bf0
PE
5298 return signame;
5299}
5300#endif /* HAVE_STRSIGNAL */
c4ea52a6 5301
ab5796a9
MB
5302/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
5303 (do not change this comment) */