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