rxvtlib_command.c

来自「具有IDE功能的编辑器」· C语言 代码 · 共 2,607 行 · 第 1/5 页

C
2,607
字号
#include "rxvtlib.h"/*--------------------------------*-C-*---------------------------------* * File:	command.c *----------------------------------------------------------------------* * $Id: command.c,v 1.85.2.23 1999/08/12 16:32:39 mason Exp $ * * All portions of code are copyright by their respective author/s. * Copyright (C) 1992      John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk> *				- original version * Copyright (C) 1994      Robert Nation <nation@rocket.sanders.lockheed.com> * 				- extensive modifications * Copyright (C) 1995      Garrett D'Amore <garrett@netcom.com> *				- vt100 printing * Copyright (C) 1995      Steven Hirsch <hirsch@emba.uvm.edu> *				- X11 mouse report mode and support for *				  DEC "private mode" save/restore functions. * Copyright (C) 1995      Jakub Jelinek <jj@gnu.ai.mit.edu> *				- key-related changes to handle Shift+function *				  keys properly. * Copyright (C) 1997      MJ Olesen <olesen@me.queensu.ca> *				- extensive modifications * Copyright (C) 1997      Raul Garcia Garcia <rgg@tid.es> *				- modification and cleanups for Solaris 2.x *				  and Linux 1.2.x * Copyright (C) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de> * Copyright (C) 1998      Geoff Wing <gcw@pobox.com> * Copyright (C) 1998      Alfredo K. Kojima <kojima@windowmaker.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *----------------------------------------------------------------------*//*{{{ substitute system functions */#if defined(__svr4__) && ! defined(_POSIX_VERSION)/* INTPROTO */int             getdtablesize (void){    struct rlimit   rlim;    getrlimit (RLIMIT_NOFILE, &rlim);    return rlim.rlim_cur;}#endif/*}}} *//*{{{ take care of suid/sgid super-user (root) privileges *//* EXTPROTO */void            privileges (int mode){#if ! defined(__CYGWIN32__)# ifdef HAVE_SETEUID    static uid_t    euid;    static gid_t    egid;    switch (mode) {    case IGNORE:	/*	 * change effective uid/gid - not real uid/gid - so we can switch	 * back to root later, as required	 */	seteuid (getuid ());	setegid (getgid ());	break;    case SAVE:	euid = geteuid ();	egid = getegid ();	break;    case RESTORE:	seteuid (euid);	setegid (egid);	break;    }# else    switch (mode) {    case IGNORE:	setuid (getuid ());	setgid (getgid ());	/* FALLTHROUGH */    case SAVE:	/* FALLTHROUGH */    case RESTORE:	break;    }# endif#endif}/*}}} *//*{{{ signal handling, exit handler *//* * Catch a SIGCHLD signal and exit if the direct child has died *//* ARGSUSED *//* INTPROTO */#ifdef STANDALONErxvtlib *match_object_to_pid (rxvtlib * o, int pid) {    static struct pid_list {	rxvtlib *o;	int pid;	struct pid_list *next;    } pid_list = {    0, 0, 0};    if (pid <= 0)	return 0;    if (o) {	struct pid_list *p;/* new list entry */	for (p = &pid_list; p->next; p = p->next);	p->next = malloc (sizeof (struct pid_list));	p->next->next = 0;	p->next->o = o;	p->next->pid = pid;	return o;    } else {	struct pid_list *p, *q = 0;/* find the list entry */	for (p = &pid_list; p && p->pid != pid; p = p->next)	    q = p;	if (!p)	    return 0;/* remove it */	q->next = p->next;	o = p->o;	free (p);	return o;    }    return 0;}RETSIGTYPE Child_signal (int unused){    int pid, save_errno = errno;    rxvtlib *o;    do {	errno = 0;    } while ((-1 == (pid = waitpid (-1, NULL, WNOHANG)))	     && (errno == EINTR));    if ((o = match_object_to_pid (0, pid)))	o->killed = EXIT_SUCCESS | DO_EXIT;    errno = save_errno;    signal (SIGCHLD, Child_signal);}#endif#ifdef STANDALONE/* * Catch a fatal signal and tidy up before quitting *//* INTPROTO */RETSIGTYPE      Exit_signal (int sig){#ifdef DEBUG_CMD    print_error ("signal %d", sig);#endif    signal (sig, SIG_DFL);#ifdef UTMP_SUPPORT    if (!(Options & Opt_utmpInhibit)) {	privileges (RESTORE);	cleanutent ();	privileges (IGNORE);    }#endif    kill (getpid (), sig);}#endif/* * Exit gracefully, clearing the utmp entry and restoring tty attributes * TODO: this should free up any known resources if we can *//* INTPROTO */void            clean_exit (void){/*    scr_release ();#if defined(UTMP_SUPPORT) || ! defined(__CYGWIN32__)    privileges (RESTORE);# ifndef __CYGWIN32__    if (changettyowner) {#ifdef DEBUG_CMD	fprintf (stderr, "Restoring \"%s\" to mode %03o, uid %d, gid %d\n",		 ttydev, ttyfd_stat.st_mode, ttyfd_stat.st_uid,		 ttyfd_stat.st_gid);#endif	chmod (ttydev, ttyfd_stat.st_mode);	chown (ttydev, ttyfd_stat.st_uid, ttyfd_stat.st_gid);    }# endif# ifdef UTMP_SUPPORT    cleanutent ();# endif    privileges (IGNORE);#endif*/}/*}}} *//*{{{ Acquire a pseudo-teletype from the system. *//* * On failure, returns -1. * On success, returns the file descriptor. * * If successful, ttydev and ptydev point to the names of the * master and slave parts *//* INTPROTO */int             rxvtlib_get_pty (rxvtlib *o){    int             fd;    char           *ptydev;    if (o->ttydev) {	free (o->ttydev);	o->ttydev = 0;    }#ifdef PTYS_ARE__GETPTY    if ((ptydev = o->ttydev = (char *) strdup (_getpty (&fd, O_RDWR | O_NDELAY, 0622, 0))) != NULL)	goto Found;#endif#ifdef PTYS_ARE_GETPTY    while ((ptydev = getpty ()) != NULL)	if ((fd = open (ptydev, O_RDWR)) >= 0) {	    o->ttydev = strdup (ptydev);	    goto Found;	}#endif#if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT)# if defined(PTYS_ARE_GETPT) || defined(PTYS_ARE_PTMX)    {	extern char    *ptsname ();#  ifdef PTYS_ARE_GETPT	if ((fd = getpt ()) >= 0)#  else	    if ((fd = open ("/dev/ptmx", O_RDWR)) >= 0)#  endif	    {		if (grantpt (fd) == 0	/* change slave permissions */		    && unlockpt (fd) == 0) {	/* slave now unlocked */		    ptydev = o->ttydev = (char *) strdup (ptsname (fd));	/* get slave's name */		    o->changettyowner = 0;		    goto Found;		}		close (fd);	    }    }# endif#endif#ifdef PTYS_ARE_PTC    if ((fd = open ("/dev/ptc", O_RDWR)) >= 0) {	ptydev = o->ttydev = (char *) strdup (ttyname (fd));	goto Found;    }#endif#ifdef PTYS_ARE_CLONE    if ((fd = open ("/dev/ptym/clone", O_RDWR)) >= 0) {	ptydev = o->ttydev = (char *) strdup (ptsname (fd));	goto Found;    }#endif#ifdef PTYS_ARE_NUMERIC    {	int             idx;	char           *c1, *c2;	char            pty_name[] = "/dev/ptyp???";	char            tty_name[] = "/dev/ttyp???";	ptydev = pty_name;	o->ttydev = tty_name;	c1 = &(pty_name[sizeof (pty_name) - 4]);	c2 = &(tty_name[sizeof (tty_name) - 4]);	for (idx = 0; idx < 256; idx++) {	    sprintf (c1, "%d", idx);	    sprintf (c2, "%d", idx);	    if (access (o->ttydev, F_OK) < 0) {		idx = 256;		break;	    }	    if ((fd = open (ptydev, O_RDWR)) >= 0) {		if (access (o->ttydev, R_OK | W_OK) == 0) {		    o->ttydev = (char *) strdup (tty_name);		    goto Found;		}		close (fd);	    }	}    }#endif/* if PTYS_ARE_SEARCHED or no other method defined */#if defined(PTYS_ARE_SEARCHED) || (!defined(PTYS_ARE_CLONE) && !defined(PTYS_ARE_GETPT) && !defined(PTYS_ARE_GETPTY) && !defined(PTYS_ARE_NUMERIC) && !defined(PTYS_ARE_PTC) && !defined(PTYS_ARE_PTMX) && !defined(PTYS_ARE_SEARCHED) && !defined(PTYS_ARE__GETPTY))    {	int             len;	const char     *c1, *c2;	char            pty_name[] = "/dev/pty??";	char            tty_name[] = "/dev/tty??";	len = sizeof (pty_name) - 3;	ptydev = pty_name;	o->ttydev = tty_name;	for (c1 = PTYCHAR1; *c1; c1++) {	    ptydev[len] = o->ttydev[len] = *c1;	    for (c2 = PTYCHAR2; *c2; c2++) {		ptydev[len + 1] = o->ttydev[len + 1] = *c2;		if ((fd = open (ptydev, O_RDWR)) >= 0) {		    if (access (o->ttydev, R_OK | W_OK) == 0) {			o->ttydev = (char *) strdup (tty_name);			goto Found;		    }		    close (fd);		}	    }	}    }#endif    print_error ("can't open pseudo-tty");    return -1;  Found:    fcntl (fd, F_SETFL, O_NDELAY);    return fd;}/*}}} *//*{{{ establish a controlling teletype for new session *//* * On some systems this can be done with ioctl() but on others we * need to re-open the slave tty. *//* INTPROTO */int             rxvtlib_get_tty (rxvtlib *o){    int             fd, i;    pid_t           pid;/* * setsid() [or setpgrp] must be before open of the terminal, * otherwise there is no controlling terminal (Solaris 2.4, HP-UX 9) */#ifndef ultrix# ifdef NO_SETSID    pid = setpgrp (0, 0);# else    pid = setsid ();# endif    if (pid < 0)#ifdef STANDALONE	perror (o->rs[Rs_name]);#else	perror ("rxvtlib_get_tty");#endif# ifdef DEBUG_TTYMODE    print_error ("(%s: line %d): PID = %d\n", __FILE__, __LINE__, pid);# endif#endif				/* ultrix */    if ((fd = open (o->ttydev, O_RDWR)) < 0	&& (fd = open ("/dev/tty", O_RDWR)) < 0) {	print_error ("can't open slave tty %s", o->ttydev);	o->killed = EXIT_FAILURE | DO_EXIT;	return -1;    }#ifdef PTYS_ARE_PTMX/* * Push STREAMS modules: *    ptem: pseudo-terminal hardware emulation module. *    ldterm: standard terminal line discipline. *    ttcompat: V7, 4BSD and XENIX STREAMS compatibility module. */    if (!o->changettyowner) {	ioctl (fd, I_PUSH, "ptem");	ioctl (fd, I_PUSH, "ldterm");	ioctl (fd, I_PUSH, "ttcompat");    }#endif    if (o->changettyowner) {	/* change ownership of tty to real uid and real group */	unsigned int    mode = 0622;	gid_t           gid = getgid ();#ifdef TTY_GID_SUPPORT	{	    struct group   *gr = getgrnam ("tty");	    if (gr) {		/* change ownership of tty to real uid, "tty" gid */		gid = gr->gr_gid;		mode = 0620;	    }	}#endif				/* TTY_GID_SUPPORT */#ifndef __CYGWIN32__	privileges (RESTORE);	fchown (fd, getuid (), gid);	/* fail silently */	fchmod (fd, mode);	privileges (IGNORE);#endif    }/* * Close all file descriptors.  If only stdin/out/err are closed, * child processes remain alive upon deletion of the window. */    for (i = 0; i < o->num_fds; i++)	if (i != fd)	    close (i);/* Reopen stdin, stdout and stderr over the tty file descriptor */    dup2 (fd, 0);		/* stdin */    dup2 (fd, 1);		/* stdout */    dup2 (fd, 2);		/* stderr */    if (fd > 2)	close (fd);#ifdef ultrix    if ((fd = open ("/dev/tty", O_RDONLY)) >= 0) {	ioctl (fd, TIOCNOTTY, 0);	close (fd);    } else {	pid = setpgrp (0, 0);	if (pid < 0)#ifdef STANDALONE	    perror (o->rs[Rs_name]);#else	    perror ("rxvtlib_get_tty");#endif    }/* no error, we could run with no tty to begin with */#else				/* ultrix */# ifdef TIOCSCTTY    ioctl (0, TIOCSCTTY, 0);# endif/* set process group */# if defined (_POSIX_VERSION) || defined (__svr4__)    tcsetpgrp (0, pid);# elif defined (TIOCSPGRP)    ioctl (0, TIOCSPGRP, &pid);# endif/* svr4 problems: reports no tty, no job control *//* # if !defined (__svr4__) && defined (TIOCSPGRP) */    close (open (o->ttydev, O_RDWR, 0));/* # endif */#endif				/* ultrix */    return fd;}/*}}} *//*{{{ debug_ttymode() */#ifdef DEBUG_TTYMODE/* INTPROTO */void            debug_ttymode (const ttymode_t * ttymode){#ifdef HAVE_TERMIOS_H/* c_iflag bits */    fprintf (stderr, "Input flags\n");/* cpp token stringize doesn't work on all machines <sigh> *//* c_iflag bits */    FOO (IGNBRK, "IGNBRK");    FOO (BRKINT, "BRKINT");    FOO (IGNPAR, "IGNPAR");    FOO (PARMRK, "PARMRK");    FOO (INPCK, "INPCK");    FOO (ISTRIP, "ISTRIP");    FOO (INLCR, "INLCR");    FOO (IGNCR, "IGNCR");    FOO (ICRNL, "ICRNL");    FOO (IXON, "IXON");    FOO (IXOFF, "IXOFF");# ifdef IUCLC    FOO (IUCLC, "IUCLC");# endif# ifdef IXANY    FOO (IXANY, "IXANY");# endif# ifdef IMAXBEL    FOO (IMAXBEL, "IMAXBEL");# endif    fprintf (stderr, "\n\n");    FOO (VINTR, "VINTR");    FOO (VQUIT, "VQUIT");    FOO (VERASE, "VERASE");    FOO (VKILL, "VKILL");    FOO (VEOF, "VEOF");    FOO (VEOL, "VEOL");# ifdef VEOL2    FOO (VEOL2, "VEOL2");# endif# ifdef VSWTC    FOO (VSWTC, "VSWTC");# endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?