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