📄 main.c
字号:
/*--------------------------------*-C-*---------------------------------* * File: main.c *----------------------------------------------------------------------* * $Id: main.c,v 1.172 2002/10/24 01:50:58 gcw 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> * Copyright (c) 1997 mj olesen <olesen@me.QueensU.CA> * - extensive modifications * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de> * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com> * - extensive modifications * * 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. *---------------------------------------------------------------------*/#include "../config.h" /* NECESSARY */#include "rxvt.h" /* NECESSARY */#include "main.intpro" /* PROTOS for internal routines */#include <signal.h>#ifdef TTY_GID_SUPPORT# include <grp.h>#endif#ifdef HAVE_TERMIOS_H# include <termios.h>#endif/*----------------------------------------------------------------------*//* rxvt_init() *//* LIBPROTO */rxvt_t *rxvt_init(int argc, const char *const *argv){ const char **cmd_argv; rxvt_t *r; r = (rxvt_t *)rxvt_calloc(1, sizeof(rxvt_t)); rxvt_set_r(r); /* only assignment to _rxvt_vars */ if (rxvt_init_vars(r) < 0) { free(r); return NULL; }/* * Save and then give up any super-user privileges * If we need privileges in any area then we must specifically request it. * We should only need to be root in these cases: * 1. write utmp entries on some systems * 2. chown tty on some systems */ rxvt_privileges(r, SAVE); rxvt_privileges(r, IGNORE); rxvt_init_secondary(r); cmd_argv = rxvt_init_resources(r, argc, argv);#if (MENUBAR_MAX) rxvt_menubar_read(r, r->h->rs[Rs_menu]);#endif#ifdef HAVE_SCROLLBARS if (r->Options & Opt_scrollBar) scrollbar_setIdle(); /* set existence for size calculations */#endif rxvt_Create_Windows(r, argc, argv); rxvt_init_xlocale(r); rxvt_scr_reset(r); /* initialize screen */ rxvt_Gr_reset(r); /* reset graphics */#ifdef DEBUG_X XSynchronize(r->Xdisplay, True); XSetErrorHandler((XErrorHandler) abort);#else XSetErrorHandler((XErrorHandler) rxvt_xerror_handler);#endif#ifdef HAVE_SCROLLBARS if (r->Options & Opt_scrollBar) rxvt_Resize_scrollBar(r); /* create and map scrollbar */#endif#if (MENUBAR_MAX) if (menubar_visible(r)) XMapWindow(r->Xdisplay, r->menuBar.win);#endif#ifdef TRANSPARENT if (r->Options & Opt_transparent) { XSelectInput(r->Xdisplay, Xroot, PropertyChangeMask); rxvt_check_our_parents(r); }#endif XMapWindow(r->Xdisplay, r->TermWin.vt); XMapWindow(r->Xdisplay, r->TermWin.parent[0]); rxvt_init_env(r); rxvt_init_command(r, cmd_argv); return r;}/* ------------------------------------------------------------------------- * * SIGNAL HANDLING & EXIT HANDLER * * ------------------------------------------------------------------------- *//* * Catch a SIGCHLD signal and exit if the direct child has died *//* ARGSUSED *//* EXTPROTO */RETSIGTYPErxvt_Child_signal(int sig __attribute__((unused))){ int pid, save_errno = errno; rxvt_t *r; do { errno = 0; } while ((pid = waitpid(-1, NULL, WNOHANG)) == -1 && errno == EINTR); r = rxvt_get_r(); if (pid == r->h->cmd_pid) exit(EXIT_SUCCESS); errno = save_errno; signal(SIGCHLD, rxvt_Child_signal);}/* * Catch a fatal signal and tidy up before quitting *//* EXTPROTO */RETSIGTYPErxvt_Exit_signal(int sig){ signal(sig, SIG_DFL);#ifdef DEBUG_CMD rxvt_print_error("signal %d", sig);#endif rxvt_clean_exit(); kill(getpid(), sig);}/* ARGSUSED *//* INTPROTO */intrxvt_xerror_handler(const Display *display __attribute__((unused)), const XErrorEvent *event){ rxvt_t *r = rxvt_get_r(); if (r->h->allowedxerror == -1) { r->h->allowedxerror = event->error_code; return 0; /* ignored anyway */ } rxvt_print_error("XError: Request: %d . %d, Error: %d", event->request_code, event->minor_code, event->error_code); /* XXX: probably should call rxvt_clean_exit() bypassing X routines */ exit(EXIT_FAILURE); /* NOTREACHED */}/*----------------------------------------------------------------------*//* * Exit gracefully, clearing the utmp entry and restoring tty attributes * TODO: if debugging, this should free up any known resources if we can *//* EXTPROTO */voidrxvt_clean_exit(void){ rxvt_t *r = rxvt_get_r();#ifdef DEBUG_SCREEN rxvt_scr_release(r);#endif rxvt_privileged_ttydev(r, RESTORE); rxvt_privileged_utmp(r, RESTORE);#ifdef USE_XIM if (r->h->Input_Context != NULL) { XDestroyIC(r->h->Input_Context); r->h->Input_Context = NULL; }#endif}/* ------------------------------------------------------------------------- * * MEMORY ALLOCATION WRAPPERS * * ------------------------------------------------------------------------- *//* EXTPROTO */void *rxvt_malloc(size_t size){ void *p; p = malloc(size); if (p) return p; fprintf(stderr, APL_NAME ": memory allocation failure. Aborting"); rxvt_clean_exit(); exit(EXIT_FAILURE); /* NOTREACHED */}/* EXTPROTO */void *rxvt_calloc(size_t number, size_t size){ void *p; p = calloc(number, size); if (p) return p; fprintf(stderr, APL_NAME ": memory allocation failure. Aborting"); rxvt_clean_exit(); exit(EXIT_FAILURE); /* NOTREACHED */}/* EXTPROTO */void *rxvt_realloc(void *ptr, size_t size){ void *p; if (ptr) p = realloc(ptr, size); else p = malloc(size); if (p) return p; fprintf(stderr, APL_NAME ": memory allocation failure. Aborting"); rxvt_clean_exit(); exit(EXIT_FAILURE); /* NOTREACHED */}/* ------------------------------------------------------------------------- * * PRIVILEGED OPERATIONS * * ------------------------------------------------------------------------- *//* take care of suid/sgid super-user (root) privileges *//* INTPROTO */voidrxvt_privileges(rxvt_t *r, int mode){#if ! defined(__CYGWIN32__)# if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)/* setreuid() is the poor man's setuid(), seteuid() */# define seteuid(a) setreuid(-1, (a))# define setegid(a) setregid(-1, (a))# define HAVE_SETEUID# endif# ifdef HAVE_SETEUID 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: r->h->euid = geteuid(); r->h->egid = getegid(); break; case RESTORE: seteuid(r->h->euid); setegid(r->h->egid); break; }# else switch (mode) { case IGNORE: setuid(getuid()); setgid(getgid()); /* FALLTHROUGH */ case SAVE: /* FALLTHROUGH */ case RESTORE: break; }# endif#endif}#ifdef UTMP_SUPPORT/* EXTPROTO */voidrxvt_privileged_utmp(rxvt_t *r, char action){ struct rxvt_hidden *h = r->h; D_MAIN((stderr, "rxvt_privileged_utmp(%c); waiting for: %c (pid: %d)", action, h->next_utmp_action, getpid())); if (h->next_utmp_action != action || (action != SAVE && action != RESTORE) || (r->Options & Opt_utmpInhibit) || h->ttydev == NULL || *h->ttydev == '\0') return; rxvt_privileges(r, RESTORE); if (action == SAVE) { h->next_utmp_action = RESTORE; rxvt_makeutent(r, h->ttydev, h->rs[Rs_display_name]); } else { /* action == RESTORE */ h->next_utmp_action = IGNORE; rxvt_cleanutent(r); } rxvt_privileges(r, IGNORE);}#endif#ifndef NO_SETOWNER_TTYDEV/* EXTPROTO */voidrxvt_privileged_ttydev(rxvt_t *r, char action){ struct rxvt_hidden *h = r->h; D_MAIN((stderr, "rxvt_privileged_ttydev(r, %c); waiting for: %c (pid: %d)", action, h->next_tty_action, getpid())); if (h->next_tty_action != action || (action != SAVE && action != RESTORE) || h->ttydev == NULL || *h->ttydev == '\0') return; rxvt_privileges(r, RESTORE); if (action == SAVE) { h->next_tty_action = RESTORE;# ifndef RESET_TTY_TO_COMMON_DEFAULTS/* store original tty status for restoration rxvt_clean_exit() -- rgg 04/12/95 */ if (lstat(h->ttydev, &h->ttyfd_stat) < 0) /* you lose out */ h->next_tty_action = IGNORE; else# endif { chown(h->ttydev, getuid(), h->ttygid); /* fail silently */ chmod(h->ttydev, h->ttymode);# ifdef HAVE_REVOKE revoke(h->ttydev);# endif } } else { /* action == RESTORE */ h->next_tty_action = IGNORE;# ifndef RESET_TTY_TO_COMMON_DEFAULTS chmod(h->ttydev, h->ttyfd_stat.st_mode); chown(h->ttydev, h->ttyfd_stat.st_uid, h->ttyfd_stat.st_gid);# else chmod(h->ttydev, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)); chown(h->ttydev, 0, 0);# endif } rxvt_privileges(r, IGNORE);# ifndef RESET_TTY_TO_COMMON_DEFAULTS D_MAIN((stderr, "%s \"%s\": mode %03o, uid %d, gid %d", action == RESTORE ? "Restoring" : (action == SAVE ? "Saving" : "UNKNOWN ERROR for"), h->ttydev, h->ttyfd_stat.st_mode, h->ttyfd_stat.st_uid, h->ttyfd_stat.st_gid));# endif}#endif/*----------------------------------------------------------------------*//* * window size/position calculcations for XSizeHint and other storage. * if width/height are non-zero then override calculated width/height *//* EXTPROTO */voidrxvt_window_calc(rxvt_t *r, unsigned int width, unsigned int height){ short recalc_x, recalc_y; int x, y, sb_w, mb_h, flags; unsigned int w, h; unsigned int max_width, max_height; r->szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity; r->szHint.win_gravity = NorthWestGravity; /* r->szHint.min_aspect.x = r->szHint.min_aspect.y = 1; */ recalc_x = recalc_y = 0; flags = 0; if (!r->h->parsed_geometry) { r->h->parsed_geometry = 1; if (r->h->rs[Rs_geometry]) flags = XParseGeometry(r->h->rs[Rs_geometry], &x, &y, &w, &h); if (flags & WidthValue) { r->TermWin.ncol = BOUND_POSITIVE_INT16(w); r->szHint.flags |= USSize; } if (flags & HeightValue) { r->TermWin.nrow = BOUND_POSITIVE_INT16(h); r->szHint.flags |= USSize; } if (flags & XValue) { r->szHint.x = x; r->szHint.flags |= USPosition; if (flags & XNegative) { recalc_x = 1; r->szHint.win_gravity = NorthEastGravity; } } if (flags & YValue) { r->szHint.y = y; r->szHint.flags |= USPosition; if (flags & YNegative) { recalc_y = 1; if (r->szHint.win_gravity == NorthEastGravity) r->szHint.win_gravity = SouthEastGravity; else r->szHint.win_gravity = SouthWestGravity; } } }/* TODO: BOUNDS */ r->TermWin.width = r->TermWin.ncol * r->TermWin.fwidth; r->TermWin.height = r->TermWin.nrow * r->TermWin.fheight; max_width = MAX_COLS * r->TermWin.fwidth; max_height = MAX_ROWS * r->TermWin.fheight; r->szHint.base_width = r->szHint.base_height = 2 * r->TermWin.int_bwidth; sb_w = mb_h = 0; r->h->window_vt_x = r->h->window_vt_y = 0; if (scrollbar_visible(r)) { sb_w = scrollbar_TotalWidth(); r->szHint.base_width += sb_w; if (!(r->Options & Opt_scrollBar_right)) r->h->window_vt_x = sb_w; } if (menubar_visible(r)) { mb_h = menuBar_TotalHeight(); r->szHint.base_height += mb_h; r->h->window_vt_y = mb_h; } r->szHint.width_inc = r->TermWin.fwidth; r->szHint.height_inc = r->TermWin.fheight; r->szHint.min_width = r->szHint.base_width + r->szHint.width_inc; r->szHint.min_height = r->szHint.base_height + r->szHint.height_inc; if (width && width - r->szHint.base_width < max_width) { r->szHint.width = width; r->TermWin.width = width - r->szHint.base_width; } else { MIN_IT(r->TermWin.width, max_width); r->szHint.width = r->szHint.base_width + r->TermWin.width; } if (height && height - r->szHint.base_height < max_height) { r->szHint.height = height; r->TermWin.height = height - r->szHint.base_height; } else { MIN_IT(r->TermWin.height, max_height); r->szHint.height = r->szHint.base_height + r->TermWin.height; } if (scrollbar_visible(r) && (r->Options & Opt_scrollBar_right)) r->h->window_sb_x = r->szHint.width - sb_w; if (recalc_x) r->szHint.x += (DisplayWidth(r->Xdisplay, Xscreen) - r->szHint.width - 2 * r->TermWin.ext_bwidth); if (recalc_y) r->szHint.y += (DisplayHeight(r->Xdisplay, Xscreen) - r->szHint.height - 2 * r->TermWin.ext_bwidth); r->TermWin.ncol = r->TermWin.width / r->TermWin.fwidth; r->TermWin.nrow = r->TermWin.height / r->TermWin.fheight; return;}/*----------------------------------------------------------------------*//* * Tell the teletype handler what size the window is. * Called after a window size change. *//* EXTPROTO */voidrxvt_tt_winsize(int fd, unsigned short col, unsigned short row){ struct winsize ws; if (fd < 0) return; ws.ws_col = col; ws.ws_row = row; ws.ws_xpixel = ws.ws_ypixel = 0; ioctl(fd, TIOCSWINSZ, &ws);}/*----------------------------------------------------------------------*//* rxvt_change_font() - Switch to a new font *//* * init = 1 - initialize * * fontname == FONT_UP - switch to bigger font * fontname == FONT_DN - switch to smaller font
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -