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