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