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