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