1 /******************************************************************************
2 * $Id: cli.c 11335 2010-10-18 03:11:51Z charles $
4 * Copyright (c) 2005-2006 Transmission authors and contributors
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
31 #include <libtransmission/transmission.h>
32 #include <libtransmission/bencode.h>
33 #include <libtransmission/tr-getopt.h>
34 #include <libtransmission/utils.h> /* tr_wait_msec */
35 #include <libtransmission/version.h>
36 #include <libtransmission/web.h> /* tr_webRun */
43 #define MEM_K_STR "KiB"
44 #define MEM_M_STR "MiB"
45 #define MEM_G_STR "GiB"
46 #define MEM_T_STR "TiB"
49 #define DISK_B_STR "B"
50 #define DISK_K_STR "KiB"
51 #define DISK_M_STR "MiB"
52 #define DISK_G_STR "GiB"
53 #define DISK_T_STR "TiB"
56 #define SPEED_B_STR "B/s"
57 #define SPEED_K_STR "KiB/s"
58 #define SPEED_M_STR "MiB/s"
59 #define SPEED_G_STR "GiB/s"
60 #define SPEED_T_STR "TiB/s"
67 #define MY_CONFIG_NAME "transmission"
68 #define MY_READABLE_NAME "transmission-cli"
71 static tr_bool showVersion
= FALSE
;
72 static tr_bool verify
= 0;
73 static sig_atomic_t gotsig
= 0;
74 static sig_atomic_t manualUpdate
= 0;
76 static const char * torrentPath
= NULL
;
79 #define TOF_DISPLAY_INTERVAL 5
80 #define TOF_DISPLAY_INTERVAL_STR "5"
81 #define TOF_DIEWHENDONE 0
82 #define TOF_DIEWHENDONE_STR "0"
83 #define TOF_CMDFILE_MAXLEN 65536
85 //static volatile char tf_shutdown = 0;
86 static int TOF_dieWhenDone
= TOF_DIEWHENDONE
;
87 static int TOF_seedLimit
= 0;
88 static int TOF_displayInterval
= TOF_DISPLAY_INTERVAL
;
89 static int TOF_checkCmd
= 0;
91 static const char * finishCall
= NULL
;
93 static const char * TOF_owner
= NULL
;
94 static char * TOF_statFile
= NULL
;
95 static FILE * TOF_statFp
= NULL
;
96 static char * TOF_cmdFile
= NULL
;
97 static FILE * TOF_cmdFp
= NULL
;
98 static char TOF_message
[512];
101 static const struct tr_option options
[] =
103 { 'b', "blocklist", "Enable peer blocklists", "b", 0, NULL
},
104 { 'B', "no-blocklist", "Disable peer blocklists", "B", 0, NULL
},
105 { 'd', "downlimit", "Set max download speed in "SPEED_K_STR
, "d", 1, "<speed>" },
106 { 'D', "no-downlimit", "Don't limit the download speed", "D", 0, NULL
},
107 { 910, "encryption-required", "Encrypt all peer connections", "er", 0, NULL
},
108 { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 0, NULL
},
109 { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", 0, NULL
},
110 { 'f', "finish", "Run a script when the torrent finishes", "f", 1, "<script>" },
111 { 'g', "config-dir", "Where to find configuration files", "g", 1, "<path>" },
112 { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL
},
113 { 'M', "no-portmap", "Disable portmapping", "M", 0, NULL
},
114 { 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR
")", "p", 1, "<port>" },
115 { 't', "tos", "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR
")", "t", 1, "<tos>" },
116 { 'u', "uplimit", "Set max upload speed in "SPEED_K_STR
, "u", 1, "<speed>" },
117 { 'U', "no-uplimit", "Don't limit the upload speed", "U", 0, NULL
},
118 { 'v', "verify", "Verify the specified torrent", "v", 0, NULL
},
119 { 'V', "version", "Show version number and exit", "V", 0, NULL
},
120 { 'w', "download-dir", "Where to save downloaded data", "w", 1, "<path>" },
121 //Torrentflux Commands:
122 { 'E', "display-interval","Time between updates of stat-file (default = "TOF_DISPLAY_INTERVAL_STR
")","E",1,"<int>"},
123 { 'L', "seedlimit","Seed-Limit (Percent) to reach before shutdown","L",1,"<int>"},
124 { 'O', "owner","Name of the owner (default = 'n/a')","O",1,"<string>"},
125 { 'W', "die-when-done", "Auto-Shutdown when done (0 = Off, 1 = On, default = "TOF_DIEWHENDONE_STR
")","W",1,NULL
},
127 { 0, NULL
, NULL
, NULL
, 0, NULL
}
133 return "A fast and easy BitTorrent client\n"
135 "Usage: " MY_READABLE_NAME
" [options] <file|url|magnet>";
138 static int parseCommandLine( tr_benc
*, int argc
, const char ** argv
);
140 static void sigHandler( int signal
);
142 /* Torrentflux -START- */
143 static int TOF_processCommands(tr_session
*h
);
144 static int TOF_execCommand(tr_session
*h
, char *s
);
145 static void TOF_print ( char *printmsg
);
146 static void TOF_free ( void );
147 static int TOF_initStatus ( void );
148 static void TOF_writeStatus ( const tr_stat
*s
, const tr_info
*info
,
149 const int state
, const char *status
);
150 static int TOF_initCommand ( void );
151 static int TOF_writePID ( void );
152 static void TOF_deletePID ( void );
153 static int TOF_writeAllowed ( void );
157 tr_strlratio( char * buf
,
161 if( (int)ratio
== TR_RATIO_NA
)
162 tr_strlcpy( buf
, _( "None" ), buflen
);
163 else if( (int)ratio
== TR_RATIO_INF
)
164 tr_strlcpy( buf
, "Inf", buflen
);
165 else if( ratio
< 10.0 )
166 tr_snprintf( buf
, buflen
, "%.2f", ratio
);
167 else if( ratio
< 100.0 )
168 tr_snprintf( buf
, buflen
, "%.1f", ratio
);
170 tr_snprintf( buf
, buflen
, "%.0f", ratio
);
174 static tr_bool waitingOnWeb
;
177 onTorrentFileDownloaded( tr_session
* session UNUSED
,
178 long response_code UNUSED
,
179 const void * response
,
180 size_t response_byte_count
,
183 tr_ctorSetMetainfo( ctor
, response
, response_byte_count
);
184 waitingOnWeb
= FALSE
;
188 getStatusStr( const tr_stat * st,
193 getStatusStr( const tr_stat
* st
, const tr_info
*information
)
199 if( st
->activity
& TR_STATUS_CHECK_WAIT
)
201 tr_snprintf( buf
, buflen
, "Waiting to verify local files" );
202 TOF_writeStatus(st
, information
, 1, buf
);
204 else if( st
->activity
& TR_STATUS_CHECK
)
206 tr_snprintf( buf
, buflen
,
207 // "Verifying local files (%.2f%%, %.2f%% valid)",
208 "%.2f%% Verifying local files (%.2f%% valid)",
209 tr_truncd( 100 * st
->recheckProgress
, 2 ),
210 tr_truncd( 100 * st
->percentDone
, 2 ) );
211 TOF_writeStatus(st
, information
, 1, buf
);
213 else if( st
->activity
& TR_STATUS_DOWNLOAD
)
219 tr_formatter_speed_KBps( upStr
, st
->pieceUploadSpeed_KBps
, sizeof( upStr
) );
220 tr_formatter_speed_KBps( dnStr
, st
->pieceDownloadSpeed_KBps
, sizeof( dnStr
) );
221 tr_strlratio( ratioStr
, st
->ratio
, sizeof( ratioStr
) );
223 tr_snprintf( buf
, buflen
,
225 "dl from %d of %d peers (%s), "
228 tr_truncd( 100 * st
->percentDone
, 1 ),
229 st
->peersSendingToUs
, st
->peersConnected
, upStr
,
230 st
->peersGettingFromUs
, dnStr
,
233 if( TOF_writeAllowed() )
238 if ( st
->eta
< 604800 ) // 7 days
240 if ( st
->eta
>= 86400 ) // 1 day
241 sprintf(TOF_eta
, "%d:",
244 if ( st
->eta
>= 3600 ) // 1 hour
245 sprintf(TOF_eta
, "%s%02d:",
246 TOF_eta
,((st
->eta
% 86400) / 3600));
248 if ( st
->eta
>= 60 ) // 1 Minute
249 sprintf(TOF_eta
, "%s%02d:",
250 TOF_eta
,((st
->eta
% 3600) / 60));
252 sprintf(TOF_eta
, "%s%02d",
253 TOF_eta
,(st
->eta
% 60));
256 sprintf(TOF_eta
, "-");
259 if ((st
->seeders
< -1) && (st
->peersConnected
== 0))
260 sprintf(TOF_eta
, "Connecting to Peers");
262 TOF_writeStatus(st
, information
, 1, TOF_eta
);
265 else if( st
->activity
& TR_STATUS_SEED
)
270 tr_formatter_speed_KBps( upStr
, st
->pieceUploadSpeed_KBps
, sizeof( upStr
) );
271 tr_strlratio( ratioStr
, st
->ratio
, sizeof( ratioStr
) );
273 tr_snprintf( buf
, buflen
,
274 "Seeding, uploading to %d of %d peer(s), %s [%s]",
275 st
->peersGettingFromUs
, st
->peersConnected
, upStr
, ratioStr
);
277 if (TOF_dieWhenDone
== 1)
279 TOF_print( (char *) "Die-when-done set, setting shutdown-flag...\n" );
284 if (TOF_seedLimit
== -1)
286 TOF_print( (char *) "Sharekill set to -1, setting shutdown-flag...\n" );
289 else if ( ( TOF_seedLimit
> 0 ) && ( ( st
->ratio
* 100.0 ) > (float)TOF_seedLimit
) )
291 sprintf( TOF_message
, "Seed-limit %d%% reached, setting shutdown-flag...\n", TOF_seedLimit
);
292 TOF_print( TOF_message
);
296 TOF_writeStatus(st
, information
, 1, "Download Succeeded" );
302 sprintf( TOF_message
, "error: %s\n", st
->errorString
);
303 TOF_print( TOF_message
);
308 getConfigDir( int argc
, const char ** argv
)
311 const char * configDir
= NULL
;
313 const int ind
= tr_optind
;
315 while(( c
= tr_getopt( getUsage( ), argc
, argv
, options
, &optarg
))) {
324 if( configDir
== NULL
)
325 configDir
= tr_getDefaultConfigDir( MY_CONFIG_NAME
);
331 main( int argc
, char ** argv
)
336 tr_torrent
* tor
= NULL
;
338 const char * configDir
;
339 uint8_t * fileContents
;
343 const tr_info
* information
;
346 tr_formatter_mem_init( MEM_K
, MEM_K_STR
, MEM_M_STR
, MEM_G_STR
, MEM_T_STR
);
347 tr_formatter_size_init( DISK_K
,DISK_K_STR
, DISK_M_STR
, DISK_G_STR
, DISK_T_STR
);
348 tr_formatter_speed_init( SPEED_K
, SPEED_K_STR
, SPEED_M_STR
, SPEED_G_STR
, SPEED_T_STR
);
350 printf( "%s %s - patched for TorrentFlux-NG\n", MY_READABLE_NAME
, LONG_VERSION_STRING
);
352 /* user needs to pass in at least one argument */
354 tr_getopt_usage( MY_READABLE_NAME
, getUsage( ), options
);
358 /* load the defaults from config file + libtransmission defaults */
359 tr_bencInitDict( &settings
, 0 );
360 configDir
= getConfigDir( argc
, (const char**)argv
);
361 //tr_sessionLoadSettings( &settings, configDir, MY_CONFIG_NAME );
363 /* the command line overrides defaults */
364 if( parseCommandLine( &settings
, argc
, (const char**)argv
) )
366 printf("Invalid commandline option given\n");
370 tr_bencDictRemove( &settings
, TR_PREFS_KEY_DOWNLOAD_DIR
);
371 getcwd( cwd
, sizeof( cwd
) );
372 tr_bencDictAddStr( &settings
, TR_PREFS_KEY_DOWNLOAD_DIR
, cwd
);
377 /* Check the options for validity */
379 fprintf( stderr
, "No torrent specified!\n" );
383 h
= tr_sessionInit( "cli", configDir
, FALSE
, &settings
);
385 ctor
= tr_ctorNew( h
);
386 tr_ctorSetMetainfoFromFile( ctor
, torrentPath
);
388 //fileContents = tr_loadFile( torrentPath, &fileLength );
389 tr_ctorSetPaused( ctor
, TR_FORCE
, FALSE
);
390 tr_ctorSetDownloadDir( ctor
, TR_FORCE
, cwd
);
391 tr_ctorSetDownloadDir( ctor
, TR_FALLBACK
, cwd
);
393 if( fileContents != NULL ) {
394 tr_ctorSetMetainfo( ctor, fileContents, fileLength );
395 } else if( !memcmp( torrentPath, "magnet:?", 8 ) ) {
396 tr_ctorSetMetainfoFromMagnetLink( ctor, torrentPath );
397 } else if( !memcmp( torrentPath, "http", 4 ) ) {
398 tr_webRun( h, torrentPath, NULL, onTorrentFileDownloaded, ctor );
400 while( waitingOnWeb ) tr_wait_msec( 1000 );
402 fprintf( stderr, "ERROR: Unrecognized torrent \"%s\".\n", torrentPath );
403 fprintf( stderr, " * If you're trying to create a torrent, use transmission-create.\n" );
404 fprintf( stderr, " * If you're trying to see a torrent's info, use transmission-show.\n" );
405 tr_sessionClose( h );
408 tr_free( fileContents );
410 // Torrentflux -START-
411 if (TOF_owner
== NULL
)
413 sprintf( TOF_message
, "No owner supplied, using 'n/a'.\n" );
414 TOF_print( TOF_message
);
415 TOF_owner
= malloc((4) * sizeof(char));
416 if (TOF_owner
== NULL
)
418 sprintf( TOF_message
, "Error : not enough mem for malloc\n" );
419 TOF_print( TOF_message
);
425 sprintf( TOF_message
, "transmission %s starting up :\n", LONG_VERSION_STRING
);
426 TOF_print( TOF_message
);
427 sprintf( TOF_message
, " - torrent : %s\n", torrentPath
);
428 TOF_print( TOF_message
);
429 sprintf( TOF_message
, " - owner : %s\n", TOF_owner
);
430 TOF_print( TOF_message
);
431 sprintf( TOF_message
, " - dieWhenDone : %d\n", TOF_dieWhenDone
);
432 TOF_print( TOF_message
);
433 sprintf( TOF_message
, " - seedLimit : %d\n", TOF_seedLimit
);
434 TOF_print( TOF_message
);
435 sprintf( TOF_message
, " - bindPort : %d\n", tr_sessionGetPeerPort(h
) );
436 TOF_print( TOF_message
);
437 sprintf( TOF_message
, " - uploadLimit : %d\n", tr_sessionGetSpeedLimit_KBps(h
, TR_UP
) );
438 TOF_print( TOF_message
);
439 sprintf( TOF_message
, " - downloadLimit : %d\n", tr_sessionGetSpeedLimit_KBps(h
, TR_DOWN
) );
440 TOF_print( TOF_message
);
441 sprintf( TOF_message
, " - natTraversal : %d\n", tr_sessionIsPortForwardingEnabled(h
) );
442 TOF_print( TOF_message
);
443 sprintf( TOF_message
, " - displayInterval : %d\n", TOF_displayInterval
);
444 TOF_print( TOF_message
);
445 sprintf( TOF_message
, " - downloadDir : %s\n", tr_sessionGetDownloadDir(h
) );
446 TOF_print( TOF_message
);
448 if (finishCall
!= NULL
)
450 sprintf( TOF_message
, " - finishCall : %s\n", finishCall
);
451 TOF_print( TOF_message
);
455 tor
= tr_torrentNew( ctor
, &error
);
457 sprintf( TOF_message
, " - downloadDir from torrent object, usually loaded from resume data : %s\n", tr_torrentGetDownloadDir( tor
) );
458 TOF_print( TOF_message
);
463 //fprintf( stderr, "Failed opening torrent file `%s'\n", torrentPath );
464 sprintf( TOF_message
, "Failed opening torrent file %s'\n", torrentPath
);
465 TOF_print( TOF_message
);
466 tr_sessionClose( h
);
470 signal( SIGINT
, sigHandler
);
472 signal( SIGHUP
, sigHandler
);
474 tr_torrentStart( tor
);
479 tr_torrentVerify( tor
);
482 // Torrentflux -START-
484 // initialize status-facility
485 if (TOF_initStatus() == 0)
487 sprintf( TOF_message
, "Failed to init status-facility. exit transmission.\n" );
488 TOF_print( TOF_message
);
492 // initialize command-facility
493 if (TOF_initCommand() == 0)
495 sprintf( TOF_message
, "Failed to init command-facility. exit transmission.\n" );
496 TOF_print( TOF_message
);
501 if (TOF_writePID() == 0)
503 sprintf( TOF_message
, "Failed to write pid-file. exit transmission.\n" );
504 TOF_print( TOF_message
);
508 sprintf( TOF_message
, "Transmission up and running.\n" );
510 information
= tr_torrentInfo( tor
);
515 char line
[LINEWIDTH
];
517 const char * messageName
[] = { NULL
, "Tracker gave a warning:",
518 "Tracker gave an error:",
521 // Torrentflux -START-
524 if( TOF_checkCmd
== TOF_displayInterval
)
527 /* If Torrentflux wants us to shutdown */
528 if (TOF_processCommands(h
))
538 //printf( "\nStopping torrent...\n" );
539 tr_torrentStop( tor
);
545 if( !tr_torrentCanManualUpdate( tor
) )
548 "\nReceived SIGHUP, but can't send a manual update now\n" );
552 "\nReceived SIGHUP: manual update scheduled\n" );
553 tr_torrentManualUpdate( tor
);
557 st
= tr_torrentStat( tor
);
558 if( st
->activity
& TR_STATUS_STOPPED
)
561 //getStatusStr( st, line, sizeof( line ) );
562 getStatusStr( st
, information
);
563 //printf( "\r%-*s", LINEWIDTH, line );
565 if( messageName
[st
->error
] )
566 fprintf( stderr
, "\n%s: %s\n", messageName
[st
->error
], st
->errorString
);
570 st
= tr_torrentStat( tor
);
572 TOF_print( (char*) "Transmission shutting down...\n");
574 /* Try for 5 seconds to delete any port mappings for nat traversal */
575 tr_sessionSetPortForwardingEnabled( h
, 0 );
576 for( i
= 0; i
< 10; i
++ )
578 if( TR_PORT_UNMAPPED
== tr_sessionIsPortForwardingEnabled( h
) )
580 /* Port mappings were deleted */
585 if (st
->percentDone
>= 1)
586 TOF_writeStatus(st
, information
, 0, "Download Succeeded" );
588 TOF_writeStatus(st
, information
, 0, "Torrent Stopped" );
591 TOF_print( (char*) "Transmission exit.\n");
594 //tr_sessionSaveSettings( h, configDir, &settings );
597 tr_bencFree( &settings
);
598 tr_sessionClose( h
);
603 tr_torrentFree( tor
);
604 tr_sessionClose( h
);
615 parseCommandLine( tr_benc
* d
, int argc
, const char ** argv
)
619 int64_t downloadLimit
, uploadLimit
;
621 while(( c
= tr_getopt( getUsage( ), argc
, argv
, options
, &optarg
)))
625 case 'b': tr_bencDictAddBool( d
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, TRUE
);
627 case 'B': tr_bencDictAddBool( d
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, FALSE
);
629 case 'd': tr_bencDictAddInt ( d
, TR_PREFS_KEY_DSPEED_KBps
, atoi( optarg
) );
630 tr_bencDictAddBool( d
, TR_PREFS_KEY_DSPEED_ENABLED
, TRUE
);
632 case 'D': tr_bencDictAddBool( d
, TR_PREFS_KEY_DSPEED_ENABLED
, FALSE
);
634 case 'f': tr_bencDictAddStr( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, optarg
);
635 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, TRUE
);
638 case 'g': /* handled above */
640 case 'm': tr_bencDictAddBool( d
, TR_PREFS_KEY_PORT_FORWARDING
, TRUE
);
642 case 'M': tr_bencDictAddBool( d
, TR_PREFS_KEY_PORT_FORWARDING
, FALSE
);
644 case 'p': tr_bencDictAddInt( d
, TR_PREFS_KEY_PEER_PORT
, atoi( optarg
) );
646 case 't': tr_bencDictAddInt( d
, TR_PREFS_KEY_PEER_SOCKET_TOS
, atoi( optarg
) );
648 case 'u': tr_bencDictAddInt( d
, TR_PREFS_KEY_USPEED_KBps
, atoi( optarg
) );
649 tr_bencDictAddBool( d
, TR_PREFS_KEY_USPEED_ENABLED
, TRUE
);
651 case 'U': tr_bencDictAddBool( d
, TR_PREFS_KEY_USPEED_ENABLED
, FALSE
);
653 case 'v': verify
= TRUE
;
655 case 'V': showVersion
= TRUE
;
657 case 'w': tr_bencDictAddStr( d
, TR_PREFS_KEY_DOWNLOAD_DIR
, optarg
);
659 case 910: tr_bencDictAddInt( d
, TR_PREFS_KEY_ENCRYPTION
, TR_ENCRYPTION_REQUIRED
);
661 case 911: tr_bencDictAddInt( d
, TR_PREFS_KEY_ENCRYPTION
, TR_ENCRYPTION_PREFERRED
);
663 case 912: tr_bencDictAddInt( d
, TR_PREFS_KEY_ENCRYPTION
, TR_CLEAR_PREFERRED
);
666 if( torrentPath
== NULL
)
667 torrentPath
= optarg
;
669 /* seems now implemented
670 case 'd': downloadLimit=atoi( optarg );
671 switch (downloadLimit) {
672 case 0: downloadLimit = -1;
674 case -2: downloadLimit = 0;
677 if (downloadLimit>=0)
679 tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED, downloadLimit );
680 tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 1 );
683 tr_bencDictAddInt( d, TR_PREFS_KEY_DSPEED_ENABLED, 0 );
686 uploadLimit=atoi( optarg );
687 switch (uploadLimit) {
688 case 0: uploadLimit = -1;
690 case -2: uploadLimit = 0;
695 tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED, uploadLimit );
696 tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 1 );
699 tr_bencDictAddInt( d, TR_PREFS_KEY_USPEED_ENABLED, 0 );
703 TOF_displayInterval
= atoi( optarg
);
706 TOF_seedLimit
= atoi( optarg
);
712 TOF_dieWhenDone
= atoi( optarg
);
722 sigHandler( int signal
)
731 manualUpdate
= 1; break;
740 /* Torrentflux -START- */
741 static void TOF_print( char *printmsg
)
744 struct tm
* timeinfo
;
746 timeinfo
= localtime(&rawtime
);
748 fprintf(stderr
, "[%4d/%02d/%02d - %02d:%02d:%02d] %s",
749 timeinfo
->tm_year
+ 1900,
750 timeinfo
->tm_mon
+ 1,
755 ((printmsg
!= NULL
) && (strlen(printmsg
) > 0)) ? printmsg
: ""
759 static int TOF_initStatus( void )
761 int len
= strlen(torrentPath
) + 5;
762 TOF_statFile
= malloc((len
+ 1) * sizeof(char));
763 if (TOF_statFile
== NULL
) {
764 TOF_print( "Error : TOF_initStatus: not enough mem for malloc\n" );
768 sprintf( TOF_statFile
, "%s.stat", torrentPath
);
770 sprintf( TOF_message
, "Initialized status-facility. (%s)\n", TOF_statFile
);
771 TOF_print( TOF_message
);
775 static int TOF_initCommand( void )
777 int len
= strlen(torrentPath
) + 4;
778 TOF_cmdFile
= malloc((len
+ 1) * sizeof(char));
779 if (TOF_cmdFile
== NULL
) {
780 TOF_print( "Error : TOF_initCommand: not enough mem for malloc\n" );
783 sprintf( TOF_cmdFile
, "%s.cmd", torrentPath
);
785 sprintf( TOF_message
, "Initialized command-facility. (%s)\n", TOF_cmdFile
);
786 TOF_print( TOF_message
);
788 // remove command-file if exists
790 TOF_cmdFp
= fopen(TOF_cmdFile
, "r");
791 if (TOF_cmdFp
!= NULL
)
794 sprintf( TOF_message
, "Removing command-file. (%s)\n", TOF_cmdFile
);
795 TOF_print( TOF_message
);
802 static int TOF_writePID( void )
805 char TOF_pidFile
[strlen(torrentPath
) + 4];
807 sprintf(TOF_pidFile
,"%s.pid",torrentPath
);
809 TOF_pidFp
= fopen(TOF_pidFile
, "w+");
810 if (TOF_pidFp
!= NULL
)
812 fprintf(TOF_pidFp
, "%d", getpid());
814 sprintf( TOF_message
, "Wrote pid-file: %s (%d)\n",
815 TOF_pidFile
, getpid() );
816 TOF_print( TOF_message
);
821 sprintf( TOF_message
, "Error opening pid-file for writting: %s (%d)\n",
822 TOF_pidFile
, getpid() );
823 TOF_print( TOF_message
);
828 static void TOF_deletePID( void )
830 char TOF_pidFile
[strlen(torrentPath
) + 4];
832 sprintf(TOF_pidFile
,"%s.pid",torrentPath
);
834 sprintf( TOF_message
, "Removing pid-file: %s (%d)\n", TOF_pidFile
, getpid() );
835 TOF_print( TOF_message
);
840 static void TOF_writeStatus( const tr_stat
*s
, const tr_info
*info
, const int state
, const char *status
)
842 if( !TOF_writeAllowed() && state
!= 0 ) return;
844 TOF_statFp
= fopen(TOF_statFile
, "w+");
845 if (TOF_statFp
!= NULL
)
847 float TOF_pd
,TOF_ratio
;
848 int TOF_seeders
,TOF_leechers
;
850 TOF_seeders
= ( s
->seeders
< 0 ) ? 0 : s
->seeders
;
851 TOF_leechers
= ( s
->leechers
< 0 ) ? 0 : s
->leechers
;
853 if (state
== 0 && s
->percentDone
< 1)
854 TOF_pd
= ( -100.0 * s
->percentDone
) - 100;
856 TOF_pd
= 100.0 * s
->percentDone
;
858 TOF_ratio
= s
->ratio
< 0 ? 0 : s
->ratio
;
861 "%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
,
863 TOF_pd
, /* Progress */
864 status
, /* Status text */
865 s
->pieceDownloadSpeed_KBps
, /* Download speed */ // versus rawDownloadSpeed
866 s
->pieceUploadSpeed_KBps
, /* Upload speed */ // versus rawUploadSpeed
867 TOF_owner
, /* Owner */
868 s
->peersSendingToUs
, TOF_seeders
, /* Seeder */
869 s
->peersGettingFromUs
, TOF_leechers
, /* Leecher */
870 100.0 * TOF_ratio
, /* ratio */
871 TOF_seedLimit
, /* seedlimit */
872 s
->uploadedEver
, /* uploaded bytes */
873 s
->downloadedEver
, /* downloaded bytes */
874 info
->totalSize
/* global size */
881 sprintf( TOF_message
, "Error opening stat-file for writting: %s\n", TOF_statFile
);
882 TOF_print( TOF_message
);
886 static int TOF_processCommands(tr_session
* h
)
889 * 0 :: do not shutdown transmission
890 * 1 :: shutdown transmission
893 /* Now Process the CommandFile */
895 int commandCount
= 0;
901 char currentLine
[128];
903 char *fileCurrentPos
;
905 /* Try opening the CommandFile */
907 TOF_cmdFp
= fopen(TOF_cmdFile
, "r");
909 /* File does not exist */
910 if( TOF_cmdFp
== NULL
)
913 sprintf( TOF_message
, "Processing command-file %s...\n", TOF_cmdFile
);
914 TOF_print( TOF_message
);
917 fseek(TOF_cmdFp
, 0L, SEEK_END
);
918 fileLen
= ftell(TOF_cmdFp
);
921 if ( fileLen
>= TOF_CMDFILE_MAXLEN
|| fileLen
< 1 )
923 if( fileLen
>= TOF_CMDFILE_MAXLEN
)
924 sprintf( TOF_message
, "Size of command-file too big, skip. (max-size: %d)\n", TOF_CMDFILE_MAXLEN
);
926 sprintf( TOF_message
, "No commands found in command-file.\n" );
928 TOF_print( TOF_message
);
934 fileBuffer
= calloc(fileLen
+ 1, sizeof(char));
935 if (fileBuffer
== NULL
)
937 TOF_print( (char*) "Not enough memory to read command-file\n" );
943 fread(fileBuffer
, fileLen
, 1, TOF_cmdFp
);
948 fileCurrentPos
= fileBuffer
;
950 while (*fileCurrentPos
)
954 startPos
= totalChars
;
955 while (*fileCurrentPos
)
959 if ( *fileCurrentPos
== 10 )
962 else if (*fileCurrentPos
!= 10)
968 currentLine
[index
++] = *fileCurrentPos
++;
979 currentLine
[index
- 1] = '\0';
981 if (TOF_execCommand(h
, currentLine
))
989 if (commandCount
== 0)
990 TOF_print( (char*) "No commands found in command-file.\n" );
998 static int TOF_execCommand(tr_session
*h
, char *s
)
1000 int i
, uploadLimit
, downloadLimit
;
1001 int len
= strlen(s
);
1006 for (i
= 0; i
< len
- 1; i
++)
1007 workload
[i
] = s
[i
+ 1];
1008 workload
[len
- 1] = '\0';
1013 TOF_print( (char*) "command: stop-request, setting shutdown-flag...\n" );
1017 if (strlen(workload
) < 1)
1019 TOF_print( (char*) "invalid upload-rate...\n" );
1023 uploadLimit
= atoi(workload
);
1024 sprintf( TOF_message
, "command: setting upload-rate to %d...\n", uploadLimit
);
1025 TOF_print( TOF_message
);
1027 tr_sessionSetSpeedLimit_KBps( h
, TR_UP
, uploadLimit
);
1028 tr_sessionLimitSpeed( h
, TR_UP
, uploadLimit
> 0 );
1033 if (strlen(workload
) < 1)
1035 TOF_print( (char*) "invalid download-rate...\n" );
1039 downloadLimit
= atoi(workload
);
1040 sprintf( TOF_message
, "command: setting download-rate to %d...\n", downloadLimit
);
1041 TOF_print( TOF_message
);
1043 tr_sessionSetSpeedLimit_KBps( h
, TR_DOWN
, downloadLimit
);
1044 tr_sessionLimitSpeed( h
, TR_DOWN
, downloadLimit
> 0 );
1048 if (strlen(workload
) < 1)
1050 TOF_print( (char*) "invalid die-when-done flag...\n" );
1054 switch (workload
[0])
1057 TOF_print( (char*) "command: setting die-when-done to 0\n" );
1058 TOF_dieWhenDone
= 0;
1061 TOF_print( (char*) "command: setting die-when-done to 1\n" );
1062 TOF_dieWhenDone
= 1;
1065 sprintf( TOF_message
, "invalid die-when-done flag: %c...\n", workload
[0] );
1066 TOF_print( TOF_message
);
1071 if (strlen(workload
) < 1)
1073 TOF_print( (char*) "invalid sharekill ratio...\n" );
1077 TOF_seedLimit
= atoi(workload
);
1078 sprintf( TOF_message
, "command: setting sharekill to %d...\n", TOF_seedLimit
);
1079 TOF_print( TOF_message
);
1083 sprintf( TOF_message
, "op-code unknown: %c\n", opcode
);
1084 TOF_print( TOF_message
);
1089 static int TOF_writeAllowed ( void )
1091 /* We want to write status every <TOF_displayInterval> seconds,
1092 but we also want to start in the first round */
1093 if( TOF_checkCmd
== 1 ) return 1;
1097 static void TOF_free ( void )
1101 if(strcmp(TOF_owner
,"n/a") == 0)
1102 free((void *)TOF_owner
);