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