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