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