Changeset 6892


Ignore:
Timestamp:
Oct 13, 2008, 10:26:02 PM (13 years ago)
Author:
charles
Message:

first batch of portability changes based on spry's winport:
(1) added tr_getcwd(), a simple portability wrapper for getcwd()
(2) cli: show the help page if no command-line arguments are provided
(3) daemon: use tr_wait() intead of sleep()
(4) daemon: SIGQUIT, SIGPIPE, SIGHUP aren't defined on windows
(5) libtransmission: a couple of small cleanups to bencode.c, list.c, web.c
(6) libtransmission: win32 portability fixes to platform.c

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/cli/cli.c

    r6825 r6892  
    6262static const char * sourceFile   = NULL;
    6363static const char * comment      = NULL;
    64 
    65 static int          parseCommandLine( int           argc,
    66                                       const char ** argv );
    67 
    68 static void         sigHandler( int signal );
    69 
    70 static char*
    71 tr_strlratio( char * buf,
    72               double ratio,
    73               size_t buflen )
    74 {
    75     if( (int)ratio == TR_RATIO_NA )
    76         tr_strlcpy( buf, _( "None" ), buflen );
    77     else if( (int)ratio == TR_RATIO_INF )
    78         tr_strlcpy( buf, "Inf", buflen );
    79     else if( ratio < 10.0 )
    80         tr_snprintf( buf, buflen, "%.2f", ratio );
    81     else if( ratio < 100.0 )
    82         tr_snprintf( buf, buflen, "%.1f", ratio );
    83     else
    84         tr_snprintf( buf, buflen, "%.0f", ratio );
    85     return buf;
    86 }
    87 
    88 static int
    89 is_rfc2396_alnum( char ch )
    90 {
    91     return ( '0' <= ch && ch <= '9' )
    92            || ( 'A' <= ch && ch <= 'Z' )
    93            || ( 'a' <= ch && ch <= 'z' );
    94 }
    95 
    96 static void
    97 escape( char *          out,
    98         const uint8_t * in,
    99         int             in_len )                     /* rfc2396 */
    100 {
    101     const uint8_t *end = in + in_len;
    102 
    103     while( in != end )
    104         if( is_rfc2396_alnum( *in ) )
    105             *out++ = (char) *in++;
    106         else
    107             out += tr_snprintf( out, 4, "%%%02X", (unsigned int)*in++ );
    108 
    109     *out = '\0';
    110 }
    111 
    112 static void
    113 torrentStateChanged( tr_torrent   * torrent   UNUSED,
    114                      cp_status_t    status    UNUSED,
    115                      void         * user_data UNUSED )
    116 {
    117     system( finishCall );
    118 }
    119 
    120 static int leftToScrape = 0;
    121 
    122 static void
    123 scrapeDoneFunc( struct tr_handle    * session UNUSED,
    124                 long                          response_code,
    125                 const void *                  response,
    126                 size_t                        response_byte_count,
    127                 void *                        host )
    128 {
    129     tr_benc top, *files;
    130 
    131     if( !tr_bencLoad( response, response_byte_count, &top, NULL )
    132       && tr_bencDictFindDict( &top, "files", &files )
    133       && files->val.l.count >= 2 )
    134     {
    135         int64_t   complete = -1, incomplete = -1, downloaded = -1;
    136         tr_benc * hash = &files->val.l.vals[1];
    137         tr_bencDictFindInt( hash, "complete", &complete );
    138         tr_bencDictFindInt( hash, "incomplete", &incomplete );
    139         tr_bencDictFindInt( hash, "downloaded", &downloaded );
    140         printf( "%4d seeders, %4d leechers, %5d downloads at %s\n",
    141                 (int)complete, (int)incomplete, (int)downloaded,
    142                 (char*)host );
    143         tr_bencFree( &top );
    144     }
    145     else
    146         fprintf( stderr, "Unable to parse response (http code %lu) at %s",
    147                  response_code,
    148                  (char*)host );
    149 
    150     --leftToScrape;
    151 }
    152 
    153 static void
    154 dumpInfo( FILE *          out,
    155           const tr_info * inf )
    156 {
    157     int             i;
    158     int             prevTier = -1;
    159     tr_file_index_t ff;
    160 
    161     fprintf( out, "hash:\t" );
    162     for( i = 0; i < SHA_DIGEST_LENGTH; ++i )
    163         fprintf( out, "%02x", inf->hash[i] );
    164     fprintf( out, "\n" );
    165 
    166     fprintf( out, "name:\t%s\n", inf->name );
    167 
    168     for( i = 0; i < inf->trackerCount; ++i )
    169     {
    170         if( prevTier != inf->trackers[i].tier )
    171         {
    172             prevTier = inf->trackers[i].tier;
    173             fprintf( out, "\ntracker tier #%d:\n", ( prevTier + 1 ) );
    174         }
    175         fprintf( out, "\tannounce:\t%s\n", inf->trackers[i].announce );
    176     }
    177 
    178     fprintf( out, "size:\t%" PRIu64 " (%" PRIu64 " * %d + %" PRIu64 ")\n",
    179              inf->totalSize, inf->totalSize / inf->pieceSize,
    180              inf->pieceSize, inf->totalSize % inf->pieceSize );
    181 
    182     if( inf->comment && *inf->comment )
    183         fprintf( out, "comment:\t%s\n", inf->comment );
    184     if( inf->creator && *inf->creator )
    185         fprintf( out, "creator:\t%s\n", inf->creator );
    186     if( inf->isPrivate )
    187         fprintf( out, "private flag set\n" );
    188 
    189     fprintf( out, "file(s):\n" );
    190     for( ff = 0; ff < inf->fileCount; ++ff )
    191         fprintf( out, "\t%s (%" PRIu64 ")\n", inf->files[ff].name,
    192                  inf->files[ff].length );
    193 }
    194 
    195 static void
    196 getStatusStr( const tr_stat * st,
    197               char *          buf,
    198               size_t          buflen )
    199 {
    200     if( st->status & TR_STATUS_CHECK_WAIT )
    201     {
    202         tr_snprintf( buf, buflen, "Waiting to verify local files" );
    203     }
    204     else if( st->status & TR_STATUS_CHECK )
    205     {
    206         tr_snprintf( buf, buflen,
    207                      "Verifying local files (%.2f%%, %.2f%% valid)",
    208                      100 * st->recheckProgress,
    209                      100.0 * st->percentDone );
    210     }
    211     else if( st->status & TR_STATUS_DOWNLOAD )
    212     {
    213         char ratioStr[80];
    214         tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) );
    215         tr_snprintf(
    216             buf, buflen,
    217             "Progress: %.1f%%, dl from %d of %d peers (%.0f KB/s), "
    218             "ul to %d (%.0f KB/s) [%s]",
    219             st->percentDone * 100.0,
    220             st->peersSendingToUs,
    221             st->peersConnected,
    222             st->rateDownload,
    223             st->peersGettingFromUs,
    224             st->rateUpload,
    225             ratioStr );
    226     }
    227     else if( st->status & TR_STATUS_SEED )
    228     {
    229         char ratioStr[80];
    230         tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) );
    231         tr_snprintf(
    232             buf, buflen,
    233             "Seeding, uploading to %d of %d peer(s), %.0f KB/s [%s]",
    234             st->peersGettingFromUs, st->peersConnected,
    235             st->rateUpload, ratioStr );
    236     }
    237     else *buf = '\0';
    238 }
    239 
    240 int
    241 main( int     argc,
    242       char ** argv )
    243 {
    244     int          error;
    245     tr_handle *  h;
    246     tr_ctor *    ctor;
    247     tr_torrent * tor = NULL;
    248     char         cwd[MAX_PATH_LENGTH];
    249 
    250     printf( "Transmission %s - http://www.transmissionbt.com/\n",
    251             LONG_VERSION_STRING );
    252 
    253     /* Get options */
    254     if( parseCommandLine( argc, (const char**)argv ) )
    255         return EXIT_FAILURE;
    256 
    257     /* Check the options for validity */
    258     if( !torrentPath )
    259     {
    260         fprintf( stderr, "No torrent specified!\n" );
    261         return EXIT_FAILURE;
    262     }
    263     if( peerPort < 1 || peerPort > 65535 )
    264     {
    265         fprintf( stderr, "Error: Port must between 1 and 65535; got %d\n",
    266                  peerPort );
    267         return EXIT_FAILURE;
    268     }
    269     if( peerSocketTOS < 0 || peerSocketTOS > 255 )
    270     {
    271         fprintf( stderr, "Error: value must between 0 and 255; got %d\n",
    272                  peerSocketTOS );
    273         return EXIT_FAILURE;
    274     }
    275 
    276     /* don't bind the port if we're just running the CLI
    277      * to get metainfo or to create a torrent */
    278     if( showInfo || showScrape || ( sourceFile != NULL ) )
    279         peerPort = -1;
    280 
    281     if( configdir == NULL )
    282         configdir = tr_getDefaultConfigDir( );
    283 
    284     /* if no download directory specified, use cwd instead */
    285     if( !downloadDir )
    286     {
    287         getcwd( cwd, sizeof( cwd ) );
    288         downloadDir = cwd;
    289     }
    290 
    291 
    292     /* Initialize libtransmission */
    293     h = tr_sessionInitFull(
    294         configdir,
    295         "cli",                            /* tag */
    296         downloadDir,                       /* where to download torrents */
    297         TR_DEFAULT_PEX_ENABLED,
    298         natTraversal,                      /* nat enabled */
    299         peerPort,
    300         encryptionMode,
    301         TR_DEFAULT_LAZY_BITFIELD_ENABLED,
    302         uploadLimit >= 0,
    303         uploadLimit,
    304         downloadLimit >= 0,
    305         downloadLimit,
    306         TR_DEFAULT_GLOBAL_PEER_LIMIT,
    307         verboseLevel + 1,                  /* messageLevel */
    308         0,                                 /* is message queueing enabled? */
    309         blocklistEnabled,
    310         peerSocketTOS,
    311         TR_DEFAULT_RPC_ENABLED,
    312         TR_DEFAULT_RPC_PORT,
    313         TR_DEFAULT_RPC_WHITELIST_ENABLED,
    314         TR_DEFAULT_RPC_WHITELIST,
    315         FALSE, "fnord", "potzrebie",
    316         TR_DEFAULT_PROXY_ENABLED,
    317         TR_DEFAULT_PROXY,
    318         TR_DEFAULT_PROXY_PORT,
    319         TR_DEFAULT_PROXY_TYPE,
    320         TR_DEFAULT_PROXY_AUTH_ENABLED,
    321         TR_DEFAULT_PROXY_USERNAME,
    322         TR_DEFAULT_PROXY_PASSWORD );
    323 
    324     if( sourceFile && *sourceFile ) /* creating a torrent */
    325     {
    326         int                   err;
    327         tr_metainfo_builder * b = tr_metaInfoBuilderCreate( h, sourceFile );
    328         tr_tracker_info       ti;
    329         ti.tier = 0;
    330         ti.announce = (char*) announce;
    331         tr_makeMetaInfo( b, torrentPath, &ti, 1, comment, isPrivate );
    332         while( !b->isDone )
    333         {
    334             tr_wait( 1000 );
    335             printf( "." );
    336         }
    337 
    338         err = b->result;
    339         tr_metaInfoBuilderFree( b );
    340         return err;
    341     }
    342 
    343     ctor = tr_ctorNew( h );
    344     tr_ctorSetMetainfoFromFile( ctor, torrentPath );
    345     tr_ctorSetPaused( ctor, TR_FORCE, showScrape );
    346     tr_ctorSetDownloadDir( ctor, TR_FORCE, downloadDir );
    347 
    348     if( showScrape )
    349     {
    350         tr_info info;
    351 
    352         if( !tr_torrentParse( h, ctor, &info ) )
    353         {
    354             int          i;
    355             const time_t start = time( NULL );
    356             for( i = 0; i < info.trackerCount; ++i )
    357             {
    358                 if( info.trackers[i].scrape )
    359                 {
    360                     const char * scrape = info.trackers[i].scrape;
    361                     char         escaped[SHA_DIGEST_LENGTH * 3 + 1];
    362                     char *       url, *host;
    363                     escape( escaped, info.hash, SHA_DIGEST_LENGTH );
    364                     url = tr_strdup_printf( "%s%cinfo_hash=%s",
    365                                             scrape,
    366                                             strchr( scrape,
    367                                                     '?' ) ? '&' : '?',
    368                                             escaped );
    369                     tr_httpParseURL( scrape, -1, &host, NULL, NULL );
    370                     ++leftToScrape;
    371                     tr_webRun( h, url, NULL, scrapeDoneFunc, host );
    372                     tr_free( host );
    373                     tr_free( url );
    374                 }
    375             }
    376 
    377             fprintf( stderr, "scraping %d trackers:\n", leftToScrape );
    378 
    379             while( leftToScrape > 0 && ( ( time( NULL ) - start ) < 20 ) )
    380                 tr_wait( 250 );
    381         }
    382         goto cleanup;
    383     }
    384 
    385     if( showInfo )
    386     {
    387         tr_info info;
    388 
    389         if( !tr_torrentParse( h, ctor, &info ) )
    390         {
    391             dumpInfo( stdout, &info );
    392             tr_metainfoFree( &info );
    393         }
    394 
    395         tr_ctorFree( ctor );
    396         goto cleanup;
    397     }
    398 
    399     tor = tr_torrentNew( h, ctor, &error );
    400     tr_ctorFree( ctor );
    401     if( !tor )
    402     {
    403         fprintf( stderr, "Failed opening torrent file `%s'\n", torrentPath );
    404         tr_sessionClose( h );
    405         return EXIT_FAILURE;
    406     }
    407 
    408     signal( SIGINT, sigHandler );
    409 #ifndef WIN32
    410     signal( SIGHUP, sigHandler );
    411 #endif
    412     tr_torrentSetStatusCallback( tor, torrentStateChanged, NULL );
    413     tr_torrentStart( tor );
    414 
    415     if( verify )
    416     {
    417         verify = 0;
    418         tr_torrentVerify( tor );
    419     }
    420 
    421     for( ; ; )
    422     {
    423         char            line[LINEWIDTH];
    424         const tr_stat * st;
    425 
    426         tr_wait( 200 );
    427 
    428         if( gotsig )
    429         {
    430             gotsig = 0;
    431             printf( "\nStopping torrent...\n" );
    432             tr_torrentStop( tor );
    433         }
    434 
    435         if( manualUpdate )
    436         {
    437             manualUpdate = 0;
    438             if( !tr_torrentCanManualUpdate( tor ) )
    439                 fprintf(
    440                     stderr,
    441                     "\nReceived SIGHUP, but can't send a manual update now\n" );
    442             else
    443             {
    444                 fprintf( stderr,
    445                          "\nReceived SIGHUP: manual update scheduled\n" );
    446                 tr_torrentManualUpdate( tor );
    447             }
    448         }
    449 
    450         st = tr_torrentStat( tor );
    451         if( st->status & TR_STATUS_STOPPED )
    452             break;
    453 
    454         getStatusStr( st, line, sizeof( line ) );
    455         printf( "\r%-*s", LINEWIDTH, line );
    456         if( st->error )
    457             fprintf( stderr, "\n%s\n", st->errorString );
    458     }
    459 
    460 cleanup:
    461     printf( "\n" );
    462     tr_sessionClose( h );
    463     return EXIT_SUCCESS;
    464 }
    465 
    466 /***
    467 ****
    468 ****
    469 ****
    470 ***/
    471 
    472 static const char *
    473 getUsage( void )
    474 {
    475     return "A fast and easy BitTorrent client\n"
    476            "\n"
    477            "Usage: " MY_NAME " [options] <torrent-filename>";
    478 }
    47964
    48065static const struct tr_option options[] =
     
    533118};
    534119
     120static const char *
     121getUsage( void )
     122{
     123    return "A fast and easy BitTorrent client\n"
     124           "\n"
     125           "Usage: " MY_NAME " [options] <torrent-filename>";
     126}
     127
     128static int          parseCommandLine( int           argc,
     129                                      const char ** argv );
     130
     131static void         sigHandler( int signal );
     132
     133static char*
     134tr_strlratio( char * buf,
     135              double ratio,
     136              size_t buflen )
     137{
     138    if( (int)ratio == TR_RATIO_NA )
     139        tr_strlcpy( buf, _( "None" ), buflen );
     140    else if( (int)ratio == TR_RATIO_INF )
     141        tr_strlcpy( buf, "Inf", buflen );
     142    else if( ratio < 10.0 )
     143        tr_snprintf( buf, buflen, "%.2f", ratio );
     144    else if( ratio < 100.0 )
     145        tr_snprintf( buf, buflen, "%.1f", ratio );
     146    else
     147        tr_snprintf( buf, buflen, "%.0f", ratio );
     148    return buf;
     149}
     150
     151static int
     152is_rfc2396_alnum( char ch )
     153{
     154    return ( '0' <= ch && ch <= '9' )
     155           || ( 'A' <= ch && ch <= 'Z' )
     156           || ( 'a' <= ch && ch <= 'z' );
     157}
     158
     159static void
     160escape( char *          out,
     161        const uint8_t * in,
     162        int             in_len )                     /* rfc2396 */
     163{
     164    const uint8_t *end = in + in_len;
     165
     166    while( in != end )
     167        if( is_rfc2396_alnum( *in ) )
     168            *out++ = (char) *in++;
     169        else
     170            out += tr_snprintf( out, 4, "%%%02X", (unsigned int)*in++ );
     171
     172    *out = '\0';
     173}
     174
     175static void
     176torrentStateChanged( tr_torrent   * torrent   UNUSED,
     177                     cp_status_t    status    UNUSED,
     178                     void         * user_data UNUSED )
     179{
     180    system( finishCall );
     181}
     182
     183static int leftToScrape = 0;
     184
     185static void
     186scrapeDoneFunc( struct tr_handle    * session UNUSED,
     187                long                          response_code,
     188                const void *                  response,
     189                size_t                        response_byte_count,
     190                void *                        host )
     191{
     192    tr_benc top, *files;
     193
     194    if( !tr_bencLoad( response, response_byte_count, &top, NULL )
     195      && tr_bencDictFindDict( &top, "files", &files )
     196      && files->val.l.count >= 2 )
     197    {
     198        int64_t   complete = -1, incomplete = -1, downloaded = -1;
     199        tr_benc * hash = &files->val.l.vals[1];
     200        tr_bencDictFindInt( hash, "complete", &complete );
     201        tr_bencDictFindInt( hash, "incomplete", &incomplete );
     202        tr_bencDictFindInt( hash, "downloaded", &downloaded );
     203        printf( "%4d seeders, %4d leechers, %5d downloads at %s\n",
     204                (int)complete, (int)incomplete, (int)downloaded,
     205                (char*)host );
     206        tr_bencFree( &top );
     207    }
     208    else
     209        fprintf( stderr, "Unable to parse response (http code %lu) at %s",
     210                 response_code,
     211                 (char*)host );
     212
     213    --leftToScrape;
     214}
     215
     216static void
     217dumpInfo( FILE *          out,
     218          const tr_info * inf )
     219{
     220    int             i;
     221    int             prevTier = -1;
     222    tr_file_index_t ff;
     223
     224    fprintf( out, "hash:\t" );
     225    for( i = 0; i < SHA_DIGEST_LENGTH; ++i )
     226        fprintf( out, "%02x", inf->hash[i] );
     227    fprintf( out, "\n" );
     228
     229    fprintf( out, "name:\t%s\n", inf->name );
     230
     231    for( i = 0; i < inf->trackerCount; ++i )
     232    {
     233        if( prevTier != inf->trackers[i].tier )
     234        {
     235            prevTier = inf->trackers[i].tier;
     236            fprintf( out, "\ntracker tier #%d:\n", ( prevTier + 1 ) );
     237        }
     238        fprintf( out, "\tannounce:\t%s\n", inf->trackers[i].announce );
     239    }
     240
     241    fprintf( out, "size:\t%" PRIu64 " (%" PRIu64 " * %d + %" PRIu64 ")\n",
     242             inf->totalSize, inf->totalSize / inf->pieceSize,
     243             inf->pieceSize, inf->totalSize % inf->pieceSize );
     244
     245    if( inf->comment && *inf->comment )
     246        fprintf( out, "comment:\t%s\n", inf->comment );
     247    if( inf->creator && *inf->creator )
     248        fprintf( out, "creator:\t%s\n", inf->creator );
     249    if( inf->isPrivate )
     250        fprintf( out, "private flag set\n" );
     251
     252    fprintf( out, "file(s):\n" );
     253    for( ff = 0; ff < inf->fileCount; ++ff )
     254        fprintf( out, "\t%s (%" PRIu64 ")\n", inf->files[ff].name,
     255                 inf->files[ff].length );
     256}
     257
     258static void
     259getStatusStr( const tr_stat * st,
     260              char *          buf,
     261              size_t          buflen )
     262{
     263    if( st->status & TR_STATUS_CHECK_WAIT )
     264    {
     265        tr_snprintf( buf, buflen, "Waiting to verify local files" );
     266    }
     267    else if( st->status & TR_STATUS_CHECK )
     268    {
     269        tr_snprintf( buf, buflen,
     270                     "Verifying local files (%.2f%%, %.2f%% valid)",
     271                     100 * st->recheckProgress,
     272                     100.0 * st->percentDone );
     273    }
     274    else if( st->status & TR_STATUS_DOWNLOAD )
     275    {
     276        char ratioStr[80];
     277        tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) );
     278        tr_snprintf(
     279            buf, buflen,
     280            "Progress: %.1f%%, dl from %d of %d peers (%.0f KB/s), "
     281            "ul to %d (%.0f KB/s) [%s]",
     282            st->percentDone * 100.0,
     283            st->peersSendingToUs,
     284            st->peersConnected,
     285            st->rateDownload,
     286            st->peersGettingFromUs,
     287            st->rateUpload,
     288            ratioStr );
     289    }
     290    else if( st->status & TR_STATUS_SEED )
     291    {
     292        char ratioStr[80];
     293        tr_strlratio( ratioStr, st->ratio, sizeof( ratioStr ) );
     294        tr_snprintf(
     295            buf, buflen,
     296            "Seeding, uploading to %d of %d peer(s), %.0f KB/s [%s]",
     297            st->peersGettingFromUs, st->peersConnected,
     298            st->rateUpload, ratioStr );
     299    }
     300    else *buf = '\0';
     301}
     302
     303int
     304main( int     argc,
     305      char ** argv )
     306{
     307    int          error;
     308    tr_handle *  h;
     309    tr_ctor *    ctor;
     310    tr_torrent * tor = NULL;
     311    char         cwd[MAX_PATH_LENGTH];
     312
     313    printf( "Transmission %s - http://www.transmissionbt.com/\n",
     314            LONG_VERSION_STRING );
     315
     316    /* user needs to pass in at least one argument */
     317    if( argc < 2 ) {
     318        tr_getopt_usage( MY_NAME, getUsage( ), options );
     319        return EXIT_FAILURE;
     320    }
     321
     322    /* Get options */
     323    if( parseCommandLine( argc, (const char**)argv ) )
     324        return EXIT_FAILURE;
     325
     326    /* Check the options for validity */
     327    if( !torrentPath )
     328    {
     329        fprintf( stderr, "No torrent specified!\n" );
     330        return EXIT_FAILURE;
     331    }
     332    if( peerPort < 1 || peerPort > 65535 )
     333    {
     334        fprintf( stderr, "Error: Port must between 1 and 65535; got %d\n",
     335                 peerPort );
     336        return EXIT_FAILURE;
     337    }
     338    if( peerSocketTOS < 0 || peerSocketTOS > 255 )
     339    {
     340        fprintf( stderr, "Error: value must between 0 and 255; got %d\n",
     341                 peerSocketTOS );
     342        return EXIT_FAILURE;
     343    }
     344
     345    /* don't bind the port if we're just running the CLI
     346     * to get metainfo or to create a torrent */
     347    if( showInfo || showScrape || ( sourceFile != NULL ) )
     348        peerPort = -1;
     349
     350    if( configdir == NULL )
     351        configdir = tr_getDefaultConfigDir( );
     352
     353    /* if no download directory specified, use cwd instead */
     354    if( !downloadDir )
     355    {
     356        tr_getcwd( cwd, sizeof( cwd ) );
     357        downloadDir = cwd;
     358    }
     359
     360
     361    /* Initialize libtransmission */
     362    h = tr_sessionInitFull(
     363        configdir,
     364        "cli",                            /* tag */
     365        downloadDir,                       /* where to download torrents */
     366        TR_DEFAULT_PEX_ENABLED,
     367        natTraversal,                      /* nat enabled */
     368        peerPort,
     369        encryptionMode,
     370        TR_DEFAULT_LAZY_BITFIELD_ENABLED,
     371        uploadLimit >= 0,
     372        uploadLimit,
     373        downloadLimit >= 0,
     374        downloadLimit,
     375        TR_DEFAULT_GLOBAL_PEER_LIMIT,
     376        verboseLevel + 1,                  /* messageLevel */
     377        0,                                 /* is message queueing enabled? */
     378        blocklistEnabled,
     379        peerSocketTOS,
     380        TR_DEFAULT_RPC_ENABLED,
     381        TR_DEFAULT_RPC_PORT,
     382        TR_DEFAULT_RPC_WHITELIST_ENABLED,
     383        TR_DEFAULT_RPC_WHITELIST,
     384        FALSE, "fnord", "potzrebie",
     385        TR_DEFAULT_PROXY_ENABLED,
     386        TR_DEFAULT_PROXY,
     387        TR_DEFAULT_PROXY_PORT,
     388        TR_DEFAULT_PROXY_TYPE,
     389        TR_DEFAULT_PROXY_AUTH_ENABLED,
     390        TR_DEFAULT_PROXY_USERNAME,
     391        TR_DEFAULT_PROXY_PASSWORD );
     392
     393    if( sourceFile && *sourceFile ) /* creating a torrent */
     394    {
     395        int                   err;
     396        tr_metainfo_builder * b = tr_metaInfoBuilderCreate( h, sourceFile );
     397        tr_tracker_info       ti;
     398        ti.tier = 0;
     399        ti.announce = (char*) announce;
     400        tr_makeMetaInfo( b, torrentPath, &ti, 1, comment, isPrivate );
     401        while( !b->isDone )
     402        {
     403            tr_wait( 1000 );
     404            printf( "." );
     405        }
     406
     407        err = b->result;
     408        tr_metaInfoBuilderFree( b );
     409        return err;
     410    }
     411
     412    ctor = tr_ctorNew( h );
     413    tr_ctorSetMetainfoFromFile( ctor, torrentPath );
     414    tr_ctorSetPaused( ctor, TR_FORCE, showScrape );
     415    tr_ctorSetDownloadDir( ctor, TR_FORCE, downloadDir );
     416
     417    if( showScrape )
     418    {
     419        tr_info info;
     420
     421        if( !tr_torrentParse( h, ctor, &info ) )
     422        {
     423            int          i;
     424            const time_t start = time( NULL );
     425            for( i = 0; i < info.trackerCount; ++i )
     426            {
     427                if( info.trackers[i].scrape )
     428                {
     429                    const char * scrape = info.trackers[i].scrape;
     430                    char         escaped[SHA_DIGEST_LENGTH * 3 + 1];
     431                    char *       url, *host;
     432                    escape( escaped, info.hash, SHA_DIGEST_LENGTH );
     433                    url = tr_strdup_printf( "%s%cinfo_hash=%s",
     434                                            scrape,
     435                                            strchr( scrape,
     436                                                    '?' ) ? '&' : '?',
     437                                            escaped );
     438                    tr_httpParseURL( scrape, -1, &host, NULL, NULL );
     439                    ++leftToScrape;
     440                    tr_webRun( h, url, NULL, scrapeDoneFunc, host );
     441                    tr_free( host );
     442                    tr_free( url );
     443                }
     444            }
     445
     446            fprintf( stderr, "scraping %d trackers:\n", leftToScrape );
     447
     448            while( leftToScrape > 0 && ( ( time( NULL ) - start ) < 20 ) )
     449                tr_wait( 250 );
     450        }
     451        goto cleanup;
     452    }
     453
     454    if( showInfo )
     455    {
     456        tr_info info;
     457
     458        if( !tr_torrentParse( h, ctor, &info ) )
     459        {
     460            dumpInfo( stdout, &info );
     461            tr_metainfoFree( &info );
     462        }
     463
     464        tr_ctorFree( ctor );
     465        goto cleanup;
     466    }
     467
     468    tor = tr_torrentNew( h, ctor, &error );
     469    tr_ctorFree( ctor );
     470    if( !tor )
     471    {
     472        fprintf( stderr, "Failed opening torrent file `%s'\n", torrentPath );
     473        tr_sessionClose( h );
     474        return EXIT_FAILURE;
     475    }
     476
     477    signal( SIGINT, sigHandler );
     478#ifndef WIN32
     479    signal( SIGHUP, sigHandler );
     480#endif
     481    tr_torrentSetStatusCallback( tor, torrentStateChanged, NULL );
     482    tr_torrentStart( tor );
     483
     484    if( verify )
     485    {
     486        verify = 0;
     487        tr_torrentVerify( tor );
     488    }
     489
     490    for( ; ; )
     491    {
     492        char            line[LINEWIDTH];
     493        const tr_stat * st;
     494
     495        tr_wait( 200 );
     496
     497        if( gotsig )
     498        {
     499            gotsig = 0;
     500            printf( "\nStopping torrent...\n" );
     501            tr_torrentStop( tor );
     502        }
     503
     504        if( manualUpdate )
     505        {
     506            manualUpdate = 0;
     507            if( !tr_torrentCanManualUpdate( tor ) )
     508                fprintf(
     509                    stderr,
     510                    "\nReceived SIGHUP, but can't send a manual update now\n" );
     511            else
     512            {
     513                fprintf( stderr,
     514                         "\nReceived SIGHUP: manual update scheduled\n" );
     515                tr_torrentManualUpdate( tor );
     516            }
     517        }
     518
     519        st = tr_torrentStat( tor );
     520        if( st->status & TR_STATUS_STOPPED )
     521            break;
     522
     523        getStatusStr( st, line, sizeof( line ) );
     524        printf( "\r%-*s", LINEWIDTH, line );
     525        if( st->error )
     526            fprintf( stderr, "\n%s\n", st->errorString );
     527    }
     528
     529cleanup:
     530    printf( "\n" );
     531    tr_sessionClose( h );
     532    return EXIT_SUCCESS;
     533}
     534
     535/***
     536****
     537****
     538****
     539***/
     540
    535541static void
    536542showUsage( void )
  • trunk/daemon/daemon.c

    r6825 r6892  
    1919#include <fcntl.h> /* open */
    2020#include <signal.h>
    21 #include <unistd.h> /* daemon, getcwd */
     21#include <unistd.h> /* daemon */
    2222
    2323#include <libtransmission/transmission.h>
     
    191191    ***/
    192192
    193     getcwd( mycwd, sizeof( mycwd ) );
     193    tr_getcwd( mycwd, sizeof( mycwd ) );
    194194    getConfigStr( dict, KEY_DOWNLOAD_DIR,    &downloadDir,       mycwd );
    195195    getConfigInt( dict, KEY_PEX_ENABLED,     &pexEnabled,
     
    468468
    469469    signal( SIGINT, gotsig );
     470    signal( SIGTERM, gotsig );
     471#ifndef WIN32
    470472    signal( SIGQUIT, gotsig );
    471     signal( SIGTERM, gotsig );
    472473    signal( SIGPIPE, SIG_IGN );
    473474    signal( SIGHUP, SIG_IGN );
     475#endif
    474476
    475477    readargs( argc, (const char**)argv, &nofork, &configDir, &downloadDir,
     
    496498
    497499    while( !closing )
    498         sleep( 1 );
     500        tr_wait( 1000 ); /* sleep one second */
    499501
    500502    saveState( mySession );
  • trunk/daemon/remote.c

    r6866 r6892  
    1515#include <stdlib.h>
    1616#include <string.h> /* strcmp */
    17 
    18 #include <unistd.h> /* getcwd */
    1917
    2018#include <libevent/event.h>
     
    156154    {
    157155        char cwd[MAX_PATH_LENGTH];
    158         getcwd( cwd, sizeof( cwd ) );
     156        tr_getcwd( cwd, sizeof( cwd ) );
    159157        tr_buildPath( buf, len, cwd, path, NULL );
    160158    }
  • trunk/libtransmission/bencode.c

    r6851 r6892  
    105105    else
    106106    {
    107         *setme_end = end + 1;
     107        *setme_end = (const uint8_t*)end + 1;
    108108        *setme_val = val;
    109109    }
     
    147147        return EILSEQ;
    148148
    149     *setme_end = end + 1 + len;
    150     *setme_str = end + 1;
     149    *setme_end = (const uint8_t*)end + 1 + len;
     150    *setme_str = (const uint8_t*)end + 1;
    151151    *setme_strlen = len;
    152152    return 0;
  • trunk/libtransmission/list.c

    r6795 r6892  
    7979
    8080void
    81 tr_list_insert_sorted( tr_list ** list,
    82                        void *    data,
    83                         int          compare(const void*, const void*) )
     81tr_list_insert_sorted( tr_list            ** list,
     82                       void                * data,
     83                       TrListCompareFunc     compare )
    8484{
    8585    /* find l, the node that we'll insert this data before */
  • trunk/libtransmission/platform.c

    r6861 r6892  
    1919#elif defined( WIN32 )
    2020 #include <windows.h>
    21  #include <shlobj.h> /* for CSIDL_APPDATA, CSIDL_PROFILE */
     21 #include <shlobj.h> /* for CSIDL_APPDATA, CSIDL_MYDOCUMENTS */
    2222#else
    2323 #ifdef SYS_DARWIN
     
    3939#include <sys/stat.h>
    4040#include <sys/types.h>
     41#ifdef WIN32
     42#include <libgen.h>
     43#endif
    4144#include <dirent.h>
    4245#include <fcntl.h>
     
    268271        {
    269272#ifdef WIN32
    270             SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, home );
     273            SHGetFolderPath( NULL, CSIDL_MYDOCUMENTS, NULL, 0, home );
    271274#elif defined( __BEOS__ ) || defined( __AMIGAOS4__ )
    272275            home = tr_strdup( "" );
     
    421424}
    422425
    423 #ifdef SYS_DARWIN
     426#if defined(SYS_DARWIN) || defined(WIN32)
    424427 #define RESUME_SUBDIR  "Resume"
    425428 #define TORRENT_SUBDIR "Torrents"
  • trunk/libtransmission/utils.c

    r6877 r6892  
    3535#include <sys/types.h>
    3636#include <sys/stat.h>
    37 #include <unistd.h> /* usleep, stat */
     37#include <unistd.h> /* usleep, stat, getcwd */
    3838
    3939#include "event.h"
    4040
    4141#ifdef WIN32
    42  #include <windows.h>   /* for Sleep */
     42 #include <direct.h> /* _getcwd */
     43 #include <windows.h> /* Sleep */
    4344#elif defined( __BEOS__ )
    4445 #include <kernel/OS.h>
     
    453454    *size = sb.st_size;
    454455    return buf;
     456}
     457
     458char*
     459tr_getcwd( char  * buffer,
     460           int     maxlen )
     461{
     462#ifdef WIN32
     463    return _getcwd( buffer, maxlen );
     464#else
     465    return getcwd( buffer, maxlen );
     466#endif
    455467}
    456468
  • trunk/libtransmission/utils.h

    r6842 r6892  
    146146char*          tr_getLogTimeStr( char * buf,
    147147                                 int    buflen );
     148
     149/**
     150 * a portability wrapper around getcwd().
     151 */
     152char*          tr_getcwd( char  * buffer,
     153                          int     maxlen );
    148154
    149155/**
  • trunk/libtransmission/web.c

    r6795 r6892  
    221221           const char *       url,
    222222           const char *       range,
    223            tr_web_done_func * done_func,
     223           tr_web_done_func   done_func,
    224224           void *             done_func_user_data )
    225225{
Note: See TracChangeset for help on using the changeset viewer.