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