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