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