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