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