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 + -
显示快捷键?