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

📄 console.cpp

📁 cTorrent advanced 3.3.2。是对 CTorrent 的一个改进版本。这是目前的最新版。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "console.h"  // def.h#include <stdlib.h>     // atoi()#include <sys/types.h>  // fstat(), FD_SET(), fork()#include <sys/stat.h>   // fstat()#include <unistd.h>     // isatty(), fork(), setsid()#include <string.h>#include <errno.h>#include <ctype.h>      // isdigit()#include <signal.h>#include <fcntl.h>      // open()#include <time.h>       // clock()#if defined(HAVE_IOCTL_H)#include <ioctl.h>      // ioctl()#elif defined(HAVE_SYS_IOCTL_H)#include <sys/ioctl.h>#endif#include "btconfig.h"#include "ctcs.h"#include "btcontent.h"#include "tracker.h"#include "peer.h"#include "peerlist.h"#include "bitfield.h"#include "bttime.h"#include "sigint.h"#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_SNPRINTF) || \    !defined(HAVE_STRCASECMP)#include "compat.h"#endif// console.cpp:  Copyright 2007-2008 Dennis Holmes  (dholmes@rahul.net)// input mode definitions#define K_CHARS 0#define K_LINES 1const char LIVE_CHAR[4] = {'-', '\\','|','/'};Console CONSOLE;static int g_console_ready = 0;//===========================================================================// ConStream class functionsConStream::ConStream(){  m_stream = (FILE *)0;  m_name = (char *)0;  m_restore = 0;  m_newline = 1;  m_suspend = 0;  m_inputmode = K_LINES;}ConStream::~ConStream(){  if( m_restore ) RestoreMode();  if( !m_suspend ) _newline();  if( m_stream ) fclose(m_stream);  if( m_name ) delete []m_name;}void ConStream::Close(){  if( m_stream ){    fclose(m_stream);    m_stream = (FILE *)0;  }  m_suspend = 1;}void ConStream::Associate(FILE *stream, const char *name, int mode){  m_stream = stream;  m_filemode = mode;  if( m_name = new char[strlen(name)+1] )    strcpy(m_name, name);  else Error(1, "Failed to allocate memory for output filename.");}int ConStream::SameDev(ConStream *master) const{  struct stat sbone, sbtwo;  if( master == this || Fileno() == master->Fileno() ) return 1;  else if( Fileno() < 0 || master->Fileno() < 0 ) return 0;  if( !fstat(Fileno(), &sbone) && !fstat(master->Fileno(), &sbtwo) )    return (sbone.st_dev==sbtwo.st_dev && sbone.st_ino==sbtwo.st_ino) ? 1 : 0;  else return 0;}int ConStream::IsTTY() const{  return (Fileno() >= 0) ? isatty(Fileno()) : 0;}void ConStream::PreserveMode(){  int r;  if( !IsTTY() ) return;#if defined(USE_TERMIOS)  r = tcgetattr(Fileno(), &m_original);#elif defined(USE_TERMIO)  r = ioctl(Fileno(), TCGETA, &m_original);#elif defined(USE_SGTTY)  r = gtty(Fileno(), &m_original);#endif  if( r < 0 ){    Error(1, "Error preserving terminal mode on fd %d:  %s", Fileno(),      strerror(errno));  }else m_restore = 1;}void ConStream::RestoreMode(){  int r;  if( !IsTTY() ) return;#if defined(USE_TERMIOS)  r = tcsetattr(Fileno(), TCSANOW, &m_original);#elif defined(USE_TERMIO)  r = ioctl(Fileno(), TCSETA, &m_original);#elif defined(USE_SGTTY)  r = stty(Fileno(), &m_original);#endif  if( r < 0 ){    Error(1, "Error restoring terminal mode on fd %d:  %s", Fileno(),      strerror(errno));  }}void ConStream::SetInputMode(int keymode){  if( m_suspend ) return;  m_inputmode = keymode;  if( !IsTTY() ) return;#if defined(USE_TERMIOS)  struct termios termset;  tcgetattr(Fileno(), &termset);#elif defined(USE_TERMIO)  struct termio termset;  ioctl(Fileno(), TCGETA, &termset);#elif defined(USE_SGTTY)  struct sgttyb termset;  gtty(Fileno(), &termset);#endif  switch(keymode) {  case K_CHARS:     // read a char at a time, no echo#if defined(USE_TERMIOS)    termset.c_lflag &= ~(ICANON | ECHO);    termset.c_cc[VMIN] = 1;    termset.c_cc[VTIME] = 0;    tcsetattr(Fileno(), TCSANOW, &termset);#elif defined(USE_TERMIO)    termset.c_lflag &= ~(ICANON | ECHO);    termset.c_cc[VMIN] = 1;    termset.c_cc[VTIME] = 0;    ioctl(Fileno(), TCSETA, &termset);#elif defined(USE_SGTTY)    termset.sg_flags |= CBREAK;    termset.sg_flags &= ~ECHO;    stty(Fileno(), &termset);#endif    break;  case K_LINES:     // read a line at a time (allow terminal editing)#if defined(USE_TERMIOS)    termset.c_lflag |= (ICANON | ECHO);    termset.c_cc[VMIN] = 1;    termset.c_cc[VTIME] = 0;    tcsetattr(Fileno(), TCSANOW, &termset);#elif defined(USE_TERMIO)    termset.c_lflag |= (ICANON | ECHO);    termset.c_cc[VMIN] = 1;    termset.c_cc[VTIME] = 0;    ioctl(Fileno(), TCSETA, &termset);#elif defined(USE_SGTTY)    termset.sg_flags &= ~CBREAK;    termset.sg_flags |= ECHO;    stty(Fileno(), &termset);#endif    break;  default:    break;  }}int ConStream::Output(const char *message, va_list ap){  if( m_suspend ) return 0;  int old_newline = m_newline;  _newline();  _convprintf(message, ap);  _newline();  fflush(m_stream);  return (old_newline==m_newline) ? 0 : 1;}int ConStream::Output_n(const char *message, va_list ap){  if( m_suspend ) return 0;  int old_newline = m_newline;  if( !message || !*message ) _newline();  else _convprintf(message, ap);  fflush(m_stream);  return (old_newline==m_newline) ? 0 : 1;}int ConStream::Update(const char *message, va_list ap){  if( m_suspend ) return 0;  int old_newline = m_newline;  if( !m_newline) fprintf(m_stream, IsTTY() ? "\r" : "\n");  _convprintf(message, ap);  fflush(m_stream);  return (old_newline==m_newline) ? 0 : 1;}char *ConStream::Input(char *field, size_t length){  if( m_suspend ) return (char *)0;  m_newline = 1;  return fgets(field, length, m_stream);}int ConStream::CharIn(){  if( m_suspend ) return 0;  return fgetc(m_stream);}inline void ConStream::_newline(){  if( !m_newline ){    fprintf(m_stream, "\n");    m_newline = 1;  }}inline int ConStream::_convprintf(const char *format, va_list ap){  int r = ( '\n' == format[strlen(format)-1] );  m_newline = r;  return vfprintf(m_stream, format, ap);}/* ConStream functions need to call Error instead of CONSOLE.Warning, because   CONSOLE may not be initialized yet (or may have been destroyed already).*/void ConStream::Error(int sev, const char *message, ...){  va_list ap;  va_start(ap, message);  /* Note the call to Warning sends only the literal message--a limitation to     deal with later. */  if( g_console_ready ) CONSOLE.Warning(sev, message);  else{    vfprintf(stderr, message, ap);    fflush(stderr);  }  va_end(ap);}//===========================================================================// Console class functionsConsole::Console(){  m_skip_status = m_status_last = 0;  m_live_idx = 0;  m_oldfd = -1;  m_status_format = 0;  int i = 0;  m_statusline[i++] = &Console::StatusLine0;  m_statusline[i++] = &Console::StatusLine1;  if( STATUSLINES > i ){    fprintf(stderr, "Unassigned status line in Console() constructor!\n");    exit(1);  }else if ( STATUSLINES < i ){    fprintf(stderr, "Value of STATUSLINES is too small!\n");    exit(1);  }  m_status_len = 80;  m_stdout.Associate(stdout, "stdout", 1);  m_stderr.Associate(stderr, "stderr", 1);  m_stdin.Associate(stdin, "stdin", 0);  m_off.Associate(NULL, "off", 1);  m_off.Suspend();  m_streams[O_NORMAL] = &m_stdout;  m_streams[O_WARNING] = &m_stderr;  m_streams[O_DEBUG] = &m_stderr;  m_streams[O_INTERACT] = &m_stdout;  m_streams[O_INPUT] = &m_stdin;  m_streams[O_INPUT]->PreserveMode();  m_streams[O_INPUT]->SetInputMode(K_CHARS);  m_conmode = K_CHARS;  if( this == &CONSOLE ) g_console_ready = 1;}Console::~Console(){  if( this == &CONSOLE ) g_console_ready = 0;}int Console::IntervalCheck(fd_set *rfdp, fd_set *wfdp){  Status(0);  if( m_oldfd >= 0 ){    FD_CLR(m_oldfd, rfdp);    m_oldfd = -1;  }  if( !m_streams[O_INPUT]->IsSuspended() ){    FD_SET(m_streams[O_INPUT]->Fileno(), rfdp);    return m_streams[O_INPUT]->Fileno();  }else{    if( m_streams[O_INPUT]->Fileno() >= 0 )      FD_CLR(m_streams[O_INPUT]->Fileno(), rfdp);    return -1;  }}void Console::User(fd_set *rfdp, fd_set *wfdp, int *nready,  fd_set *rfdnextp, fd_set *wfdnextp){  static char pending = '\0';  static int inc, count;  char c, param[MAXPATHLEN], *s;  if( m_streams[O_INPUT]->Fileno() >= 0 &&      FD_ISSET(m_streams[O_INPUT]->Fileno(), rfdp) ){    FD_CLR(m_streams[O_INPUT]->Fileno(), rfdnextp);    (*nready)--;    if( K_LINES==m_streams[O_INPUT]->GetInputMode() ){  // command parameter      SyncNewlines(O_INPUT);      if( m_streams[O_INPUT]->Input(param, sizeof(param)) ){        if( s = strchr(param, '\n') ) *s = '\0';        if( '0'==pending ){          if( OperatorMenu(param) ) pending = '\0';        }else{          m_streams[O_INPUT]->SetInputMode(K_CHARS);          if( *param ) switch( pending ){          case 'n':				// get1file            if( arg_file_to_download ) delete []arg_file_to_download;            arg_file_to_download = new char[strlen(param) + 1];            if( !arg_file_to_download )              Warning(1, "error, failed to allocate memory for option");            else strcpy(arg_file_to_download, param);            BTCONTENT.SetFilter();            break;          case 'S':				// CTCS server            if( !strchr(param, ':') )              Interact("Invalid input");            else{              if( arg_ctcs ) delete []arg_ctcs;              if(0==strcmp(":", param)){                if(arg_ctcs) CTCS.Reset(1);                arg_ctcs = (char*) 0;              }else{                arg_ctcs = new char[strlen(param) + 1];                if( !arg_ctcs )                  Warning(1, "error, failed to allocate memory for option");                else{                  strcpy(arg_ctcs, param);                  CTCS.Initial();                  CTCS.Reset(1);                }              }            }            break;          case 'X':				// completion command (user exit)            if( arg_completion_exit ) delete []arg_completion_exit;            arg_completion_exit = new char[strlen(param) + 1];            if( !arg_completion_exit )              Warning(1, "error, failed to allocate memory for option");            else strcpy(arg_completion_exit, param);            break;          case 'Q':				// quit            if( 'y'==*param || 'Y'==*param ){              Tracker.ClearRestart();              Tracker.SetStoped();            }            break;          default:            Interact("Input mode error");          }        }      }else{        if( m_streams[O_INPUT]->Eof() ){          Interact("End of input reached.");          if( ChangeChannel(O_INPUT, "off") < 0 )            m_streams[O_INPUT]->Suspend();        }else if(errno){          if( ENODEV==errno || ENOTTY==errno ) m_streams[O_INPUT]->Suspend();          else Interact("Input error:  %s", strerror(errno));        }else Interact("Input error!");      }      if( '0' != pending ){          m_streams[O_INPUT]->SetInputMode(K_CHARS);          Status(1);      }    }else{     // command character received      m_skip_status = 1;      if( (c = m_streams[O_INPUT]->CharIn()) == EOF ){        if( m_streams[O_INPUT]->Eof() ){          Interact("End of input reached.");          if( ChangeChannel(O_INPUT, "off") < 0 )            m_streams[O_INPUT]->Suspend();        }else if(errno){          if( ENODEV==errno || ENOTTY==errno ) m_streams[O_INPUT]->Suspend();          else Interact("Input error:  %s", strerror(errno));        }else Interact("Input error!");        return;      }      if( c!='+' && c!='-' ) pending = c;      switch( c ){      case 'h':				// help      case '?':				// help        Interact("Available commands:");        Interact(" %-9s%-30s %-9s%s", "[Esc/0]", "Operator menu",          "m[+/-]", "Adjust min peers count");        Interact(" %-9s%-30s %-9s%s", "d[+/-]", "Adjust download limit",          "M[+/-]", "Adjust max peers count");        Interact(" %-9s%-30s %-9s%s", "u[+/-]", "Adjust upload limit",          "C[+/-]", "Adjust max cache size");        Interact(" %-9s%-30s %-9s%s", "n", "Download specific files",          "S", "Set/change CTCS server");        Interact(" %-9s%-30s %-9s%s", "e[+/-]", "Adjust seed exit time",          "v", "Toggle verbose mode");        Interact(" %-9s%-30s %-9s%s", "E[+/-]", "Adjust seed exit ratio",          "Q", "Quit");        Interact(" %-9s%-30s %-9s%s", "X", "Completion command",

⌨️ 快捷键说明

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