⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zhcon.cpp

📁 zhcon是工作在Linux控制台下的高效双字节中/日/韩(CJK)虚拟终端
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// vi:ts=4:shiftwidth=4:expandtab/***************************************************************************                          zhcon.cpp  -  description                             -------------------    begin                : Fri Mar 23 2001    copyright            : (C) 2001 by ejoy    email                : ejoy@users.sourceforge.net ***************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <iostream>#include <unistd.h>#include <cstdlib>#include <cstdio>#include <sys/ioctl.h>#if defined(linux)    #include <linux/limits.h>    #include <linux/kd.h>    #include <linux/vt.h>    #include <pty.h>#elif defined(__FreeBSD__)    #include <termios.h>    //#include <machine/console.h>    #include <sys/consio.h>    #include <libutil.h>    #define TCSETA TIOCSETA#endif#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include <pwd.h>#include <stdexcept>#include <algorithm>#include <locale.h>#include "global.h"#include "console.h"#include "encfilter.h"#include "inputclient.h"#include "inputmanager.h"#include "nativeinputserver.h"#ifdef HAVE_UNICON_LIB    #include "uniconinputserver.h"#endif// for termcap, must include after gpm.h, why?#include <term.h>#include "gbkdecoder.h"#include "gbdecoder.h"#include "big5decoder.h"#include "gb2big5decoder.h"#include "big52gbdecoder.h"#include "jisdecoder.h"#include "kscdecoder.h"#include "configfile.h"//#include "fade.h"#include "zhcon.h"#include "basefont.h"#include "encfilter.h"#include "cmdline.h"//#include "popwin.h"BaseFont* gpHzFont;BaseFont* gpAscFont;#ifndef NDEBUG#include "debug.h"ofstream debug("debug");#endifZhcon* Zhcon::mpZhcon = NULL;int Zhcon::mTtyPid = 0;Zhcon::STATE Zhcon::mState = STOP;void Zhcon::SignalVtLeave(int signo) {    if(Zhcon::mpZhcon != NULL) mpZhcon->VtDoLeave();}void Zhcon::SignalVtEnter(int signo) {    if(Zhcon::mpZhcon != NULL) mpZhcon->VtDoEnter();}Zhcon::Zhcon(int argc, char* argv[]):mpCon(NULL),mpInputManager(NULL){    Zhcon::mpZhcon = this;    mConFd = mTtyFd = -1;    /* let's call our CMDLINE Parser */    if (cmdline_parser(argc, argv, &mArgs) != 0) {        cmdline_parser_print_help();        throw runtime_error("fail to parse command line arguments");    }    if (mArgs.utf8_flag)            UseEncodingFilter = 1;}Zhcon::~Zhcon() {    CleanUp();    Zhcon::mpZhcon = NULL;}void Zhcon::Init() {    //reading config file    string cfgfile = getenv("HOME");    cfgfile += "/.zhconrc";    if (access(cfgfile.c_str(), R_OK) != 0)        cfgfile = "/etc/zhcon.conf";    //for debug,a pause enable us to attach zhcon's pid in gdb    //char c;cin>>c;    ConfigFile f(cfgfile.c_str());    //the InitXXX sequence is important,do not change    //unless you know what you are doing    InitTty();    // set blank line height, must before init font    InitGraphDev(f);    GraphMode();	seteuid(getuid());    InitLocale(f); // include init font    InitCon(f);    InitMisc(f);    VtSignalLeave();    InstallSignal();    ForkPty();    // if setlocale run before forkpty, it cause FreeBSD hang    SetEncode(mDefaultEncode, mDefaultEncode);    InitInputManager(f);    if (f.GetOption("startupmsg",true))        StartupMsg();}void Zhcon::Run() {    InputEvt evt;    Encode e;    int t = 0;//    fadeout();//    fadein();    mState = RUNNING;    while (mState == RUNNING) {        mpCon->CursorBlink();        mpInputManager->Process(evt);        gpScreen->Update(); //   force ggi to update screen        if (evt.oper != InputEvt::Nothing) {            DoInputEvt(evt);            continue;        }        if (++t < 10 || mAutoEncode == MANUAL)            continue;                    t = 0;        e = mpCon->DetectBufferEncode();        switch (e) {            case ASCII:                SetEncode(mDefaultEncode, mDefaultEncode);                break;            case GB2312:                SetEncode(GB2312,                          mAutoEncode ==                          AUTO_BIG5 ? BIG5 : GB2312);                break;            case BIG5:                SetEncode(BIG5,                          mAutoEncode ==                          AUTO_GB ? GB2312 : BIG5);                break;            default:               assert(!"Wrong encode!");        }    } //while}void Zhcon::DoInputEvt(InputEvt &evt) {    switch (evt.oper) {        case InputEvt::SetEnco:            switch (evt.sub) {                case 1:                    SetEncode(GB2312, GB2312);                    break;                case 2:                    SetEncode(GBK, GBK);                    break;                case 3:                    SetEncode(BIG5, BIG5);                    break;                case 4:                    SetEncode(JIS, JIS);                    break;                case 5:                    SetEncode(KSC, KSC);                    break;                default:                    break;            }            break;        case InputEvt::AutoEncoSwitch:            switch (mAutoEncode) {                case AUTO:                    mAutoEncode = AUTO_GB;                    break;                case AUTO_GB:                    mAutoEncode = AUTO_BIG5;                    break;                case AUTO_BIG5:                    mAutoEncode = MANUAL;                    break;                case MANUAL:                    mAutoEncode = AUTO;                    break;            }            mpInputManager->Redraw();            Beep();            break;        default:            break;    }}//fork a new pty to run user's shellvoid Zhcon::ForkPty() {    char name[50];    mTtyPid = forkpty(&mTtyFd, name, NULL, NULL);    if (mTtyPid == -1)        throw runtime_error("forkpty fail!");    ioctl(0, TIOCSCTTY, 0);    if (mTtyPid == 0) {        //child        struct passwd *userpd;        if ((userpd = getpwuid(getuid())) == NULL)            throw runtime_error("can not get user's shell!");        /* close all opened file */        int open_max = sysconf(_SC_OPEN_MAX);        for (int i = 3; i < open_max; i++)            close(i);        setsid();        // seteuid(getuid());   /* for security */        //TODO: handle error condition        if (mArgs.inputs_num > 0) {            // the second arg of execvp must be terminated by a NULL pointer            // we have to create a new one with NULL pointer at the end            char** args = (char**)malloc(sizeof(char*)*(mArgs.inputs_num+1));            for (size_t i = 0; i < mArgs.inputs_num; ++i)                args[i] = mArgs.inputs[i];            args[mArgs.inputs_num] = NULL;            cout << "Executing [";            for (size_t i = 0; i < mArgs.inputs_num; ++i)                cout << ' ' << args[i] << ' ';            cout << ']' << endl;            execvp(args[0], args);        } else            execlp(userpd->pw_shell, userpd->pw_shell, (char *) 0);        exit(0);    }}void Zhcon::InstallSignal() {    struct sigaction act;    act.sa_handler = SignalHandle;    act.sa_flags = 0;    sigemptyset(&act.sa_mask);    sigaction(SIGHUP, &act, NULL);    sigaction(SIGINT, &act, NULL);    sigaction(SIGQUIT, &act, NULL);    sigaction(SIGILL, &act, NULL);    sigaction(SIGABRT, &act, NULL);    sigaction(SIGIOT, &act, NULL);    sigaction(SIGBUS, &act, NULL);    sigaction(SIGFPE, &act, NULL);    sigaction(SIGTERM, &act, NULL);    act.sa_handler = &SignalChild;    sigemptyset(&act.sa_mask);    act.sa_flags = 0;    sigaction(SIGCHLD, &act, NULL);    //    act.sa_handler = &SignalAlarm;    //    sigemptyset(&act.sa_mask);    //    act.sa_flags = 0;    //    sigaction(SIGALRM, &act, NULL);}//do some clean up before quitvoid Zhcon::CleanUp() {    struct sigaction act;    /* done in procress and block all serious signal to prevent interrupt */    act.sa_handler = SIG_IGN;    act.sa_flags = 0;    sigemptyset(&act.sa_mask);    sigaction(SIGHUP, &act, NULL);    sigaction(SIGINT, &act, NULL);    sigaction(SIGQUIT, &act, NULL);    sigaction(SIGILL, &act, NULL);    sigaction(SIGABRT, &act, NULL);    sigaction(SIGIOT, &act, NULL);    sigaction(SIGBUS, &act, NULL);    sigaction(SIGFPE, &act, NULL);    VtSignalClean();#if defined(__FreeBSD__)    ioctl(0, VT_RELDISP, 1);#endif    GraphDev::Close();    delete gpAscFont;    delete gpHzFont;    delete gpDecoder;    delete mpCon;    delete mpInputManager;    if (mConFd != -1) {        // need restore signal ?        tcsetattr(mConFd, TCSAFLUSH, &mOldTermios);        // restore console blanking#if defined(linux)        write(mConFd, "\033[9;10]",7);  // default 10 minutes#elif defined(__FreeBSD__)         int BlankTime = 5;  // default 5 minutes        ioctl(mConFd, CONS_BLANKTIME, &BlankTime);#endif        ioctl(mConFd, KDSETMODE, KD_TEXT);  // special for vga        ioctl(mConFd, TIOCSWINSZ, &mOldWinSize);        // for mouse, keep text mode clean        // write(mConFd, "\n", 1);        // make visible cursor, use termcap "ve" instead        //write(mConFd, "\E[?25h\E[?0c", 11);        if (mpCapCursorOn) write(mConFd, mpCapCursorOn, strlen(mpCapCursorOn));        close(mConFd);    }    if (mArgs.utf8_flag)        CleanupEncodingFilter();    setenv("LC_ALL", mOldLocale.c_str(), 1);}char  Zhcon::mCapBuf[512] = {0};char* Zhcon::mpCapClearScr = NULL;char* Zhcon::mpCapCursorOff = NULL;char* Zhcon::mpCapCursorOn = NULL;void Zhcon::InitTty() {    // Using throw cause core dump when call destruct    if (!isatty(fileno(stdout))) {        printf("This is an interactive api, don't redirect stdout.\r\n");        exit(1);    }    char *TtyName = ttyname(fileno(stdout));    if (!TtyName) {        printf("Can not get current tty name.\r\n");        exit(1);    }        if (!(strncmp("/dev/tty", TtyName, 8) == 0 ||        strncmp("/dev/vc/", TtyName, 8) == 0)) {        fprintf(stderr, "warning!!!\n");        fprintf(stderr, "%s is not real tty or vc, are your running under X-Window?\n", TtyName);#ifndef HAVE_GGI_LIB        fprintf(stderr, "libggi support not complied in, can not run under X-Window, now quit\n");        exit(1);#endif    }        mConFd = open(TtyName, O_RDWR);    if (mConFd == -1)        throw runtime_error("Can not open console!");    if (tcgetattr(mConFd, &mOldTermios) < 0)        throw runtime_error("Can't get console termios.");    struct termios t;    t = mOldTermios;    t.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | NOFLSH);    t.c_iflag &= ~(BRKINT | ICRNL | ISTRIP | IXON);    t.c_cflag &= ~(CSIZE | PARENB);    t.c_cflag |= CS8;    t.c_oflag &= ~(OPOST);    t.c_cc[VMIN] = 1;    t.c_cc[VTIME] = 0;#if defined(linux)    t.c_line = 0;#elif defined(__FreeBSD__)    t.c_cc[VDISCARD] = _POSIX_VDISABLE;    t.c_cc[VLNEXT] = _POSIX_VDISABLE;    t.c_cc[VSTART] = _POSIX_VDISABLE;    t.c_cc[VSTOP] = _POSIX_VDISABLE;

⌨️ 快捷键说明

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