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