source: trunk/cli/transmissioncli.c @ 198

Last change on this file since 198 was 198, checked in by titer, 16 years ago

Nicer make output. Also moved the CLI client to its own folder like
other interfaces.

File size: 8.4 KB
Line 
1/******************************************************************************
2 * Copyright (c) 2005 Eric Petit
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *****************************************************************************/
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <getopt.h>
28#include <signal.h>
29#include <transmission.h>
30#ifdef SYS_BEOS
31#include <kernel/OS.h>
32#define usleep snooze
33#endif
34
35#define USAGE \
36"Usage: %s [options] file.torrent [options]\n\n" \
37"Options:\n" \
38"  -h, --help           Print this help and exit\n" \
39"  -i, --info           Print metainfo and exit\n" \
40"  -s, --scrape         Print counts of seeders/leechers and exit\n" \
41"  -v, --verbose <int>  Verbose level (0 to 2, default = 0)\n" \
42"  -p, --port <int>     Port we should listen on (default = %d)\n" \
43"  -u, --upload <int>   Maximum upload rate (-1 = no limit, default = 20)\n" \
44"  -f, --finish <shell script> Command you wish to run on completion\n"
45
46static int             showHelp     = 0;
47static int             showInfo     = 0;
48static int             showScrape   = 0;
49static int             verboseLevel = 0;
50static int             bindPort     = TR_DEFAULT_PORT;
51static int             uploadLimit  = 20;
52static char          * torrentPath  = NULL;
53static volatile char   mustDie      = 0;
54
55static char          * finishCall   = NULL;
56
57static int  parseCommandLine ( int argc, char ** argv );
58static void sigHandler       ( int signal );
59
60int main( int argc, char ** argv )
61{
62    int i, error;
63    tr_handle_t  * h;
64    tr_torrent_t * tor;
65    tr_stat_t    * s;
66
67    printf( "Transmission %s - http://transmission.m0k.org/\n\n",
68            VERSION_STRING );
69
70    /* Get options */
71    if( parseCommandLine( argc, argv ) )
72    {
73        printf( USAGE, argv[0], TR_DEFAULT_PORT );
74        return 1;
75    }
76
77    if( showHelp )
78    {
79        printf( USAGE, argv[0], TR_DEFAULT_PORT );
80        return 0;
81    }
82
83    if( verboseLevel < 0 )
84    {
85        verboseLevel = 0;
86    }
87    else if( verboseLevel > 9 )
88    {
89        verboseLevel = 9;
90    }
91    if( verboseLevel )
92    {
93        static char env[11];
94        sprintf( env, "TR_DEBUG=%d", verboseLevel );
95        putenv( env );
96    }
97
98    if( bindPort < 1 || bindPort > 65535 )
99    {
100        printf( "Invalid port '%d'\n", bindPort );
101        return 1;
102    }
103
104    /* Initialize libtransmission */
105    h = tr_init();
106
107    /* Open and parse torrent file */
108    if( !( tor = tr_torrentInit( h, torrentPath, &error ) ) )
109    {
110        printf( "Failed opening torrent file `%s'\n", torrentPath );
111        goto failed;
112    }
113
114    if( showInfo )
115    {
116        tr_info_t * info = tr_torrentInfo( tor );
117
118        /* Print torrent info (quite à la btshowmetainfo) */
119        printf( "hash:     " );
120        for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
121        {
122            printf( "%02x", info->hash[i] );
123        }
124        printf( "\n" );
125        printf( "tracker:  %s:%d\n",
126                info->trackerAddress, info->trackerPort );
127        printf( "announce: %s\n", info->trackerAnnounce );
128        printf( "size:     %lld (%lld * %d + %lld)\n",
129                info->totalSize, info->totalSize / info->pieceSize,
130                info->pieceSize, info->totalSize % info->pieceSize );
131        printf( "file(s):\n" );
132        for( i = 0; i < info->fileCount; i++ )
133        {
134            printf( " %s (%lld)\n", info->files[i].name,
135                    info->files[i].length );
136        }
137
138        goto cleanup;
139    }
140
141    if( showScrape )
142    {
143        int seeders, leechers;
144
145        if( tr_torrentScrape( tor, &seeders, &leechers ) )
146        {
147            printf( "Scrape failed.\n" );
148        }
149        else
150        {
151            printf( "%d seeder(s), %d leecher(s).\n", seeders, leechers );
152        }
153
154        goto cleanup;
155    }
156
157    signal( SIGINT, sigHandler );
158
159    tr_setBindPort( h, bindPort );
160    tr_setUploadLimit( h, uploadLimit );
161   
162    tr_torrentSetFolder( tor, "." );
163    tr_torrentStart( tor );
164
165    while( !mustDie )
166    {
167        char string[80];
168        int  chars = 0;
169        int result;
170
171        sleep( 1 );
172
173        s = tr_torrentStat( tor );
174
175        if( s->status & TR_STATUS_CHECK )
176        {
177            chars = snprintf( string, 80,
178                "Checking files... %.2f %%", 100.0 * s->progress );
179        }
180        else if( s->status & TR_STATUS_DOWNLOAD )
181        {
182            chars = snprintf( string, 80,
183                "Progress: %.2f %%, %d peer%s, dl from %d (%.2f KB/s), "
184                "ul to %d (%.2f KB/s)", 100.0 * s->progress,
185                s->peersTotal, ( s->peersTotal == 1 ) ? "" : "s",
186                s->peersUploading, s->rateDownload,
187                s->peersDownloading, s->rateUpload );
188        }
189        else if( s->status & TR_STATUS_SEED )
190        {
191            chars = snprintf( string, 80,
192                "Seeding, uploading to %d of %d peer(s), %.2f KB/s",
193                s->peersDownloading, s->peersTotal,
194                s->rateUpload );
195        }
196        memset( &string[chars], ' ', 79 - chars );
197        string[79] = '\0';
198        fprintf( stderr, "\r%s", string );
199
200        if( s->error & TR_ETRACKER )
201        {
202            fprintf( stderr, "\n%s\n", s->trackerError );
203        }
204        else if( verboseLevel > 0 )
205        {
206            fprintf( stderr, "\n" );
207        }
208       
209        if( tr_getFinished( tor ) )
210        {
211            result = system(finishCall);
212        }
213    }
214    fprintf( stderr, "\n" );
215
216    /* Try for 5 seconds to notice the tracker that we are leaving */
217    tr_torrentStop( tor );
218    for( i = 0; i < 10; i++ )
219    {
220        s = tr_torrentStat( tor );
221        if( s->status & TR_STATUS_PAUSE )
222        {
223            /* The 'stopped' message was sent */
224            break;
225        }
226        usleep( 500000 );
227    }
228   
229cleanup:
230    tr_torrentClose( h, tor );
231
232failed:
233    tr_close( h );
234
235    return 0;
236}
237
238static int parseCommandLine( int argc, char ** argv )
239{
240    for( ;; )
241    {
242        static struct option long_options[] =
243          { { "help",    no_argument,       NULL, 'h' },
244            { "info",    no_argument,       NULL, 'i' },
245            { "scrape",  no_argument,       NULL, 's' },
246            { "verbose", required_argument, NULL, 'v' },
247            { "port",    required_argument, NULL, 'p' },
248            { "upload",  required_argument, NULL, 'u' },
249            { "finish",  required_argument, NULL, 'f' },
250            { 0, 0, 0, 0} };
251
252        int c, optind = 0;
253        c = getopt_long( argc, argv, "hisv:p:u:f:", long_options, &optind );
254        if( c < 0 )
255        {
256            break;
257        }
258        switch( c )
259        {
260            case 'h':
261                showHelp = 1;
262                break;
263            case 'i':
264                showInfo = 1;
265                break;
266            case 's':
267                showScrape = 1;
268                break;
269            case 'v':
270                verboseLevel = atoi( optarg );
271                break;
272            case 'p':
273                bindPort = atoi( optarg );
274                break;
275            case 'u':
276                uploadLimit = atoi( optarg );
277                break;
278            case 'f':
279                finishCall = optarg;
280                break;
281            default:
282                return 1;
283        }
284    }
285
286    if( optind > argc - 1  )
287    {
288        return !showHelp;
289    }
290
291    torrentPath = argv[optind];
292
293    return 0;
294}
295
296static void sigHandler( int signal )
297{
298    switch( signal )
299    {
300        case SIGINT:
301            mustDie = 1;
302            break;
303
304        default:
305            break;
306    }
307}
Note: See TracBrowser for help on using the repository browser.