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