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