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