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