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