* configure.in: Look for the closedir function.
[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);
1b929d25
JB
2930
2931 /* Some systems allocate the buffer and the DIR all in one block.
2932 Why in the world are we freeing this ourselves anyway? */
2933 if (dirp->dd_buf != (char *)(dirp + 1))
2934 xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
9ac0d9e0 2935 xfree ((char *) dirp);
86a5659e
JB
2936}
2937#endif /* not AIX */
2938#endif /* SYSV_SYSTEM_DIR */
2939
2940#ifdef NONSYSTEM_DIR_LIBRARY
2941
2942DIR *
2943opendir (filename)
2944 char *filename; /* name of directory */
2945{
2946 register DIR *dirp; /* -> malloc'ed storage */
2947 register int fd; /* file descriptor for read */
2948 struct stat sbuf; /* result of fstat */
2949
2950 fd = sys_open (filename, 0);
2951 if (fd < 0)
2952 return 0;
2953
9ac0d9e0 2954 BLOCK_INPUT;
86a5659e
JB
2955 if (fstat (fd, &sbuf) < 0
2956 || (sbuf.st_mode & S_IFMT) != S_IFDIR
2957 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2958 {
2959 sys_close (fd);
9ac0d9e0 2960 UNBLOCK_INPUT;
86a5659e
JB
2961 return 0; /* bad luck today */
2962 }
9ac0d9e0 2963 UNBLOCK_INPUT;
86a5659e
JB
2964
2965 dirp->dd_fd = fd;
2966 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2967
2968 return dirp;
2969}
2970
2971void
2972closedir (dirp)
2973 register DIR *dirp; /* stream from opendir */
2974{
2975 sys_close (dirp->dd_fd);
9ac0d9e0 2976 xfree ((char *) dirp);
86a5659e
JB
2977}
2978
2979
2980#ifndef VMS
2981#define DIRSIZ 14
2982struct olddir
2983 {
2984 ino_t od_ino; /* inode */
2985 char od_name[DIRSIZ]; /* filename */
2986 };
2987#endif /* not VMS */
2988
2989struct direct dir_static; /* simulated directory contents */
2990
2991/* ARGUSED */
2992struct direct *
2993readdir (dirp)
2994 register DIR *dirp; /* stream from opendir */
2995{
2996#ifndef VMS
2997 register struct olddir *dp; /* -> directory data */
2998#else /* VMS */
2999 register struct dir$_name *dp; /* -> directory data */
3000 register struct dir$_version *dv; /* -> version data */
3001#endif /* VMS */
3002
3003 for (; ;)
3004 {
3005 if (dirp->dd_loc >= dirp->dd_size)
3006 dirp->dd_loc = dirp->dd_size = 0;
3007
3008 if (dirp->dd_size == 0 /* refill buffer */
3009 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3010 return 0;
3011
3012#ifndef VMS
3013 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3014 dirp->dd_loc += sizeof (struct olddir);
3015
3016 if (dp->od_ino != 0) /* not deleted entry */
3017 {
3018 dir_static.d_ino = dp->od_ino;
3019 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
3020 dir_static.d_name[DIRSIZ] = '\0';
3021 dir_static.d_namlen = strlen (dir_static.d_name);
3022 dir_static.d_reclen = sizeof (struct direct)
3023 - MAXNAMLEN + 3
3024 + dir_static.d_namlen - dir_static.d_namlen % 4;
3025 return &dir_static; /* -> simulated structure */
3026 }
3027#else /* VMS */
3028 dp = (struct dir$_name *) dirp->dd_buf;
3029 if (dirp->dd_loc == 0)
3030 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3031 : dp->dir$b_namecount;
3032 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3033 dir_static.d_ino = dv->dir$w_fid_num;
3034 dir_static.d_namlen = dp->dir$b_namecount;
3035 dir_static.d_reclen = sizeof (struct direct)
3036 - MAXNAMLEN + 3
3037 + dir_static.d_namlen - dir_static.d_namlen % 4;
3038 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3039 dir_static.d_name[dir_static.d_namlen] = '\0';
3040 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3041 return &dir_static;
3042#endif /* VMS */
3043 }
3044}
3045
3046#ifdef VMS
3047/* readdirver is just like readdir except it returns all versions of a file
3048 as separate entries. */
3049
3050/* ARGUSED */
3051struct direct *
3052readdirver (dirp)
3053 register DIR *dirp; /* stream from opendir */
3054{
3055 register struct dir$_name *dp; /* -> directory data */
3056 register struct dir$_version *dv; /* -> version data */
3057
3058 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3059 dirp->dd_loc = dirp->dd_size = 0;
3060
3061 if (dirp->dd_size == 0 /* refill buffer */
3062 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3063 return 0;
3064
3065 dp = (struct dir$_name *) dirp->dd_buf;
3066 if (dirp->dd_loc == 0)
3067 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3068 : dp->dir$b_namecount;
3069 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3070 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3071 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3072 dir_static.d_namlen = strlen (dir_static.d_name);
3073 dir_static.d_ino = dv->dir$w_fid_num;
3074 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3075 + dir_static.d_namlen - dir_static.d_namlen % 4;
3076 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3077 return &dir_static;
3078}
3079
3080#endif /* VMS */
3081
3082#endif /* NONSYSTEM_DIR_LIBRARY */
3083\f
3084/* Functions for VMS */
3085#ifdef VMS
91bac16a 3086#include "vms-pwd.h"
86a5659e
JB
3087#include <acldef.h>
3088#include <chpdef.h>
3089#include <jpidef.h>
3090
3091/* Return as a string the VMS error string pertaining to STATUS.
3092 Reuses the same static buffer each time it is called. */
3093
3094char *
3095vmserrstr (status)
3096 int status; /* VMS status code */
3097{
3098 int bufadr[2];
3099 short len;
3100 static char buf[257];
3101
3102 bufadr[0] = sizeof buf - 1;
3103 bufadr[1] = (int) buf;
3104 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
3105 return "untranslatable VMS error status";
3106 buf[len] = '\0';
3107 return buf;
3108}
3109
3110#ifdef access
3111#undef access
3112
3113/* The following is necessary because 'access' emulation by VMS C (2.0) does
3114 * not work correctly. (It also doesn't work well in version 2.3.)
3115 */
3116
3117#ifdef VMS4_4
3118
3119#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
3120 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
3121
3122typedef union {
3123 struct {
3124 unsigned short s_buflen;
3125 unsigned short s_code;
3126 char *s_bufadr;
3127 unsigned short *s_retlenadr;
3128 } s;
3129 int end;
3130} item;
3131#define buflen s.s_buflen
3132#define code s.s_code
3133#define bufadr s.s_bufadr
3134#define retlenadr s.s_retlenadr
3135
3136#define R_OK 4 /* test for read permission */
3137#define W_OK 2 /* test for write permission */
3138#define X_OK 1 /* test for execute (search) permission */
3139#define F_OK 0 /* test for presence of file */
3140
3141int
3142sys_access (path, mode)
3143 char *path;
3144 int mode;
3145{
3146 static char *user = NULL;
3147 char dir_fn[512];
3148
3149 /* translate possible directory spec into .DIR file name, so brain-dead
3150 * access can treat the directory like a file. */
3151 if (directory_file_name (path, dir_fn))
3152 path = dir_fn;
3153
3154 if (mode == F_OK)
3155 return access (path, mode);
3156 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
3157 return -1;
3158 {
3159 int stat;
3160 int flags;
3161 int acces;
3162 unsigned short int dummy;
3163 item itemlst[3];
3164 static int constant = ACL$C_FILE;
3165 DESCRIPTOR (path_desc, path);
3166 DESCRIPTOR (user_desc, user);
3167
3168 flags = 0;
3169 acces = 0;
3170 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
3171 return stat;
3172 if (mode & R_OK)
3173 acces |= CHP$M_READ;
3174 if (mode & W_OK)
3175 acces |= CHP$M_WRITE;
3176 itemlst[0].buflen = sizeof (int);
3177 itemlst[0].code = CHP$_FLAGS;
3178 itemlst[0].bufadr = (char *) &flags;
3179 itemlst[0].retlenadr = &dummy;
3180 itemlst[1].buflen = sizeof (int);
3181 itemlst[1].code = CHP$_ACCESS;
3182 itemlst[1].bufadr = (char *) &acces;
3183 itemlst[1].retlenadr = &dummy;
3184 itemlst[2].end = CHP$_END;
3185 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
3186 return stat == SS$_NORMAL ? 0 : -1;
3187 }
3188}
3189
3190#else /* not VMS4_4 */
3191
3192#include <prvdef.h>
3193#define ACE$M_WRITE 2
3194#define ACE$C_KEYID 1
3195
3196static unsigned short memid, grpid;
3197static unsigned int uic;
3198
3199/* Called from init_sys_modes, so it happens not very often
3200 but at least each time Emacs is loaded. */
3201sys_access_reinit ()
3202{
3203 uic = 0;
3204}
3205
3206int
3207sys_access (filename, type)
3208 char * filename;
3209 int type;
3210{
3211 struct FAB fab;
3212 struct XABPRO xab;
3213 int status, size, i, typecode, acl_controlled;
3214 unsigned int *aclptr, *aclend, aclbuf[60];
3215 union prvdef prvmask;
3216
3217 /* Get UIC and GRP values for protection checking. */
3218 if (uic == 0)
3219 {
3220 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
3221 if (! (status & 1))
3222 return -1;
3223 memid = uic & 0xFFFF;
3224 grpid = uic >> 16;
3225 }
3226
3227 if (type != 2) /* not checking write access */
3228 return access (filename, type);
3229
3230 /* Check write protection. */
3231
3232#define CHECKPRIV(bit) (prvmask.bit)
3233#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
3234
3235 /* Find privilege bits */
986ffb24 3236 status = SYS$SETPRV (0, 0, 0, prvmask);
86a5659e
JB
3237 if (! (status & 1))
3238 error ("Unable to find privileges: %s", vmserrstr (status));
3239 if (CHECKPRIV (PRV$V_BYPASS))
3240 return 0; /* BYPASS enabled */
3241 fab = cc$rms_fab;
3242 fab.fab$b_fac = FAB$M_GET;
3243 fab.fab$l_fna = filename;
3244 fab.fab$b_fns = strlen (filename);
3245 fab.fab$l_xab = &xab;
3246 xab = cc$rms_xabpro;
3247 xab.xab$l_aclbuf = aclbuf;
3248 xab.xab$w_aclsiz = sizeof (aclbuf);
986ffb24 3249 status = SYS$OPEN (&fab, 0, 0);
86a5659e
JB
3250 if (! (status & 1))
3251 return -1;
986ffb24 3252 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3253 /* Check system access */
3254 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
3255 return 0;
3256 /* Check ACL entries, if any */
3257 acl_controlled = 0;
3258 if (xab.xab$w_acllen > 0)
3259 {
3260 aclptr = aclbuf;
3261 aclend = &aclbuf[xab.xab$w_acllen / 4];
3262 while (*aclptr && aclptr < aclend)
3263 {
3264 size = (*aclptr & 0xff) / 4;
3265 typecode = (*aclptr >> 8) & 0xff;
3266 if (typecode == ACE$C_KEYID)
3267 for (i = size - 1; i > 1; i--)
3268 if (aclptr[i] == uic)
3269 {
3270 acl_controlled = 1;
3271 if (aclptr[1] & ACE$M_WRITE)
3272 return 0; /* Write access through ACL */
3273 }
3274 aclptr = &aclptr[size];
3275 }
3276 if (acl_controlled) /* ACL specified, prohibits write access */
3277 return -1;
3278 }
3279 /* No ACL entries specified, check normal protection */
3280 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
3281 return 0;
3282 if (WRITEABLE (XAB$V_GRP) &&
3283 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
3284 return 0; /* Group writeable */
3285 if (WRITEABLE (XAB$V_OWN) &&
3286 (xab.xab$l_uic & 0xFFFF) == memid)
3287 return 0; /* Owner writeable */
3288
3289 return -1; /* Not writeable */
3290}
3291#endif /* not VMS4_4 */
3292#endif /* access */
3293
3294static char vtbuf[NAM$C_MAXRSS+1];
3295
3296/* translate a vms file spec to a unix path */
3297char *
3298sys_translate_vms (vfile)
3299 char * vfile;
3300{
3301 char * p;
3302 char * targ;
3303
3304 if (!vfile)
3305 return 0;
3306
3307 targ = vtbuf;
3308
3309 /* leading device or logical name is a root directory */
3310 if (p = strchr (vfile, ':'))
3311 {
3312 *targ++ = '/';
3313 while (vfile < p)
3314 *targ++ = *vfile++;
3315 vfile++;
3316 *targ++ = '/';
3317 }
3318 p = vfile;
3319 if (*p == '[' || *p == '<')
3320 {
3321 while (*++vfile != *p + 2)
3322 switch (*vfile)
3323 {
3324 case '.':
3325 if (vfile[-1] == *p)
3326 *targ++ = '.';
3327 *targ++ = '/';
3328 break;
3329
3330 case '-':
3331 *targ++ = '.';
3332 *targ++ = '.';
3333 break;
3334
3335 default:
3336 *targ++ = *vfile;
3337 break;
3338 }
3339 vfile++;
3340 *targ++ = '/';
3341 }
3342 while (*vfile)
3343 *targ++ = *vfile++;
3344
3345 return vtbuf;
3346}
3347
3348static char utbuf[NAM$C_MAXRSS+1];
3349
3350/* translate a unix path to a VMS file spec */
3351char *
3352sys_translate_unix (ufile)
3353 char * ufile;
3354{
3355 int slash_seen = 0;
3356 char *p;
3357 char * targ;
3358
3359 if (!ufile)
3360 return 0;
3361
3362 targ = utbuf;
3363
3364 if (*ufile == '/')
3365 {
3366 ufile++;
3367 }
3368
3369 while (*ufile)
3370 {
3371 switch (*ufile)
3372 {
3373 case '/':
3374 if (slash_seen)
3375 if (index (&ufile[1], '/'))
3376 *targ++ = '.';
3377 else
3378 *targ++ = ']';
3379 else
3380 {
3381 *targ++ = ':';
3382 if (index (&ufile[1], '/'))
3383 *targ++ = '[';
3384 slash_seen = 1;
3385 }
3386 break;
3387
3388 case '.':
3389 if (strncmp (ufile, "./", 2) == 0)
3390 {
3391 if (!slash_seen)
3392 {
3393 *targ++ = '[';
3394 slash_seen = 1;
3395 }
3396 ufile++; /* skip the dot */
3397 if (index (&ufile[1], '/'))
3398 *targ++ = '.';
3399 else
3400 *targ++ = ']';
3401 }
3402 else if (strncmp (ufile, "../", 3) == 0)
3403 {
3404 if (!slash_seen)
3405 {
3406 *targ++ = '[';
3407 slash_seen = 1;
3408 }
3409 *targ++ = '-';
3410 ufile += 2; /* skip the dots */
3411 if (index (&ufile[1], '/'))
3412 *targ++ = '.';
3413 else
3414 *targ++ = ']';
3415 }
3416 else
3417 *targ++ = *ufile;
3418 break;
3419
3420 default:
3421 *targ++ = *ufile;
3422 break;
3423 }
3424 ufile++;
3425 }
3426 *targ = '\0';
3427
3428 return utbuf;
3429}
3430
3431char *
3432getwd (pathname)
3433 char *pathname;
3434{
3435 char *ptr;
210b2b4f 3436 extern char *getcwd ();
86a5659e 3437
210b2b4f
JB
3438#define MAXPATHLEN 1024
3439
9ac0d9e0 3440 ptr = xmalloc (MAXPATHLEN);
210b2b4f
JB
3441 getcwd (ptr, MAXPATHLEN);
3442 strcpy (pathname, ptr);
9ac0d9e0 3443 xfree (ptr);
210b2b4f
JB
3444
3445 return pathname;
86a5659e
JB
3446}
3447
3448getppid ()
3449{
3450 long item_code = JPI$_OWNER;
3451 unsigned long parent_id;
3452 int status;
3453
3454 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3455 {
3456 errno = EVMSERR;
3457 vaxc$errno = status;
3458 return -1;
3459 }
3460 return parent_id;
3461}
3462
3463#undef getuid
3464unsigned
3465sys_getuid ()
3466{
3467 return (getgid () << 16) | getuid ();
3468}
3469
3470int
3471sys_read (fildes, buf, nbyte)
3472 int fildes;
3473 char *buf;
3474 unsigned int nbyte;
3475{
3476 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3477}
3478
3479#if 0
3480int
3481sys_write (fildes, buf, nbyte)
3482 int fildes;
3483 char *buf;
3484 unsigned int nbyte;
3485{
3486 register int nwrote, rtnval = 0;
3487
3488 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3489 nbyte -= nwrote;
3490 buf += nwrote;
3491 rtnval += nwrote;
3492 }
3493 if (nwrote < 0)
3494 return rtnval ? rtnval : -1;
3495 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3496 return rtnval ? rtnval : -1;
3497 return (rtnval + nwrote);
3498}
3499#endif /* 0 */
3500
3501/*
3502 * VAX/VMS VAX C RTL really loses. It insists that records
3503 * end with a newline (carriage return) character, and if they
3504 * don't it adds one (nice of it isn't it!)
3505 *
3506 * Thus we do this stupidity below.
3507 */
3508
3509int
3510sys_write (fildes, buf, nbytes)
3511 int fildes;
3512 char *buf;
3513 unsigned int nbytes;
3514{
3515 register char *p;
3516 register char *e;
23b0668c
JB
3517 int sum = 0;
3518 struct stat st;
3519
3520 fstat (fildes, &st);
86a5659e 3521 p = buf;
86a5659e
JB
3522 while (nbytes > 0)
3523 {
23b0668c
JB
3524 int len, retval;
3525
3526 /* Handle fixed-length files with carriage control. */
3527 if (st.st_fab_rfm == FAB$C_FIX
3528 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3529 {
3530 len = st.st_fab_mrs;
3531 retval = write (fildes, p, min (len, nbytes));
3532 if (retval != len)
3533 return -1;
3534 retval++; /* This skips the implied carriage control */
3535 }
3536 else
3537 {
3538 e = p + min (MAXIOSIZE, nbytes) - 1;
3539 while (*e != '\n' && e > p) e--;
3540 if (p == e) /* Ok.. so here we add a newline... sigh. */
3541 e = p + min (MAXIOSIZE, nbytes) - 1;
3542 len = e + 1 - p;
3543 retval = write (fildes, p, len);
3544 if (retval != len)
3545 return -1;
3546 }
3547 p += retval;
3548 sum += retval;
86a5659e
JB
3549 nbytes -= retval;
3550 }
3551 return sum;
3552}
3553
3554/* Create file NEW copying its attributes from file OLD. If
3555 OLD is 0 or does not exist, create based on the value of
3556 vms_stmlf_recfm. */
3557
3558/* Protection value the file should ultimately have.
3559 Set by create_copy_attrs, and use by rename_sansversions. */
3560static unsigned short int fab_final_pro;
3561
3562int
3563creat_copy_attrs (old, new)
3564 char *old, *new;
3565{
3566 struct FAB fab = cc$rms_fab;
3567 struct XABPRO xabpro;
3568 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3569 extern int vms_stmlf_recfm;
3570
3571 if (old)
3572 {
3573 fab.fab$b_fac = FAB$M_GET;
3574 fab.fab$l_fna = old;
3575 fab.fab$b_fns = strlen (old);
3576 fab.fab$l_xab = (char *) &xabpro;
3577 xabpro = cc$rms_xabpro;
3578 xabpro.xab$l_aclbuf = aclbuf;
3579 xabpro.xab$w_aclsiz = sizeof aclbuf;
3580 /* Call $OPEN to fill in the fab & xabpro fields. */
986ffb24 3581 if (SYS$OPEN (&fab, 0, 0) & 1)
86a5659e 3582 {
986ffb24 3583 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3584 fab.fab$l_alq = 0; /* zero the allocation quantity */
3585 if (xabpro.xab$w_acllen > 0)
3586 {
3587 if (xabpro.xab$w_acllen > sizeof aclbuf)
3588 /* If the acl buffer was too short, redo open with longer one.
3589 Wouldn't need to do this if there were some system imposed
3590 limit on the size of an ACL, but I can't find any such. */
3591 {
3592 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
3593 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
986ffb24
JB
3594 if (SYS$OPEN (&fab, 0, 0) & 1)
3595 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3596 else
3597 old = 0;
3598 }
3599 }
3600 else
3601 xabpro.xab$l_aclbuf = 0;
3602 }
3603 else
3604 old = 0;
3605 }
3606 fab.fab$l_fna = new;
3607 fab.fab$b_fns = strlen (new);
3608 if (!old)
3609 {
3610 fab.fab$l_xab = 0;
3611 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
3612 fab.fab$b_rat = FAB$M_CR;
3613 }
3614
3615 /* Set the file protections such that we will be able to manipulate
3616 this file. Once we are done writing and renaming it, we will set
3617 the protections back. */
3618 if (old)
3619 fab_final_pro = xabpro.xab$w_pro;
3620 else
986ffb24 3621 SYS$SETDFPROT (0, &fab_final_pro);
86a5659e
JB
3622 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
3623
3624 /* Create the new file with either default attrs or attrs copied
3625 from old file. */
3626 if (!(SYS$CREATE (&fab, 0, 0) & 1))
3627 return -1;
986ffb24 3628 SYS$CLOSE (&fab, 0, 0);
86a5659e
JB
3629 /* As this is a "replacement" for creat, return a file descriptor
3630 opened for writing. */
3631 return open (new, O_WRONLY);
3632}
3633
3634#ifdef creat
3635#undef creat
3636#include <varargs.h>
3637#ifdef __GNUC__
3638#ifndef va_count
3639#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3640#endif
3641#endif
3642
3643sys_creat (va_alist)
3644 va_dcl
3645{
eb8c3be9 3646 va_list list_incrementer;
86a5659e
JB
3647 char *name;
3648 int mode;
3649 int rfd; /* related file descriptor */
3650 int fd; /* Our new file descriptor */
3651 int count;
3652 struct stat st_buf;
3653 char rfm[12];
3654 char rat[15];
3655 char mrs[13];
3656 char fsz[13];
3657 extern int vms_stmlf_recfm;
3658
3659 va_count (count);
eb8c3be9
JB
3660 va_start (list_incrementer);
3661 name = va_arg (list_incrementer, char *);
3662 mode = va_arg (list_incrementer, int);
86a5659e 3663 if (count > 2)
eb8c3be9
JB
3664 rfd = va_arg (list_incrementer, int);
3665 va_end (list_incrementer);
86a5659e
JB
3666 if (count > 2)
3667 {
3668 /* Use information from the related file descriptor to set record
3669 format of the newly created file. */
3670 fstat (rfd, &st_buf);
3671 switch (st_buf.st_fab_rfm)
3672 {
3673 case FAB$C_FIX:
3674 strcpy (rfm, "rfm = fix");
3675 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
3676 strcpy (rat, "rat = ");
3677 if (st_buf.st_fab_rat & FAB$M_CR)
3678 strcat (rat, "cr");
3679 else if (st_buf.st_fab_rat & FAB$M_FTN)
3680 strcat (rat, "ftn");
3681 else if (st_buf.st_fab_rat & FAB$M_PRN)
3682 strcat (rat, "prn");
3683 if (st_buf.st_fab_rat & FAB$M_BLK)
3684 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3685 strcat (rat, ", blk");
3686 else
3687 strcat (rat, "blk");
3688 return creat (name, 0, rfm, rat, mrs);
3689
3690 case FAB$C_VFC:
3691 strcpy (rfm, "rfm = vfc");
3692 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
3693 strcpy (rat, "rat = ");
3694 if (st_buf.st_fab_rat & FAB$M_CR)
3695 strcat (rat, "cr");
3696 else if (st_buf.st_fab_rat & FAB$M_FTN)
3697 strcat (rat, "ftn");
3698 else if (st_buf.st_fab_rat & FAB$M_PRN)
3699 strcat (rat, "prn");
3700 if (st_buf.st_fab_rat & FAB$M_BLK)
3701 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3702 strcat (rat, ", blk");
3703 else
3704 strcat (rat, "blk");
3705 return creat (name, 0, rfm, rat, fsz);
3706
3707 case FAB$C_STM:
3708 strcpy (rfm, "rfm = stm");
3709 break;
3710
3711 case FAB$C_STMCR:
3712 strcpy (rfm, "rfm = stmcr");
3713 break;
3714
3715 case FAB$C_STMLF:
3716 strcpy (rfm, "rfm = stmlf");
3717 break;
3718
3719 case FAB$C_UDF:
3720 strcpy (rfm, "rfm = udf");
3721 break;
3722
3723 case FAB$C_VAR:
3724 strcpy (rfm, "rfm = var");
3725 break;
3726 }
3727 strcpy (rat, "rat = ");
3728 if (st_buf.st_fab_rat & FAB$M_CR)
3729 strcat (rat, "cr");
3730 else if (st_buf.st_fab_rat & FAB$M_FTN)
3731 strcat (rat, "ftn");
3732 else if (st_buf.st_fab_rat & FAB$M_PRN)
3733 strcat (rat, "prn");
3734 if (st_buf.st_fab_rat & FAB$M_BLK)
3735 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3736 strcat (rat, ", blk");
3737 else
3738 strcat (rat, "blk");
3739 }
3740 else
3741 {
3742 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3743 strcpy (rat, "rat=cr");
3744 }
3745 /* Until the VAX C RTL fixes the many bugs with modes, always use
3746 mode 0 to get the user's default protection. */
3747 fd = creat (name, 0, rfm, rat);
3748 if (fd < 0 && errno == EEXIST)
3749 {
3750 if (unlink (name) < 0)
3751 report_file_error ("delete", build_string (name));
3752 fd = creat (name, 0, rfm, rat);
3753 }
3754 return fd;
3755}
3756#endif /* creat */
3757
3758/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3759sys_fwrite (ptr, size, num, fp)
3760 register char * ptr;
3761 FILE * fp;
3762{
3763 register int tot = num * size;
3764
3765 while (tot--)
3766 fputc (*ptr++, fp);
3767}
3768
3769/*
3770 * The VMS C library routine creat actually creates a new version of an
3771 * existing file rather than truncating the old version. There are times
3772 * when this is not the desired behavior, for instance, when writing an
3773 * auto save file (you only want one version), or when you don't have
3774 * write permission in the directory containing the file (but the file
3775 * itself is writable). Hence this routine, which is equivalent to
3776 * "close (creat (fn, 0));" on Unix if fn already exists.
3777 */
3778int
3779vms_truncate (fn)
3780 char *fn;
3781{
3782 struct FAB xfab = cc$rms_fab;
3783 struct RAB xrab = cc$rms_rab;
3784 int status;
3785
3786 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3787 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3788 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3789 xfab.fab$l_fna = fn;
3790 xfab.fab$b_fns = strlen (fn);
3791 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3792 xfab.fab$b_dns = 2;
3793 xrab.rab$l_fab = &xfab;
3794
3795 /* This gibberish opens the file, positions to the first record, and
3796 deletes all records from there until the end of file. */
986ffb24 3797 if ((SYS$OPEN (&xfab) & 01) == 01)
86a5659e 3798 {
986ffb24
JB
3799 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
3800 (SYS$FIND (&xrab) & 01) == 01 &&
3801 (SYS$TRUNCATE (&xrab) & 01) == 01)
86a5659e
JB
3802 status = 0;
3803 else
3804 status = -1;
3805 }
3806 else
3807 status = -1;
986ffb24 3808 SYS$CLOSE (&xfab);
86a5659e
JB
3809 return status;
3810}
3811
3812/* Define this symbol to actually read SYSUAF.DAT. This requires either
3813 SYSPRV or a readable SYSUAF.DAT. */
3814
3815#ifdef READ_SYSUAF
3816/*
3817 * getuaf.c
3818 *
3819 * Routine to read the VMS User Authorization File and return
3820 * a specific user's record.
3821 */
3822
3823static struct UAF retuaf;
3824
3825struct UAF *
3826get_uaf_name (uname)
3827 char * uname;
3828{
3829 register status;
3830 struct FAB uaf_fab;
3831 struct RAB uaf_rab;
3832
3833 uaf_fab = cc$rms_fab;
3834 uaf_rab = cc$rms_rab;
3835 /* initialize fab fields */
3836 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3837 uaf_fab.fab$b_fns = 21;
3838 uaf_fab.fab$b_fac = FAB$M_GET;
3839 uaf_fab.fab$b_org = FAB$C_IDX;
3840 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3841 /* initialize rab fields */
3842 uaf_rab.rab$l_fab = &uaf_fab;
3843 /* open the User Authorization File */
986ffb24 3844 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3845 if (!(status&1))
3846 {
3847 errno = EVMSERR;
3848 vaxc$errno = status;
3849 return 0;
3850 }
986ffb24 3851 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3852 if (!(status&1))
3853 {
3854 errno = EVMSERR;
3855 vaxc$errno = status;
3856 return 0;
3857 }
3858 /* read the requested record - index is in uname */
3859 uaf_rab.rab$l_kbf = uname;
3860 uaf_rab.rab$b_ksz = strlen (uname);
3861 uaf_rab.rab$b_rac = RAB$C_KEY;
3862 uaf_rab.rab$l_ubf = (char *)&retuaf;
3863 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3864 status = SYS$GET (&uaf_rab);
86a5659e
JB
3865 if (!(status&1))
3866 {
3867 errno = EVMSERR;
3868 vaxc$errno = status;
3869 return 0;
3870 }
3871 /* close the User Authorization File */
986ffb24 3872 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3873 if (!(status&1))
3874 {
3875 errno = EVMSERR;
3876 vaxc$errno = status;
3877 return 0;
3878 }
986ffb24 3879 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3880 if (!(status&1))
3881 {
3882 errno = EVMSERR;
3883 vaxc$errno = status;
3884 return 0;
3885 }
3886 return &retuaf;
3887}
3888
3889struct UAF *
3890get_uaf_uic (uic)
3891 unsigned long uic;
3892{
3893 register status;
3894 struct FAB uaf_fab;
3895 struct RAB uaf_rab;
3896
3897 uaf_fab = cc$rms_fab;
3898 uaf_rab = cc$rms_rab;
3899 /* initialize fab fields */
3900 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3901 uaf_fab.fab$b_fns = 21;
3902 uaf_fab.fab$b_fac = FAB$M_GET;
3903 uaf_fab.fab$b_org = FAB$C_IDX;
3904 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3905 /* initialize rab fields */
3906 uaf_rab.rab$l_fab = &uaf_fab;
3907 /* open the User Authorization File */
986ffb24 3908 status = SYS$OPEN (&uaf_fab);
86a5659e
JB
3909 if (!(status&1))
3910 {
3911 errno = EVMSERR;
3912 vaxc$errno = status;
3913 return 0;
3914 }
986ffb24 3915 status = SYS$CONNECT (&uaf_rab);
86a5659e
JB
3916 if (!(status&1))
3917 {
3918 errno = EVMSERR;
3919 vaxc$errno = status;
3920 return 0;
3921 }
3922 /* read the requested record - index is in uic */
3923 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3924 uaf_rab.rab$l_kbf = (char *) &uic;
3925 uaf_rab.rab$b_ksz = sizeof uic;
3926 uaf_rab.rab$b_rac = RAB$C_KEY;
3927 uaf_rab.rab$l_ubf = (char *)&retuaf;
3928 uaf_rab.rab$w_usz = sizeof retuaf;
986ffb24 3929 status = SYS$GET (&uaf_rab);
86a5659e
JB
3930 if (!(status&1))
3931 {
3932 errno = EVMSERR;
3933 vaxc$errno = status;
3934 return 0;
3935 }
3936 /* close the User Authorization File */
986ffb24 3937 status = SYS$DISCONNECT (&uaf_rab);
86a5659e
JB
3938 if (!(status&1))
3939 {
3940 errno = EVMSERR;
3941 vaxc$errno = status;
3942 return 0;
3943 }
986ffb24 3944 status = SYS$CLOSE (&uaf_fab);
86a5659e
JB
3945 if (!(status&1))
3946 {
3947 errno = EVMSERR;
3948 vaxc$errno = status;
3949 return 0;
3950 }
3951 return &retuaf;
3952}
3953
3954static struct passwd retpw;
3955
3956struct passwd *
3957cnv_uaf_pw (up)
3958 struct UAF * up;
3959{
3960 char * ptr;
3961
3962 /* copy these out first because if the username is 32 chars, the next
3963 section will overwrite the first byte of the UIC */
3964 retpw.pw_uid = up->uaf$w_mem;
3965 retpw.pw_gid = up->uaf$w_grp;
3966
3967 /* I suppose this is not the best sytle, to possibly overwrite one
3968 byte beyond the end of the field, but what the heck... */
3969 ptr = &up->uaf$t_username[UAF$S_USERNAME];
3970 while (ptr[-1] == ' ')
3971 ptr--;
3972 *ptr = '\0';
3973 strcpy (retpw.pw_name, up->uaf$t_username);
3974
3975 /* the rest of these are counted ascii strings */
3976 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3977 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3978 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3979 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3980 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3981 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3982 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3983 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3984
3985 return &retpw;
3986}
3987#else /* not READ_SYSUAF */
3988static struct passwd retpw;
3989#endif /* not READ_SYSUAF */
3990
3991struct passwd *
3992getpwnam (name)
3993 char * name;
3994{
3995#ifdef READ_SYSUAF
3996 struct UAF *up;
3997#else
3998 char * user;
3999 char * dir;
4000 unsigned char * full;
4001#endif /* READ_SYSUAF */
4002 char *ptr = name;
4003
4004 while (*ptr)
4005 {
4006 if ('a' <= *ptr && *ptr <= 'z')
4007 *ptr -= 040;
4008 ptr++;
4009 }
4010#ifdef READ_SYSUAF
4011 if (!(up = get_uaf_name (name)))
4012 return 0;
4013 return cnv_uaf_pw (up);
4014#else
4015 if (strcmp (name, getenv ("USER")) == 0)
4016 {
4017 retpw.pw_uid = getuid ();
4018 retpw.pw_gid = getgid ();
4019 strcpy (retpw.pw_name, name);
4020 if (full = egetenv ("FULLNAME"))
4021 strcpy (retpw.pw_gecos, full);
4022 else
4023 *retpw.pw_gecos = '\0';
4024 strcpy (retpw.pw_dir, egetenv ("HOME"));
4025 *retpw.pw_shell = '\0';
4026 return &retpw;
4027 }
4028 else
4029 return 0;
4030#endif /* not READ_SYSUAF */
4031}
4032
4033struct passwd *
4034getpwuid (uid)
4035 unsigned long uid;
4036{
4037#ifdef READ_SYSUAF
4038 struct UAF * up;
4039
4040 if (!(up = get_uaf_uic (uid)))
4041 return 0;
4042 return cnv_uaf_pw (up);
4043#else
4044 if (uid == sys_getuid ())
4045 return getpwnam (egetenv ("USER"));
4046 else
4047 return 0;
4048#endif /* not READ_SYSUAF */
4049}
4050
4051/* return total address space available to the current process. This is
4052 the sum of the current p0 size, p1 size and free page table entries
4053 available. */
4054vlimit ()
4055{
4056 int item_code;
4057 unsigned long free_pages;
4058 unsigned long frep0va;
4059 unsigned long frep1va;
4060 register status;
4061
4062 item_code = JPI$_FREPTECNT;
4063 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
4064 {
4065 errno = EVMSERR;
4066 vaxc$errno = status;
4067 return -1;
4068 }
4069 free_pages *= 512;
4070
4071 item_code = JPI$_FREP0VA;
4072 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
4073 {
4074 errno = EVMSERR;
4075 vaxc$errno = status;
4076 return -1;
4077 }
4078 item_code = JPI$_FREP1VA;
4079 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
4080 {
4081 errno = EVMSERR;
4082 vaxc$errno = status;
4083 return -1;
4084 }
4085
4086 return free_pages + frep0va + (0x7fffffff - frep1va);
4087}
4088
4089define_logical_name (varname, string)
4090 char *varname;
4091 char *string;
4092{
4093 struct dsc$descriptor_s strdsc =
4094 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
4095 struct dsc$descriptor_s envdsc =
4096 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4097 struct dsc$descriptor_s lnmdsc =
4098 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4099
4100 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
4101}
4102
4103delete_logical_name (varname)
4104 char *varname;
4105{
4106 struct dsc$descriptor_s envdsc =
4107 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
4108 struct dsc$descriptor_s lnmdsc =
4109 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
4110
4111 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
4112}
4113
4114ulimit ()
4115{}
4116
86a5659e
JB
4117setpgrp ()
4118{}
4119
4120execvp ()
4121{
4122 error ("execvp system call not implemented");
4123}
4124
4125int
4126rename (from, to)
4127 char *from, *to;
4128{
4129 int status;
4130 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
4131 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
4132 char from_esn[NAM$C_MAXRSS];
4133 char to_esn[NAM$C_MAXRSS];
4134
4135 from_fab.fab$l_fna = from;
4136 from_fab.fab$b_fns = strlen (from);
4137 from_fab.fab$l_nam = &from_nam;
4138 from_fab.fab$l_fop = FAB$M_NAM;
4139
4140 from_nam.nam$l_esa = from_esn;
4141 from_nam.nam$b_ess = sizeof from_esn;
4142
4143 to_fab.fab$l_fna = to;
4144 to_fab.fab$b_fns = strlen (to);
4145 to_fab.fab$l_nam = &to_nam;
4146 to_fab.fab$l_fop = FAB$M_NAM;
4147
4148 to_nam.nam$l_esa = to_esn;
4149 to_nam.nam$b_ess = sizeof to_esn;
4150
4151 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
4152
4153 if (status & 1)
4154 return 0;
4155 else
4156 {
4157 if (status == RMS$_DEV)
4158 errno = EXDEV;
4159 else
4160 errno = EVMSERR;
4161 vaxc$errno = status;
4162 return -1;
4163 }
4164}
4165
4166/* This function renames a file like `rename', but it strips
4167 the version number from the "to" filename, such that the "to" file is
4168 will always be a new version. It also sets the file protection once it is
4169 finished. The protection that we will use is stored in fab_final_pro,
4170 and was set when we did a creat_copy_attrs to create the file that we
4171 are renaming.
4172
4173 We could use the chmod function, but Eunichs uses 3 bits per user category
eb8c3be9 4174 to describe the protection, and VMS uses 4 (write and delete are separate
86a5659e
JB
4175 bits). To maintain portability, the VMS implementation of `chmod' wires
4176 the W and D bits together. */
4177
4178
4179static struct fibdef fib; /* We need this initialized to zero */
4180char vms_file_written[NAM$C_MAXRSS];
4181
4182int
4183rename_sans_version (from,to)
4184 char *from, *to;
4185{
4186 short int chan;
4187 int stat;
4188 short int iosb[4];
4189 int status;
4190 struct FAB to_fab = cc$rms_fab;
4191 struct NAM to_nam = cc$rms_nam;
4192 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
4193 struct dsc$descriptor fib_attr[2]
4194 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
4195 char to_esn[NAM$C_MAXRSS];
4196
4197 $DESCRIPTOR (disk,to_esn);
4198
4199 to_fab.fab$l_fna = to;
4200 to_fab.fab$b_fns = strlen (to);
4201 to_fab.fab$l_nam = &to_nam;
4202 to_fab.fab$l_fop = FAB$M_NAM;
4203
4204 to_nam.nam$l_esa = to_esn;
4205 to_nam.nam$b_ess = sizeof to_esn;
4206
4207 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
4208
4209 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
4210 *(to_nam.nam$l_ver) = '\0';
4211
4212 stat = rename (from, to_esn);
4213 if (stat < 0)
4214 return stat;
4215
4216 strcpy (vms_file_written, to_esn);
4217
4218 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
4219 to_fab.fab$b_fns = strlen (vms_file_written);
4220
4221 /* Now set the file protection to the correct value */
986ffb24 4222 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
86a5659e
JB
4223
4224 /* Copy these fields into the fib */
4225 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
4226 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
4227 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
4228
986ffb24 4229 SYS$CLOSE (&to_fab, 0, 0);
86a5659e 4230
986ffb24 4231 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
86a5659e 4232 if (!stat)
986ffb24
JB
4233 LIB$SIGNAL (stat);
4234 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
86a5659e
JB
4235 0, 0, 0, &fib_attr, 0);
4236 if (!stat)
986ffb24
JB
4237 LIB$SIGNAL (stat);
4238 stat = SYS$DASSGN (chan);
86a5659e 4239 if (!stat)
986ffb24 4240 LIB$SIGNAL (stat);
0137dbf7 4241 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
4242 return 0;
4243}
4244
4245link (file, new)
4246 char * file, * new;
4247{
4248 register status;
4249 struct FAB fab;
4250 struct NAM nam;
4251 unsigned short fid[3];
4252 char esa[NAM$C_MAXRSS];
4253
4254 fab = cc$rms_fab;
4255 fab.fab$l_fop = FAB$M_OFP;
4256 fab.fab$l_fna = file;
4257 fab.fab$b_fns = strlen (file);
4258 fab.fab$l_nam = &nam;
4259
4260 nam = cc$rms_nam;
4261 nam.nam$l_esa = esa;
4262 nam.nam$b_ess = NAM$C_MAXRSS;
4263
4264 status = SYS$PARSE (&fab);
4265 if ((status & 1) == 0)
4266 {
4267 errno = EVMSERR;
4268 vaxc$errno = status;
4269 return -1;
4270 }
4271 status = SYS$SEARCH (&fab);
4272 if ((status & 1) == 0)
4273 {
4274 errno = EVMSERR;
4275 vaxc$errno = status;
4276 return -1;
4277 }
4278
4279 fid[0] = nam.nam$w_fid[0];
4280 fid[1] = nam.nam$w_fid[1];
4281 fid[2] = nam.nam$w_fid[2];
4282
4283 fab.fab$l_fna = new;
4284 fab.fab$b_fns = strlen (new);
4285
4286 status = SYS$PARSE (&fab);
4287 if ((status & 1) == 0)
4288 {
4289 errno = EVMSERR;
4290 vaxc$errno = status;
4291 return -1;
4292 }
4293
4294 nam.nam$w_fid[0] = fid[0];
4295 nam.nam$w_fid[1] = fid[1];
4296 nam.nam$w_fid[2] = fid[2];
4297
4298 nam.nam$l_esa = nam.nam$l_name;
4299 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
4300
4301 status = SYS$ENTER (&fab);
4302 if ((status & 1) == 0)
4303 {
4304 errno = EVMSERR;
4305 vaxc$errno = status;
4306 return -1;
4307 }
4308
4309 return 0;
4310}
4311
4312croak (badfunc)
4313 char *badfunc;
4314{
4315 printf ("%s not yet implemented\r\n", badfunc);
4316 reset_sys_modes ();
4317 exit (1);
4318}
4319
4320long
4321random ()
4322{
4323 /* Arrange to return a range centered on zero. */
4324 return rand () - (1 << 30);
4325}
4326
4327srandom (seed)
4328{
4329 srand (seed);
4330}
4331#endif /* VMS */
4332\f
4333#ifdef AIX
4334
4335/* Called from init_sys_modes. */
4336hft_init ()
4337{
4338 int junk;
4339
4340 /* If we're not on an HFT we shouldn't do any of this. We determine
4341 if we are on an HFT by trying to get an HFT error code. If this
4342 call fails, we're not on an HFT. */
4343#ifdef IBMR2AIX
4344 if (ioctl (0, HFQERROR, &junk) < 0)
4345 return;
4346#else /* not IBMR2AIX */
4347 if (ioctl (0, HFQEIO, 0) < 0)
4348 return;
4349#endif /* not IBMR2AIX */
4350
4351 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4352 as the rubout key's ASCII code. Here this is changed. The bug is that
4353 there's no way to determine the old mapping, so in reset_sys_modes
4354 we need to assume that the normal map had been present. Of course, this
4355 code also doesn't help if on a terminal emulator which doesn't understand
4356 HFT VTD's. */
4357 {
4358 struct hfbuf buf;
4359 struct hfkeymap keymap;
4360
4361 buf.hf_bufp = (char *)&keymap;
4362 buf.hf_buflen = sizeof (keymap);
4363 keymap.hf_nkeys = 2;
4364 keymap.hfkey[0].hf_kpos = 15;
4365 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4366#ifdef IBMR2AIX
4367 keymap.hfkey[0].hf_keyidh = '<';
4368#else /* not IBMR2AIX */
4369 keymap.hfkey[0].hf_page = '<';
4370#endif /* not IBMR2AIX */
4371 keymap.hfkey[0].hf_char = 127;
4372 keymap.hfkey[1].hf_kpos = 15;
4373 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4374#ifdef IBMR2AIX
4375 keymap.hfkey[1].hf_keyidh = '<';
4376#else /* not IBMR2AIX */
4377 keymap.hfkey[1].hf_page = '<';
4378#endif /* not IBMR2AIX */
4379 keymap.hfkey[1].hf_char = 127;
4380 hftctl (0, HFSKBD, &buf);
4381 }
4382 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4383 at times. */
4384 line_ins_del_ok = char_ins_del_ok = 0;
4385}
4386
4387/* Reset the rubout key to backspace. */
4388
4389hft_reset ()
4390{
4391 struct hfbuf buf;
4392 struct hfkeymap keymap;
4393 int junk;
4394
4395#ifdef IBMR2AIX
4396 if (ioctl (0, HFQERROR, &junk) < 0)
4397 return;
4398#else /* not IBMR2AIX */
4399 if (ioctl (0, HFQEIO, 0) < 0)
4400 return;
4401#endif /* not IBMR2AIX */
4402
4403 buf.hf_bufp = (char *)&keymap;
4404 buf.hf_buflen = sizeof (keymap);
4405 keymap.hf_nkeys = 2;
4406 keymap.hfkey[0].hf_kpos = 15;
4407 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4408#ifdef IBMR2AIX
4409 keymap.hfkey[0].hf_keyidh = '<';
4410#else /* not IBMR2AIX */
4411 keymap.hfkey[0].hf_page = '<';
4412#endif /* not IBMR2AIX */
4413 keymap.hfkey[0].hf_char = 8;
4414 keymap.hfkey[1].hf_kpos = 15;
4415 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4416#ifdef IBMR2AIX
4417 keymap.hfkey[1].hf_keyidh = '<';
4418#else /* not IBMR2AIX */
4419 keymap.hfkey[1].hf_page = '<';
4420#endif /* not IBMR2AIX */
4421 keymap.hfkey[1].hf_char = 8;
4422 hftctl (0, HFSKBD, &buf);
4423}
4424
4425#endif /* AIX */