diff -crB transmission-2.73.orig/cli/cli.c transmission-2.73/cli/cli.c *** transmission-2.73.orig/cli/cli.c 2012-10-24 15:01:06.309690617 +0200 --- transmission-2.73/cli/cli.c 2012-11-03 01:34:26.523402999 +0100 *************** *** 73,78 **** --- 73,101 ---- static const char * torrentPath = NULL; + //Torrentflux + #define TOF_DISPLAY_INTERVAL 5 + #define TOF_DISPLAY_INTERVAL_STR "5" + #define TOF_DIEWHENDONE 0 + #define TOF_DIEWHENDONE_STR "0" + #define TOF_CMDFILE_MAXLEN 65536 + + //static volatile char tf_shutdown = 0; + static int TOF_dieWhenDone = TOF_DIEWHENDONE; + static int TOF_seedLimit = 0; + static int TOF_displayInterval = TOF_DISPLAY_INTERVAL; + static int TOF_checkCmd = 0; + + static const char * finishCall = NULL; + + static const char * TOF_owner = NULL; + static char * TOF_statFile = NULL; + static FILE * TOF_statFp = NULL; + static char * TOF_cmdFile = NULL; + static FILE * TOF_cmdFp = NULL; + static char TOF_message[512]; + //END Torrentflux + static const struct tr_option options[] = { { 'b', "blocklist", "Enable peer blocklists", "b", 0, NULL }, *************** *** 93,98 **** --- 116,127 ---- { 'v', "verify", "Verify the specified torrent", "v", 0, NULL }, { 'V', "version", "Show version number and exit", "V", 0, NULL }, { 'w', "download-dir", "Where to save downloaded data", "w", 1, "" }, + //Torrentflux Commands: + { 'E', "display-interval","Time between updates of stat-file (default = "TOF_DISPLAY_INTERVAL_STR")","E",1,""}, + { 'L', "seedlimit","Seed-Limit (Percent) to reach before shutdown","L",1,""}, + { 'O', "owner","Name of the owner (default = 'n/a')","O",1,""}, + { 'W', "die-when-done", "Auto-Shutdown when done (0 = Off, 1 = On, default = "TOF_DIEWHENDONE_STR")","W",1,NULL}, + //END { 0, NULL, NULL, NULL, 0, NULL } }; *************** *** 108,113 **** --- 137,156 ---- static void sigHandler( int signal ); + /* Torrentflux -START- */ + static int TOF_processCommands(tr_session *h); + static int TOF_execCommand(tr_session *h, char *s); + static void TOF_print ( char *printmsg ); + static void TOF_free ( void ); + static int TOF_initStatus ( void ); + static void TOF_writeStatus ( const tr_stat *s, const tr_info *info, + const int state, const char *status ); + static int TOF_initCommand ( void ); + static int TOF_writePID ( void ); + static void TOF_deletePID ( void ); + static int TOF_writeAllowed ( void ); + /* -END- */ + static char* tr_strlratio( char * buf, double ratio, *************** *** 140,161 **** tr_ctorSetMetainfo( ctor, response, response_byte_count ); waitingOnWeb = false; } ! static void getStatusStr( const tr_stat * st, char * buf, size_t buflen ) { if( st->activity == TR_STATUS_CHECK_WAIT ) { tr_snprintf( buf, buflen, "Waiting to verify local files" ); } else if( st->activity == TR_STATUS_CHECK ) { tr_snprintf( buf, buflen, ! "Verifying local files (%.2f%%, %.2f%% valid)", tr_truncd( 100 * st->recheckProgress, 2 ), tr_truncd( 100 * st->percentDone, 2 ) ); } else if( st->activity == TR_STATUS_DOWNLOAD ) { --- 183,214 ---- tr_ctorSetMetainfo( ctor, response, response_byte_count ); waitingOnWeb = false; } ! /* static void getStatusStr( const tr_stat * st, char * buf, size_t buflen ) + */ + static void + getStatusStr( const tr_stat * st, const tr_info *information ) { + char TOF_eta[80]; + char buf[512]; + size_t buflen=512; + if( st->activity == TR_STATUS_CHECK_WAIT ) { tr_snprintf( buf, buflen, "Waiting to verify local files" ); + TOF_writeStatus(st, information, 1, buf ); } else if( st->activity == TR_STATUS_CHECK ) { tr_snprintf( buf, buflen, ! //"Verifying local files (%.2f%%, %.2f%% valid)", ! "%.2f%% Verifying local files (%.2f%% valid)", tr_truncd( 100 * st->recheckProgress, 2 ), tr_truncd( 100 * st->percentDone, 2 ) ); + TOF_writeStatus(st, information, 1, buf ); } else if( st->activity == TR_STATUS_DOWNLOAD ) { *************** *** 176,181 **** --- 229,266 ---- st->peersSendingToUs, st->peersConnected, dnStr, st->peersGettingFromUs, upStr, ratioStr ); + + if( TOF_writeAllowed() ) + { + strcpy(TOF_eta,""); + if ( st->eta > 0 ) + { + if ( st->eta < 604800 ) // 7 days + { + if ( st->eta >= 86400 ) // 1 day + sprintf(TOF_eta, "%d:", + st->eta / 86400); + + if ( st->eta >= 3600 ) // 1 hour + sprintf(TOF_eta, "%s%02d:", + TOF_eta,((st->eta % 86400) / 3600)); + + if ( st->eta >= 60 ) // 1 Minute + sprintf(TOF_eta, "%s%02d:", + TOF_eta,((st->eta % 3600) / 60)); + + sprintf(TOF_eta, "%s%02d", + TOF_eta,(st->eta % 60)); + } + else + sprintf(TOF_eta, "-"); + } + + if ((st->seeders < -1) && (st->peersConnected == 0)) + sprintf(TOF_eta, "Connecting to Peers"); + + TOF_writeStatus(st, information, 1, TOF_eta ); + } } else if( st->activity == TR_STATUS_SEED ) { *************** *** 188,195 **** --- 273,307 ---- tr_snprintf( buf, buflen, "Seeding, uploading to %d of %d peer(s), %s [%s]", st->peersGettingFromUs, st->peersConnected, upStr, ratioStr ); + + if (TOF_dieWhenDone == 1) + { + TOF_print( (char *) "Die-when-done set, setting shutdown-flag...\n" ); + gotsig = 1; + } + else + { + if (TOF_seedLimit == -1) + { + TOF_print( (char *) "Sharekill set to -1, setting shutdown-flag...\n" ); + gotsig = 1; + } + else if ( ( TOF_seedLimit > 0 ) && ( ( st->ratio * 100.0 ) > (float)TOF_seedLimit ) ) + { + sprintf( TOF_message, "Seed-limit %d%% reached, setting shutdown-flag...\n", TOF_seedLimit ); + TOF_print( TOF_message ); + gotsig = 1; + } + } + TOF_writeStatus(st, information, 1, "Download Succeeded" ); } else *buf = '\0'; + + if( st->error ) + { + sprintf( TOF_message, "error: %s\n", st->errorString ); + TOF_print( TOF_message ); + } } static const char* *************** *** 233,239 **** tr_formatter_size_init( DISK_K,DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR ); tr_formatter_speed_init( SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR ); ! printf( "%s %s\n", MY_READABLE_NAME, LONG_VERSION_STRING ); /* user needs to pass in at least one argument */ if( argc < 2 ) { --- 345,356 ---- tr_formatter_size_init( DISK_K,DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR ); tr_formatter_speed_init( SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR ); ! int i; ! const tr_info * information; ! char cwd[1024]; ! ! //printf( "%s %s\n", MY_READABLE_NAME, LONG_VERSION_STRING ); ! printf( "%s %s - patched for TorrentFlux-NG\n", MY_READABLE_NAME, LONG_VERSION_STRING ); /* user needs to pass in at least one argument */ if( argc < 2 ) { *************** *** 244,254 **** /* load the defaults from config file + libtransmission defaults */ tr_bencInitDict( &settings, 0 ); configDir = getConfigDir( argc, (const char**)argv ); ! tr_sessionLoadSettings( &settings, configDir, MY_CONFIG_NAME ); /* the command line overrides defaults */ if( parseCommandLine( &settings, argc, (const char**)argv ) ) return EXIT_FAILURE; if( showVersion ) return 0; --- 361,378 ---- /* load the defaults from config file + libtransmission defaults */ tr_bencInitDict( &settings, 0 ); configDir = getConfigDir( argc, (const char**)argv ); ! //tr_sessionLoadSettings( &settings, configDir, MY_CONFIG_NAME ); /* the command line overrides defaults */ if( parseCommandLine( &settings, argc, (const char**)argv ) ) + { + printf("Invalid commandline option given\n"); return EXIT_FAILURE; + } + + tr_bencDictRemove( &settings, TR_PREFS_KEY_DOWNLOAD_DIR ); + getcwd( cwd, sizeof( cwd ) ); + tr_bencDictAddStr( &settings, TR_PREFS_KEY_DOWNLOAD_DIR, cwd ); if( showVersion ) return 0; *************** *** 272,280 **** h = tr_sessionInit( "cli", configDir, false, &settings ); ctor = tr_ctorNew( h ); ! fileContents = tr_loadFile( torrentPath, &fileLength ); tr_ctorSetPaused( ctor, TR_FORCE, false ); if( fileContents != NULL ) { tr_ctorSetMetainfo( ctor, fileContents, fileLength ); } else if( !memcmp( torrentPath, "magnet:?", 8 ) ) { --- 396,408 ---- h = tr_sessionInit( "cli", configDir, false, &settings ); ctor = tr_ctorNew( h ); + tr_ctorSetMetainfoFromFile( ctor, torrentPath ); ! //fileContents = tr_loadFile( torrentPath, &fileLength ); tr_ctorSetPaused( ctor, TR_FORCE, false ); + tr_ctorSetDownloadDir( ctor, TR_FORCE, cwd ); + tr_ctorSetDownloadDir( ctor, TR_FALLBACK, cwd ); + /* if( fileContents != NULL ) { tr_ctorSetMetainfo( ctor, fileContents, fileLength ); } else if( !memcmp( torrentPath, "magnet:?", 8 ) ) { *************** *** 291,302 **** return EXIT_FAILURE; } tr_free( fileContents ); tor = tr_torrentNew( ctor, &error ); tr_ctorFree( ctor ); if( !tor ) { ! fprintf( stderr, "Failed opening torrent file `%s'\n", torrentPath ); tr_sessionClose( h ); return EXIT_FAILURE; } --- 419,482 ---- return EXIT_FAILURE; } tr_free( fileContents ); + */ + + // Torrentflux -START- + if (TOF_owner == NULL) + { + sprintf( TOF_message, "No owner supplied, using 'n/a'.\n" ); + TOF_print( TOF_message ); + TOF_owner = malloc((4) * sizeof(char)); + if (TOF_owner == NULL) + { + sprintf( TOF_message, "Error : not enough mem for malloc\n" ); + TOF_print( TOF_message ); + goto failed; + } + } + + // Output for log + sprintf( TOF_message, "transmission %s starting up :\n", LONG_VERSION_STRING ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - torrent : %s\n", torrentPath ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - owner : %s\n", TOF_owner ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - dieWhenDone : %d\n", TOF_dieWhenDone ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - seedLimit : %d\n", TOF_seedLimit ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - bindPort : %d\n", tr_sessionGetPeerPort(h) ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - uploadLimit : %d\n", tr_sessionGetSpeedLimit_KBps(h, TR_UP ) ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - downloadLimit : %d\n", tr_sessionGetSpeedLimit_KBps(h, TR_DOWN ) ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - natTraversal : %d\n", tr_sessionIsPortForwardingEnabled(h) ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - displayInterval : %d\n", TOF_displayInterval ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - downloadDir : %s\n", tr_sessionGetDownloadDir(h) ); + TOF_print( TOF_message ); + + if (finishCall != NULL) + { + sprintf( TOF_message, " - finishCall : %s\n", finishCall ); + TOF_print( TOF_message ); + } + // -END- tor = tr_torrentNew( ctor, &error ); + + sprintf( TOF_message, " - downloadDir from torrent object, usually loaded from resume data : %s\n", tr_torrentGetDownloadDir( tor ) ); + TOF_print( TOF_message ); + tr_ctorFree( ctor ); if( !tor ) { ! //fprintf( stderr, "Failed opening torrent file `%s'\n", torrentPath ); ! sprintf( TOF_message, "Failed opening torrent file %s'\n", torrentPath ); ! TOF_print( TOF_message ); tr_sessionClose( h ); return EXIT_FAILURE; } *************** *** 313,318 **** --- 493,529 ---- tr_torrentVerify( tor ); } + // Torrentflux -START- + + // initialize status-facility + if (TOF_initStatus() == 0) + { + sprintf( TOF_message, "Failed to init status-facility. exit transmission.\n" ); + TOF_print( TOF_message ); + goto failed; + } + + // initialize command-facility + if (TOF_initCommand() == 0) + { + sprintf( TOF_message, "Failed to init command-facility. exit transmission.\n" ); + TOF_print( TOF_message ); + goto failed; + } + + // write pid + if (TOF_writePID() == 0) + { + sprintf( TOF_message, "Failed to write pid-file. exit transmission.\n" ); + TOF_print( TOF_message ); + goto failed; + } + + sprintf( TOF_message, "Transmission up and running.\n" ); + + information = tr_torrentInfo( tor ); + // -END- + for( ; ; ) { char line[LINEWIDTH]; *************** *** 321,332 **** "Tracker gave an error:", "Error:" }; tr_wait_msec( 200 ); if( gotsig ) { gotsig = 0; ! printf( "\nStopping torrent...\n" ); tr_torrentStop( tor ); } --- 532,555 ---- "Tracker gave an error:", "Error:" }; + // Torrentflux -START- + TOF_checkCmd++; + + if( TOF_checkCmd == TOF_displayInterval) + { + TOF_checkCmd = 1; + /* If Torrentflux wants us to shutdown */ + if (TOF_processCommands(h)) + gotsig = 1; + } + // -END- + tr_wait_msec( 200 ); if( gotsig ) { gotsig = 0; ! //printf( "\nStopping torrent...\n" ); tr_torrentStop( tor ); } *************** *** 349,367 **** if( st->activity == TR_STATUS_STOPPED ) break; ! getStatusStr( st, line, sizeof( line ) ); ! printf( "\r%-*s", LINEWIDTH, line ); if( messageName[st->error] ) fprintf( stderr, "\n%s: %s\n", messageName[st->error], st->errorString ); } ! tr_sessionSaveSettings( h, configDir, &settings ); printf( "\n" ); tr_bencFree( &settings ); tr_sessionClose( h ); return EXIT_SUCCESS; } /*** --- 572,625 ---- if( st->activity == TR_STATUS_STOPPED ) break; ! //getStatusStr( st, line, sizeof( line ) ); ! getStatusStr( st, information); ! //printf( "\r%-*s", LINEWIDTH, line ); if( messageName[st->error] ) fprintf( stderr, "\n%s: %s\n", messageName[st->error], st->errorString ); } ! //tr_sessionSaveSettings( h, configDir, &settings ); ! ! // Torrentflux -START- ! const tr_stat * st; ! st = tr_torrentStat( tor ); ! ! TOF_print( (char*) "Transmission shutting down...\n"); ! ! /* Try for 5 seconds to delete any port mappings for nat traversal */ ! tr_sessionSetPortForwardingEnabled( h, 0 ); ! for( i = 0; i < 10; i++ ) ! { ! if( TR_PORT_UNMAPPED == tr_sessionIsPortForwardingEnabled( h ) ) ! { ! /* Port mappings were deleted */ ! break; ! } ! tr_wait_msec( 500 ); ! } ! if (st->percentDone >= 1) ! TOF_writeStatus(st, information, 0, "Download Succeeded" ); ! else ! TOF_writeStatus(st, information, 0, "Torrent Stopped" ); ! ! TOF_deletePID(); ! TOF_print( (char*) "Transmission exit.\n"); ! TOF_free(); ! // -END- ! printf( "\n" ); tr_bencFree( &settings ); tr_sessionClose( h ); return EXIT_SUCCESS; + + failed: + TOF_free(); + tr_torrentFree( tor ); + tr_sessionClose( h ); + return EXIT_FAILURE; } /*** *************** *** 375,380 **** --- 633,639 ---- { int c; const char * optarg; + int64_t downloadLimit, uploadLimit; while(( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ))) { *************** *** 391,396 **** --- 650,656 ---- break; case 'f': tr_bencDictAddStr( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, optarg ); tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, true ); + finishCall = optarg; break; case 'g': /* handled above */ break; *************** *** 423,428 **** --- 683,700 ---- if( torrentPath == NULL ) torrentPath = optarg; break; + case 'E': + TOF_displayInterval = atoi( optarg ); + break; + case 'L': + TOF_seedLimit = atoi( optarg ); + break; + case 'O': + TOF_owner = optarg; + break; + case 'W': + TOF_dieWhenDone = atoi( optarg ); + break; default: return 1; } } *************** *** 448,450 **** --- 720,1089 ---- } } + + /* Torrentflux -START- */ + static void TOF_print( char *printmsg ) + { + time_t rawtime; + struct tm * timeinfo; + time(&rawtime); + timeinfo = localtime(&rawtime); + + fprintf(stderr, "[%4d/%02d/%02d - %02d:%02d:%02d] %s", + timeinfo->tm_year + 1900, + timeinfo->tm_mon + 1, + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec, + ((printmsg != NULL) && (strlen(printmsg) > 0)) ? printmsg : "" + ); + } + + static int TOF_initStatus( void ) + { + int len = strlen(torrentPath) + 5; + TOF_statFile = malloc((len + 1) * sizeof(char)); + if (TOF_statFile == NULL) { + TOF_print( "Error : TOF_initStatus: not enough mem for malloc\n" ); + return 0; + } + + sprintf( TOF_statFile, "%s.stat", torrentPath ); + + sprintf( TOF_message, "Initialized status-facility. (%s)\n", TOF_statFile ); + TOF_print( TOF_message ); + return 1; + } + + static int TOF_initCommand( void ) + { + int len = strlen(torrentPath) + 4; + TOF_cmdFile = malloc((len + 1) * sizeof(char)); + if (TOF_cmdFile == NULL) { + TOF_print( "Error : TOF_initCommand: not enough mem for malloc\n" ); + return 0; + } + sprintf( TOF_cmdFile, "%s.cmd", torrentPath ); + + sprintf( TOF_message, "Initialized command-facility. (%s)\n", TOF_cmdFile ); + TOF_print( TOF_message ); + + // remove command-file if exists + TOF_cmdFp = NULL; + TOF_cmdFp = fopen(TOF_cmdFile, "r"); + if (TOF_cmdFp != NULL) + { + fclose(TOF_cmdFp); + sprintf( TOF_message, "Removing command-file. (%s)\n", TOF_cmdFile ); + TOF_print( TOF_message ); + remove(TOF_cmdFile); + TOF_cmdFp = NULL; + } + return 1; + } + + static int TOF_writePID( void ) + { + FILE * TOF_pidFp; + char TOF_pidFile[strlen(torrentPath) + 4]; + + sprintf(TOF_pidFile,"%s.pid",torrentPath); + + TOF_pidFp = fopen(TOF_pidFile, "w+"); + if (TOF_pidFp != NULL) + { + fprintf(TOF_pidFp, "%d", getpid()); + fclose(TOF_pidFp); + sprintf( TOF_message, "Wrote pid-file: %s (%d)\n", + TOF_pidFile , getpid() ); + TOF_print( TOF_message ); + return 1; + } + else + { + sprintf( TOF_message, "Error opening pid-file for writting: %s (%d)\n", + TOF_pidFile , getpid() ); + TOF_print( TOF_message ); + return 0; + } + } + + static void TOF_deletePID( void ) + { + char TOF_pidFile[strlen(torrentPath) + 4]; + + sprintf(TOF_pidFile,"%s.pid",torrentPath); + + sprintf( TOF_message, "Removing pid-file: %s (%d)\n", TOF_pidFile , getpid() ); + TOF_print( TOF_message ); + + remove(TOF_pidFile); + } + + static void TOF_writeStatus( const tr_stat *s, const tr_info *info, const int state, const char *status ) + { + if( !TOF_writeAllowed() && state != 0 ) return; + + TOF_statFp = fopen(TOF_statFile, "w+"); + if (TOF_statFp != NULL) + { + float TOF_pd,TOF_ratio; + int TOF_seeders,TOF_leechers; + + TOF_seeders = ( s->seeders < 0 ) ? 0 : s->seeders; + TOF_leechers = ( s->leechers < 0 ) ? 0 : s->leechers; + + if (state == 0 && s->percentDone < 1) + TOF_pd = ( -100.0 * s->percentDone ) - 100; + else + TOF_pd = 100.0 * s->percentDone; + + TOF_ratio = s->ratio < 0 ? 0 : s->ratio; + + fprintf(TOF_statFp, + "%d\n%.1f\n%s\n%.1f kB/s\n%.1f kB/s\n%s\n%d (%d)\n%d (%d)\n%.1f\n%d\n%" PRIu64 "\n%" PRIu64 "\n%" PRIu64, + state, /* State */ + TOF_pd, /* Progress */ + status, /* Status text */ + s->pieceDownloadSpeed_KBps, /* Download speed */ // versus rawDownloadSpeed + s->pieceUploadSpeed_KBps, /* Upload speed */ // versus rawUploadSpeed + TOF_owner, /* Owner */ + s->peersSendingToUs, TOF_seeders, /* Seeder */ + s->peersGettingFromUs, TOF_leechers, /* Leecher */ + 100.0 * TOF_ratio, /* ratio */ + TOF_seedLimit, /* seedlimit */ + s->uploadedEver, /* uploaded bytes */ + s->downloadedEver, /* downloaded bytes */ + info->totalSize /* global size */ + ); + fclose(TOF_statFp); + + } + else + { + sprintf( TOF_message, "Error opening stat-file for writting: %s\n", TOF_statFile ); + TOF_print( TOF_message ); + } + } + + static int TOF_processCommands(tr_session * h) + { + /* return values: + * 0 :: do not shutdown transmission + * 1 :: shutdown transmission + */ + + /* Now Process the CommandFile */ + + int commandCount = 0; + int isNewline; + long fileLen; + long index; + long startPos; + long totalChars; + char currentLine[128]; + char *fileBuffer; + char *fileCurrentPos; + + /* Try opening the CommandFile */ + TOF_cmdFp = NULL; + TOF_cmdFp = fopen(TOF_cmdFile, "r"); + + /* File does not exist */ + if( TOF_cmdFp == NULL ) + return 0; + + sprintf( TOF_message, "Processing command-file %s...\n", TOF_cmdFile ); + TOF_print( TOF_message ); + + // get length + fseek(TOF_cmdFp, 0L, SEEK_END); + fileLen = ftell(TOF_cmdFp); + rewind(TOF_cmdFp); + + if ( fileLen >= TOF_CMDFILE_MAXLEN || fileLen < 1 ) + { + if( fileLen >= TOF_CMDFILE_MAXLEN ) + sprintf( TOF_message, "Size of command-file too big, skip. (max-size: %d)\n", TOF_CMDFILE_MAXLEN ); + else + sprintf( TOF_message, "No commands found in command-file.\n" ); + + TOF_print( TOF_message ); + /* remove file */ + remove(TOF_cmdFile); + goto finished; + } + + fileBuffer = calloc(fileLen + 1, sizeof(char)); + if (fileBuffer == NULL) + { + TOF_print( (char*) "Not enough memory to read command-file\n" ); + /* remove file */ + remove(TOF_cmdFile); + goto finished; + } + + fread(fileBuffer, fileLen, 1, TOF_cmdFp); + fclose(TOF_cmdFp); + remove(TOF_cmdFile); + TOF_cmdFp = NULL; + totalChars = 0L; + fileCurrentPos = fileBuffer; + + while (*fileCurrentPos) + { + index = 0L; + isNewline = 0; + startPos = totalChars; + while (*fileCurrentPos) + { + if (!isNewline) + { + if ( *fileCurrentPos == 10 ) + isNewline = 1; + } + else if (*fileCurrentPos != 10) + { + break; + } + ++totalChars; + if ( index < 127 ) + currentLine[index++] = *fileCurrentPos++; + else + { + fileCurrentPos++; + break; + } + } + + if ( index > 1 ) + { + commandCount++; + currentLine[index - 1] = '\0'; + + if (TOF_execCommand(h, currentLine)) + { + free(fileBuffer); + return 1; + } + } + } + + if (commandCount == 0) + TOF_print( (char*) "No commands found in command-file.\n" ); + + free(fileBuffer); + + finished: + return 0; + } + + static int TOF_execCommand(tr_session *h, char *s) + { + int i, uploadLimit, downloadLimit; + int len = strlen(s); + char opcode; + char workload[len]; + + opcode = s[0]; + for (i = 0; i < len - 1; i++) + workload[i] = s[i + 1]; + workload[len - 1] = '\0'; + + switch (opcode) + { + case 'q': + TOF_print( (char*) "command: stop-request, setting shutdown-flag...\n" ); + return 1; + + case 'u': + if (strlen(workload) < 1) + { + TOF_print( (char*) "invalid upload-rate...\n" ); + return 0; + } + + uploadLimit = atoi(workload); + sprintf( TOF_message, "command: setting upload-rate to %d...\n", uploadLimit ); + TOF_print( TOF_message ); + + tr_sessionSetSpeedLimit_KBps( h, TR_UP, uploadLimit ); + tr_sessionLimitSpeed( h, TR_UP, uploadLimit > 0 ); + + return 0; + + case 'd': + if (strlen(workload) < 1) + { + TOF_print( (char*) "invalid download-rate...\n" ); + return 0; + } + + downloadLimit = atoi(workload); + sprintf( TOF_message, "command: setting download-rate to %d...\n", downloadLimit ); + TOF_print( TOF_message ); + + tr_sessionSetSpeedLimit_KBps( h, TR_DOWN, downloadLimit ); + tr_sessionLimitSpeed( h, TR_DOWN, downloadLimit > 0 ); + return 0; + + case 'w': + if (strlen(workload) < 1) + { + TOF_print( (char*) "invalid die-when-done flag...\n" ); + return 0; + } + + switch (workload[0]) + { + case '0': + TOF_print( (char*) "command: setting die-when-done to 0\n" ); + TOF_dieWhenDone = 0; + break; + case '1': + TOF_print( (char*) "command: setting die-when-done to 1\n" ); + TOF_dieWhenDone = 1; + break; + default: + sprintf( TOF_message, "invalid die-when-done flag: %c...\n", workload[0] ); + TOF_print( TOF_message ); + } + return 0; + + case 'l': + if (strlen(workload) < 1) + { + TOF_print( (char*) "invalid sharekill ratio...\n" ); + return 0; + } + + TOF_seedLimit = atoi(workload); + sprintf( TOF_message, "command: setting sharekill to %d...\n", TOF_seedLimit ); + TOF_print( TOF_message ); + return 0; + + default: + sprintf( TOF_message, "op-code unknown: %c\n", opcode ); + TOF_print( TOF_message ); + } + return 0; + } + + static int TOF_writeAllowed ( void ) + { + /* We want to write status every seconds, + but we also want to start in the first round */ + if( TOF_checkCmd == 1 ) return 1; + return 0; + } + + static void TOF_free ( void ) + { + free(TOF_cmdFile); + free(TOF_statFile); + if(strcmp(TOF_owner,"n/a") == 0) + free((void *)TOF_owner); + } + + /* -END- */ \ No newline at end of file diff -crB transmission-2.73.orig/libtransmission/transmission.h transmission-2.73/libtransmission/transmission.h *** transmission-2.73.orig/libtransmission/transmission.h 2012-10-24 14:59:15.649687988 +0200 --- transmission-2.73/libtransmission/transmission.h 2012-11-03 01:34:33.755403001 +0100 *************** *** 1948,1953 **** --- 1948,1969 ---- /** Number of webseeds that are sending data to us. */ int webseedsSendingToUs; + //TorrentFlux -START- + /** Number of seeders that the tracker says this torrent has */ + int seeders; + + /** Number of leechers that the tracker says this torrent has */ + int leechers; + + /** Number of downloaders that the tracker says this torrent has. + This is a new key introduced in BEP 21 and may not be supported by some trackers. + If the tracker doesn't support this key, the value here will be -1. */ + int downloaders; + + /** Number of finished downloads that the tracker says torrent has */ + int timesCompleted; + //-END- + /** Byte count of all the piece data we'll have downloaded when we're done, whether or not we have it yet. This may be less than tr_info.totalSize if only some of the torrent's files are wanted.