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