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