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