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