--- cli.c.orig Fri Feb 13 10:41:10 2009 +++ cli.c Thu Feb 26 20:37:50 2009 @@ -36,8 +36,16 @@ #include /* tr_webRun */ #define LINEWIDTH 80 -#define MY_NAME "transmission-cli" +#define MY_NAME "transmission" +//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 +//END + static tr_bool showInfo = 0; static tr_bool showScrape = 0; static tr_bool isPrivate = 0; @@ -51,6 +59,22 @@ static const char * sourceFile = NULL; static const char * comment = NULL; +/* Torrentflux -START- */ +//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 * 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- */ + + static const struct tr_option options[] = { { 'a', "announce", "Set the new torrent's announce URL", "a", 1, "" }, @@ -76,6 +100,12 @@ { 'U', "no-uplimit", "Don't limit the upload speed", "U", 0, NULL }, { 'v', "verify", "Verify the specified torrent", "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 } }; @@ -91,6 +121,21 @@ 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, @@ -219,48 +264,86 @@ } static void -getStatusStr( const tr_stat * st, - char * buf, - size_t buflen ) +getStatusStr( const tr_stat * st, const tr_info *information ) { + char TOF_eta[50]; if( st->activity & TR_STATUS_CHECK_WAIT ) { - tr_snprintf( buf, buflen, "Waiting to verify local files" ); + TOF_writeStatus(st, information, 1, "Waiting to verify local files" ); } else if( st->activity & TR_STATUS_CHECK ) { + /* tr_snprintf( buf, buflen, "Verifying local files (%.2f%%, %.2f%% valid)", 100 * st->recheckProgress, 100.0 * st->percentDone ); + */ + sprintf(TOF_eta, "%.2f%% Verifying local files",100 * st->recheckProgress); + TOF_writeStatus(st, information, 1, TOF_eta ); } else if( st->activity & TR_STATUS_DOWNLOAD ) { - char ratioStr[80]; - tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) ); - tr_snprintf( - buf, buflen, - "Progress: %.1f%%, dl from %d of %d peers (%.0f KB/s), " - "ul to %d (%.0f KB/s) [%s]", - st->percentDone * 100.0, - st->peersSendingToUs, - st->peersConnected, - st->pieceDownloadSpeed, - st->peersGettingFromUs, - st->pieceUploadSpeed, - 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 ) { - char ratioStr[80]; - tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) ); - tr_snprintf( - buf, buflen, - "Seeding, uploading to %d of %d peer(s), %.0f KB/s [%s]", - st->peersGettingFromUs, st->peersConnected, - st->pieceUploadSpeed, ratioStr ); + if (TOF_dieWhenDone == 1) + { + TOF_print( "Die-when-done set, setting shutdown-flag...\n" ); + gotsig = 1; + } + else + { + if (TOF_seedLimit == -1) + { + TOF_print( "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* @@ -290,14 +373,16 @@ main( int argc, char ** argv ) { - int error; + int i, error; tr_session * h; tr_ctor * ctor; tr_torrent * tor = NULL; tr_benc settings; + const tr_info *information; const char * configDir; + char cwd[1024]; - printf( "Transmission %s - http://www.transmissionbt.com/\n", + printf( "Transmission %s - http://www.transmissionbt.com/ - modified for Torrentflux-b4rt\n", LONG_VERSION_STRING ); /* user needs to pass in at least one argument */ @@ -309,17 +394,23 @@ /* load the defaults from config file + libtransmission defaults */ tr_bencInitDict( &settings, 0 ); configDir = getConfigDir( argc, (const char**)argv ); - tr_sessionLoadSettings( &settings, configDir, MY_NAME ); + //tr_sessionLoadSettings( &settings, configDir, MY_NAME ); /* the command line overrides defaults */ if( parseCommandLine( &settings, argc, (const char**)argv ) ) + { + printf("Invalid commandline option given\n"); return EXIT_FAILURE; + } /* Check the options for validity */ if( !torrentPath ) { fprintf( stderr, "No torrent specified!\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 ); /* don't bind the port if we're just running the CLI to get metainfo or to create a torrent */ @@ -350,7 +441,9 @@ ctor = tr_ctorNew( h ); tr_ctorSetMetainfoFromFile( ctor, torrentPath ); tr_ctorSetPaused( ctor, TR_FORCE, showScrape ); - + tr_ctorSetDownloadDir( ctor, TR_FORCE, cwd ); + tr_ctorSetDownloadDir( ctor, TR_FALLBACK, cwd ); + if( showScrape ) { tr_info info; @@ -387,6 +480,52 @@ goto cleanup; } + //* 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(h, TR_UP ) ); + TOF_print( TOF_message ); + sprintf( TOF_message, " - downloadLimit : %d\n", tr_sessionGetSpeedLimit(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- */ + + if( showInfo ) { tr_info info; @@ -402,10 +541,19 @@ } tor = tr_torrentNew( h, 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 ); + //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; } @@ -423,17 +571,61 @@ 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]; + //char line[LINEWIDTH]; const tr_stat * st; + /* 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( 200 ); if( gotsig ) { gotsig = 0; - printf( "\nStopping torrent...\n" ); + //printf( "\nStopping torrent...\n" ); tr_torrentStop( tor ); } @@ -441,9 +633,11 @@ { manualUpdate = 0; if( !tr_torrentCanManualUpdate( tor ) ) + { fprintf( stderr, "\nReceived SIGHUP, but can't send a manual update now\n" ); + } else { fprintf( stderr, @@ -454,22 +648,61 @@ st = tr_torrentStat( tor ); if( st->activity & TR_STATUS_STOPPED ) + { break; - - getStatusStr( st, line, sizeof( line ) ); - printf( "\r%-*s", LINEWIDTH, line ); + } + getStatusStr( st, information); + //printf( "\r%-*s", LINEWIDTH, line ); + if( st->error ) fprintf( stderr, "\n%s\n", st->errorString ); } + + + { + const tr_stat * st; + st = tr_torrentStat( tor ); + + TOF_print("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( 500 ); + } + if (st->percentDone >= 1) + TOF_writeStatus(st, information, 0, "Download Succeeded" ); + else + TOF_writeStatus(st, information, 0, "Torrent Stopped" ); + TOF_deletePID(); + + TOF_print("Transmission exit.\n"); + + TOF_free(); + } + cleanup: - tr_sessionSaveSettings( h, configDir, &settings ); +// tr_sessionSaveSettings( h, configDir, &settings ); printf( "\n" ); tr_bencFree( &settings ); tr_sessionClose( h ); return EXIT_SUCCESS; + +failed: + TOF_free(); + tr_torrentFree( tor ); + tr_sessionClose( h ); + return EXIT_FAILURE; + } /*** @@ -481,6 +714,7 @@ static int parseCommandLine( tr_benc * d, int argc, const char ** argv ) { + int64_t downloadLimit, uploadLimit; int c; const char * optarg; @@ -497,8 +731,22 @@ break; case 'c': comment = optarg; break; - case 'd': tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED, atoi( optarg ) ); - tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 1 ); + case 'd': downloadLimit=atoi( optarg ); + switch (downloadLimit) { + case 0: + downloadLimit = -1; + break; + case -2: + downloadLimit = 0; + break; + } + if (downloadLimit>=0) + { + tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED, downloadLimit ); + tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 1 ); + } + else + tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 0 ); break; case 'D': tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 0 ); break; @@ -521,8 +769,23 @@ break; case 't': tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_SOCKET_TOS, atoi( optarg ) ); break; - case 'u': tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED, atoi( optarg ) ); - tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 1 ); + case 'u': + uploadLimit=atoi( optarg ); + switch (uploadLimit) { + case 0: + uploadLimit = -1; + break; + case -2: + uploadLimit = 0; + break; + } + if (uploadLimit>=0) + { + tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED, uploadLimit ); + tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 1 ); + } + else + tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 0 ); break; case 'U': tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 0 ); break; @@ -530,6 +793,18 @@ break; case 'w': tr_bencDictAddStr( d, TR_PREFS_KEY_DOWNLOAD_DIR, 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; case 910: tr_bencDictAddInt( d, TR_PREFS_KEY_ENCRYPTION, TR_ENCRYPTION_REQUIRED ); break; case 911: tr_bencDictAddInt( d, TR_PREFS_KEY_ENCRYPTION, TR_ENCRYPTION_PREFERRED ); @@ -564,3 +839,369 @@ } } + +/* 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, /* Download speed */ // versus rawDownloadSpeed + s->pieceUploadSpeed, /* 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( "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( "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( "command: stop-request, setting shutdown-flag...\n" ); + return 1; + + case 'u': + if (strlen(workload) < 1) + { + TOF_print( "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( h, TR_UP, uploadLimit ); + tr_sessionSetSpeedLimitEnabled( h, TR_UP, uploadLimit > 0 ); + return 0; + + case 'd': + if (strlen(workload) < 1) + { + TOF_print( "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( h, TR_DOWN, downloadLimit ); + tr_sessionSetSpeedLimitEnabled( h, TR_DOWN, downloadLimit > 0 ); + return 0; + + case 'w': + if (strlen(workload) < 1) + { + TOF_print( "invalid die-when-done flag...\n" ); + return 0; + } + + switch (workload[0]) + { + case '0': + TOF_print( "command: setting die-when-done to 0\n" ); + TOF_dieWhenDone = 0; + break; + case '1': + TOF_print( "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( "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(TOF_owner); +} + +/* -END- */ +