📄 sysdep.c
字号:
/* Interfaces to system-dependent kernel and library entries. Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.This file is part of GNU Emacs.GNU Emacs is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Emacs is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Emacs; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <signal.h>#include <setjmp.h>#include "config.h"#include "lisp.h"#undef NULL#define min(x,y) ((x) > (y) ? (y) : (x))/* In this file, open, read and write refer to the system calls, not our sugared interfaces sys_open, sys_read and sys_write. Contrariwise, for systems where we use the system calls directly, define sys_read, etc. here as aliases for them. */#ifndef read#define sys_read read#define sys_write write#endif /* `read' is not a macro */#undef read#undef write#ifndef close#define sys_close close#else #undef close#endif#ifndef open#define sys_open open#else /* `open' is a macro */#undef open#endif /* `open' is a macro */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>extern int errno;#ifndef VMS#ifndef BSD4_4extern char *sys_errlist[];#endif#endifchar __progname[] = "emacs";#ifdef VMS#include <rms.h>#include <ttdef.h>#include <tt2def.h>#include <iodef.h>#include <ssdef.h>#include <descrip.h>#include <ctype.h>#include <file.h>#ifndef RAB$C_BID#include <rab.h>#endif#define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */#endif /* VMS */#ifndef BSD4_1#ifdef BSD /* this is done this way to avoid defined(BSD) || defined (USG) because the vms compiler doesn't grok `defined' */#include <fcntl.h>#endif#ifdef USG#include <fcntl.h>#endif#endif /* not 4.1 bsd */#ifdef BSD#include <sys/ioctl.h>#ifdef BSD4_1#include <wait.h>#else /* not 4.1 */#include <sys/wait.h>#endif /* not 4.1 */#endif /* BSD */#ifdef STRIDE#include <sys/ioctl.h>#endif #ifdef mips#include <sys/ioctl.h>#endif #ifdef AIX/* Get files for keyboard remapping */#define HFNKEYS 2#include <sys/hft.h>#include <sys/devinfo.h>#endif/* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs. */#ifdef BSD4_1#undef LLITOUT#define LLITOUT 0#endif /* 4.1 */#ifdef HAVE_TERMIO#ifdef IBMR2AIX#include <termio.h>#include <termios.h>#ifdef TIOCGETP#undef TIOCGETP#endif#define TIOCGETP TCGETS#undef TIOCSETN#define TIOCSETN TCSETSW#undef TIOCSETP#define TIOCSETP TCSETSF#undef TCSETAW#define TCSETAW TCSETS#else#include <termio.h>#undef TIOCGETP#define TIOCGETP TCGETA#undef TIOCSETN#define TIOCSETN TCSETAW#undef TIOCSETP#define TIOCSETP TCSETAF#endif#ifndef IBMR2AIX#define TERMINAL struct termio#else#define TERMINAL struct termios#endif#define OSPEED(str) (str.c_cflag & CBAUD)#define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))#define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)#endif /* HAVE_TERMIO */#ifdef XENIX#undef TIOCGETC /* Avoid confusing some conditionals that test this. */#endif#ifdef BROKEN_TIOCGETC#undef TIOCGETC#endif#ifndef HAVE_TERMIO#ifndef VMS#include <sgtty.h>#define TERMINAL struct sgttyb#define OSPEED(str) str.sg_ospeed#define SETOSPEED(str,new) (str.sg_ospeed = (new))#define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS)#undef TCSETAW#define TCSETAW TIOCSETN#endif /* not VMS */#endif /* not HAVE_TERMIO */#ifdef USG#include <sys/utsname.h>#include <memory.h>#include <string.h>#ifdef TIOCGWINSZ#ifndef IRIS_4D#ifndef mips#ifndef aix386#ifndef NO_SIOCTL_H/* Some USG systems with TIOCGWINSZ need this file; some don't have it. We don't know how to distinguish them. If this #include gets an error, just delete it. */#include <sys/sioctl.h>#endif#ifdef NEED_PTEM_H#include <sys/stream.h>#include <sys/ptem.h>#endif#endif /* not aix386 */#endif /* not mips */#endif /* not IRIS_4D */#endif /* TIOCGWINSZ */#ifdef HAVE_TIMEVAL#ifdef HPUX#include <time.h>#else#include <sys/time.h>#endif#endif /* HAVE_TIMEVAL */#endif /* USG */#ifdef VMS#include "window.h"#endif #ifdef NEED_BSDTTY#include <sys/bsdtty.h>#endif #if defined (HPUX) && defined (HAVE_PTYS)#include <sys/ptyio.h>#endif #ifdef AIX#include <sys/pty.h>#include <unistd.h>#endif /* AIX */#ifdef SYSV_PTYS#include <sys/tty.h>#include <sys/pty.h>#endif#ifdef BROKEN_FIONREAD#undef FIONREAD#endifextern int quit_char;#include "termhooks.h"#include "termchar.h"#include "termopts.h"#include "dispextern.h"#ifdef NONSYSTEM_DIR_LIBRARY#include "ndir.h"#endif /* NONSYSTEM_DIR_LIBRARY */#ifndef sigmask#define sigmask(no) (1L << ((no) - 1))#endif/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals testing SIGCHLD. */#ifndef VMS#ifdef SIGCLD#ifndef SIGCHLD#define SIGCHLD SIGCLD#endif /* not SIGCHLD */#endif /* SIGCLD */#endif /* not VMS */static int baud_convert[] =#ifdef BAUD_CONVERT BAUD_CONVERT;#else { 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 };#endifextern short ospeed;#ifdef VMSstatic struct iosb{ short status; short offset; short termlen; short term;} input_iosb;int kbd_input_ast ();int waiting_for_ast;int stop_input;int input_ef = 0;int timer_ef = 0;int process_ef = 0;int input_eflist;int timer_eflist;static int input_chan;static $DESCRIPTOR (input_dsc, "TT");static int terminator_mask[2] = { 0, 0 };static struct sensemode { short status; unsigned char xmit_baud; unsigned char rcv_baud; unsigned char crfill; unsigned char lffill; unsigned char parity; unsigned char unused; char class; char type; short scr_wid; unsigned long tt_char : 24, scr_len : 8; unsigned long tt2_char;} sensemode_iosb;#define TERMINAL struct sensemode#define OSPEED(str) (str.xmit_baud)#define TABS_OK(str) ((str.tt_char & TT$M_MECHTAB) != 0)#endif /* VMS */discard_tty_input (){ TERMINAL buf; if (noninteractive) return;#ifdef VMS end_kbd_input (); SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, &buf, 0, 0, terminator_mask, 0, 0); queue_kbd_input ();#else /* not VMS */ ioctl (0, TIOCGETP, &buf); ioctl (0, TIOCSETP, &buf);#endif /* not VMS */}#ifdef SIGTSTPstuff_char (c) char c;{/* Should perhaps error if in batch mode */#ifdef TIOCSTI ioctl (0, TIOCSTI, &c);#else /* no TIOCSTI */ error ("Cannot stuff terminal input characters in this version of Unix.");#endif /* no TIOCSTI */}#endif /* SIGTSTP */init_baud_rate (){ TERMINAL sg; if (noninteractive) ospeed = 0; else {#ifdef VMS SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0, &sg.class, 12, 0, 0, 0, 0 );#else SETOSPEED (sg, B9600); ioctl (0, TIOCGETP, &sg);#endif /* not VMS */ ospeed = OSPEED (sg); } baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0] ? baud_convert[ospeed] : 9600); if (baud_rate == 0) baud_rate = 1200;}/*ARGSUSED*/set_exclusive_use (fd) int fd;{#ifdef FIOCLEX ioctl (fd, FIOCLEX, 0);#endif /* Ok to do nothing if this feature does not exist */}#ifndef subprocesseswait_without_blocking (){#ifdef BSD wait3 (0, WNOHANG | WUNTRACED, 0);#else croak ("wait_without_blocking");#endif}#endif /* not subprocesses */int wait_debugging; /* Set nonzero to make following function work under dbx (at least for bsd). *//* Wait for subprocess with process id `pid' to terminate and make sure it will get eliminated (not remain forever as a zombie) */wait_for_termination (pid) int pid;{ while (1) {#ifdef subprocesses#if defined(BSD) || (defined(HPUX) && !defined(HPUX_5)) /* Note that kill returns -1 even if the process is just a zombie now. But inevitably a SIGCHLD interrupt should be generated and child_sig will do wait3 and make the process go away. */ /* There is some indication that there is a bug involved with termination of subprocesses, perhaps involving a kernel bug too, but no idea what it is. Just as a hunch we signal SIGCHLD to see if that causes the problem to go away or get worse. */#ifdef BSD4_1 extern int synch_process_pid; sighold (SIGCHLD); if (synch_process_pid == 0) { sigrelse (SIGCHLD); break; } if (wait_debugging) sleep (1); else sigpause (SIGCHLD);#else /* not BSD4_1 */ sigsetmask (1 << (SIGCHLD - 1)); if (0 > kill (pid, 0)) { sigsetmask (0); kill (getpid (), SIGCHLD); break; } if (wait_debugging) sleep (1); else sigpause (0);#endif /* not BSD4_1 */#else /* not BSD, and not HPUX version >= 6 */#ifdef UNIPLUS if (0 > kill (pid, 0)) break; wait (0);#else /* neither BSD nor UNIPLUS: random sysV */ if (0 > kill (pid, 0)) break; pause ();#endif /* not UNIPLUS */#endif /* not BSD, and not HPUX version >= 6 */#else /* not subprocesses */#ifndef BSD4_1 if (0 > kill (pid, 0)) break; wait (0);#else /* BSD4_1 */ int status; status = wait (0); if (status == pid || status == -1) break;#endif /* BSD4_1 */#endif /* not subprocesses */ }}#ifdef subprocesses/* * flush any pending output * (may flush input as well; it does not matter the way we use it) */ flush_pending_output (channel) int channel;{#ifdef TCFLSH ioctl (channel, TCFLSH, 1);#else#ifdef TIOCFLUSH int zero = 0; /* 3rd arg should be ignored but some 4.2 kernels actually want the address of an int and nonzero means something different. */ ioctl (channel, TIOCFLUSH, &zero);#endif#endif}/* Set up the terminal at the other end of a pseudo-terminal that we will be controlling an inferior through. It should not echo or do line-editing, since that is done in Emacs. No padding needed for insertion into an Emacs buffer. */child_setup_tty (out) int out;{ TERMINAL s; ioctl (out, TIOCGETP, &s);#ifdef HAVE_TERMIO s.c_oflag |= OPOST; /* Enable output postprocessing */ s.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */ s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); /* No output delays */ s.c_lflag &= ~ECHO; /* Disable echo */ s.c_lflag |= ISIG; /* Enable signals */ s.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on input */ s.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on output *//* said to be unnecesary s.c_cc[VMIN] = 1; /* minimum number of characters to accept s.c_cc[VTIME] = 0; /* wait forever for at least 1 character*/ s.c_lflag |= ICANON; /* Enable erase/kill and eof processing */ s.c_cc[VEOF] = 04; /* insure that EOF is Control-D */ s.c_cc[VERASE] = 0377; /* disable erase processing */ s.c_cc[VKILL] = 0377; /* disable kill processing */#ifdef HPUX s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */#endif HPUX#ifdef AIX/* AIX enhanced edit loses NULs, so disable it */#ifndef IBMR2AIX s.c_line = 0; s.c_iflag &= ~ASCEDIT;#endif /* Also, PTY overloads NUL and BREAK. don't ignore break, but don't signal either, so it looks like NUL. */ s.c_iflag &= ~IGNBRK; s.c_iflag &= ~BRKINT;/* QUIT and INTR work better as signals, so disable character forms */ s.c_cc[VQUIT] = 0377; s.c_cc[VINTR] = 0377; s.c_cc[VEOL] = 0377; s.c_lflag &= ~ISIG; s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */#endif /* AIX */#else /* not HAVE_TERMIO */ s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);#endif /* not HAVE_TERMIO */ ioctl (out, TIOCSETN, &s);#ifdef BSD4_1 if (interrupt_input) reset_sigio ();#endif /* BSD4_1 */#ifdef RTU { int zero = 0; ioctl (out, FIOASYNC, &zero); }#endif /* RTU */}#endif /* subprocesses *//*ARGSUSED*/setpgrp_of_tty (pid) int pid;{#ifdef IBMR2AIX tcsetpgrp ( 0, pid);#else#ifdef TIOCSPGRP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -