* sysdep.c [ultrix] (init_sys_modes): Don't set LLITOUT; it
[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;
37fd7901
JB
1171#ifdef ultrix
1172 /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
1173 anything, and leaving it in breaks the meta key. Go figure. */
1174 tty.lmode &= ~LLITOUT;
1175#endif
91bac16a
JB
1176
1177#ifdef BSD4_1
1178 lmode = tty.lmode;
1179#endif
1180
50b8cf60 1181#endif /* HAVE_TCHARS */
91bac16a
JB
1182#endif /* not HAVE_TERMIO */
1183
50b8cf60 1184#ifdef HAVE_LTCHARS
91bac16a 1185 tty.ltchars = new_ltchars;
50b8cf60 1186#endif /* HAVE_LTCHARS */
91bac16a
JB
1187
1188 EMACS_SET_TTY (input_fd, &tty, 0);
86a5659e
JB
1189
1190 /* This code added to insure that, if flow-control is not to be used,
0137dbf7 1191 we have an unlocked terminal at the start. */
91bac16a 1192
86a5659e
JB
1193#ifdef TCXONC
1194 if (!flow_control) ioctl (0, TCXONC, 1);
1195#endif
1196#ifndef APOLLO
1197#ifdef TIOCSTART
1198 if (!flow_control) ioctl (0, TIOCSTART, 0);
1199#endif
1200#endif
1201
1202#ifdef AIX
1203 hft_init ();
1204#ifdef IBMR2AIX
1205 {
1206 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
1207 to be only LF. This is the way that is done. */
1208 struct termio tty;
1209
1210 if (ioctl (1, HFTGETID, &tty) != -1)
1211 write (1, "\033[20l", 5);
1212 }
1213#endif
1214#endif
1215
86a5659e
JB
1216#ifdef VMS
1217/* Appears to do nothing when in PASTHRU mode.
91bac16a 1218 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
86a5659e
JB
1219 interrupt_signal, oob_chars, 0, 0, 0, 0);
1220*/
1221 queue_kbd_input (0);
1222#endif /* VMS */
1223 }
1224
1225#ifdef F_SETFL
eb8c3be9 1226#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
86a5659e
JB
1227 if (interrupt_input)
1228 {
1229 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
1230 fcntl (0, F_SETOWN, getpid ());
1231 init_sigio ();
1232 }
1233#endif /* F_GETOWN */
1234#endif /* F_SETFL */
1235
1236#ifdef BSD4_1
1237 if (interrupt_input)
1238 init_sigio ();
1239#endif
1240
1241#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
1242#undef _IOFBF
1243#endif
1244#ifdef _IOFBF
1245 /* This symbol is defined on recent USG systems.
1246 Someone says without this call USG won't really buffer the file
1247 even with a call to setbuf. */
1248 setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
1249#else
1250 setbuf (stdout, _sobuf);
1251#endif
1252 set_terminal_modes ();
1253 if (term_initted && no_redraw_on_reenter)
1254 {
1255 if (display_completed)
1256 direct_output_forward_char (0);
1257 }
1258 else
1259 {
0137dbf7
JB
1260 frame_garbaged = 1;
1261#ifdef MULTI_FRAME
1262 if (FRAMEP (Vterminal_frame))
1263 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
86a5659e
JB
1264#endif
1265 }
91bac16a 1266
86a5659e
JB
1267 term_initted = 1;
1268}
1269
1270/* Return nonzero if safe to use tabs in output.
1271 At the time this is called, init_sys_modes has not been done yet. */
1272
1273tabs_safe_p ()
1274{
91bac16a
JB
1275 struct emacs_tty tty;
1276
1277 EMACS_GET_TTY (input_fd, &tty);
1278 return EMACS_TTY_TABS_OK (&tty);
86a5659e
JB
1279}
1280
1281/* Get terminal size from system.
1282 Store number of lines into *heightp and width into *widthp.
1283 If zero or a negative number is stored, the value is not valid. */
1284
0137dbf7 1285get_frame_size (widthp, heightp)
86a5659e
JB
1286 int *widthp, *heightp;
1287{
86a5659e 1288
86a5659e 1289#ifdef TIOCGWINSZ
91bac16a
JB
1290
1291 /* BSD-style. */
86a5659e 1292 struct winsize size;
91bac16a
JB
1293
1294 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1295 *widthp = *heightp = 0;
1296 else
1297 {
1298 *widthp = size.ws_col;
1299 *heightp = size.ws_row;
1300 }
1301
1302#else
1303#ifdef TIOCGSIZE
1304
1305 /* SunOS - style. */
1306 struct ttysize size;
1307
1308 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1309 *widthp = *heightp = 0;
1310 else
1311 {
1312 *widthp = size.ts_cols;
1313 *heightp = size.ts_lines;
1314 }
1315
1316#else
86a5659e 1317#ifdef VMS
91bac16a
JB
1318
1319 struct sensemode tty;
1320
1321 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
86a5659e
JB
1322 &tty.class, 12, 0, 0, 0, 0);
1323 *widthp = tty.scr_wid;
1324 *heightp = tty.scr_len;
91bac16a 1325
86a5659e 1326#else /* system doesn't know size */
91bac16a 1327
86a5659e
JB
1328 *widthp = 0;
1329 *heightp = 0;
91bac16a
JB
1330
1331#endif /* not VMS */
1332#endif /* not SunOS-style */
1333#endif /* not BSD-style */
86a5659e 1334}
91bac16a 1335
86a5659e 1336\f
91bac16a 1337/* Prepare the terminal for exiting Emacs; move the cursor to the
0137dbf7 1338 bottom of the frame, turn off interrupt-driven I/O, etc. */
86a5659e
JB
1339reset_sys_modes ()
1340{
1341 if (noninteractive)
1342 {
1343 fflush (stdout);
1344 return;
1345 }
1346 if (!term_initted)
1347 return;
1348 if (read_socket_hook || !EQ (Vwindow_system, Qnil))
1349 return;
0137dbf7
JB
1350 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
1351 clear_end_of_line (FRAME_WIDTH (selected_frame));
86a5659e 1352 /* clear_end_of_line may move the cursor */
0137dbf7 1353 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
86a5659e
JB
1354#ifdef IBMR2AIX
1355 {
1356 /* HFT devices normally use ^J as a LF/CR. We forced it to
1357 do the LF only. Now, we need to reset it. */
1358 struct termio tty;
1359
1360 if (ioctl (1, HFTGETID, &tty) != -1)
1361 write (1, "\033[20h", 5);
1362 }
1363#endif
1364
1365 reset_terminal_modes ();
1366 fflush (stdout);
1367#ifdef BSD
1368#ifndef BSD4_1
1369 /* Avoid possible loss of output when changing terminal modes. */
1370 fsync (fileno (stdout));
1371#endif
1372#endif
91bac16a 1373
86a5659e 1374#ifdef F_SETFL
eb8c3be9 1375#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
86a5659e
JB
1376 if (interrupt_input)
1377 {
1378 reset_sigio ();
1379 fcntl (0, F_SETOWN, old_fcntl_owner);
1380 }
1381#endif /* F_SETOWN */
1382#endif /* F_SETFL */
1383#ifdef BSD4_1
1384 if (interrupt_input)
1385 reset_sigio ();
1386#endif /* BSD4_1 */
91bac16a 1387
1334b321 1388 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
91bac16a 1389 ;
86a5659e
JB
1390
1391#ifdef AIX
1392 hft_reset ();
1393#endif
9ae8f997
JB
1394
1395#ifdef BSD
1396 widen_foreground_group ();
1397#endif
86a5659e
JB
1398}
1399\f
1400#ifdef HAVE_PTYS
1401
1402/* Set up the proper status flags for use of a pty. */
1403
1404setup_pty (fd)
1405 int fd;
1406{
1407 /* I'm told that TOICREMOTE does not mean control chars
1408 "can't be sent" but rather that they don't have
1409 input-editing or signaling effects.
1410 That should be good, because we have other ways
1411 to do those things in Emacs.
1412 However, telnet mode seems not to work on 4.2.
1413 So TIOCREMOTE is turned off now. */
1414
1415 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1416 will hang. In particular, the "timeout" feature (which
1417 causes a read to return if there is no data available)
1418 does this. Also it is known that telnet mode will hang
1419 in such a way that Emacs must be stopped (perhaps this
1420 is the same problem).
1421
1422 If TIOCREMOTE is turned off, then there is a bug in
1423 hp-ux which sometimes loses data. Apparently the
1424 code which blocks the master process when the internal
1425 buffer fills up does not work. Other than this,
1426 though, everything else seems to work fine.
1427
1428 Since the latter lossage is more benign, we may as well
1429 lose that way. -- cph */
1430#ifdef FIONBIO
1431#ifdef SYSV_PTYS
1432 {
1433 int on = 1;
1434 ioctl (fd, FIONBIO, &on);
1435 }
1436#endif
1437#endif
1438#ifdef IBMRTAIX
1439 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1440 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1441 /* cause EMACS not to die when it should, i.e., when its own controlling */
1442 /* tty goes away. I've complained to the AIX developers, and they may */
1443 /* change this behavior, but I'm not going to hold my breath. */
1444 signal (SIGHUP, SIG_IGN);
1445#endif
1446}
1447#endif /* HAVE_PTYS */
1448\f
1449#ifdef VMS
1450
1451/* Assigning an input channel is done at the start of Emacs execution.
1452 This is called each time Emacs is resumed, also, but does nothing
1453 because input_chain is no longer zero. */
1454
1455init_vms_input ()
1456{
1457 int status;
1458
91bac16a 1459 if (input_fd == 0)
86a5659e 1460 {
91bac16a 1461 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
86a5659e
JB
1462 if (! (status & 1))
1463 LIB$STOP (status);
1464 }
1465}
1466
1467/* Deassigning the input channel is done before exiting. */
1468
1469stop_vms_input ()
1470{
91bac16a 1471 return SYS$DASSGN (input_fd);
86a5659e
JB
1472}
1473
1474short input_buffer;
1475
1476/* Request reading one character into the keyboard buffer.
1477 This is done as soon as the buffer becomes empty. */
1478
1479queue_kbd_input ()
1480{
1481 int status;
210b2b4f
JB
1482 extern kbd_input_ast ();
1483
86a5659e
JB
1484 waiting_for_ast = 0;
1485 stop_input = 0;
91bac16a 1486 status = SYS$QIO (0, input_fd, IO$_READVBLK,
86a5659e
JB
1487 &input_iosb, kbd_input_ast, 1,
1488 &input_buffer, 1, 0, terminator_mask, 0, 0);
1489}
1490
1491int input_count;
1492
1493/* Ast routine that is called when keyboard input comes in
1494 in accord with the SYS$QIO above. */
1495
1496kbd_input_ast ()
1497{
1498 register int c = -1;
1499 int old_errno = errno;
ffd56f97 1500 extern EMACS_TIME *input_available_clear_time;
86a5659e
JB
1501
1502 if (waiting_for_ast)
1503 SYS$SETEF (input_ef);
1504 waiting_for_ast = 0;
1505 input_count++;
1506#ifdef ASTDEBUG
1507 if (input_count == 25)
1508 exit (1);
1509 printf ("Ast # %d,", input_count);
1510 printf (" iosb = %x, %x, %x, %x",
1511 input_iosb.offset, input_iosb.status, input_iosb.termlen,
1512 input_iosb.term);
1513#endif
1514 if (input_iosb.offset)
1515 {
1516 c = input_buffer;
1517#ifdef ASTDEBUG
1518 printf (", char = 0%o", c);
1519#endif
1520 }
1521#ifdef ASTDEBUG
1522 printf ("\n");
1523 fflush (stdout);
1524 sleep (1);
1525#endif
1526 if (! stop_input)
1527 queue_kbd_input ();
1528 if (c >= 0)
1529 {
1530 struct input_event e;
1531 e.kind = ascii_keystroke;
210b2b4f
JB
1532 XSET (e.code, Lisp_Int, c);
1533#ifdef MULTI_FRAME
1534 XSET(e.frame_or_window, Lisp_Frame, selected_frame);
1535#else
1536 e.frame_or_window = Qnil;
1537#endif
86a5659e
JB
1538 kbd_buffer_store_event (&e);
1539 }
ffd56f97
JB
1540 if (input_available_clear_time)
1541 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
86a5659e
JB
1542 errno = old_errno;
1543}
1544
1545/* Wait until there is something in kbd_buffer. */
1546
1547wait_for_kbd_input ()
1548{
1549 extern int have_process_input, process_exited;
1550
1551 /* If already something, avoid doing system calls. */
1552 if (detect_input_pending ())
1553 {
1554 return;
1555 }
1556 /* Clear a flag, and tell ast routine above to set it. */
1557 SYS$CLREF (input_ef);
1558 waiting_for_ast = 1;
1559 /* Check for timing error: ast happened while we were doing that. */
1560 if (!detect_input_pending ())
1561 {
1562 /* No timing error: wait for flag to be set. */
1563 set_waiting_for_input (0);
1564 SYS$WFLOR (input_ef, input_eflist);
1565 clear_waiting_for_input (0);
1566 if (!detect_input_pending ())
1567 /* Check for subprocess input availability */
1568 {
1569 int dsp = have_process_input || process_exited;
1570
1571 SYS$CLREF (process_ef);
1572 if (have_process_input)
1573 process_command_input ();
1574 if (process_exited)
1575 process_exit ();
1576 if (dsp)
1577 {
1578 update_mode_lines++;
1579 redisplay_preserve_echo_area ();
1580 }
1581 }
1582 }
1583 waiting_for_ast = 0;
1584}
1585
1586/* Get rid of any pending QIO, when we are about to suspend
1587 or when we want to throw away pending input.
1588 We wait for a positive sign that the AST routine has run
1589 and therefore there is no I/O request queued when we return.
1590 SYS$SETAST is used to avoid a timing error. */
1591
1592end_kbd_input ()
1593{
1594#ifdef ASTDEBUG
1595 printf ("At end_kbd_input.\n");
1596 fflush (stdout);
1597 sleep (1);
1598#endif
1599 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
1600 {
91bac16a 1601 SYS$CANCEL (input_fd);
86a5659e
JB
1602 return;
1603 }
1604
1605 SYS$SETAST (0);
1606 /* Clear a flag, and tell ast routine above to set it. */
1607 SYS$CLREF (input_ef);
1608 waiting_for_ast = 1;
1609 stop_input = 1;
91bac16a 1610 SYS$CANCEL (input_fd);
86a5659e
JB
1611 SYS$SETAST (1);
1612 SYS$WAITFR (input_ef);
1613 waiting_for_ast = 0;
1614}
1615
1616/* Wait for either input available or time interval expiry. */
1617
1618input_wait_timeout (timeval)
1619 int timeval; /* Time to wait, in seconds */
1620{
1621 int time [2];
1622 static int zero = 0;
1623 static int large = -10000000;
1624
1625 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1626
1627 /* If already something, avoid doing system calls. */
1628 if (detect_input_pending ())
1629 {
1630 return;
1631 }
1632 /* Clear a flag, and tell ast routine above to set it. */
1633 SYS$CLREF (input_ef);
1634 waiting_for_ast = 1;
1635 /* Check for timing error: ast happened while we were doing that. */
1636 if (!detect_input_pending ())
1637 {
1638 /* No timing error: wait for flag to be set. */
1639 SYS$CANTIM (1, 0);
1640 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1641 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
1642 }
1643 waiting_for_ast = 0;
1644}
1645
1646/* The standard `sleep' routine works some other way
1647 and it stops working if you have ever quit out of it.
1648 This one continues to work. */
1649
1650sys_sleep (timeval)
1651 int timeval;
1652{
1653 int time [2];
1654 static int zero = 0;
1655 static int large = -10000000;
1656
1657 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1658
1659 SYS$CANTIM (1, 0);
1660 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1661 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
1662}
1663
1664init_sigio ()
1665{
1666 request_sigio ();
1667}
1668
1669reset_sigio ()
1670{
1671 unrequest_sigio ();
1672}
1673
1674request_sigio ()
1675{
1676 croak ("request sigio");
1677}
1678
1679unrequest_sigio ()
1680{
1681 croak ("unrequest sigio");
1682}
1683
1684#endif /* VMS */
1685\f
1686/* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1687#ifndef CANNOT_DUMP
1688#define NEED_STARTS
1689#endif
1690
1691#ifndef SYSTEM_MALLOC
1692#ifndef NEED_STARTS
1693#define NEED_STARTS
1694#endif
1695#endif
1696
1697#ifdef NEED_STARTS
1698/* Some systems that cannot dump also cannot implement these. */
1699
1700/*
1701 * Return the address of the start of the text segment prior to
1702 * doing an unexec. After unexec the return value is undefined.
1703 * See crt0.c for further explanation and _start.
1704 *
1705 */
1706
1707#ifndef CANNOT_UNEXEC
1708char *
1709start_of_text ()
1710{
1711#ifdef TEXT_START
1712 return ((char *) TEXT_START);
1713#else
1714#ifdef GOULD
1715 extern csrt ();
1716 return ((char *) csrt);
1717#else /* not GOULD */
1718 extern int _start ();
1719 return ((char *) _start);
1720#endif /* GOULD */
1721#endif /* TEXT_START */
1722}
1723#endif /* not CANNOT_UNEXEC */
1724
1725/*
1726 * Return the address of the start of the data segment prior to
1727 * doing an unexec. After unexec the return value is undefined.
1728 * See crt0.c for further information and definition of data_start.
1729 *
1730 * Apparently, on BSD systems this is etext at startup. On
1731 * USG systems (swapping) this is highly mmu dependent and
1732 * is also dependent on whether or not the program is running
1733 * with shared text. Generally there is a (possibly large)
1734 * gap between end of text and start of data with shared text.
1735 *
1736 * On Uniplus+ systems with shared text, data starts at a
1737 * fixed address. Each port (from a given oem) is generally
1738 * different, and the specific value of the start of data can
1739 * be obtained via the UniPlus+ specific "uvar" system call,
1740 * however the method outlined in crt0.c seems to be more portable.
1741 *
1742 * Probably what will have to happen when a USG unexec is available,
1743 * at least on UniPlus, is temacs will have to be made unshared so
1744 * that text and data are contiguous. Then once loadup is complete,
1745 * unexec will produce a shared executable where the data can be
1746 * at the normal shared text boundry and the startofdata variable
1747 * will be patched by unexec to the correct value.
1748 *
1749 */
1750
1751char *
1752start_of_data ()
1753{
1754#ifdef DATA_START
1755 return ((char *) DATA_START);
6c65530f
JB
1756#else
1757#ifdef ORDINARY_LINK
1758 /*
1759 * This is a hack. Since we're not linking crt0.c or pre_crt0.c,
1760 * data_start isn't defined. We take the address of environ, which
1761 * is known to live at or near the start of the system crt0.c, and
1762 * we don't sweat the handful of bytes that might lose.
1763 */
1764 extern char **environ;
1765
1766 return((char *) &environ);
86a5659e
JB
1767#else
1768 extern int data_start;
1769 return ((char *) &data_start);
6c65530f
JB
1770#endif /* ORDINARY_LINK */
1771#endif /* DATA_START */
86a5659e
JB
1772}
1773#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1774
1775#ifndef CANNOT_DUMP
1776/* Some systems that cannot dump also cannot implement these. */
1777
1778/*
1779 * Return the address of the end of the text segment prior to
1780 * doing an unexec. After unexec the return value is undefined.
1781 */
1782
1783char *
1784end_of_text ()
1785{
1786#ifdef TEXT_END
1787 return ((char *) TEXT_END);
1788#else
1789 extern int etext;
1790 return ((char *) &etext);
1791#endif
1792}
1793
1794/*
1795 * Return the address of the end of the data segment prior to
1796 * doing an unexec. After unexec the return value is undefined.
1797 */
1798
1799char *
1800end_of_data ()
1801{
1802#ifdef DATA_END
1803 return ((char *) DATA_END);
1804#else
1805 extern int edata;
1806 return ((char *) &edata);
1807#endif
1808}
1809
1810#endif /* not CANNOT_DUMP */
1811\f
1812/* Get_system_name returns as its value
1813 a string for the Lisp function system-name to return. */
1814
1815#ifdef BSD4_1
1816#include <whoami.h>
1817#endif
1818
e36ba278
RS
1819/* Can't have this within the function since `static' is #defined to
1820 nothing for some USG systems. */
86a5659e 1821#ifdef USG
e36ba278
RS
1822#ifdef HAVE_GETHOSTNAME
1823static char get_system_name_name[256];
1824#else /* not HAVE_GETHOSTNAME */
86a5659e 1825static struct utsname get_system_name_name;
e36ba278
RS
1826#endif /* not HAVE_GETHOSTNAME */
1827#endif /* USG */
86a5659e 1828
f8a80313
RS
1829#ifndef BSD4_1
1830#ifndef USG
1831#ifndef VMS
1832#ifdef HAVE_SOCKETS
1833#include <sys/socket.h>
1834#include <netdb.h>
1835#endif /* HAVE_SOCKETS */
1836#endif /* not VMS */
1837#endif /* not USG */
1838#endif /* not BSD4_1 */
1839
86a5659e
JB
1840char *
1841get_system_name ()
1842{
1843#ifdef USG
e36ba278
RS
1844#ifdef HAVE_GETHOSTNAME
1845 gethostname (get_system_name_name, sizeof (get_system_name_name));
1846 return get_system_name_name;
1847#else /* not HAVE_GETHOSTNAME */
86a5659e
JB
1848 uname (&get_system_name_name);
1849 return (get_system_name_name.nodename);
e36ba278 1850#endif /* not HAVE_GETHOSTNAME */
86a5659e
JB
1851#else /* Not USG */
1852#ifdef BSD4_1
1853 return sysname;
1854#else /* not USG, not 4.1 */
1855 static char system_name_saved[32];
1856#ifdef VMS
1857 char *sp;
1858 if ((sp = egetenv ("SYS$NODE")) == 0)
1859 sp = "vax-vms";
1860 else
1861 {
1862 char *end;
1863
1864 if ((end = index (sp, ':')) != 0)
1865 *end = '\0';
1866 }
1867 strcpy (system_name_saved, sp);
1868#else /* not VMS */
1869 gethostname (system_name_saved, sizeof (system_name_saved));
f8a80313
RS
1870#ifdef HAVE_SOCKETS
1871 /* Turn the hostname into the official, fully-qualified hostname.
1872 Don't do this if we're going to dump; this can confuse system
1873 libraries on some machines and make the dumped emacs core dump. */
1874#ifndef CANNOT_DUMP
1875 if (initialized)
1876#endif /* not CANNOT_DUMP */
1877 {
1878 struct hostent *hp;
1879 hp = gethostbyname (system_name_saved);
1880 if (hp && strlen (hp->h_name) < sizeof(system_name_saved))
1881 strcpy (system_name_saved, hp->h_name);
1882 }
1883#endif /* HAVE_SOCKETS */
86a5659e
JB
1884#endif /* not VMS */
1885 return system_name_saved;
1886#endif /* not USG, not 4.1 */
1887#endif /* not USG */
1888}
210b2b4f
JB
1889
1890#ifdef VMS
1891#ifndef HAVE_GETHOSTNAME
1892void gethostname(buf, len)
1893 char *buf;
1894 int len;
1895{
1896 char *s;
1897 s = getenv ("SYS$NODE");
1898 if (s == NULL)
1899 buf[0] = '\0';
1900 else {
1901 strncpy (buf, s, len - 2);
1902 buf[len - 1] = '\0';
1903 } /* else */
1904} /* static void gethostname */
1905#endif /* ! HAVE_GETHOSTNAME */
1906#endif /* VMS */
1907
86a5659e
JB
1908\f
1909#ifndef VMS
1910#ifndef HAVE_SELECT
1911
1912#ifdef HAVE_X_WINDOWS
1913/* Cause explanatory error message at compile time,
1914 since the select emulation is not good enough for X. */
1915int *x = &x_windows_lose_if_no_select_system_call;
1916#endif
1917
1918/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1919 * Only checks read descriptors.
1920 */
1921/* How long to wait between checking fds in select */
1922#define SELECT_PAUSE 1
1923int select_alarmed;
1924
1925/* For longjmp'ing back to read_input_waiting. */
1926
1927jmp_buf read_alarm_throw;
1928
1929/* Nonzero if the alarm signal should throw back to read_input_waiting.
1930 The read_socket_hook function sets this to 1 while it is waiting. */
1931
1932int read_alarm_should_throw;
1933
1934SIGTYPE
1935select_alarm ()
1936{
1937 select_alarmed = 1;
1938#ifdef BSD4_1
1939 sigrelse (SIGALRM);
1940#else /* not BSD4_1 */
1941 signal (SIGALRM, SIG_IGN);
1942#endif /* not BSD4_1 */
1943 if (read_alarm_should_throw)
1944 longjmp (read_alarm_throw, 1);
1945}
1946
1947/* Only rfds are checked. */
1948int
1949select (nfds, rfds, wfds, efds, timeout)
1950 int nfds;
1951 int *rfds, *wfds, *efds, *timeout;
1952{
1953 int ravail = 0, orfds = 0, old_alarm;
1954 int timeoutval = timeout ? *timeout : 100000;
1955 int *local_timeout = &timeoutval;
1956 extern int proc_buffered_char[];
1957#ifndef subprocesses
1958 int process_tick = 0, update_tick = 0;
1959#else
1960 extern int process_tick, update_tick;
1961#endif
1962 SIGTYPE (*old_trap) ();
1963 unsigned char buf;
1964
1965 if (rfds)
1966 {
1967 orfds = *rfds;
1968 *rfds = 0;
1969 }
1970 if (wfds)
1971 *wfds = 0;
1972 if (efds)
1973 *efds = 0;
1974
1975 /* If we are looking only for the terminal, with no timeout,
1976 just read it and wait -- that's more efficient. */
1977 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
1978 {
1979 if (! detect_input_pending ())
1980 read_input_waiting ();
1981 *rfds = 1;
1982 return 1;
1983 }
1984
1985 /* Once a second, till the timer expires, check all the flagged read
1986 * descriptors to see if any input is available. If there is some then
1987 * set the corresponding bit in the return copy of rfds.
1988 */
1989 while (1)
1990 {
1991 register int to_check, bit, fd;
1992
1993 if (rfds)
1994 {
1995 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
1996 {
1997 if (orfds & bit)
1998 {
1999 int avail = 0, status = 0;
2000
2001 if (bit == 1)
2002 avail = detect_input_pending (); /* Special keyboard handler */
2003 else
2004 {
2005#ifdef FIONREAD
2006 status = ioctl (fd, FIONREAD, &avail);
2007#else /* no FIONREAD */
2008 /* Hoping it will return -1 if nothing available
2009 or 0 if all 0 chars requested are read. */
2010 if (proc_buffered_char[fd] >= 0)
2011 avail = 1;
2012 else
2013 {
2014 avail = read (fd, &buf, 1);
2015 if (avail > 0)
2016 proc_buffered_char[fd] = buf;
2017 }
2018#endif /* no FIONREAD */
2019 }
2020 if (status >= 0 && avail > 0)
2021 {
2022 (*rfds) |= bit;
2023 ravail++;
2024 }
2025 }
2026 }
2027 }
2028 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
2029 break;
2030 old_alarm = alarm (0);
34567704 2031 old_trap = signal (SIGALRM, select_alarm);
86a5659e
JB
2032 select_alarmed = 0;
2033 alarm (SELECT_PAUSE);
2034 /* Wait for a SIGALRM (or maybe a SIGTINT) */
2035 while (select_alarmed == 0 && *local_timeout != 0
2036 && process_tick == update_tick)
2037 {
2038 /* If we are interested in terminal input,
2039 wait by reading the terminal.
2040 That makes instant wakeup for terminal input at least. */
2041 if (orfds & 1)
2042 {
2043 read_input_waiting ();
2044 if (detect_input_pending ())
2045 select_alarmed = 1;
2046 }
2047 else
2048 pause ();
2049 }
2050 (*local_timeout) -= SELECT_PAUSE;
2051 /* Reset the old alarm if there was one */
2052 alarm (0);
2053 signal (SIGALRM, old_trap);
2054 if (old_alarm != 0)
2055 {
2056 /* Reset or forge an interrupt for the original handler. */
2057 old_alarm -= SELECT_PAUSE;
2058 if (old_alarm <= 0)
2059 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
2060 else
2061 alarm (old_alarm);
2062 }
2063 if (*local_timeout == 0) /* Stop on timer being cleared */
2064 break;
2065 }
2066 return ravail;
2067}
2068
2069/* Read keyboard input into the standard buffer,
2070 waiting for at least one character. */
2071
2072/* Make all keyboard buffers much bigger when using X windows. */
2073#ifdef HAVE_X_WINDOWS
2074#define BUFFER_SIZE_FACTOR 16
2075#else
2076#define BUFFER_SIZE_FACTOR 1
2077#endif
2078
2079read_input_waiting ()
2080{
2081 char buf[256 * BUFFER_SIZE_FACTOR];
2082 struct input_event e;
34567704
JB
2083 int nread, i;
2084 extern int quit_char;
86a5659e
JB
2085
2086 if (read_socket_hook)
2087 {
2088 read_alarm_should_throw = 0;
2089 if (! setjmp (read_alarm_throw))
2090 nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
2091 else
2092 nread = -1;
2093 }
2094 else
2095 nread = read (fileno (stdin), buf, 1);
2096
2097 /* Scan the chars for C-g and store them in kbd_buffer. */
2098 e.kind = ascii_keystroke;
6c65530f 2099 e.frame_or_window = selected_frame;
57ef1664 2100 e.modifiers = 0;
86a5659e
JB
2101 for (i = 0; i < nread; i++)
2102 {
2103 XSET (e.code, Lisp_Int, buf[i]);
2104 kbd_buffer_store_event (&e);
2105 /* Don't look at input that follows a C-g too closely.
2106 This reduces lossage due to autorepeat on C-g. */
34567704 2107 if (buf[i] == quit_char)
86a5659e
JB
2108 break;
2109 }
2110}
2111
2112#endif /* not HAVE_SELECT */
2113#endif /* not VMS */
2114\f
2115#ifdef BSD4_1
86a5659e
JB
2116/*
2117 * Partially emulate 4.2 open call.
2118 * open is defined as this in 4.1.
2119 *
2120 * - added by Michael Bloom @ Citicorp/TTI
2121 *
2122 */
2123
2124int
2125sys_open (path, oflag, mode)
2126 char *path;
2127 int oflag, mode;
2128{
2129 if (oflag & O_CREAT)
2130 return creat (path, mode);
2131 else
2132 return open (path, oflag);
2133}
2134
2135init_sigio ()
2136{
2137 if (noninteractive)
2138 return;
2139 lmode = LINTRUP | lmode;
2140 ioctl (0, TIOCLSET, &lmode);
2141}
2142
2143reset_sigio ()
2144{
2145 if (noninteractive)
2146 return;
2147 lmode = ~LINTRUP & lmode;
2148 ioctl (0, TIOCLSET, &lmode);
2149}
2150
2151request_sigio ()
2152{
2153 sigrelse (SIGTINT);
2154
2155 interrupts_deferred = 0;
2156}
2157
2158unrequest_sigio ()
2159{
2160 sighold (SIGTINT);
2161
2162 interrupts_deferred = 1;
2163}
2164
2165/* still inside #ifdef BSD4_1 */
2166#ifdef subprocesses
2167
2168int sigheld; /* Mask of held signals */
2169
2170sigholdx (signum)
2171 int signum;
2172{
2173 sigheld |= sigbit (signum);
2174 sighold (signum);
2175}
2176
2177sigisheld (signum)
2178 int signum;
2179{
2180 sigheld |= sigbit (signum);
2181}
2182
2183sigunhold (signum)
2184 int signum;
2185{
2186 sigheld &= ~sigbit (signum);
2187 sigrelse (signum);
2188}
2189
2190sigfree () /* Free all held signals */
2191{
2192 int i;
2193 for (i = 0; i < NSIG; i++)
2194 if (sigheld & sigbit (i))
2195 sigrelse (i);
2196 sigheld = 0;
2197}
2198
2199sigbit (i)
2200{
2201 return 1 << (i - 1);
2202}
2203#endif /* subprocesses */
2204#endif /* BSD4_1 */
2205\f
2206/* POSIX signals support - DJB */
2207/* Anyone with POSIX signals should have ANSI C declarations */
2208
2209#ifdef POSIX_SIGNALS
2210
2211sigset_t old_mask, empty_mask, full_mask, temp_mask;
2212static struct sigaction new_action, old_action;
2213
2214init_signals ()
2215{
00eaaa32
JB
2216 sigemptyset (&empty_mask);
2217 sigfillset (&full_mask);
86a5659e
JB
2218}
2219
86a5659e
JB
2220signal_handler_t
2221sys_signal (int signal_number, signal_handler_t action)
2222{
2223#ifdef DGUX
2224 /* This gets us restartable system calls for efficiency.
2225 The "else" code will works as well. */
2226 return (berk_signal (signal_number, action));
2227#else
2228 sigemptyset (&new_action.sa_mask);
2229 new_action.sa_handler = action;
4a785b6e 2230 new_action.sa_flags = 0;
d32b2f3c 2231 sigaction (signal_number, &new_action, &old_action);
86a5659e
JB
2232 return (old_action.sa_handler);
2233#endif /* DGUX */
2234}
2235
e065a56e
JB
2236#ifndef __GNUC__
2237/* If we're compiling with GCC, we don't need this function, since it
2238 can be written as a macro. */
2239sigset_t
2240sys_sigmask (int sig)
2241{
2242 sigset_t mask;
2243 sigemptyset (&mask);
2244 sigaddset (&mask, sig);
2245 return mask;
2246}
2247#endif
2248
86a5659e
JB
2249int
2250sys_sigpause (sigset_t new_mask)
2251{
2252 /* pause emulating berk sigpause... */
2253 sigsuspend (&new_mask);
2254 return (EINTR);
2255}
2256
2257/* I'd like to have these guys return pointers to the mask storage in here,
2258 but there'd be trouble if the code was saving multiple masks. I'll be
2259 safe and pass the structure. It normally won't be more than 2 bytes
2260 anyhow. - DJB */
2261
2262sigset_t
2263sys_sigblock (sigset_t new_mask)
2264{
2265 sigset_t old_mask;
2266 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2267 return (old_mask);
2268}
2269
2270sigset_t
2271sys_sigunblock (sigset_t new_mask)
2272{
2273 sigset_t old_mask;
2274 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2275 return (old_mask);
2276}
2277
2278sigset_t
2279sys_sigsetmask (sigset_t new_mask)
2280{
2281 sigset_t old_mask;
2282 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2283 return (old_mask);
2284}
2285
2286#endif /* POSIX_SIGNALS */
2287\f
2288#ifndef BSTRING
2289
2290void
2291bzero (b, length)
2292 register char *b;
2293 register int length;
2294{
2295#ifdef VMS
2296 short zero = 0;
2297 long max_str = 65535;
2298
2299 while (length > max_str) {
2300 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2301 length -= max_str;
2302 b += max_str;
2303 }
2304 max_str = length;
2305 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
2306#else
2307 while (length-- > 0)
2308 *b++ = 0;
2309#endif /* not VMS */
2310}
2311
2312/* Saying `void' requires a declaration, above, where bcopy is used
2313 and that declaration causes pain for systems where bcopy is a macro. */
2314bcopy (b1, b2, length)
2315 register char *b1;
2316 register char *b2;
2317 register int length;
2318{
2319#ifdef VMS
2320 long max_str = 65535;
2321
2322 while (length > max_str) {
2323 (void) LIB$MOVC3 (&max_str, b1, b2);
2324 length -= max_str;
2325 b1 += max_str;
2326 b2 += max_str;
2327 }
2328 max_str = length;
2329 (void) LIB$MOVC3 (&length, b1, b2);
2330#else
2331 while (length-- > 0)
2332 *b2++ = *b1++;
2333#endif /* not VMS */
2334}
2335
2336int
2337bcmp (b1, b2, length) /* This could be a macro! */
2338 register char *b1;
2339 register char *b2;
2340 register int length;
2341{
2342#ifdef VMS
2343 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
2344 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
2345
2346 return STR$COMPARE (&src1, &src2);
2347#else
2348 while (length-- > 0)
2349 if (*b1++ != *b2++)
2350 return 1;
2351
2352 return 0;
2353#endif /* not VMS */
2354}
2355#endif /* not BSTRING */
2356\f
9927a7b1 2357#ifndef HAVE_RANDOM
86a5659e
JB
2358#ifdef USG
2359/*
2360 * The BSD random returns numbers in the range of
2361 * 0 to 2e31 - 1. The USG rand returns numbers in the
2362 * range of 0 to 2e15 - 1. This is probably not significant
2363 * in this usage.
2364 */
2365
2366long
2367random ()
2368{
2369 /* Arrange to return a range centered on zero. */
2370 return (rand () << 15) + rand () - (1 << 29);
2371}
2372
2373srandom (arg)
2374 int arg;
2375{
2376 srand (arg);
2377}
2378
2379#endif /* USG */
2380
2381#ifdef BSD4_1
2382long random ()
2383{
2384 /* Arrange to return a range centered on zero. */
2385 return (rand () << 15) + rand () - (1 << 29);
2386}
2387
2388srandom (arg)
2389 int arg;
2390{
2391 srand (arg);
2392}
2393#endif /* BSD4_1 */
9927a7b1 2394#endif
86a5659e
JB
2395\f
2396#ifdef WRONG_NAME_INSQUE
2397
2398insque (q,p)
2399 caddr_t q,p;
2400{
2401 _insque (q,p);
2402}
2403
2404#endif
2405\f
2406#ifdef VMS
2407
2408#ifdef getenv
2409/* If any place else asks for the TERM variable,
2410 allow it to be overridden with the EMACS_TERM variable
2411 before attempting to translate the logical name TERM. As a last
2412 resort, ask for VAX C's special idea of the TERM variable. */
2413#undef getenv
2414char *
2415sys_getenv (name)
2416 char *name;
2417{
2418 register char *val;
2419 static char buf[256];
2420 static struct dsc$descriptor_s equiv
2421 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2422 static struct dsc$descriptor_s d_name
2423 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2424 short eqlen;
2425
2426 if (!strcmp (name, "TERM"))
2427 {
2428 val = (char *) getenv ("EMACS_TERM");
2429 if (val)
2430 return val;
2431 }
2432
2433 d_name.dsc$w_length = strlen (name);
2434 d_name.dsc$a_pointer = name;
986ffb24 2435 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
86a5659e
JB
2436 {
2437 char *str = (char *) xmalloc (eqlen + 1);
2438 bcopy (buf, str, eqlen);
2439 str[eqlen] = '\0';
2440 /* This is a storage leak, but a pain to fix. With luck,
2441 no one will ever notice. */
2442 return str;
2443 }
2444 return (char *) getenv (name);
2445}
2446#endif /* getenv */
2447
2448#ifdef abort
2449/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2450 to force a call on the debugger from within the image. */
2451#undef abort
2452sys_abort ()
2453{
2454 reset_sys_modes ();
2455 LIB$SIGNAL (SS$_DEBUG);
2456}
2457#endif /* abort */
2458#endif /* VMS */
2459\f
2460#ifdef VMS
2461#ifdef LINK_CRTL_SHARE
2462#ifdef SHAREABLE_LIB_BUG
eb8c3be9 2463/* Variables declared noshare and initialized in sharable libraries
86a5659e
JB
2464 cannot be shared. The VMS linker incorrectly forces you to use a private
2465 version which is uninitialized... If not for this "feature", we
2466 could use the C library definition of sys_nerr and sys_errlist. */
2467int sys_nerr = 35;
2468char *sys_errlist[] =
2469 {
2470 "error 0",
2471 "not owner",
2472 "no such file or directory",
2473 "no such process",
2474 "interrupted system call",
2475 "i/o error",
2476 "no such device or address",
2477 "argument list too long",
2478 "exec format error",
2479 "bad file number",
2480 "no child process",
2481 "no more processes",
2482 "not enough memory",
2483 "permission denied",
2484 "bad address",
2485 "block device required",
2486 "mount devices busy",
2487 "file exists",
2488 "cross-device link",
2489 "no such device",
2490 "not a directory",
2491 "is a directory",
2492 "invalid argument",
2493 "file table overflow",
2494 "too many open files",
2495 "not a typewriter",
2496 "text file busy",
2497 "file too big",
2498 "no space left on device",
2499 "illegal seek",
2500 "read-only file system",
2501 "too many links",
2502 "broken pipe",
2503 "math argument",
2504 "result too large",
2505 "I/O stream empty",
2506 "vax/vms specific error code nontranslatable error"
2507 };
2508#endif /* SHAREABLE_LIB_BUG */
2509#endif /* LINK_CRTL_SHARE */
2510#endif /* VMS */
2511\f
2512#ifdef INTERRUPTIBLE_OPEN
2513
2514int
2515/* VARARGS 2 */
2516sys_open (path, oflag, mode)
2517 char *path;
2518 int oflag, mode;
2519{
2520 register int rtnval;
2521
2522 while ((rtnval = open (path, oflag, mode)) == -1
2523 && (errno == EINTR));
2524 return (rtnval);
2525}
2526
2527#endif /* INTERRUPTIBLE_OPEN */
2528
2529#ifdef INTERRUPTIBLE_CLOSE
2530
2531sys_close (fd)
2532 int fd;
2533{
2534 register int rtnval;
2535
2536 while ((rtnval = close (fd)) == -1
2537 && (errno == EINTR));
2538 return rtnval;
2539}
2540
2541#endif /* INTERRUPTIBLE_CLOSE */
2542
2543#ifdef INTERRUPTIBLE_IO
2544
2545int
2546sys_read (fildes, buf, nbyte)
2547 int fildes;
2548 char *buf;
2549 unsigned int nbyte;
2550{
2551 register int rtnval;
2552
2553 while ((rtnval = read (fildes, buf, nbyte)) == -1
2554 && (errno == EINTR));
2555 return (rtnval);
2556}
2557
2558int
2559sys_write (fildes, buf, nbyte)
2560 int fildes;
2561 char *buf;
2562 unsigned int nbyte;
2563{
2564 register int rtnval;
2565
2566 while ((rtnval = write (fildes, buf, nbyte)) == -1
2567 && (errno == EINTR));
2568 return (rtnval);
2569}
2570
2571#endif /* INTERRUPTIBLE_IO */
2572\f
2573#ifdef USG
2574/*
2575 * All of the following are for USG.
2576 *
2577 * On USG systems the system calls are INTERRUPTIBLE by signals
2578 * that the user program has elected to catch. Thus the system call
2579 * must be retried in these cases. To handle this without massive
2580 * changes in the source code, we remap the standard system call names
2581 * to names for our own functions in sysdep.c that do the system call
2582 * with retries. Actually, for portability reasons, it is good
2583 * programming practice, as this example shows, to limit all actual
eb8c3be9 2584 * system calls to a single occurrence in the source. Sure, this
86a5659e
JB
2585 * adds an extra level of function call overhead but it is almost
2586 * always negligible. Fred Fish, Unisoft Systems Inc.
2587 */
2588
00eaaa32 2589#ifndef HAVE_SYS_SIGLIST
86a5659e
JB
2590char *sys_siglist[NSIG + 1] =
2591{
2592#ifdef AIX
2593/* AIX has changed the signals a bit */
2594 "bogus signal", /* 0 */
2595 "hangup", /* 1 SIGHUP */
2596 "interrupt", /* 2 SIGINT */
2597 "quit", /* 3 SIGQUIT */
2598 "illegal instruction", /* 4 SIGILL */
2599 "trace trap", /* 5 SIGTRAP */
2600 "IOT instruction", /* 6 SIGIOT */
2601 "crash likely", /* 7 SIGDANGER */
2602 "floating point exception", /* 8 SIGFPE */
2603 "kill", /* 9 SIGKILL */
2604 "bus error", /* 10 SIGBUS */
2605 "segmentation violation", /* 11 SIGSEGV */
2606 "bad argument to system call", /* 12 SIGSYS */
2607 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2608 "alarm clock", /* 14 SIGALRM */
2609 "software termination signum", /* 15 SIGTERM */
2610 "user defined signal 1", /* 16 SIGUSR1 */
2611 "user defined signal 2", /* 17 SIGUSR2 */
2612 "death of a child", /* 18 SIGCLD */
2613 "power-fail restart", /* 19 SIGPWR */
2614 "bogus signal", /* 20 */
2615 "bogus signal", /* 21 */
2616 "bogus signal", /* 22 */
2617 "bogus signal", /* 23 */
2618 "bogus signal", /* 24 */
2619 "LAN I/O interrupt", /* 25 SIGAIO */
2620 "PTY I/O interrupt", /* 26 SIGPTY */
2621 "I/O intervention required", /* 27 SIGIOINT */
2622 "HFT grant", /* 28 SIGGRANT */
2623 "HFT retract", /* 29 SIGRETRACT */
2624 "HFT sound done", /* 30 SIGSOUND */
2625 "HFT input ready", /* 31 SIGMSG */
2626#else /* not AIX */
2627 "bogus signal", /* 0 */
2628 "hangup", /* 1 SIGHUP */
2629 "interrupt", /* 2 SIGINT */
2630 "quit", /* 3 SIGQUIT */
2631 "illegal instruction", /* 4 SIGILL */
2632 "trace trap", /* 5 SIGTRAP */
2633 "IOT instruction", /* 6 SIGIOT */
2634 "EMT instruction", /* 7 SIGEMT */
2635 "floating point exception", /* 8 SIGFPE */
2636 "kill", /* 9 SIGKILL */
2637 "bus error", /* 10 SIGBUS */
2638 "segmentation violation", /* 11 SIGSEGV */
2639 "bad argument to system call", /* 12 SIGSYS */
2640 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2641 "alarm clock", /* 14 SIGALRM */
2642 "software termination signum", /* 15 SIGTERM */
2643 "user defined signal 1", /* 16 SIGUSR1 */
2644 "user defined signal 2", /* 17 SIGUSR2 */
2645 "death of a child", /* 18 SIGCLD */
2646 "power-fail restart", /* 19 SIGPWR */
2647#endif /* not AIX */
2648 0
2649 };
70080de1 2650#endif /* HAVE_SYS_SIGLIST */
86a5659e
JB
2651
2652/*
2653 * Warning, this function may not duplicate 4.2 action properly
2654 * under error conditions.
2655 */
2656
2657#ifndef MAXPATHLEN
2658/* In 4.1, param.h fails to define this. */
2659#define MAXPATHLEN 1024
2660#endif
2661
2662#ifndef HAVE_GETWD
2663
2664char *
2665getwd (pathname)
2666 char *pathname;
2667{
2668 char *npath, *spath;
2669 extern char *getcwd ();
2670
9ac0d9e0 2671 BLOCK_INPUT; /* getcwd uses malloc */
86a5659e
JB
2672 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2673 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2674 up to first slash. Should be harmless on other systems. */
2675 while (*npath && *npath != '/')
2676 npath++;
2677 strcpy (pathname, npath);
2678 free (spath); /* getcwd uses malloc */
9ac0d9e0 2679 UNBLOCK_INPUT;
86a5659e
JB
2680 return pathname;
2681}
2682
2683#endif /* HAVE_GETWD */
2684
2685/*
2686 * Emulate rename using unlink/link. Note that this is
2687 * only partially correct. Also, doesn't enforce restriction
2688 * that files be of same type (regular->regular, dir->dir, etc).
2689 */
2690
4746118a
JB
2691#ifndef HAVE_RENAME
2692
86a5659e
JB
2693rename (from, to)
2694 char *from;
2695 char *to;
2696{
2697 if (access (from, 0) == 0)
2698 {
2699 unlink (to);
2700 if (link (from, to) == 0)
2701 if (unlink (from) == 0)
2702 return (0);
2703 }
2704 return (-1);
2705}
2706
4746118a
JB
2707#endif
2708
86a5659e
JB
2709#ifndef HAVE_VFORK
2710
2711/*
2712 * Substitute fork for vfork on USG flavors.
2713 */
2714
2715vfork ()
2716{
2717 return (fork ());
2718}
2719
2720#endif /* not HAVE_VFORK */
2721
2722#ifdef MISSING_UTIMES
2723
2724/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2725
2726utimes ()
2727{
2728}
2729#endif
2730
2731#ifdef IRIS_UTIME
2732
2733/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2734 utimbuf structure defined anywhere but in the man page. */
2735
2736struct utimbuf
2737 {
2738 long actime;
2739 long modtime;
2740 };
2741
2742utimes (name, tvp)
2743 char *name;
2744 struct timeval tvp[];
2745{
2746 struct utimbuf utb;
2747 utb.actime = tvp[0].tv_sec;
2748 utb.modtime = tvp[1].tv_sec;
2749 utime (name, &utb);
2750}
2751#endif /* IRIS_UTIME */
2752
2753
2754#ifdef HPUX
2755#ifndef HAVE_PERROR
2756
2757/* HPUX curses library references perror, but as far as we know
2758 it won't be called. Anyway this definition will do for now. */
2759
2760perror ()
2761{
2762}
2763
2764#endif /* not HAVE_PERROR */
2765#endif /* HPUX */
2766
2767#ifndef HAVE_DUP2
2768
2769/*
2770 * Emulate BSD dup2. First close newd if it already exists.
2771 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2772 * until we are, then close the unsuccessful ones.
2773 */
2774
2775dup2 (oldd, newd)
2776 int oldd;
2777 int newd;
2778{
2779 register int fd, ret;
2780
2781 sys_close (newd);
2782
2783#ifdef F_DUPFD
2784 fd = fcntl (oldd, F_DUPFD, newd);
2785 if (fd != newd)
2786 error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
2787#else
2788 fd = dup (old);
2789 if (fd == -1)
2790 return -1;
2791 if (fd == new)
2792 return new;
2793 ret = dup2 (old,new);
2794 sys_close (fd);
2795 return ret;
2796#endif
2797}
2798
2799#endif /* not HAVE_DUP2 */
2800
2801/*
2802 * Gettimeofday. Simulate as much as possible. Only accurate
2803 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2804 * Only needed when subprocesses are defined.
2805 */
2806
2807#ifdef subprocesses
2808#ifndef VMS
2809#ifndef HAVE_GETTIMEOFDAY
2810#ifdef HAVE_TIMEVAL
2811
2812/* ARGSUSED */
2813gettimeofday (tp, tzp)
2814 struct timeval *tp;
2815 struct timezone *tzp;
2816{
2817 extern long time ();
2818
2819 tp->tv_sec = time ((long *)0);
2820 tp->tv_usec = 0;
4ca7594f
RS
2821 if (tzp != 0)
2822 tzp->tz_minuteswest = -1;
86a5659e
JB
2823}
2824
2825#endif
2826#endif
2827#endif
2828#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
2829
2830/*
2831 * This function will go away as soon as all the stubs fixed. (fnf)
2832 */
2833
2834croak (badfunc)
2835 char *badfunc;
2836{
2837 printf ("%s not yet implemented\r\n", badfunc);
2838 reset_sys_modes ();
2839 exit (1);
2840}
2841
2842#endif /* USG */
2843\f
2844#ifdef DGUX
2845
2846char *sys_siglist[NSIG + 1] =
2847{
2848 "null signal", /* 0 SIGNULL */
2849 "hangup", /* 1 SIGHUP */
2850 "interrupt", /* 2 SIGINT */
2851 "quit", /* 3 SIGQUIT */
2852 "illegal instruction", /* 4 SIGILL */
2853 "trace trap", /* 5 SIGTRAP */
2854 "abort termination", /* 6 SIGABRT */
2855 "SIGEMT", /* 7 SIGEMT */
2856 "floating point exception", /* 8 SIGFPE */
2857 "kill", /* 9 SIGKILL */
2858 "bus error", /* 10 SIGBUS */
2859 "segmentation violation", /* 11 SIGSEGV */
2860 "bad argument to system call", /* 12 SIGSYS */
2861 "write on a pipe with no reader", /* 13 SIGPIPE */
2862 "alarm clock", /* 14 SIGALRM */
2863 "software termination signal", /* 15 SIGTERM */
2864 "user defined signal 1", /* 16 SIGUSR1 */
2865 "user defined signal 2", /* 17 SIGUSR2 */
2866 "child stopped or terminated", /* 18 SIGCLD */
2867 "power-fail restart", /* 19 SIGPWR */
2868 "window size changed", /* 20 SIGWINCH */
2869 "undefined", /* 21 */
eb8c3be9 2870 "pollable event occurred", /* 22 SIGPOLL */
86a5659e
JB
2871 "sendable stop signal not from tty", /* 23 SIGSTOP */
2872 "stop signal from tty", /* 24 SIGSTP */
2873 "continue a stopped process", /* 25 SIGCONT */
2874 "attempted background tty read", /* 26 SIGTTIN */
2875 "attempted background tty write", /* 27 SIGTTOU */
2876 "undefined", /* 28 */
2877 "undefined", /* 29 */
2878 "undefined", /* 30 */
2879 "undefined", /* 31 */
2880 "undefined", /* 32 */
2881 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
2882 "I/O is possible", /* 34 SIGIO */
2883 "exceeded cpu time limit", /* 35 SIGXCPU */
2884 "exceeded file size limit", /* 36 SIGXFSZ */
2885 "virtual time alarm", /* 37 SIGVTALRM */
2886 "profiling time alarm", /* 38 SIGPROF */
2887 "undefined", /* 39 */
2888 "file record locks revoked", /* 40 SIGLOST */
2889 "undefined", /* 41 */
2890 "undefined", /* 42 */
2891 "undefined", /* 43 */
2892 "undefined", /* 44 */
2893 "undefined", /* 45 */
2894 "undefined", /* 46 */
2895 "undefined", /* 47 */
2896 "undefined", /* 48 */
2897 "undefined", /* 49 */
2898 "undefined", /* 50 */
2899 "undefined", /* 51 */
2900 "undefined", /* 52 */
2901 "undefined", /* 53 */
2902 "undefined", /* 54 */
2903 "undefined", /* 55 */
2904 "undefined", /* 56 */
2905 "undefined", /* 57 */
2906 "undefined", /* 58 */
2907 "undefined", /* 59 */
2908 "undefined", /* 60 */
2909 "undefined", /* 61 */
2910 "undefined", /* 62 */
2911 "undefined", /* 63 */
2912 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
2913 0
2914};
2915
2916#endif /* DGUX */
2917\f
2918/* Directory routines for systems that don't have them. */
2919
2920#ifdef SYSV_SYSTEM_DIR
2921
2922#include <dirent.h>
2923
2924#ifndef AIX
2925int
2926closedir (dirp)
2927 register DIR *dirp; /* stream from opendir */
2928{
2929 sys_close (dirp->dd_fd);
9ac0d9e0
JB
2930 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
2931 xfree ((char *) dirp);
86a5659e
JB
2932}
2933#endif /* not AIX */
2934#endif /* SYSV_SYSTEM_DIR */
2935
2936#ifdef NONSYSTEM_DIR_LIBRARY
2937
2938DIR *
2939opendir (filename)
2940 char *filename; /* name of directory */
2941{
2942 register DIR *dirp; /* -> malloc'ed storage */
2943 register int fd; /* file descriptor for read */
2944 struct stat sbuf; /* result of fstat */
2945
2946 fd = sys_open (filename, 0);
2947 if (fd < 0)
2948 return 0;
2949
9ac0d9e0 2950 BLOCK_INPUT;
86a5659e
JB
2951 if (fstat (fd, &sbuf) < 0
2952 || (sbuf.st_mode & S_IFMT) != S_IFDIR
2953 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2954 {
2955 sys_close (fd);
9ac0d9e0 2956 UNBLOCK_INPUT;
86a5659e
JB
2957 return 0; /* bad luck today */
2958 }
9ac0d9e0 2959 UNBLOCK_INPUT;
86a5659e
JB
2960
2961 dirp->dd_fd = fd;
2962 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2963
2964 return dirp;
2965}
2966
2967void
2968closedir (dirp)
2969 register DIR *dirp; /* stream from opendir */
2970{
2971 sys_close (dirp->dd_fd);
9ac0d9e0 2972 xfree ((char *) dirp);
86a5659e
JB
2973}
2974
2975
2976#ifndef VMS
2977#define DIRSIZ 14
2978struct olddir
2979 {
2980 ino_t od_ino; /* inode */
2981 char od_name[DIRSIZ]; /* filename */
2982 };
2983#endif /* not VMS */
2984
2985struct direct dir_static; /* simulated directory contents */
2986
2987/* ARGUSED */
2988struct direct *
2989readdir (dirp)
2990 register DIR *dirp; /* stream from opendir */
2991{
2992#ifndef VMS
2993 register struct olddir *dp; /* -> directory data */
2994#else /* VMS */
2995 register struct dir$_name *dp; /* -> directory data */
2996 register struct dir$_version *dv; /* -> version data */
2997#endif /* VMS */
2998
2999 for (; ;)
3000 {
3001 if (dirp->dd_loc >= dirp->dd_size)
3002 dirp->dd_loc = dirp->dd_size = 0;
3003
3004 if (dirp->dd_size == 0 /* refill buffer */
3005 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3006 return 0;
3007
3008#ifndef VMS
3009 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3010 dirp->dd_loc += sizeof (struct olddir);
3011
3012 if (dp->od_ino != 0) /* not deleted entry */
3013 {
3014 dir_static.d_ino = dp->od_ino;
3015 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3016 dir_static.d_name[DIRSIZ] = '\0';
3017 dir_static.d_namlen = strlen (dir_static.d_name);
3018 dir_static.d_reclen = sizeof (struct direct)
3019 - MAXNAMLEN + 3
3020 + dir_static.d_namlen - dir_static.d_namlen % 4;
3021 return &dir_static; /* -> simulated structure */
3022 }
3023#else /* VMS */
3024 dp = (struct dir$_name *) dirp->dd_buf;
3025 if (dirp->dd_loc == 0)
3026 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3027 : dp->dir$b_namecount;
3028 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3029 dir_static.d_ino = dv->dir$w_fid_num;
3030 dir_static.d_namlen = dp->dir$b_namecount;
3031 dir_static.d_reclen = sizeof (struct direct)
3032 - MAXNAMLEN + 3
3033 + dir_static.d_namlen - dir_static.d_namlen % 4;
3034 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3035 dir_static.d_name[dir_static.d_namlen] = '\0';
3036 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3037 return &dir_static;
3038#endif /* VMS */
3039 }
3040}
3041
3042#ifdef VMS
3043/* readdirver is just like readdir except it returns all versions of a file
3044 as separate entries. */
3045
3046/* ARGUSED */
3047struct direct *
3048readdirver (dirp)
3049 register DIR *dirp; /* stream from opendir */
3050{
3051 register struct dir$_name *dp; /* -> directory data */
3052 register struct dir$_version *dv; /* -> version data */
3053
3054 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3055 dirp->dd_loc = dirp->dd_size = 0;
3056
3057 if (dirp->dd_size == 0 /* refill buffer */
3058 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3059 return 0;
3060
3061 dp = (struct dir$_name *) dirp->dd_buf;
3062 if (dirp->dd_loc == 0)
3063 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3064 : dp->dir$b_namecount;
3065 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3066 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3067 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3068 dir_static.d_namlen = strlen (dir_static.d_name);
3069 dir_static.d_ino = dv->dir$w_fid_num;
3070 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3071 + dir_static.d_namlen - dir_static.d_namlen % 4;
3072 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3073 return &dir_static;
3074}
3075
3076#endif /* VMS */
3077
3078#endif /* NONSYSTEM_DIR_LIBRARY */
3079\f
3080/* Functions for VMS */
3081#ifdef VMS
91bac16a 3082#include "vms-pwd.h"
86a5659e
JB
3083#include <acldef.h>
3084#include <chpdef.h>
3085#include <jpidef.h>
3086
3087/* Return as a string the VMS error string pertaining to STATUS.
3088 Reuses the same static buffer each time it is called. */
3089
3090char *
3091vmserrstr (status)
3092 int status; /* VMS status code */
3093{
3094 int bufadr[2];
3095 short len;
3096 static char buf[257];
3097
3098 bufadr[0] = sizeof buf - 1;
3099 bufadr[1] = (int) buf;
3100 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3101 return "untranslatable VMS error status";
3102 buf[len] = '\0';
3103 return buf;
3104}
3105
3106#ifdef access
3107#undef access
3108
3109/* The following is necessary because 'access' emulation by VMS C (2.0) does
3110 * not work correctly. (It also doesn't work well in version 2.3.)
3111 */
3112
3113#ifdef VMS4_4
3114
3115#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3116 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3117
3118typedef union {
3119 struct {
3120 unsigned short s_buflen;
3121 unsigned short s_code;
3122 char *s_bufadr;
3123 unsigned short *s_retlenadr;
3124 } s;
3125 int end;
3126} item;
3127#define buflen s.s_buflen
3128#define code s.s_code
3129#define bufadr s.s_bufadr
3130#define retlenadr s.s_retlenadr
3131
3132#define R_OK 4 /* test for read permission */
3133#define W_OK 2 /* test for write permission */
3134#define X_OK 1 /* test for execute (search) permission */
3135#define F_OK 0 /* test for presence of file */
3136
3137int
3138sys_access (path, mode)
3139 char *path;
3140 int mode;
3141{
3142 static char *user = NULL;
3143 char dir_fn[512];
3144
3145 /* translate possible directory spec into .DIR file name, so brain-dead
3146 * access can treat the directory like a file. */
3147 if (directory_file_name (path, dir_fn))
3148 path = dir_fn;
3149
3150 if (mode == F_OK)
3151 return access (path, mode);
3152 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3153 return -1;
3154 {
3155 int stat;
3156 int flags;
3157 int acces;
3158 unsigned short int dummy;
3159 item itemlst[3];
3160 static int constant = ACL$C_FILE;
3161 DESCRIPTOR (path_desc, path);
3162 DESCRIPTOR (user_desc, user);
3163
3164 flags = 0;
3165 acces = 0;
3166 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3167 return stat;
3168 if (mode & R_OK)
3169 acces |= CHP$M_READ;
3170 if (mode & W_OK)
3171 acces |= CHP$M_WRITE;
3172 itemlst[0].buflen = sizeof (int);
3173 itemlst[0].code = CHP$_FLAGS;
3174 itemlst[0].bufadr = (char *) &flags;
3175 itemlst[0].retlenadr = &dummy;
3176 itemlst[1].buflen = sizeof (int);
3177 itemlst[1].code = CHP$_ACCESS;
3178 itemlst[1].bufadr = (char *) &acces;
3179 itemlst[1].retlenadr = &dummy;
3180 itemlst[2].end = CHP$_END;
3181 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3182 return stat == SS$_NORMAL ? 0 : -1;
3183 }
3184}
3185
3186#else /* not VMS4_4 */
3187
3188#include <prvdef.h>
3189#define ACE$M_WRITE 2
3190#define ACE$C_KEYID 1
3191
3192static unsigned short memid, grpid;
3193static unsigned int uic;
3194
3195/* Called from init_sys_modes, so it happens not very often
3196 but at least each time Emacs is loaded. */
3197sys_access_reinit ()
3198{
3199 uic = 0;
3200}
3201
3202int
3203sys_access (filename, type)
3204 char * filename;
3205 int type;
3206{
3207 struct FAB fab;
3208 struct XABPRO xab;
3209 int status, size, i, typecode, acl_controlled;
3210 unsigned int *aclptr, *aclend, aclbuf[60];
3211 union prvdef prvmask;
3212
3213 /* Get UIC and GRP values for protection checking. */
3214 if (uic == 0)
3215 {
3216 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3217 if (! (status & 1))
3218 return -1;
3219 memid = uic & 0xFFFF;
3220 grpid = uic >> 16;
3221 }
3222
3223 if (type != 2) /* not checking write access */
3224 return access (filename, type);
3225
3226 /* Check write protection. */
3227
3228#define CHECKPRIV(bit) (prvmask.bit)
3229#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3230
3231 /* Find privilege bits */
986ffb24 3232 status = SYS$SETPRV (0, 0, 0, prvmask);
86a5659e
JB
3233 if (! (status & 1))
3234 error ("Unable to find privileges: %s", vmserrstr (status));
3235 if (CHECKPRIV (PRV$V_BYPASS))
3236 return 0; /* BYPASS enabled */
3237 fab = cc$rms_fab;
3238 fab.fab$b_fac = FAB$M_GET;
3239 fab.fab$l_fna = filename;
3240 fab.fab$b_fns = strlen (filename);
3241 fab.fab$l_xab = &xab;
3242 xab = cc$rms_xabpro;
3243 xab.xab$l_aclbuf = aclbuf;
3244 xab.xab$w_aclsiz = sizeof (aclbuf);
986ffb24 3245 status = SYS$OPEN (&fab, 0, 0);
86a5659e
JB
3246 if (! (status & 1))
3247 return -1;
986ffb24 3248 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3249 /* Check system access */
3250 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
3251 return 0;
3252 /* Check ACL entries, if any */
3253 acl_controlled = 0;
3254 if (xab.xab$w_acllen > 0)
3255 {
3256 aclptr = aclbuf;
3257 aclend = &aclbuf[xab.xab$w_acllen / 4];
3258 while (*aclptr && aclptr < aclend)
3259 {
3260 size = (*aclptr & 0xff) / 4;
3261 typecode = (*aclptr >> 8) & 0xff;
3262 if (typecode == ACE$C_KEYID)
3263 for (i = size - 1; i > 1; i--)
3264 if (aclptr[i] == uic)
3265 {
3266 acl_controlled = 1;
3267 if (aclptr[1] & ACE$M_WRITE)
3268 return 0; /* Write access through ACL */
3269 }
3270 aclptr = &aclptr[size];
3271 }
3272 if (acl_controlled) /* ACL specified, prohibits write access */
3273 return -1;
3274 }
3275 /* No ACL entries specified, check normal protection */
3276 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
3277 return 0;
3278 if (WRITEABLE (XAB$V_GRP) &&
3279 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3280 return 0; /* Group writeable */
3281 if (WRITEABLE (XAB$V_OWN) &&
3282 (xab.xab$l_uic & 0xFFFF) == memid)
3283 return 0; /* Owner writeable */
3284
3285 return -1; /* Not writeable */
3286}
3287#endif /* not VMS4_4 */
3288#endif /* access */
3289
3290static char vtbuf[NAM$C_MAXRSS+1];
3291
3292/* translate a vms file spec to a unix path */
3293char *
3294sys_translate_vms (vfile)
3295 char * vfile;
3296{
3297 char * p;
3298 char * targ;
3299
3300 if (!vfile)
3301 return 0;
3302
3303 targ = vtbuf;
3304
3305 /* leading device or logical name is a root directory */
3306 if (p = strchr (vfile, ':'))
3307 {
3308 *targ++ = '/';
3309 while (vfile < p)
3310 *targ++ = *vfile++;
3311 vfile++;
3312 *targ++ = '/';
3313 }
3314 p = vfile;
3315 if (*p == '[' || *p == '<')
3316 {
3317 while (*++vfile != *p + 2)
3318 switch (*vfile)
3319 {
3320 case '.':
3321 if (vfile[-1] == *p)
3322 *targ++ = '.';
3323 *targ++ = '/';
3324 break;
3325
3326 case '-':
3327 *targ++ = '.';
3328 *targ++ = '.';
3329 break;
3330
3331 default:
3332 *targ++ = *vfile;
3333 break;
3334 }
3335 vfile++;
3336 *targ++ = '/';
3337 }
3338 while (*vfile)
3339 *targ++ = *vfile++;
3340
3341 return vtbuf;
3342}
3343
3344static char utbuf[NAM$C_MAXRSS+1];
3345
3346/* translate a unix path to a VMS file spec */
3347char *
3348sys_translate_unix (ufile)
3349 char * ufile;
3350{
3351 int slash_seen = 0;
3352 char *p;
3353 char * targ;
3354
3355 if (!ufile)
3356 return 0;
3357
3358 targ = utbuf;
3359
3360 if (*ufile == '/')
3361 {
3362 ufile++;
3363 }
3364
3365 while (*ufile)
3366 {
3367 switch (*ufile)
3368 {
3369 case '/':
3370 if (slash_seen)
3371 if (index (&ufile[1], '/'))
3372 *targ++ = '.';
3373 else
3374 *targ++ = ']';
3375 else
3376 {
3377 *targ++ = ':';
3378 if (index (&ufile[1], '/'))
3379 *targ++ = '[';
3380 slash_seen = 1;
3381 }
3382 break;
3383
3384 case '.':
3385 if (strncmp (ufile, "./", 2) == 0)
3386 {
3387 if (!slash_seen)
3388 {
3389 *targ++ = '[';
3390 slash_seen = 1;
3391 }
3392 ufile++; /* skip the dot */
3393 if (index (&ufile[1], '/'))
3394 *targ++ = '.';
3395 else
3396 *targ++ = ']';
3397 }
3398 else if (strncmp (ufile, "../", 3) == 0)
3399 {
3400 if (!slash_seen)
3401 {
3402 *targ++ = '[';
3403 slash_seen = 1;
3404 }
3405 *targ++ = '-';
3406 ufile += 2; /* skip the dots */
3407 if (index (&ufile[1], '/'))
3408 *targ++ = '.';
3409 else
3410 *targ++ = ']';
3411 }
3412 else
3413 *targ++ = *ufile;
3414 break;
3415
3416 default:
3417 *targ++ = *ufile;
3418 break;
3419 }
3420 ufile++;
3421 }
3422 *targ = '\0';
3423
3424 return utbuf;
3425}
3426
3427char *
3428getwd (pathname)
3429 char *pathname;
3430{
3431 char *ptr;
210b2b4f 3432 extern char *getcwd ();
86a5659e 3433
210b2b4f
JB
3434#define MAXPATHLEN 1024
3435
9ac0d9e0 3436 ptr = xmalloc (MAXPATHLEN);
210b2b4f
JB
3437 getcwd (ptr, MAXPATHLEN);
3438 strcpy (pathname, ptr);
9ac0d9e0 3439 xfree (ptr);
210b2b4f
JB
3440
3441 return pathname;
86a5659e
JB
3442}
3443
3444getppid ()
3445{
3446 long item_code = JPI$_OWNER;
3447 unsigned long parent_id;
3448 int status;
3449
3450 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3451 {
3452 errno = EVMSERR;
3453 vaxc$errno = status;
3454 return -1;
3455 }
3456 return parent_id;
3457}
3458
3459#undef getuid
3460unsigned
3461sys_getuid ()
3462{
3463 return (getgid () << 16) | getuid ();
3464}
3465
3466int
3467sys_read (fildes, buf, nbyte)
3468 int fildes;
3469 char *buf;
3470 unsigned int nbyte;
3471{
3472 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3473}
3474
3475#if 0
3476int
3477sys_write (fildes, buf, nbyte)
3478 int fildes;
3479 char *buf;
3480 unsigned int nbyte;
3481{
3482 register int nwrote, rtnval = 0;
3483
3484 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3485 nbyte -= nwrote;
3486 buf += nwrote;
3487 rtnval += nwrote;
3488 }
3489 if (nwrote < 0)
3490 return rtnval ? rtnval : -1;
3491 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3492 return rtnval ? rtnval : -1;
3493 return (rtnval + nwrote);
3494}
3495#endif /* 0 */
3496
3497/*
3498 * VAX/VMS VAX C RTL really loses. It insists that records
3499 * end with a newline (carriage return) character, and if they
3500 * don't it adds one (nice of it isn't it!)
3501 *
3502 * Thus we do this stupidity below.
3503 */
3504
3505int
3506sys_write (fildes, buf, nbytes)
3507 int fildes;
3508 char *buf;
3509 unsigned int nbytes;
3510{
3511 register char *p;
3512 register char *e;
23b0668c
JB
3513 int sum = 0;
3514 struct stat st;
3515
3516 fstat (fildes, &st);
86a5659e 3517 p = buf;
86a5659e
JB
3518 while (nbytes > 0)
3519 {
23b0668c
JB
3520 int len, retval;
3521
3522 /* Handle fixed-length files with carriage control. */
3523 if (st.st_fab_rfm == FAB$C_FIX
3524 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3525 {
3526 len = st.st_fab_mrs;
3527 retval = write (fildes, p, min (len, nbytes));
3528 if (retval != len)
3529 return -1;
3530 retval++; /* This skips the implied carriage control */
3531 }
3532 else
3533 {
3534 e = p + min (MAXIOSIZE, nbytes) - 1;
3535 while (*e != '\n' && e > p) e--;
3536 if (p == e) /* Ok.. so here we add a newline... sigh. */
3537 e = p + min (MAXIOSIZE, nbytes) - 1;
3538 len = e + 1 - p;
3539 retval = write (fildes, p, len);
3540 if (retval != len)
3541 return -1;
3542 }
3543 p += retval;
3544 sum += retval;
86a5659e
JB
3545 nbytes -= retval;
3546 }
3547 return sum;
3548}
3549
3550/* Create file NEW copying its attributes from file OLD. If
3551 OLD is 0 or does not exist, create based on the value of
3552 vms_stmlf_recfm. */
3553
3554/* Protection value the file should ultimately have.
3555 Set by create_copy_attrs, and use by rename_sansversions. */
3556static unsigned short int fab_final_pro;
3557
3558int
3559creat_copy_attrs (old, new)
3560 char *old, *new;
3561{
3562 struct FAB fab = cc$rms_fab;
3563 struct XABPRO xabpro;
3564 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3565 extern int vms_stmlf_recfm;
3566
3567 if (old)
3568 {
3569 fab.fab$b_fac = FAB$M_GET;
3570 fab.fab$l_fna = old;
3571 fab.fab$b_fns = strlen (old);
3572 fab.fab$l_xab = (char *) &xabpro;
3573 xabpro = cc$rms_xabpro;
3574 xabpro.xab$l_aclbuf = aclbuf;
3575 xabpro.xab$w_aclsiz = sizeof aclbuf;
3576 /* Call $OPEN to fill in the fab & xabpro fields. */
986ffb24 3577 if (SYS$OPEN (&fab, 0, 0) & 1)
86a5659e 3578 {
986ffb24 3579 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3580 fab.fab$l_alq = 0; /* zero the allocation quantity */
3581 if (xabpro.xab$w_acllen > 0)
3582 {
3583 if (xabpro.xab$w_acllen > sizeof aclbuf)
3584 /* If the acl buffer was too short, redo open with longer one.
3585 Wouldn't need to do this if there were some system imposed
3586 limit on the size of an ACL, but I can't find any such. */
3587 {
3588 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
3589 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
986ffb24
JB
3590 if (SYS$OPEN (&fab, 0, 0) & 1)
3591 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3592 else
3593 old = 0;
3594 }
3595 }
3596 else
3597 xabpro.xab$l_aclbuf = 0;
3598 }
3599 else
3600 old = 0;
3601 }
3602 fab.fab$l_fna = new;
3603 fab.fab$b_fns = strlen (new);
3604 if (!old)
3605 {
3606 fab.fab$l_xab = 0;
3607 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
3608 fab.fab$b_rat = FAB$M_CR;
3609 }
3610
3611 /* Set the file protections such that we will be able to manipulate
3612 this file. Once we are done writing and renaming it, we will set
3613 the protections back. */
3614 if (old)
3615 fab_final_pro = xabpro.xab$w_pro;
3616 else
986ffb24 3617 SYS$SETDFPROT (0, &fab_final_pro);
86a5659e
JB
3618 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
3619
3620 /* Create the new file with either default attrs or attrs copied
3621 from old file. */
3622 if (!(SYS$CREATE (&fab, 0, 0) & 1))
3623 return -1;
986ffb24 3624 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3625 /* As this is a "replacement" for creat, return a file descriptor
3626 opened for writing. */
3627 return open (new, O_WRONLY);
3628}
3629
3630#ifdef creat
3631#undef creat
3632#include <varargs.h>
3633#ifdef __GNUC__
3634#ifndef va_count
3635#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3636#endif
3637#endif
3638
3639sys_creat (va_alist)
3640 va_dcl
3641{
eb8c3be9 3642 va_list list_incrementer;
86a5659e
JB
3643 char *name;
3644 int mode;
3645 int rfd; /* related file descriptor */
3646 int fd; /* Our new file descriptor */
3647 int count;
3648 struct stat st_buf;
3649 char rfm[12];
3650 char rat[15];
3651 char mrs[13];
3652 char fsz[13];
3653 extern int vms_stmlf_recfm;
3654
3655 va_count (count);
eb8c3be9
JB
3656 va_start (list_incrementer);
3657 name = va_arg (list_incrementer, char *);
3658 mode = va_arg (list_incrementer, int);
86a5659e 3659 if (count > 2)
eb8c3be9
JB
3660 rfd = va_arg (list_incrementer, int);
3661 va_end (list_incrementer);
86a5659e
JB
3662 if (count > 2)
3663 {
3664 /* Use information from the related file descriptor to set record
3665 format of the newly created file. */
3666 fstat (rfd, &st_buf);
3667 switch (st_buf.st_fab_rfm)
3668 {
3669 case FAB$C_FIX:
3670 strcpy (rfm, "rfm = fix");
3671 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
3672 strcpy (rat, "rat = ");
3673 if (st_buf.st_fab_rat & FAB$M_CR)
3674 strcat (rat, "cr");
3675 else if (st_buf.st_fab_rat & FAB$M_FTN)
3676 strcat (rat, "ftn");
3677 else if (st_buf.st_fab_rat & FAB$M_PRN)
3678 strcat (rat, "prn");
3679 if (st_buf.st_fab_rat & FAB$M_BLK)
3680 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3681 strcat (rat, ", blk");
3682 else
3683 strcat (rat, "blk");
3684 return creat (name, 0, rfm, rat, mrs);
3685
3686 case FAB$C_VFC:
3687 strcpy (rfm, "rfm = vfc");
3688 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
3689 strcpy (rat, "rat = ");
3690 if (st_buf.st_fab_rat & FAB$M_CR)
3691 strcat (rat, "cr");
3692 else if (st_buf.st_fab_rat & FAB$M_FTN)
3693 strcat (rat, "ftn");
3694 else if (st_buf.st_fab_rat & FAB$M_PRN)
3695 strcat (rat, "prn");
3696 if (st_buf.st_fab_rat & FAB$M_BLK)
3697 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3698 strcat (rat, ", blk");
3699 else
3700 strcat (rat, "blk");
3701 return creat (name, 0, rfm, rat, fsz);
3702
3703 case FAB$C_STM:
3704 strcpy (rfm, "rfm = stm");
3705 break;
3706
3707 case FAB$C_STMCR:
3708 strcpy (rfm, "rfm = stmcr");
3709 break;
3710
3711 case FAB$C_STMLF:
3712 strcpy (rfm, "rfm = stmlf");
3713 break;
3714
3715 case FAB$C_UDF:
3716 strcpy (rfm, "rfm = udf");
3717 break;
3718
3719 case FAB$C_VAR:
3720 strcpy (rfm, "rfm = var");
3721 break;
3722 }
3723 strcpy (rat, "rat = ");
3724 if (st_buf.st_fab_rat & FAB$M_CR)
3725 strcat (rat, "cr");
3726 else if (st_buf.st_fab_rat & FAB$M_FTN)
3727 strcat (rat, "ftn");
3728 else if (st_buf.st_fab_rat & FAB$M_PRN)
3729 strcat (rat, "prn");
3730 if (st_buf.st_fab_rat & FAB$M_BLK)
3731 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3732 strcat (rat, ", blk");
3733 else
3734 strcat (rat, "blk");
3735 }
3736 else
3737 {
3738 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3739 strcpy (rat, "rat=cr");
3740 }
3741 /* Until the VAX C RTL fixes the many bugs with modes, always use
3742 mode 0 to get the user's default protection. */
3743 fd = creat (name, 0, rfm, rat);
3744 if (fd < 0 && errno == EEXIST)
3745 {
3746 if (unlink (name) < 0)
3747 report_file_error ("delete", build_string (name));
3748 fd = creat (name, 0, rfm, rat);
3749 }
3750 return fd;
3751}
3752#endif /* creat */
3753
3754/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3755sys_fwrite (ptr, size, num, fp)
3756 register char * ptr;
3757 FILE * fp;
3758{
3759 register int tot = num * size;
3760
3761 while (tot--)
3762 fputc (*ptr++, fp);
3763}
3764
3765/*
3766 * The VMS C library routine creat actually creates a new version of an
3767 * existing file rather than truncating the old version. There are times
3768 * when this is not the desired behavior, for instance, when writing an
3769 * auto save file (you only want one version), or when you don't have
3770 * write permission in the directory containing the file (but the file
3771 * itself is writable). Hence this routine, which is equivalent to
3772 * "close (creat (fn, 0));" on Unix if fn already exists.
3773 */
3774int
3775vms_truncate (fn)
3776 char *fn;
3777{
3778 struct FAB xfab = cc$rms_fab;
3779 struct RAB xrab = cc$rms_rab;
3780 int status;
3781
3782 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3783 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3784 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3785 xfab.fab$l_fna = fn;
3786 xfab.fab$b_fns = strlen (fn);
3787 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3788 xfab.fab$b_dns = 2;
3789 xrab.rab$l_fab = &xfab;
3790
3791 /* This gibberish opens the file, positions to the first record, and
3792 deletes all records from there until the end of file. */
986ffb24 3793 if ((SYS$OPEN (&xfab) & 01) == 01)
86a5659e 3794 {
986ffb24
JB
3795 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
3796 (SYS$FIND (&xrab) & 01) == 01 &&
3797 (SYS$TRUNCATE (&xrab) & 01) == 01)
86a5659e
JB
3798 status = 0;
3799 else
3800 status = -1;
3801 }
3802 else
3803 status = -1;
986ffb24 3804 SYS$CLOSE (&xfab);
86a5659e
JB
3805 return status;
3806}
3807
3808/* Define this symbol to actually read SYSUAF.DAT. This requires either
3809 SYSPRV or a readable SYSUAF.DAT. */
3810
3811#ifdef READ_SYSUAF
3812/*
3813 * getuaf.c
3814 *
3815 * Routine to read the VMS User Authorization File and return
3816 * a specific user's record.
3817 */
3818
3819static struct UAF retuaf;
3820
3821struct UAF *
3822get_uaf_name (uname)
3823 char * uname;
3824{
3825 register status;
3826 struct FAB uaf_fab;
3827 struct RAB uaf_rab;
3828
3829 uaf_fab = cc$rms_fab;
3830 uaf_rab = cc$rms_rab;
3831 /* initialize fab fields */
3832 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3833 uaf_fab.fab$b_fns = 21;
3834 uaf_fab.fab$b_fac = FAB$M_GET;
3835 uaf_fab.fab$b_org = FAB$C_IDX;
3836 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3837 /* initialize rab fields */
3838 uaf_rab.rab$l_fab = &uaf_fab;
3839 /* open the User Authorization File */
986ffb24 3840 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3841 if (!(status&1))
3842 {
3843 errno = EVMSERR;
3844 vaxc$errno = status;
3845 return 0;
3846 }
986ffb24 3847 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3848 if (!(status&1))
3849 {
3850 errno = EVMSERR;
3851 vaxc$errno = status;
3852 return 0;
3853 }
3854 /* read the requested record - index is in uname */
3855 uaf_rab.rab$l_kbf = uname;
3856 uaf_rab.rab$b_ksz = strlen (uname);
3857 uaf_rab.rab$b_rac = RAB$C_KEY;
3858 uaf_rab.rab$l_ubf = (char *)&retuaf;
3859 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3860 status = SYS$GET (&uaf_rab);
86a5659e
JB
3861 if (!(status&1))
3862 {
3863 errno = EVMSERR;
3864 vaxc$errno = status;
3865 return 0;
3866 }
3867 /* close the User Authorization File */
986ffb24 3868 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3869 if (!(status&1))
3870 {
3871 errno = EVMSERR;
3872 vaxc$errno = status;
3873 return 0;
3874 }
986ffb24 3875 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3876 if (!(status&1))
3877 {
3878 errno = EVMSERR;
3879 vaxc$errno = status;
3880 return 0;
3881 }
3882 return &retuaf;
3883}
3884
3885struct UAF *
3886get_uaf_uic (uic)
3887 unsigned long uic;
3888{
3889 register status;
3890 struct FAB uaf_fab;
3891 struct RAB uaf_rab;
3892
3893 uaf_fab = cc$rms_fab;
3894 uaf_rab = cc$rms_rab;
3895 /* initialize fab fields */
3896 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3897 uaf_fab.fab$b_fns = 21;
3898 uaf_fab.fab$b_fac = FAB$M_GET;
3899 uaf_fab.fab$b_org = FAB$C_IDX;
3900 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3901 /* initialize rab fields */
3902 uaf_rab.rab$l_fab = &uaf_fab;
3903 /* open the User Authorization File */
986ffb24 3904 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3905 if (!(status&1))
3906 {
3907 errno = EVMSERR;
3908 vaxc$errno = status;
3909 return 0;
3910 }
986ffb24 3911 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3912 if (!(status&1))
3913 {
3914 errno = EVMSERR;
3915 vaxc$errno = status;
3916 return 0;
3917 }
3918 /* read the requested record - index is in uic */
3919 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3920 uaf_rab.rab$l_kbf = (char *) &uic;
3921 uaf_rab.rab$b_ksz = sizeof uic;
3922 uaf_rab.rab$b_rac = RAB$C_KEY;
3923 uaf_rab.rab$l_ubf = (char *)&retuaf;
3924 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3925 status = SYS$GET (&uaf_rab);
86a5659e
JB
3926 if (!(status&1))
3927 {
3928 errno = EVMSERR;
3929 vaxc$errno = status;
3930 return 0;
3931 }
3932 /* close the User Authorization File */
986ffb24 3933 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3934 if (!(status&1))
3935 {
3936 errno = EVMSERR;
3937 vaxc$errno = status;
3938 return 0;
3939 }
986ffb24 3940 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3941 if (!(status&1))
3942 {
3943 errno = EVMSERR;
3944 vaxc$errno = status;
3945 return 0;
3946 }
3947 return &retuaf;
3948}
3949
3950static struct passwd retpw;
3951
3952struct passwd *
3953cnv_uaf_pw (up)
3954 struct UAF * up;
3955{
3956 char * ptr;
3957
3958 /* copy these out first because if the username is 32 chars, the next
3959 section will overwrite the first byte of the UIC */
3960 retpw.pw_uid = up->uaf$w_mem;
3961 retpw.pw_gid = up->uaf$w_grp;
3962
3963 /* I suppose this is not the best sytle, to possibly overwrite one
3964 byte beyond the end of the field, but what the heck... */
3965 ptr = &up->uaf$t_username[UAF$S_USERNAME];
3966 while (ptr[-1] == ' ')
3967 ptr--;
3968 *ptr = '\0';
3969 strcpy (retpw.pw_name, up->uaf$t_username);
3970
3971 /* the rest of these are counted ascii strings */
3972 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3973 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3974 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3975 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3976 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3977 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3978 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3979 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3980
3981 return &retpw;
3982}
3983#else /* not READ_SYSUAF */
3984static struct passwd retpw;
3985#endif /* not READ_SYSUAF */
3986
3987struct passwd *
3988getpwnam (name)
3989 char * name;
3990{
3991#ifdef READ_SYSUAF
3992 struct UAF *up;
3993#else
3994 char * user;
3995 char * dir;
3996 unsigned char * full;
3997#endif /* READ_SYSUAF */
3998 char *ptr = name;
3999
4000 while (*ptr)
4001 {
4002 if ('a' <= *ptr && *ptr <= 'z')
4003 *ptr -= 040;
4004 ptr++;
4005 }
4006#ifdef READ_SYSUAF
4007 if (!(up = get_uaf_name (name)))
4008 return 0;
4009 return cnv_uaf_pw (up);
4010#else
4011 if (strcmp (name, getenv ("USER")) == 0)
4012 {
4013 retpw.pw_uid = getuid ();
4014 retpw.pw_gid = getgid ();
4015 strcpy (retpw.pw_name, name);
4016 if (full = egetenv ("FULLNAME"))
4017 strcpy (retpw.pw_gecos, full);
4018 else
4019 *retpw.pw_gecos = '\0';
4020 strcpy (retpw.pw_dir, egetenv ("HOME"));
4021 *retpw.pw_shell = '\0';
4022 return &retpw;
4023 }
4024 else
4025 return 0;
4026#endif /* not READ_SYSUAF */
4027}
4028
4029struct passwd *
4030getpwuid (uid)
4031 unsigned long uid;
4032{
4033#ifdef READ_SYSUAF
4034 struct UAF * up;
4035
4036 if (!(up = get_uaf_uic (uid)))
4037 return 0;
4038 return cnv_uaf_pw (up);
4039#else
4040 if (uid == sys_getuid ())
4041 return getpwnam (egetenv ("USER"));
4042 else
4043 return 0;
4044#endif /* not READ_SYSUAF */
4045}
4046
4047/* return total address space available to the current process. This is
4048 the sum of the current p0 size, p1 size and free page table entries
4049 available. */
4050vlimit ()
4051{
4052 int item_code;
4053 unsigned long free_pages;
4054 unsigned long frep0va;
4055 unsigned long frep1va;
4056 register status;
4057
4058 item_code = JPI$_FREPTECNT;
4059 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4060 {
4061 errno = EVMSERR;
4062 vaxc$errno = status;
4063 return -1;
4064 }
4065 free_pages *= 512;
4066
4067 item_code = JPI$_FREP0VA;
4068 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4069 {
4070 errno = EVMSERR;
4071 vaxc$errno = status;
4072 return -1;
4073 }
4074 item_code = JPI$_FREP1VA;
4075 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4076 {
4077 errno = EVMSERR;
4078 vaxc$errno = status;
4079 return -1;
4080 }
4081
4082 return free_pages + frep0va + (0x7fffffff - frep1va);
4083}
4084
4085define_logical_name (varname, string)
4086 char *varname;
4087 char *string;
4088{
4089 struct dsc$descriptor_s strdsc =
4090 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4091 struct dsc$descriptor_s envdsc =
4092 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4093 struct dsc$descriptor_s lnmdsc =
4094 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4095
4096 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4097}
4098
4099delete_logical_name (varname)
4100 char *varname;
4101{
4102 struct dsc$descriptor_s envdsc =
4103 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4104 struct dsc$descriptor_s lnmdsc =
4105 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4106
4107 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4108}
4109
4110ulimit ()
4111{}
4112
86a5659e
JB
4113setpgrp ()
4114{}
4115
4116execvp ()
4117{
4118 error ("execvp system call not implemented");
4119}
4120
4121int
4122rename (from, to)
4123 char *from, *to;
4124{
4125 int status;
4126 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4127 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4128 char from_esn[NAM$C_MAXRSS];
4129 char to_esn[NAM$C_MAXRSS];
4130
4131 from_fab.fab$l_fna = from;
4132 from_fab.fab$b_fns = strlen (from);
4133 from_fab.fab$l_nam = &from_nam;
4134 from_fab.fab$l_fop = FAB$M_NAM;
4135
4136 from_nam.nam$l_esa = from_esn;
4137 from_nam.nam$b_ess = sizeof from_esn;
4138
4139 to_fab.fab$l_fna = to;
4140 to_fab.fab$b_fns = strlen (to);
4141 to_fab.fab$l_nam = &to_nam;
4142 to_fab.fab$l_fop = FAB$M_NAM;
4143
4144 to_nam.nam$l_esa = to_esn;
4145 to_nam.nam$b_ess = sizeof to_esn;
4146
4147 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4148
4149 if (status & 1)
4150 return 0;
4151 else
4152 {
4153 if (status == RMS$_DEV)
4154 errno = EXDEV;
4155 else
4156 errno = EVMSERR;
4157 vaxc$errno = status;
4158 return -1;
4159 }
4160}
4161
4162/* This function renames a file like `rename', but it strips
4163 the version number from the "to" filename, such that the "to" file is
4164 will always be a new version. It also sets the file protection once it is
4165 finished. The protection that we will use is stored in fab_final_pro,
4166 and was set when we did a creat_copy_attrs to create the file that we
4167 are renaming.
4168
4169 We could use the chmod function, but Eunichs uses 3 bits per user category
eb8c3be9 4170 to describe the protection, and VMS uses 4 (write and delete are separate
86a5659e
JB
4171 bits). To maintain portability, the VMS implementation of `chmod' wires
4172 the W and D bits together. */
4173
4174
4175static struct fibdef fib; /* We need this initialized to zero */
4176char vms_file_written[NAM$C_MAXRSS];
4177
4178int
4179rename_sans_version (from,to)
4180 char *from, *to;
4181{
4182 short int chan;
4183 int stat;
4184 short int iosb[4];
4185 int status;
4186 struct FAB to_fab = cc$rms_fab;
4187 struct NAM to_nam = cc$rms_nam;
4188 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4189 struct dsc$descriptor fib_attr[2]
4190 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4191 char to_esn[NAM$C_MAXRSS];
4192
4193 $DESCRIPTOR (disk,to_esn);
4194
4195 to_fab.fab$l_fna = to;
4196 to_fab.fab$b_fns = strlen (to);
4197 to_fab.fab$l_nam = &to_nam;
4198 to_fab.fab$l_fop = FAB$M_NAM;
4199
4200 to_nam.nam$l_esa = to_esn;
4201 to_nam.nam$b_ess = sizeof to_esn;
4202
4203 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4204
4205 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4206 *(to_nam.nam$l_ver) = '\0';
4207
4208 stat = rename (from, to_esn);
4209 if (stat < 0)
4210 return stat;
4211
4212 strcpy (vms_file_written, to_esn);
4213
4214 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4215 to_fab.fab$b_fns = strlen (vms_file_written);
4216
4217 /* Now set the file protection to the correct value */
986ffb24 4218 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
86a5659e
JB
4219
4220 /* Copy these fields into the fib */
4221 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4222 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4223 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4224
986ffb24 4225 SYS$CLOSE (&to_fab, 0, 0);
86a5659e 4226
986ffb24 4227 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
86a5659e 4228 if (!stat)
986ffb24
JB
4229 LIB$SIGNAL (stat);
4230 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
86a5659e
JB
4231 0, 0, 0, &fib_attr, 0);
4232 if (!stat)
986ffb24
JB
4233 LIB$SIGNAL (stat);
4234 stat = SYS$DASSGN (chan);
86a5659e 4235 if (!stat)
986ffb24 4236 LIB$SIGNAL (stat);
0137dbf7 4237 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
4238 return 0;
4239}
4240
4241link (file, new)
4242 char * file, * new;
4243{
4244 register status;
4245 struct FAB fab;
4246 struct NAM nam;
4247 unsigned short fid[3];
4248 char esa[NAM$C_MAXRSS];
4249
4250 fab = cc$rms_fab;
4251 fab.fab$l_fop = FAB$M_OFP;
4252 fab.fab$l_fna = file;
4253 fab.fab$b_fns = strlen (file);
4254 fab.fab$l_nam = &nam;
4255
4256 nam = cc$rms_nam;
4257 nam.nam$l_esa = esa;
4258 nam.nam$b_ess = NAM$C_MAXRSS;
4259
4260 status = SYS$PARSE (&fab);
4261 if ((status & 1) == 0)
4262 {
4263 errno = EVMSERR;
4264 vaxc$errno = status;
4265 return -1;
4266 }
4267 status = SYS$SEARCH (&fab);
4268 if ((status & 1) == 0)
4269 {
4270 errno = EVMSERR;
4271 vaxc$errno = status;
4272 return -1;
4273 }
4274
4275 fid[0] = nam.nam$w_fid[0];
4276 fid[1] = nam.nam$w_fid[1];
4277 fid[2] = nam.nam$w_fid[2];
4278
4279 fab.fab$l_fna = new;
4280 fab.fab$b_fns = strlen (new);
4281
4282 status = SYS$PARSE (&fab);
4283 if ((status & 1) == 0)
4284 {
4285 errno = EVMSERR;
4286 vaxc$errno = status;
4287 return -1;
4288 }
4289
4290 nam.nam$w_fid[0] = fid[0];
4291 nam.nam$w_fid[1] = fid[1];
4292 nam.nam$w_fid[2] = fid[2];
4293
4294 nam.nam$l_esa = nam.nam$l_name;
4295 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
4296
4297 status = SYS$ENTER (&fab);
4298 if ((status & 1) == 0)
4299 {
4300 errno = EVMSERR;
4301 vaxc$errno = status;
4302 return -1;
4303 }
4304
4305 return 0;
4306}
4307
4308croak (badfunc)
4309 char *badfunc;
4310{
4311 printf ("%s not yet implemented\r\n", badfunc);
4312 reset_sys_modes ();
4313 exit (1);
4314}
4315
4316long
4317random ()
4318{
4319 /* Arrange to return a range centered on zero. */
4320 return rand () - (1 << 30);
4321}
4322
4323srandom (seed)
4324{
4325 srand (seed);
4326}
4327#endif /* VMS */
4328\f
4329#ifdef AIX
4330
4331/* Called from init_sys_modes. */
4332hft_init ()
4333{
4334 int junk;
4335
4336 /* If we're not on an HFT we shouldn't do any of this. We determine
4337 if we are on an HFT by trying to get an HFT error code. If this
4338 call fails, we're not on an HFT. */
4339#ifdef IBMR2AIX
4340 if (ioctl (0, HFQERROR, &junk) < 0)
4341 return;
4342#else /* not IBMR2AIX */
4343 if (ioctl (0, HFQEIO, 0) < 0)
4344 return;
4345#endif /* not IBMR2AIX */
4346
4347 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4348 as the rubout key's ASCII code. Here this is changed. The bug is that
4349 there's no way to determine the old mapping, so in reset_sys_modes
4350 we need to assume that the normal map had been present. Of course, this
4351 code also doesn't help if on a terminal emulator which doesn't understand
4352 HFT VTD's. */
4353 {
4354 struct hfbuf buf;
4355 struct hfkeymap keymap;
4356
4357 buf.hf_bufp = (char *)&keymap;
4358 buf.hf_buflen = sizeof (keymap);
4359 keymap.hf_nkeys = 2;
4360 keymap.hfkey[0].hf_kpos = 15;
4361 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4362#ifdef IBMR2AIX
4363 keymap.hfkey[0].hf_keyidh = '<';
4364#else /* not IBMR2AIX */
4365 keymap.hfkey[0].hf_page = '<';
4366#endif /* not IBMR2AIX */
4367 keymap.hfkey[0].hf_char = 127;
4368 keymap.hfkey[1].hf_kpos = 15;
4369 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4370#ifdef IBMR2AIX
4371 keymap.hfkey[1].hf_keyidh = '<';
4372#else /* not IBMR2AIX */
4373 keymap.hfkey[1].hf_page = '<';
4374#endif /* not IBMR2AIX */
4375 keymap.hfkey[1].hf_char = 127;
4376 hftctl (0, HFSKBD, &buf);
4377 }
4378 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4379 at times. */
4380 line_ins_del_ok = char_ins_del_ok = 0;
4381}
4382
4383/* Reset the rubout key to backspace. */
4384
4385hft_reset ()
4386{
4387 struct hfbuf buf;
4388 struct hfkeymap keymap;
4389 int junk;
4390
4391#ifdef IBMR2AIX
4392 if (ioctl (0, HFQERROR, &junk) < 0)
4393 return;
4394#else /* not IBMR2AIX */
4395 if (ioctl (0, HFQEIO, 0) < 0)
4396 return;
4397#endif /* not IBMR2AIX */
4398
4399 buf.hf_bufp = (char *)&keymap;
4400 buf.hf_buflen = sizeof (keymap);
4401 keymap.hf_nkeys = 2;
4402 keymap.hfkey[0].hf_kpos = 15;
4403 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4404#ifdef IBMR2AIX
4405 keymap.hfkey[0].hf_keyidh = '<';
4406#else /* not IBMR2AIX */
4407 keymap.hfkey[0].hf_page = '<';
4408#endif /* not IBMR2AIX */
4409 keymap.hfkey[0].hf_char = 8;
4410 keymap.hfkey[1].hf_kpos = 15;
4411 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4412#ifdef IBMR2AIX
4413 keymap.hfkey[1].hf_keyidh = '<';
4414#else /* not IBMR2AIX */
4415 keymap.hfkey[1].hf_page = '<';
4416#endif /* not IBMR2AIX */
4417 keymap.hfkey[1].hf_char = 8;
4418 hftctl (0, HFSKBD, &buf);
4419}
4420
4421#endif /* AIX */