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