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