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