Changeset 6298


Ignore:
Timestamp:
Jul 8, 2008, 4:50:34 PM (13 years ago)
Author:
charles
Message:

have daemon and cli use tr-getopt too.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/cli/transmissioncli.c

    r6156 r6298  
    2727#include <string.h>
    2828#include <unistd.h>
    29 #include <getopt.h>
    3029#include <signal.h>
    3130
     
    3433#include <libtransmission/makemeta.h>
    3534#include <libtransmission/metainfo.h> /* tr_metainfoFree */
     35#include <libtransmission/tr-getopt.h>
    3636#include <libtransmission/utils.h> /* tr_wait */
    3737#include <libtransmission/web.h> /* tr_webRun */
    3838
    39 
    40 /* macro to shut up "unused parameter" warnings */
    41 #ifdef __GNUC__
    42 #define UNUSED                  __attribute__((unused))
    43 #else
    44 #define UNUSED
    45 #endif
    46 
    47 const char * USAGE =
    48 "Usage: %s [-car[-m]] [-dfginpsuv] [-h] file.torrent [output-dir]\n\n"
    49 "Options:\n"
    50 "  -h, --help                Print this help and exit\n"
    51 "  -i, --info                Print metainfo and exit\n"
    52 "  -s, --scrape              Print counts of seeders/leechers and exit\n"
    53 "  -V, --version             Print the version number and exit\n"
    54 "  -c, --create-from <file>  Create torrent from the specified source file.\n"
    55 "  -a, --announce <url>      Used in conjunction with -c.\n"
    56 "  -g, --config-dir <path>   Where to look for configuration files\n"
    57 "  -o, --output-dir <path>   Where to save downloaded data\n"
    58 "  -r, --private             Used in conjunction with -c.\n"
    59 "  -m, --comment <text>      Adds an optional comment when creating a torrent.\n"
    60 "  -d, --download <int>      Max download rate (-1 = no limit, default = -1)\n"
    61 "  -f, --finish <script>     Command you wish to run on completion\n"
    62 "  -n  --nat-traversal       Attempt NAT traversal using NAT-PMP or UPnP IGD\n"
    63 "  -p, --port <int>          Port we should listen on (default = %d)\n"
    64 "  -t, --tos <int>           Peer socket TOS (0 to 255, default = 8)\n"
    65 "  -u, --upload <int>        Maximum upload rate (-1 = no limit, default = 20)\n"
    66 "  -v, --verbose <int>       Verbose level (0 to 2, default = 0)\n"
    67 "  -y, --recheck             Force a recheck of the torrent data\n";
    68 
    69 static int           showHelp      = 0;
     39#define MY_NAME "transmission-cli"
     40
    7041static int           showInfo      = 0;
    7142static int           showScrape    = 0;
    72 static int           showVersion   = 0;
    7343static int           isPrivate     = 0;
    7444static int           verboseLevel  = 0;
     
    7747static int           uploadLimit   = 20;
    7848static int           downloadLimit = -1;
    79 static char        * torrentPath   = NULL;
    8049static int           natTraversal  = 0;
    81 static int           recheckData   = 0;
     50static int           verify        = 0;
    8251static sig_atomic_t  gotsig        = 0;
    8352static sig_atomic_t  manualUpdate  = 0;
    84 static char          downloadDir[MAX_PATH_LENGTH] = { '\0' };
    85 
    86 static char          * finishCall   = NULL;
    87 static char          * announce     = NULL;
    88 static char          * configdir    = NULL;
    89 static char          * sourceFile   = NULL;
    90 static char          * comment      = NULL;
    91 
    92 static int  parseCommandLine ( int argc, char ** argv );
     53
     54static const char   * torrentPath   = NULL;
     55static const char   * downloadDir   = NULL;
     56static const char   * finishCall   = NULL;
     57static const char   * announce     = NULL;
     58static const char   * configdir    = NULL;
     59static const char   * sourceFile   = NULL;
     60static const char   * comment      = NULL;
     61
     62static int  parseCommandLine ( int argc, const char ** argv );
    9363static void sigHandler       ( int signal );
    9464
     
    172142    tr_ctor * ctor;
    173143    tr_torrent * tor = NULL;
     144    char cwd[MAX_PATH_LENGTH];
    174145
    175146    printf( "Transmission %s - http://www.transmissionbt.com/\n",
     
    177148
    178149    /* Get options */
    179     if( parseCommandLine( argc, argv ) )
    180     {
    181         printf( USAGE, argv[0], TR_DEFAULT_PORT );
     150    if( parseCommandLine( argc, (const char**)argv ) )
    182151        return EXIT_FAILURE;
    183     }
    184 
    185     if( showVersion )
    186         return EXIT_SUCCESS;
    187 
    188     if( showHelp )
    189     {
    190         printf( USAGE, argv[0], TR_DEFAULT_PORT );
    191         return EXIT_SUCCESS;
    192     }
    193 
    194     if( peerPort < 1 || peerPort > 65535 )
    195     {
     152
     153    /* Check the options for validity */
     154    if( !torrentPath ) {
     155        printf( "No torrent specified!\n" );
     156        return EXIT_FAILURE;
     157    }
     158    if( peerPort < 1 || peerPort > 65535 ) {
    196159        printf( "Invalid port '%d'\n", peerPort );
    197160        return EXIT_FAILURE;
    198161    }
    199 
    200     if( peerSocketTOS < 0 || peerSocketTOS > 255 )
    201     {
     162    if( peerSocketTOS < 0 || peerSocketTOS > 255 ) {
    202163        printf( "Invalid TOS '%d'\n", peerSocketTOS );
    203164        return EXIT_FAILURE;
     
    210171
    211172    if( configdir == NULL )
    212         configdir = strdup( tr_getDefaultConfigDir( ) );
     173        configdir = tr_getDefaultConfigDir( );
     174
     175    /* if no download directory specified, use cwd instead */
     176    if( !downloadDir ) {
     177        getcwd( cwd, sizeof( cwd ) );
     178        downloadDir = cwd;
     179    }
     180
    213181
    214182    /* Initialize libtransmission */
     
    247215        tr_tracker_info ti;
    248216        ti.tier = 0;
    249         ti.announce = announce;
     217        ti.announce = (char*) announce;
    250218        tr_makeMetaInfo( builder, torrentPath, &ti, 1, comment, isPrivate );
    251219        while( !builder->isDone ) {
     
    385353        }
    386354       
    387         if( recheckData )
    388         {
    389             recheckData = 0;
     355        if( verify )
     356        {
     357            verify = 0;
    390358            tr_torrentVerify( tor );
    391359        }
     
    457425}
    458426
     427/***
     428****
     429****
     430****
     431***/
     432
     433static const char *
     434getUsage( void )
     435{
     436    return "A fast and easy BitTorrent client\n"
     437           "\n"
     438           "Usage: "MY_NAME" [options] <torrent-filename>";
     439}
     440
     441const struct tr_option options[] = {
     442    { 'a', "announce",     "When creating a new torrent, set its announce URL",   "a", 1, "<url>" },
     443    { 'c', "comment",      "When creating a new torrent, set its comment field",  "c", 1, "<comment>" },
     444    { 'd', "downlimit",    "Set the maxiumum download speed in KB/s",             "d", 1, "<number>" },
     445    { 'D', "no-downlimit", "Don't limit the download speed",                      "D", 0, NULL },
     446    { 'f', "finish",       "Set a script to run when the torrent finishes",       "f", 1, "<script>" },
     447    { 'g', "config-dir",   "Where to look for configuration files",               "g", 1, "<path>" },
     448    { 'i', "info",         "Show torrent details and exit",                       "i", 0, NULL },
     449    { 'm', "portmap",      "Enable portmapping via NAT-PMP or UPnP",              "m", 0, NULL },
     450    { 'M', "no-portmap",   "Disable portmapping",                                 "M", 0, NULL },
     451    { 'n', "new",          "Create a new torrent from a file or directory",       "n", 1, "<path>" },
     452    { 'p', "port",         "Port to listen for incoming peers (Default: "TR_DEFAULT_RPC_PORT_STR")", "p", 1, "<port>" },
     453    { 'r', "private",      "When creating a new torrent, set its 'private' flag", "r", 0, NULL },
     454    { 's', "scrape",       "Scrape the torrent and exit",                         "s", 0, NULL },
     455    { 't', "tos",          "Peer socket TOS (0 to 255, default="TR_DEFAULT_PEER_SOCKET_TOS_STR")", "t", 1, "<number>"},
     456    { 'u', "uplimit",      "Set the maxiumum upload speed in KB/s",               "u", 1, "<number>" },
     457    { 'U', "no-uplimit",   "Don't limit the upload speed",                        "U", 0, NULL },
     458    { 'v', "verify",       "Verify the specified torrent",                        "v", 0, NULL },
     459    { 'w', "download-dir", "Where to save downloaded data",                       "w", 1, "<path>" },
     460    { 0, NULL, NULL, NULL, 0, NULL }
     461};
     462
     463static void
     464showUsage( void )
     465{
     466    tr_getopt_usage( MY_NAME, getUsage(), options );
     467    exit( 0 );
     468}
     469
    459470static int
    460 parseCommandLine( int argc, char ** argv )
    461 {
    462     for( ;; )
    463     {
    464         static const struct option long_options[] = {
    465             { "announce",      required_argument, NULL, 'a' },
    466             { "create-from",   required_argument, NULL, 'c' },
    467             { "download",      required_argument, NULL, 'd' },
    468             { "finish",        required_argument, NULL, 'f' },
    469             { "config-dir",    required_argument, NULL, 'g' },
    470             { "help",          no_argument,       NULL, 'h' },
    471             { "info",          no_argument,       NULL, 'i' },
    472             { "comment",       required_argument, NULL, 'm' },
    473             { "nat-traversal", no_argument,       NULL, 'n' },
    474             { "output-dir",    required_argument, NULL, 'o' },
    475             { "port",          required_argument, NULL, 'p' },
    476             { "private",       no_argument,       NULL, 'r' },
    477             { "scrape",        no_argument,       NULL, 's' },
    478             { "tos",           required_argument, NULL, 't' },
    479             { "upload",        required_argument, NULL, 'u' },
    480             { "verbose",       required_argument, NULL, 'v' },
    481             { "version",       no_argument,       NULL, 'V' },
    482             { "recheck",       no_argument,       NULL, 'y' },
    483             { 0, 0, 0, 0} };
    484         int optind = 0;
    485         int c = getopt_long( argc, argv,
    486                              "a:c:d:f:g:him:no:p:rst:u:v:Vy",
    487                              long_options, &optind );
    488         if( c < 0 )
    489         {
    490             break;
    491         }
     471numarg( const char * arg )
     472{
     473    char * end = NULL;
     474    const long num = strtol( arg, &end, 10 );
     475    if( *end ) {
     476        fprintf( stderr, "Not a number: \"%s\"\n", arg );
     477        showUsage( );
     478    }
     479    return num;
     480}
     481
     482static int
     483parseCommandLine( int argc, const char ** argv )
     484{
     485    int c;
     486    const char * optarg;
     487
     488    while(( c = tr_getopt( getUsage(), argc, argv, options, &optarg )))
     489    {
    492490        switch( c )
    493491        {
    494492            case 'a': announce = optarg; break;
    495             case 'c': sourceFile = optarg; break;
    496             case 'd': downloadLimit = atoi( optarg ); break;
     493            case 'c': comment = optarg; break;
     494            case 'd': downloadLimit = numarg( optarg ); break;
     495            case 'D': downloadLimit = -1; break;
    497496            case 'f': finishCall = optarg; break;
    498             case 'g': configdir = strdup( optarg ); break;
    499             case 'h': showHelp = 1; break;
     497            case 'g': configdir = optarg; break;
    500498            case 'i': showInfo = 1; break;
    501             case 'm': comment = optarg; break;
    502             case 'n': natTraversal = 1; break;
    503             case 'o': tr_strlcpy( downloadDir, optarg, sizeof( downloadDir ) ); break;
    504             case 'p': peerPort = atoi( optarg ); break;
     499            case 'm': natTraversal = 1; break;
     500            case 'M': natTraversal = 0; break;
     501            case 'n': sourceFile = optarg; break;
     502            case 'p': peerPort = numarg( optarg ); break;
    505503            case 'r': isPrivate = 1; break;
    506504            case 's': showScrape = 1; break;
    507             case 't': peerSocketTOS = atoi( optarg ); break;
    508             case 'u': uploadLimit = atoi( optarg ); break;
    509             case 'v': verboseLevel = atoi( optarg ); break;
    510             case 'V': showVersion = 1; break;
    511             case 'y': recheckData = 1; break;
     505            case 't': peerSocketTOS = numarg( optarg ); break;
     506            case 'u': uploadLimit = numarg( optarg ); break;
     507            case 'U': uploadLimit = -1; break;
     508            case 'v': verify = 1; break;
     509            case 'w': downloadDir = optarg; break;
     510            case TR_OPT_UNK: torrentPath = optarg; break;
    512511            default: return 1;
    513512        }
    514513    }
    515514
    516     if( !*downloadDir )
    517         getcwd( downloadDir, sizeof( downloadDir ) );
    518 
    519     if( showHelp || showVersion )
    520         return 0;
    521 
    522     if( optind >= argc )
    523         return 1;
    524 
    525     torrentPath = argv[optind];
    526515    return 0;
    527516}
    528517
    529 static void sigHandler( int signal )
     518static void
     519sigHandler( int signal )
    530520{
    531521    switch( signal )
    532522    {
    533         case SIGINT:
    534             gotsig = 1;
    535             break;
    536            
    537         case SIGHUP:
    538             manualUpdate = 1;
    539             break;
    540 
    541         default:
    542             break;
    543     }
    544 }
     523        case SIGINT: gotsig = 1; break;
     524        case SIGHUP: manualUpdate = 1; break;
     525        default: break;
     526    }
     527}
  • trunk/daemon/daemon.c

    r6238 r6298  
    1818
    1919#include <fcntl.h> /* open */
    20 #include <getopt.h>
    2120#include <signal.h>
    2221#include <unistd.h> /* daemon, getcwd */
     
    2524#include <libtransmission/bencode.h>
    2625#include <libtransmission/rpc.h>
     26#include <libtransmission/tr-getopt.h>
    2727#include <libtransmission/utils.h>
    2828#include <libtransmission/version.h>
     
    9090    replaceInt( &d, KEY_DSPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) );
    9191    replaceInt( &d, KEY_USPEED,          tr_sessionGetSpeedLimit( s, TR_UP ) );
    92 fprintf( stderr, "session says its speed upload speed limit is %d\n", tr_sessionGetSpeedLimit( s, TR_UP ) );
    9392    replaceInt( &d, KEY_USPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_UP ) );
    9493    replaceInt( &d, KEY_ENCRYPTION,      tr_sessionGetEncryption( s ) );
     
    214213}
    215214
    216 static void
    217 daemonUsage( void )
    218 {
    219     puts( "Usage: " MY_NAME " [options]\n"
    220           "\n"
    221           "Transmission "LONG_VERSION_STRING" http://www.transmissionbt.com/\n"
    222           "A fast and easy BitTorrent client\n"
    223           "\n"
    224           "  -a  --acl <list>         Access Control List.  (Default: "TR_DEFAULT_RPC_ACL")\n"
    225           "  -b  --blocklist          Enable peer blocklists\n"
    226           "  -b0 --blocklist=0        Disable peer blocklists\n"
    227           "  -d  --download-dir <dir> Where store downloaded data\n"
    228           "  -f  --foreground         Run in the foreground and log to stderr\n"
    229           "  -g  --config-dir <dir>   Where to look for torrents and "CONFIG_FILE"\n"
    230           "  -h  --help               Display this message and exit\n"
    231           "  -p  --port=n             Port to listen to for requests  (Default: "TR_DEFAULT_RPC_PORT_STR")\n"
    232           "  -t  --auth               Require authentication\n"
    233           "  -t0 --auth=0             Don't require authentication\n"
    234           "  -u  --username <user>    Set username for authentication\n"
    235           "  -w  --password <pass>    Set password for authentication\n"
    236           "\n"
    237           MY_NAME" is a headless Transmission session\n"
    238           "that can be controlled via transmission-remote or Clutch.\n" );
     215static const char *
     216getUsage( void )
     217{
     218    return "Transmission "LONG_VERSION_STRING"  http://www.transmissionbt.com/\n"
     219           "A fast and easy BitTorrent client\n"
     220           "\n"
     221           MY_NAME" is a headless Transmission session\n"
     222           "that can be controlled via transmission-remote or Clutch.\n"
     223           "\n"
     224           "Usage: "MY_NAME" [options]";
     225}
     226
     227const struct tr_option options[] = {
     228    { 'a', "acl",       "Access Control List.  (Default: "TR_DEFAULT_RPC_ACL")", "a", 1, "<list>" },
     229    { 'b', "blocklist", "Enable peer blocklists",             "b", 0, NULL },
     230    { 'B', "no-blocklist", "Disable peer blocklists",         "B", 0, NULL },
     231    { 'f', "foreground", "Run in the foreground instead of daemonizing", "f", 0, NULL },
     232    { 'g', "config-dir",   "Where to look for configuration files", "g", 1, "<path>" },
     233    { 'p', "port",         "Port to listen for incoming peers (Default: "TR_DEFAULT_RPC_PORT_STR")", "p", 1, "<port>" },
     234    { 't', "auth",         "Requre authentication",           "t", 0, NULL },
     235    { 'T', "no-auth",      "Don't require authentication",    "T", 0, NULL },
     236    { 'u', "username",     "Set username for authentication", "u", 1, "<username>" },
     237    { 's', "password",     "Set password for authentication", "s", 1, "<password>" },
     238    { 'w', "download-dir", "Where to save downloaded data",   "w", 1, "<path>" },
     239    { 0, NULL, NULL, NULL, 0, NULL }
     240};
     241
     242static void
     243showUsage( void )
     244{
     245    tr_getopt_usage( MY_NAME, getUsage(), options );
    239246    exit( 0 );
    240247}
    241248
    242249static void
    243 readargs( int argc, char ** argv,
    244           int * nofork, char ** configDir, char ** downloadDir,
    245           int * rpcPort, char ** acl, int * authRequired, char ** username, char ** password,
     250readargs( int argc, const char ** argv,
     251          int * nofork, const char ** configDir, const char ** downloadDir,
     252          int * rpcPort, const char ** acl, int * authRequired, const char ** username, const char ** password,
    246253          int * blocklistEnabled )
    247254{
    248     int opt;
    249     char shortopts[] = "a:b::d:fg:hp:t::u:w:";
    250     struct option longopts[] = {
    251         { "acl",           required_argument,  NULL, 'a'  },
    252         { "blocklist",     optional_argument,  NULL, 'b'  },
    253         { "download-dir",  required_argument,  NULL, 'd'  },
    254         { "foreground",    no_argument,        NULL, 'f'  },
    255         { "config-dir",    required_argument,  NULL, 'g'  },
    256         { "help",          no_argument,        NULL, 'h'  },
    257         { "port",          required_argument,  NULL, 'p'  },
    258         { "auth",          optional_argument,  NULL, 't'  },
    259         { "username",      required_argument,  NULL, 'u'  },
    260         { "password",      required_argument,  NULL, 'w'  },
    261         { NULL,            0,                  NULL, '\0' }
    262     };
    263     while((( opt = getopt_long( argc, argv, shortopts, longopts, NULL ))) != -1 ) {
    264         switch( opt ) {
    265             case 'a': *acl = tr_strdup( optarg ); break;
    266             case 'b': *blocklistEnabled = optarg ? atoi(optarg)!=0 : TRUE; break;
    267             case 'd': *downloadDir = tr_strdup( optarg ); break;
     255    int c;
     256    const char * optarg;
     257    while(( c = tr_getopt( getUsage(), argc, argv, options, &optarg )))
     258    {
     259        switch( c )
     260        {
     261            case 'a': *acl = optarg; break;
     262            case 'b': *blocklistEnabled = 1; break;
     263            case 'B': *blocklistEnabled = 0; break;
    268264            case 'f': *nofork = 1; break;
    269             case 'n': *authRequired = FALSE; break;
    270             case 'g': *configDir = tr_strdup( optarg ); break;
    271             case 't': *authRequired = optarg ? atoi(optarg)!=0 : TRUE; break;
    272             case 'u': *username = tr_strdup( optarg ); break;
    273             case 'w': *password = tr_strdup( optarg ); break;
     265            case 'g': *configDir = optarg; break;
    274266            case 'p': *rpcPort = atoi( optarg ); break;
    275             default: daemonUsage( ); break;
     267            case 't': *authRequired = TRUE; break;
     268            case 'T': *authRequired = FALSE; break;
     269            case 'u': *username = optarg; break;
     270            case 's': *password = optarg; break;
     271            case 'w': *downloadDir = optarg; break;
     272            default: showUsage( ); break;
    276273        }
    277274    }
     
    345342    int authRequired = -1;
    346343    int blocklistEnabled = -1;
    347     char * configDir = NULL;
    348     char * downloadDir = NULL;
    349     char * acl = NULL;
    350     char * username = NULL;
    351     char * password = NULL;
     344    const char * configDir = NULL;
     345    const char * downloadDir = NULL;
     346    const char * acl = NULL;
     347    const char * username = NULL;
     348    const char * password = NULL;
    352349
    353350    signal( SIGINT, gotsig );
     
    357354    signal( SIGHUP, SIG_IGN );
    358355
    359     readargs( argc, argv, &nofork, &configDir, &downloadDir,
     356    readargs( argc, (const char*)argv, &nofork, &configDir, &downloadDir,
    360357              &rpcPort, &acl, &authRequired, &username, &password,
    361358              &blocklistEnabled );
     
    384381    printf( " done.\n" );
    385382
    386     tr_free( configDir );
    387     tr_free( downloadDir );
    388     tr_free( username );
    389     tr_free( password );
    390     tr_free( acl );
    391383    return 0;
    392384}
  • trunk/libtransmission/tr-getopt.c

    r6297 r6298  
    7373  printf( description, progName );
    7474  printf( "\n\n" );
    75   printf( "Usage:\n" );
     75  printf( "Options:\n" );
    7676
    7777  help.val = -1;
  • trunk/libtransmission/transmission.h

    r6199 r6298  
    115115/** @see tr_sessionInitFull */
    116116#define TR_DEFAULT_PEER_SOCKET_TOS          8
     117/** @see tr_sessionInitFull */
     118#define TR_DEFAULT_PEER_SOCKET_TOS_STR      "8"
    117119/** @see tr_sessionInitFull */
    118120#define TR_DEFAULT_BLOCKLIST_ENABLED        0
Note: See TracChangeset for help on using the changeset viewer.