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