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