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