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