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