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

📄 console.cpp

📁 最新的enhanced ctorrent源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <stdlib.h>     // atoi()#include <sys/types.h>  // fstat(), FD_SET()#include <sys/stat.h>   // fstat()#include <unistd.h>     // isatty()#include <string.h>#include <errno.h>#include <ctype.h>      // isdigit()#include <signal.h>#include "btconfig.h"#include "console.h"#include "ctcs.h"#include "btcontent.h"#include "tracker.h"#include "peer.h"#include "peerlist.h"#include "bttime.h"#include "sigint.h"// console.cpp:  Copyright 2007 Dennis Holmes  (dholmes@rahul.net)// input mode definitions#define K_CHARS 0#define K_LINES 1const char LIVE_CHAR[4] = {'-', '\\','|','/'};Console CONSOLE;//===========================================================================// ConStream class functionsConStream::ConStream(){  m_stream = (FILE *)0;  m_name = (char *)0;  m_newline = 1;  m_suspend = 0;  m_inputmode = K_LINES;}ConStream::~ConStream(){  if( !m_suspend ) _newline();  if( m_stream ) fclose(m_stream);  if( m_name ) delete []m_name;}void ConStream::Associate(FILE *stream, const char *name){  m_stream = stream;  if( m_name = new char[strlen(name)+1] )    strcpy(m_name, name);  else CONSOLE.Warning(1, "Failed to allocate memory for output filename.");}int ConStream::SameDev(ConStream *master) const{  struct stat sbone, sbtwo;  if( master == this ) return 1;  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;}void ConStream::PreserveMode(){  if( !isatty(Fileno()) ) return;#if defined(USE_TERMIOS)  tcgetattr(Fileno(), &m_original);#elif defined(USE_TERMIO)  ioctl(Fileno(), TCGETA, &m_original);#elif defined(USE_SGTTY)  gtty(Fileno(), &m_original);#endif}void ConStream::RestoreMode(){  if( !isatty(Fileno()) ) return;#if defined(USE_TERMIOS)  tcsetattr(Fileno(), TCSANOW, &m_original);#elif defined(USE_TERMIO)  ioctl(Fileno(), TCSETA, &m_original);#elif defined(USE_SGTTY)  stty(Fileno(), &m_original);#endif}void ConStream::SetInputMode(int keymode){  if( m_suspend || !isatty(Fileno()) ) 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);    tcsetattr(Fileno(), TCSANOW, &termset);#elif defined(USE_TERMIO)    termset.c_lflag &= ~(ICANON | ECHO);    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);    tcsetattr(Fileno(), TCSANOW, &termset);#elif defined(USE_TERMIO)    termset.c_lflag |= (ICANON | ECHO);    ioctl(Fileno(), TCSETA, &termset);#elif defined(USE_SGTTY)    termset.sg_flags &= ~CBREAK;    termset.sg_flags |= ECHO;    stty(Fileno(), &termset);#endif    break;  default:    break;  }  m_inputmode = keymode;}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 ) _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, isatty(Fileno()) ? "\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);}//===========================================================================// Console class functionsConsole::Console(){  m_skip_status = m_status_last = 0;  m_live_idx = 0;  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_stdout.Associate(stdout, "stdout");  m_stderr.Associate(stderr, "stderr");  m_stdin.Associate(stdin, "stdin");  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;}Console::~Console(){  m_streams[O_INPUT]->RestoreMode();}int Console::IntervalCheck(fd_set *rfdp, fd_set *wfdp){   Status(0);   FD_SET(m_streams[O_INPUT]->Fileno(), rfdp);   return m_streams[O_INPUT]->Fileno();}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[256], *s;  if( 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, 256) ){        if( s = strchr(param, '\n') ) *s = '\0';        if( '0'==pending ){          if( OperatorMenu(param) ) pending = '\0';        }else{          if( *param ) switch( pending ){          case 'n':				// get1file            if( isdigit(*param) ){              arg_file_to_download = atoi(param);              BTCONTENT.SetFilter();            }            break;          case 'S':				// CTCS server            if( !strchr(param, ':') )              Interact("Invalid input");            else{              if( arg_ctcs ) delete []arg_ctcs;              arg_ctcs = new char[strlen(param) + 1];              strcpy(arg_ctcs, param);              CTCS.Initial();              CTCS.Reset(1);            }            break;          case 'Q':				// quit            if( 'y'==*param || 'Y'==*param ) Tracker.SetStoped();            break;          default:            Interact("Input error!");          }        }      }else{        if(errno) Interact("Input error: %s", strerror(errno));        m_streams[O_INPUT]->SetInputMode(K_CHARS);        Status(1);      }      if( '0' != pending ){          m_streams[O_INPUT]->SetInputMode(K_CHARS);          Status(1);      }    }else{     // command character received      m_skip_status = 1;      c = m_streams[O_INPUT]->CharIn();      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 file",          "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");        break;      case 'd':				// download bw limit      case 'u':				// upload bw limit      case 'e':				// seed time      case 'E':				// seed ratio      case 'm':				// min peers      case 'M':				// max peers      case 'C':				// max cache size        inc = 1; count = 0;        Interact_n("");        break;      case 'n':{				// get1file        m_streams[O_INPUT]->SetInputMode(K_LINES);        ShowFiles();        Interact("Enter 0 for all files (normal behavior).");        Interact_n("Get file number (currently %d): ",          (int)arg_file_to_download);        }break;      case 'S':				// CTCS server        m_streams[O_INPUT]->SetInputMode(K_LINES);        Interact_n("");        if( arg_ctcs )          Interact_n("CTCS server:port (currently %s): ", arg_ctcs);        else Interact_n("CTCS server:port: ");        break;      case 'v':				// verbose        if( arg_verbose && m_streams[O_INPUT] != m_streams[O_DEBUG] )          Debug("Verbose output off");        arg_verbose = !arg_verbose;        Interact("Verbose output %s", arg_verbose ? "on" : "off");        break;      case 'Q':				// quit        if( !Tracker.IsQuitting() ){          m_streams[O_INPUT]->SetInputMode(K_LINES);          Interact_n("");          Interact_n("Quit:  Are you sure? ");        }        break;      case '+':				// increase value      case '-':				// decrease value        if( ('+'==c && inc<0) || ('-'==c && inc>0) ) inc *= -1;        switch( pending ){          int value;        case 'd': cfg_max_bandwidth_down +=            ( (cfg_max_bandwidth_down * (abs(inc)/100.0) < 1) ? inc :                (int)(cfg_max_bandwidth_down * (inc/100.0)) );          if( cfg_max_bandwidth_down < 0 ) cfg_max_bandwidth_down = 0;          break;        case 'u': cfg_max_bandwidth_up +=            ( (cfg_max_bandwidth_up * (abs(inc)/100.0) < 1) ? inc :                (int)(cfg_max_bandwidth_up * (inc/100.0)) );          if( cfg_max_bandwidth_up < 0 ) cfg_max_bandwidth_up = 0;          break;        case 'e': cfg_seed_hours += inc;          if( cfg_seed_hours < 0 ) cfg_seed_hours = 0;          break;        case 'E': cfg_seed_ratio += inc / 10.0;          if( cfg_seed_ratio < 0 ) cfg_seed_ratio = 0;          break;        case 'm': value = (int)cfg_min_peers; value += inc;          cfg_min_peers = (value < 1) ? 1 : (size_t)value;          if( cfg_min_peers > cfg_max_peers ) cfg_min_peers = cfg_max_peers;          break;        case 'M': value = (int)cfg_max_peers; value += inc;          cfg_max_peers = (value < (int)cfg_min_peers) ?                          cfg_min_peers : (size_t)value;          if( cfg_max_peers > 1000 ) cfg_max_peers = 1000;          break;        case 'C': value = (int)cfg_cache_size; value += inc;          cfg_cache_size = (value < 0) ? 0 : (size_t)value;          BTCONTENT.CacheConfigure();          break;        default:          Status(1);          break;        }        if( 10==++count ) inc *= 2;        else if( 5==count ) inc *= 5;        if( arg_ctcs ){          if( 'd'==pending || 'u'==pending ) CTCS.Send_bw();          else CTCS.Send_Config();        }        break;      case '0':				// operator menu      case 0x1b:				// Escape key        pending = '0';        OperatorMenu("");        break;      default:        Status(1);        break;      }      switch( pending ){      case 'd': InteractU("DL Limit: %d B/s ", (int)cfg_max_bandwidth_down);        break;      case 'u': InteractU("UL Limit: %d B/s ", (int)cfg_max_bandwidth_up);        break;      case 'e': InteractU("Seed time: %.1f hours ", BTCONTENT.GetSeedTime() ?          cfg_seed_hours - (now - BTCONTENT.GetSeedTime())/(double)3600 :          (double)cfg_seed_hours);        break;      case 'E': InteractU("Seed ratio: %.2f ", (double)cfg_seed_ratio);        break;      case 'm': InteractU("Minimum peers: %d ", (int)cfg_min_peers);        break;      case 'M': InteractU("Maximum peers: %d ", (int)cfg_max_peers);        break;      case 'C': InteractU("Maximum cache: %d MB ", (int)cfg_cache_size);        break;      default:        break;      }    }  }}// Return non-zero to exit operator menu mode.int Console::OperatorMenu(const char *param){  static int oper_mode = 0;  static int channel, n_opt;  if( 0==oper_mode ){    Interact("Operator Menu");    n_opt = 0;    Interact(" Output Channels:");    Interact(" %2d) Normal/status:  %s", ++n_opt,                                         m_streams[O_NORMAL]->GetName());    Interact(" %2d) Interactive:    %s", ++n_opt,                                         m_streams[O_INTERACT]->GetName());    Interact(" %2d) Error/warning:  %s", ++n_opt,                                         m_streams[O_WARNING]->GetName());    Interact(" %2d) Debug/verbose:  %s", ++n_opt,                                         m_streams[O_DEBUG]->GetName());    char buffer[80];    Interact(" Status Line Formats:");    for( int i=0; i < STATUSLINES; i++ ){      (CONSOLE.*m_statusline[i])(buffer, sizeof(buffer));      Interact(" %c%d) %s", (i==m_status_format) ? '*' : ' ', ++n_opt, buffer);    }    Interact(" Other options:");    Interact(" %2d) View detailed status", ++n_opt);    if( WORLD.IsPaused() )      Interact(" %2d) Resume (continue upload/download)", ++n_opt);    else Interact(" %2d) Pause (suspend upload/download)", ++n_opt);    Interact_n("Enter selection: ");    m_streams[O_INPUT]->SetInputMode(K_LINES);    oper_mode = 1;    return 0;  }  else if( 1==oper_mode ){    if( !*param ){ oper_mode = 0; Interact("Exiting menu"); return 1; }    int sel = atoi(param);    if( sel < 1 || sel > n_opt ){       Interact_n("Enter selection: ");      return 0;    }    if( sel <= O_NCHANNELS ){  // change output channel      channel = sel - 1;      Interact("Possible values are:");      Interact(" %s", m_stdout.GetName());      Interact(" %s", m_stderr.GetName());      Interact(" a filename");      Interact_n("Enter a destination: ");      m_streams[O_INPUT]->SetInputMode(K_LINES);      oper_mode = 2;      return 0;    }else if( sel <= O_NCHANNELS + STATUSLINES ){      m_status_format = sel - (O_NCHANNELS+1);      oper_mode = 0;      return OperatorMenu("");    }else if( sel == 1 + O_NCHANNELS + STATUSLINES ){  // detailed status      Interact("");      Interact("Torrent: %s", arg_metainfo_file);      ShowFiles();      Interact("");      Interact("Download rate: %dB/s   Limit: %dB/s   Total: %llu",        (int)(Self.RateDL()), (int)cfg_max_bandwidth_down,        (unsigned long long)(Self.TotalDL()));      Interact("  Upload rate: %dB/s   Limit: %dB/s   Total: %llu",        (int)(Self.RateUL()), (int)cfg_max_bandwidth_up,        (unsigned long long)(Self.TotalUL()));

⌨️ 快捷键说明

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