/****************************************************************************** * Copyright (C) 2005 by la9527 * * * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.* ******************************************************************************/ #include #include #include #include #include #include #include #include "define.h" #include "drawset.h" #include "colorcfgload.h" #include "mlscfgload.h" #include "mlslocale.h" #include "reader.h" #include "mainframe.h" #include "mlsdialog.h" //#define __DEBUGMODE__ using namespace MLSUTIL; using namespace MLS; namespace { // 처음 기본 세팅 bool _bMcdExe = false; ///< MCD실행 여부 ENCODING _nLangSet = AUTO; ///< 언어 설정 LINECODE _nLineSet = ACSLINE; ///< LINE MODE vector _vCfgFile, _vColFile, _vKeyFile, _vEditorKeyFile; } /// @brief 시그널 처리를 하는 함수 /// @param sig 시그널 번호 void signal_action(int sig) { switch(sig) { case SIGINT: // Copy & paste를 위해서 Ctrl-C를 사용합니다. ungetch(3); return; } CursesDestroy(); # if (__GNUC__ * 1000 + __GNUC_MINOR__) >= 3000 printf("Signal [%d] [%s]\n", sig, strsignal(sig)); # else printf("Signal [%d]\n", sig); # endif exit(0); } /// @brief 시그널블럭 처리를 한다. /// @return 성공할 경우 SUCCESS int signal_blocking(void) { struct sigaction act; // 다음은 시그널이 들어왔을 때 실행 함수 act.sa_handler = signal_action; // 다음 주석을 해제 하면 시그널 무시 //act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, 0); /* 2 Interrupt (ANSI). */ #ifndef __DEBUGMODE__ sigaction(SIGHUP, &act, 0); /* 1 Hangup (POSIX). */ sigaction(SIGQUIT, &act, 0); /* 3 Quit (POSIX). */ sigaction(SIGILL, &act, 0); /* 4 Illegal instruction (ANSI). */ sigaction(SIGTRAP, &act, 0); /* 5 Trace trap (POSIX). */ sigaction(SIGABRT, &act, 0); /* 6 Abort (ANSI). */ sigaction(SIGBUS, &act, 0); /* 7 BUS error (4.2 BSD). */ sigaction(SIGFPE, &act, 0); /* 8 Floating-point exception (ANSI). */ // sigaction(SIGKILL, &act, 0); /* 9 Kill, unblockable (POSIX). */ sigaction(SIGUSR1, &act, 0); /* 10 User-defined signal 1 (POSIX). */ sigaction(SIGSEGV, &act, 0); /* 11 Segmentation violation (ANSI). */ sigaction(SIGUSR2, &act, 0); /* 12 User-defined signal 2 (POSIX). */ sigaction(SIGPIPE, &act, 0); /* 13 Broken pipe (POSIX). */ sigaction(SIGALRM, &act, 0); /* 14 Alarm clock (POSIX). */ sigaction(SIGTERM, &act, 0); /* 15 Termination (ANSI). */ // sigaction(SIGCHLD, &act, 0); /* 17 Child status has changed (POSIX). */ sigaction(SIGCONT, &act, 0); /* 18 Continue (POSIX). */ sigaction(SIGSTOP, &act, 0); /* 19 Stop, unblockable (POSIX). */ sigaction(SIGTSTP, &act, 0); /* 20 Keyboard stop (POSIX). */ sigaction(SIGTTIN, &act, 0); /* 21 Background read from tty (POSIX). */ sigaction(SIGTTOU, &act, 0); /* 22 Background write to tty (POSIX). */ sigaction(SIGURG, &act, 0); /* 23 Urgent condition on socket (4.2 BSD). */ sigaction(SIGXFSZ, &act, 0); /* 24 CPU limit exceeded (4.2 BSD). */ sigaction(SIGXCPU, &act, 0); /* 25 File size limit exceeded (4.2 BSD). */ sigaction(SIGVTALRM, &act, 0); /* 26 File size limit exceeded (4.2 BSD). */ sigaction(SIGPROF, &act, 0); /* 27 Profiling alarm clock (4.2 BSD). */ // sigaction(SIGWINCH, &act, 0); /* 28 Window size change (4.3 BSD, Sun). */ sigaction(SIGIO, &act, 0); /* 29 I/O now possible (4.2 BSD). Pollable event occurred (System V).*/ sigaction(SIGSYS, &act, 0); /* 31 Bad system call. (Unused) */ #ifdef LINUX sigaction(SIGSTKFLT, &act, 0); /* 16 Stack fault. */ sigaction(SIGPWR, &act, 0); /* 30 Power failure restart (System V). */ #endif #endif return 0; } /// @brief mls 시작시 초기화 함수 /// /// config준비. 설정파일 읽기, 컬러셋 읽기, history읽기를 한다. /// @return 성공여부 0일때 성공 bool Initialize() { int t; const char *succMsg = "[\033[01;36m SUCCESS \033[0m]"; const char *failMsg = "[\033[01;31m FAIL \033[0m]"; const char *errMsg = "[\033[01;31m ERROR \033[0m]"; char* cwd = getcwd(NULL, 0); if (cwd == NULL) { String sMsg; sMsg.AppendBlank(60, "%s", strerror(errno)); cout << sMsg.c_str(); cout << errMsg << endl; return false; } if (access(cwd, R_OK | X_OK) == -1) { String sMsg; sMsg.AppendBlank(60, "%s", strerror(errno)); cout << sMsg.c_str(); cout << errMsg << endl; return false; } free(cwd); Set_Locale(_nLangSet); // Locale 설정 string sCfgDefaultPath, sCfgColorPath; sCfgDefaultPath = sCfgDefaultPath + __LINM_CFGPATH__ + "/default.cfg"; sCfgColorPath = sCfgColorPath + __LINM_CFGPATH__ + "/colorset.cfg"; { // Config 준비.. struct passwd *pw = getpwuid(getuid()); { std::string home = pw->pw_dir; home += '/'; g_tCfg.SetStaticValue("Home", home); } // . config dir 지정 g_tCfg.SetStaticValue("CfgHome", g_tCfg.GetValue("Static", "Home") + ".linm/"); g_tCfg.SetStaticValue("TmpDir", g_tCfg.GetValue("Static", "Home") + ".linm/linm_tmpdir/"); g_tColorCfg.Init(); // 홈에 .linm를 만든다. mcd treeinfo를 저장하기 위해서도 필요 mkdir((g_tCfg.GetValue("Static", "Home") + ".linm").c_str(), 0755); // 파일 복사에 필요한 tmp 디렉토리. mkdir((g_tCfg.GetValue("Static", "TmpDir")).c_str(), 0777); } { // 설정 파일 읽기 _vCfgFile.push_back( g_tCfg.GetValue("Static", "CfgHome") + "default.cfg" ); _vCfgFile.push_back( sCfgDefaultPath ); for (t=0; t<_vCfgFile.size(); t++) { string cfgfile = _vCfgFile[t]; if (g_tCfg.Load(cfgfile.c_str())) { g_tCfg.SetStaticValue("CfgFile", cfgfile); #ifdef __DEBUGMODE__ String sMsg; sMsg.AppendBlank(60, "Load configuration %s", cfgfile.c_str()); cout << sMsg.c_str(); cout << succMsg << endl; #endif if (cfgfile == sCfgDefaultPath) { string sCmd = "cp " + sCfgDefaultPath + " " + g_tCfg.GetValue("Static", "Home") + ".linm"; system(sCmd.c_str()); } break; } else { String sMsg; sMsg.AppendBlank(60, "Load configuration %s", cfgfile.c_str()); cout << sMsg.c_str(); cout << failMsg << endl; } } if (t == _vCfgFile.size()) { String sMsg; sMsg.AppendBlank(60, "Load configuration "); cout << sMsg.c_str(); cout << failMsg << endl; return false; } } { // 컬러셋 읽기 if ( g_tCfg.GetValue("Default", "ColorSetFile") != "") _vColFile.push_back( g_tCfg.GetValue("Static", "CfgHome") + g_tCfg.GetValue("Default", "ColorSetFile")); _vColFile.push_back( sCfgColorPath ); for (t=0; t<_vColFile.size(); t++) { string colfile = _vColFile[t]; if (g_tColorCfg.Load(colfile.c_str())) { g_tCfg.SetStaticValue("ColFile", colfile); #ifdef __DEBUGMODE__ String sMsg; sMsg.AppendBlank(60, "Load colorset %s", colfile.c_str()); cout << sMsg.c_str(); cout << succMsg << endl; #endif if (colfile == sCfgColorPath) { string sCmd = "cp " + sCfgColorPath + " " + g_tCfg.GetValue("Static", "Home") + ".linm"; system(sCmd.c_str()); } break; } else { String sMsg; sMsg.AppendBlank(60, "Load colorset %s", colfile.c_str()); cout << failMsg << endl; } } if (t == _vColFile.size()) { String sMsg; sMsg.AppendBlank(60, "Load colorset"); cout << sMsg.c_str(); cout << failMsg << endl; return false; } } return true; } /// @brief Mls keybind파일, mls editor keybind 파일을 읽는다. /// /// MainFrame 안에 KeyBind가 있기 때문에 따로 만듬. /// @return keybind 파일 읽기 성공여부. bool Load_KeyFile() { int t; const char *succMsg = "[\033[01;36m SUCCESS \033[0m]"; const char *failMsg = "[\033[01;31m FAIL \033[0m]"; string sKeyCfgPath; sKeyCfgPath = sKeyCfgPath + __LINM_CFGPATH__ + "/keyset.cfg"; {// Key Binding file을 읽는다. if (g_tCfg.GetValue("Default", "KeySetFile") != "") _vKeyFile.push_back( g_tCfg.GetValue("Static", "CfgHome") + g_tCfg.GetValue("Default", "KeySetFile")); _vKeyFile.push_back( sKeyCfgPath ); for (t=0; t<_vKeyFile.size(); t++) { string keyfile = _vKeyFile[t]; if ( g_tKeyCfg.Load(keyfile) ) { g_tCfg.SetStaticValue("KeyFile", keyfile); #ifdef __DEBUGMODE__ String sMsg; sMsg.AppendBlank(60, "Load key settings... %s", keyfile.c_str()); cout << sMsg.c_str(); cout << succMsg << endl; #endif if (keyfile == sKeyCfgPath) { string sCmd = "cp " + sKeyCfgPath + " " + g_tCfg.GetValue("Home") + ".linm"; system(sCmd.c_str()); } break; } else { String sMsg; sMsg.AppendBlank(60, "Load key settings... %s", keyfile.c_str()); cout << sMsg.c_str(); cout << failMsg << endl; } } if (t==_vKeyFile.size()) { String sMsg; sMsg.AppendBlank(60, "Load key settings... "); cout << sMsg.c_str(); cout << failMsg << endl; return false; } } return true; } /// @brief print help void PrintHelp(void) { const char *sStr_Ko = "LinM 는 도스용 파일관리 툴 Mdir의 리눅스 클론입니다.\n" "프로그램의 기능 버그, 추가할 사항, 기타 문의는 " "프로젝트 홈페이지나, 개발자 이메일을 통해서 연락주십시오.\n\n" " * 프로젝트 홈페이지 : http://mls.kldp.net/\n" " * 옵션 설명\n" "\t --help : 도움말\n" "\t --lang=CODE : 출력언어 설정, 사용가능한 CODE는 \n" "\t : us(영어), ko(한글, utf-8), ko_euckr(한글, euc-kr)입니다.\n" #ifdef __DEBUGMODE__ "\t --debug=FILE : 디버그 메시지를 지정된 파일로 출력\n" #endif "\t --cfg=FILE : 설정파일 지정\n" "\t --col=FILE : 컬러셋 파일 지정\n" "\t --key=FILE : 키 파일 지정\n" "\t --noline : 선형태를 -,|,+ 로 바꿈\n" "\t --mcd : 바로 MCD 실행 \n"; const char *sStr_En = "LinM is a clone of Mdir, the famous file manager from the MS-DOS age. \n" "LinM is rich full-screen text mode shell application that assist you copy, move, delete" "files and directories, search for files and run commands in the subshell.\n\n" " * Project homepage : http://mls.kldp.net/\n" " * Option\n" "\t --help : print this page\n" "\t --lang=CODE : set language, following codes are available\n" "\t : us(english), ko(korean, utf-8), ko_euckr(korean, euc-kr)\n" #ifdef __DEBUGMODE__ "\t --debug=FILE : redirect debug message to FILE\n" #endif "\t --cfg=FILE : load config file\n" "\t --col=FILE : load colorset file\n" "\t --key=FILE : load keybind file\n" "\t --noline : change box code to ascii character(-,|,+)\n" "\t --mcd : excute Mcd \n"; cout << ChgEngKor(sStr_En, sStr_Ko) << endl; } /// @brief Option 처리함수 /// @param argc 프로그램 시작인자 개수 /// @param argv 프로그램 시작 인자 void OptionProc(int argc, char * const argv[]) { char opt = -1; struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "noline", no_argument, NULL, 'n' }, { "mcd", no_argument, NULL, 'm' }, { "lang", required_argument, NULL, 'l' }, { "debug", required_argument, NULL, 'd' }, { "cfg", required_argument, NULL, 'c' }, { "col", required_argument, NULL, 's' }, { "key", required_argument, NULL, 'k' }, { NULL, 0, NULL, 0 } }; if ( getenv("TERM") ) { string sTerm = getenv("TERM"); // 일반 콘솔 화면에서는 한글 처리가 미흡하기 때문에 // TERM 이 linux 이면 영문으로 나오게 한다. // 옵션으로 한글을 바꿀수 있다. if (sTerm == "linux") { _nLangSet = US; //e_nBoxLineCode = CHARLINE; // 검토.. } if (sTerm == "cygwin") { _nLangSet = KO_EUCKR; e_nBoxLineCode = CHARLINE; } } string sLogFile = "/dev/null"; cout << "LinM "<< VERSION << ", user-friendly graphic shell, 2006" << endl << endl; while((opt = getopt_long(argc, argv, "hnmldcsk:", longopts, NULL)) != -1) { switch(opt) { case 'n': // noline e_nBoxLineCode = CHARLINE; break; case 'l': // lang if (!optarg) break; if (!strcmp(optarg, "us")) _nLangSet = US; else if (!strcmp(optarg, "ko_euckr")) _nLangSet = KO_EUCKR; else if (!strcmp(optarg, "ko")) _nLangSet = KO_UTF8; break; #ifdef __DEBUGMODE__ case 'd': // debug if (optarg) sLogFile = optarg; break; #endif case 'm': // mcd _bMcdExe = true; break; case 'c': // 컨피그 파일 if (optarg) _vCfgFile.push_back(optarg); break; case 's': // 컬러셋 파일 if (optarg) _vColFile.push_back(optarg); break; case 'k': // keybind 파일 if (optarg) _vKeyFile.push_back(optarg); break; case '?': // 오류 case 'h': // help default: Set_Locale(_nLangSet); PrintHelp(); exit(0); } } #ifdef __DEBUGMODE__ if (sLogFile != "/dev/null") g_Log.SetFile(sLogFile); int fd = 0; if ((fd = open(sLogFile.c_str(), O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { printf("Log file open error : %s ", sLogFile.c_str()); exit(0); } else { //dup2(fd, 2); // stderr에 리다이렉션한다. close(fd); } #endif } void CopyConfFiles() { if (g_tCfg.getVersion() != VERSION) { bool bYN = YNBox(_("Error"), _("configuration files are not compatible. configuration files copy ?"), true); if (bYN == true) { system( "mkdir ~/.linm/back 2> /dev/null > /dev/null; " "mv ~/linm/* ~/.linm/back 2> /dev/null > /dev/null; " "cp " __LINM_CFGPATH__ "* ~/.linm 2> /dev/null > /dev/null"); g_tCfg.Load((g_tCfg.GetValue("Static", "CfgHome") + "default.cfg").c_str()); g_tColorCfg.Load((g_tCfg.GetValue("Static", "CfgHome") + "colorset.cfg").c_str()); g_tKeyCfg.Load((g_tCfg.GetValue("Static", "CfgHome") + "keyset.cfg").c_str()); } } } int main(int argc, char *argv[]) { OptionProc(argc, argv); if (Initialize() == false) return SUCCESS; if (Load_KeyFile() == false) return SUCCESS; signal_blocking(); CursesInit(); MouseInit(); try { CopyConfFiles(); if (_bMcdExe) g_tMainFrame.DoMcd(); g_tMainFrame.Do(); CursesDestroy(); } catch(Exception& ex) { CursesDestroy(); cout << "Exception Error !!! -" << ex << endl; } #ifdef __DEBUGMODE__ catch(...) { CursesDestroy(); cout << "exception error !!!" << endl; } #endif g_Log.Write("Main Success Exit ..."); if (g_tCfg.GetValue("Static", "TmpDir") != "") { string sTmpDel = "rm -rf " + g_tCfg.GetValue("Static", "TmpDir") + "*"; system( sTmpDel.c_str() ); } return SUCCESS; }