From 415214f15ba6f4acca9f66a5f8356ed5f7d777a3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 7 Jul 2008 21:23:34 +0000 Subject: [PATCH] (daemon) allow wildcards to be used when adding torrents again, such as "transmission-remote -a ~/Desktop/*torrent" --- daemon/Makefile.am | 4 +- daemon/getopts.c | 208 +++++++++++++++++++++++++++++++++++++++++ daemon/getopts.h | 59 ++++++++++++ daemon/remote.c | 224 +++++++++++++++++++++++---------------------- 4 files changed, 383 insertions(+), 112 deletions(-) create mode 100644 daemon/getopts.c create mode 100644 daemon/getopts.h diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 3f1f6f64b..f07ddecaa 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -20,5 +20,7 @@ LDADD = \ $(LIBCURL_LIBS) \ $(PTHREAD_LIBS) -lm +noinst_HEADERS = getopts.h + transmission_daemon_SOURCES = daemon.c -transmission_remote_SOURCES = remote.c +transmission_remote_SOURCES = remote.c getopts.c diff --git a/daemon/getopts.c b/daemon/getopts.c new file mode 100644 index 000000000..19e825a1a --- /dev/null +++ b/daemon/getopts.c @@ -0,0 +1,208 @@ +/* getopts.c - Command line argument parser + * + * Whom: Steve Mertz + * Date: 20010111 + * Why: Because I couldn't find one that I liked. So I wrote this one. + * +*/ +/* + * Copyright (c) 2001-2004 Steve Mertz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of Dragon Ware nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#include +#include +#include + +#include "getopts.h" + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +int option_index = 1; + +static const char* +getArgName( const struct options * opt ) +{ + if( !opt->args ) return ""; + if( opt->argName ) return opt->argName; + return ""; +} + +static void +getopts_usage_line( const struct options * opt, int nameWidth, int shortWidth, int argWidth ) +{ + const char * name = opt->name ? opt->name : ""; + const char * shortName = opt->shortName ? opt->shortName : ""; + const char * arg = getArgName( opt ); + printf( " -%*s, --%-*s %-*s %s\n", shortWidth, shortName, nameWidth, name, argWidth, arg, opt->description ); +} + +/* int getopts_usage() + * + * Returns: 1 - Successful + */ +int getopts_usage(const char *progName, const char *usage, struct options opts[]) +{ + int count; + int nameWidth = 0; + int shortWidth = 0; + int argWidth = 0; + struct options help; + + for( count=0; opts[count].description; ++count ) + { + const char * arg; + + if( opts[count].name ) + nameWidth = MAX( nameWidth, (int)strlen( opts[count].name ) ); + + if( opts[count].shortName ) + shortWidth = MAX( shortWidth, (int)strlen( opts[count].shortName ) ); + + if(( arg = getArgName( &opts[count] ))) + argWidth = MAX( argWidth, (int)strlen( arg ) ); + } + + if( !usage ) + usage = "Usage: %s [options]"; + printf( usage, progName ); + printf( "\n\n" ); + printf( "Usage:\n" ); + + help.number = -1; + help.name = "help"; + help.description = "Display this help page and exit"; + help.shortName = "h"; + help.args = 0; + getopts_usage_line( &help, nameWidth, shortWidth, argWidth ); + + for( count=0; opts[count].description; ++count ) + getopts_usage_line( &opts[count], nameWidth, shortWidth, argWidth ); + + return 1; +} + +/* int getopts() + * + * Returns: -1 - Couldn't allocate memory. Please handle me. + * 0 - No arguements to parse + * # - The number in the struct for the matched arg. + * +*/ +int +getopts( const char * usage, + int argc, + char ** argv, + struct options * opts, + char ** args ) +{ + int argCounter, sizeOfArgs; + if (argc == 1 || option_index == argc) + return 0; + +/* Search for '-h' or '--help' first. Then we can just exit */ + for (argCounter = 1; argCounter < argc; argCounter++) + { + if (!strcmp(argv[argCounter], "-h") || !strcmp(argv[argCounter], "--help")) + { +useage: +fprintf( stderr, "dkdkdkdkdkd\n" ); + getopts_usage(argv[0], usage, opts); + exit(0); + } + } +/* End of -h --help section */ + + *args = NULL; + if (option_index <= argc) + { + for (argCounter = 0; opts[argCounter].number!=0; argCounter++) + { + if ((opts[argCounter].name && !strcmp(opts[argCounter].name, (argv[option_index]+2))) || + (opts[argCounter].shortName && !strcmp(opts[argCounter].shortName, (argv[option_index]+1)))) + { + if (opts[argCounter].args) + { + option_index++; + if (option_index >= argc) + goto useage; +/* This grossness that follows is to support having a '-' in the argument. */ + if (*argv[option_index] == '-') + { + int optionSeeker; + for (optionSeeker = 0; opts[optionSeeker].description; optionSeeker++) + { + if ((opts[optionSeeker].name && + !strcmp(opts[optionSeeker].name, (argv[option_index]+2))) || + (opts[optionSeeker].shortName && + !strcmp(opts[optionSeeker].shortName, (argv[option_index]+1)))) + { + goto useage; + } + } +/* End of gross hack for supporting '-' in arguments. */ + } + sizeOfArgs = strlen(argv[option_index]); +#ifdef __cplusplus + if ((*args = (char *)calloc(1, sizeOfArgs+1)) == NULL) +#else + if ((*args = calloc(1, sizeOfArgs+1)) == NULL) +#endif + return -1; + strncpy(*args, argv[option_index], sizeOfArgs); + } + option_index++; + return opts[argCounter].number; + } + } +/** The Option doesn't exist. We should warn them. */ + //if (*argv[option_index] == '-') + { + sizeOfArgs = strlen(argv[option_index]); +#ifdef __cplusplus + if ((*args = (char *)calloc(1, sizeOfArgs+1)) == NULL) +#else + if ((*args = calloc(1, sizeOfArgs+1)) == NULL) +#endif + return -1; + strncpy(*args, argv[option_index], sizeOfArgs); + option_index++; + return -2; + } + } + return 0; +} + + + + + + diff --git a/daemon/getopts.h b/daemon/getopts.h new file mode 100644 index 000000000..43a25b472 --- /dev/null +++ b/daemon/getopts.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001-2004 Steve Mertz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of Dragon Ware nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ +#ifndef __GET_OPT_H__ +#define __GET_OPT_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern int option_index; + +struct options +{ + int number; /* Number, which is returned from getopt() */ + char *name; /* Long name */ + char *description; /* Description */ + char *shortName; /* Short name */ + int args; /* Does the option take an argument? */ + char *argName; /* Argument name, for the `help' option */ +}; + +int getopts(const char * summary, int argc, char **argv, struct options opts[], char **args); +int getopts_usage(const char *progName, const char * summary, struct options opts[]); + +#ifdef __cplusplus +} +#endif + +#endif /* __GET_OPT_H__ */ diff --git a/daemon/remote.c b/daemon/remote.c index fcac570d2..1588ca296 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -14,7 +14,6 @@ #include #include /* strcmp */ -#include #include /* getcwd */ #include @@ -27,50 +26,58 @@ #include #include +#include "getopts.h" + #define MY_NAME "transmission-remote" #define DEFAULT_HOST "localhost" #define DEFAULT_PORT TR_DEFAULT_RPC_PORT enum { TAG_LIST, TAG_DETAILS, TAG_FILES, TAG_PEERS }; +static const char* +getUsage( void ) +{ + return "Transmission "LONG_VERSION_STRING" http://www.transmissionbt.com/\n" + "A fast and easy BitTorrent client\n" + "\n" + "Usage: "MY_NAME" [host] [options]\n" + " "MY_NAME" [port] [options]\n" + " "MY_NAME" [host:port] [options]"; +} + +static struct options opts[] = +{ + { 'a', "add", "Add torrent files", "a", 0, NULL }, + { 'd', "downlimit", "Set the maximum download speed in KB/s", "d", 1, "" }, + { 'D', "no-downlimit", "Don't limit the download speed", "D", 0, NULL }, + { 'e', "encryption", "Set encryption mode [required, preferred, tolerated]", "e", 1, "" }, + { 'f', "files", "Get a file list for the current torrent(s)", "f", 0, NULL }, + { 'g', "debug", "Print debugging information", "g", 0, NULL }, + { 'h', "help", "Show this help page and exit", "h", 0, NULL }, + { 'i', "info", "Show details of the current torrent(s)", "i", 0, NULL }, + { 'l', "list", "List all torrents", "l", 0, NULL }, + { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL }, + { 'M', "no-portmap", "Disable portmapping", "M", 0, NULL }, + { 'n', "auth", "Set username for authentication", "n", 1, ":" }, + { 'p', "port", "Port to listen for incoming peers", "p", 1, "" }, + { 'r', "remove", "Remove the current torrent(s)", "r", 0, NULL }, + { 's', "start", "Start the current torrent(s)", "s", 0, NULL }, + { 'S', "stop", "Stop the current torrent(s)", "S", 0, NULL }, + { 't', "torrent", "Set the current torrent(s)", "t", 1, "" }, + { 'u', "uplimit", "Set the maximum upload speed in KB/s", "u", 1, "" }, + { 'U', "no-uplimit", "Don't limit the upload speed", "U", 0, NULL }, + { 'v', "verify", "Verify the current torrent(s)", "v", 0, NULL }, + { 'w', "download-dir", "Set the download folder for new torrents", "w", 1, "" }, + { 'x', "pex", "Enable peer exchange (PEX)", "x", 0, NULL }, + { 'X', "no-pex", "Disable peer exchange (PEX)", "X", 0, NULL }, + { 0, NULL, NULL, NULL, 0, NULL } +}; + static void showUsage( void ) { - puts( "Transmission "LONG_VERSION_STRING" http://www.transmissionbt.com/\n" - "A fast and easy BitTorrent client\n" - "\n" - "Usage: "MY_NAME" [host] [options]\n" - " "MY_NAME" [port] [options]\n" - " "MY_NAME" [host:port] [options]\n" - "\n" - "Options:\n" - " -a --add Add a torrent\n" - " -d --download-limit Max download rate in KiB/s\n" - " -D --download-unlimited No download rate limit\n" - " -e --encryption required Require encryption for all peers\n" - " -e --encryption preferred Prefer peers to use encryption\n" - " -e --encryption tolerated Prefer peers to use plaintext\n" - " -f --files Get a file list for the specified torrent\n" - " -g --debug Print debugging information\n" - " -h --help Display this message and exit\n" - " -i --info Detailed information for the specified torrent\n" - " -l --list List all torrents\n" - " -m --port-mapping Automatic port mapping via NAT-PMP or UPnP\n" - " -M --no-port-mapping Disable automatic port mapping\n" - " -p --port Port to listen for incoming peers\n" - " -r --remove Remove the torrent with the given ID\n" - " -r --remove all Remove all torrents\n" - " -s --start Start the torrent with the given ID\n" - " -s --start all Start all stopped torrents\n" - " -S --stop Stop the torrent with the given ID\n" - " -S --stop all Stop all running torrents\n" - " -t --auth : Username and password for authentication\n" - " -u --upload-limit Max upload rate in KiB/s\n" - " -U --upload-unlimited No upload rate limit\n" - " -v --verify Verify the torrent's local data\n" - " -w --download-dir Folder to set for new torrents\n" - " -x --enable-pex Enable peer exchange\n" - " -X --disable-pex Disable peer exchange\n" ); +fprintf( stderr, "asdfasdfasdfasdfasdfasdf\n"); + getopts_usage( MY_NAME, getUsage(), opts ); exit( 0 ); } @@ -114,63 +121,61 @@ getEncodedMetainfo( const char * filename ) return b64; } +static void +addIdArg( tr_benc * args, const char * id ) +{ + if( !*id ) { + fprintf( stderr, "No torrent specified! Please use the -t option first.\n" ); + id = "-1"; /* no torrent will have this ID, so should be a no-op */ + } else if( strcmp( id, "all" ) ) { + tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), id, strlen(id) ); + } +} + static void readargs( int argc, char ** argv ) { - int opt; - char optstr[] = "a:d:De:f:ghi:lmMp:r:s:S:t:u:Uv:w:xX"; - - const struct option longopts[] = - { - { "add", required_argument, NULL, 'a' }, - { "download-limit", required_argument, NULL, 'd' }, - { "download-unlimited", no_argument, NULL, 'D' }, - { "encryption", required_argument, NULL, 'e' }, - { "files", required_argument, NULL, 'f' }, - { "debug", no_argument, NULL, 'g' }, - { "help", no_argument, NULL, 'h' }, - { "info", required_argument, NULL, 'i' }, - { "list", no_argument, NULL, 'l' }, - { "port-mapping", no_argument, NULL, 'm' }, - { "no-port-mapping", no_argument, NULL, 'M' }, - { "port", required_argument, NULL, 'p' }, - { "remove", required_argument, NULL, 'r' }, - { "start", required_argument, NULL, 's' }, - { "stop", required_argument, NULL, 'S' }, - { "auth", required_argument, NULL, 't' }, - { "upload-limit", required_argument, NULL, 'u' }, - { "upload-unlimited", no_argument, NULL, 'U' }, - { "verify", required_argument, NULL, 'v' }, - { "download-dir", required_argument, NULL, 'w' }, - { "enable-pex", no_argument, NULL, 'x' }, - { "disable-pex", no_argument, NULL, 'X' }, - { NULL, 0, NULL, 0 } - }; - - while((( opt = getopt_long( argc, argv, optstr, longopts, NULL ))) != -1 ) + int c; + int addingTorrents = 0; + char * optarg; + char id[4096]; + + *id = '\0'; + + while(( c = getopts( getUsage(), argc, argv, opts, &optarg ))) { - char * tmp; char buf[MAX_PATH_LENGTH]; int addArg = TRUE; - int64_t fields = 0; tr_benc top, *args; tr_bencInitDict( &top, 3 ); + int64_t fields = 0; args = tr_bencDictAddDict( &top, "arguments", 0 ); - switch( opt ) +fprintf( stderr, "got opt [%c][%s]\n", (char)c, (optarg?optarg:"(null)") ); + switch( c ) { - case 'g': debug = 1; - addArg = FALSE; + case -2: /* special case: recognize options we didn't set above */ +fprintf( stderr, "hello world\n" ); + if( addingTorrents ) { + char * tmp; +fprintf( stderr, "adding filename [%s]\n", optarg ); + tr_bencDictAddStr( &top, "method", "torrent-add" ); + tr_bencDictAddStr( args, "metainfo", ((tmp=getEncodedMetainfo(optarg))) ); + tr_free( tmp ); + } else { + fprintf( stderr, "Unknown option: %s\n", optarg ); + addArg = FALSE; + } break; - case 't': auth = tr_strdup( optarg ); + case 'a': addingTorrents = 1; addArg = FALSE; break; - case 'h': showUsage( ); - addArg = FALSE; + case 'd': tr_bencDictAddStr( &top, "method", "session-set" ); + tr_bencDictAddInt( args, "speed-limit-down", numarg( optarg ) ); + tr_bencDictAddInt( args, "speed-limit-down-enabled", 1 ); break; - case 'a': tr_bencDictAddStr( &top, "method", "torrent-add" ); - tr_bencDictAddStr( args, "metainfo", ((tmp=getEncodedMetainfo(optarg))) ); - tr_free( tmp ); + case 'D': tr_bencDictAddStr( &top, "method", "session-set" ); + tr_bencDictAddInt( args, "speed-limit-down-enabled", 0 ); break; case 'e': tr_bencDictAddStr( &top, "method", "session-set" ); tr_bencDictAddStr( args, "encryption", optarg ); @@ -183,34 +188,23 @@ readargs( int argc, char ** argv ) | TR_RPC_TORRENT_FIELD_PRIORITIES; tr_bencDictAddInt( args, "fields", fields ); break; + case 'g': debug = 1; + addArg = FALSE; + break; case 'i': tr_bencDictAddStr( &top, "method", "torrent-get" ); tr_bencDictAddInt( &top, "tag", TAG_DETAILS ); - tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); + addIdArg( args, id ); fields = TR_RPC_TORRENT_FIELD_ACTIVITY - | TR_RPC_TORRENT_FIELD_ANNOUNCE - | TR_RPC_TORRENT_FIELD_ERROR - | TR_RPC_TORRENT_FIELD_HISTORY - | TR_RPC_TORRENT_FIELD_ID - | TR_RPC_TORRENT_FIELD_INFO - | TR_RPC_TORRENT_FIELD_SCRAPE - | TR_RPC_TORRENT_FIELD_SIZE - | TR_RPC_TORRENT_FIELD_TRACKER_STATS; + | TR_RPC_TORRENT_FIELD_ANNOUNCE + | TR_RPC_TORRENT_FIELD_ERROR + | TR_RPC_TORRENT_FIELD_HISTORY + | TR_RPC_TORRENT_FIELD_ID + | TR_RPC_TORRENT_FIELD_INFO + | TR_RPC_TORRENT_FIELD_SCRAPE + | TR_RPC_TORRENT_FIELD_SIZE + | TR_RPC_TORRENT_FIELD_TRACKER_STATS; tr_bencDictAddInt( args, "fields", fields ); break; - case 'd': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "speed-limit-down", numarg( optarg ) ); - tr_bencDictAddInt( args, "speed-limit-down-enabled", 1 ); - break; - case 'D': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "speed-limit-down-enabled", 0 ); - break; - case 'u': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "speed-limit-up", numarg( optarg ) ); - tr_bencDictAddInt( args, "speed-limit-up-enabled", 1 ); - break; - case 'U': tr_bencDictAddStr( &top, "method", "session-set" ); - tr_bencDictAddInt( args, "speed-limit-up-enabled", 0 ); - break; case 'l': tr_bencDictAddStr( &top, "method", "torrent-get" ); tr_bencDictAddInt( &top, "tag", TAG_LIST ); fields = TR_RPC_TORRENT_FIELD_ID @@ -224,24 +218,33 @@ readargs( int argc, char ** argv ) case 'M': tr_bencDictAddStr( &top, "method", "session-set" ); tr_bencDictAddInt( args, "port-forwarding-enabled", 0 ); break; + case 'n': auth = tr_strdup( optarg ); + addArg = FALSE; + break; case 'p': tr_bencDictAddStr( &top, "method", "session-set" ); tr_bencDictAddInt( args, "port", numarg( optarg ) ); break; case 'r': tr_bencDictAddStr( &top, "method", "torrent-remove" ); - if( strcmp( optarg, "all" ) ) - tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); + addIdArg( args, id ); break; case 's': tr_bencDictAddStr( &top, "method", "torrent-start" ); - if( strcmp( optarg, "all" ) ) - tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); + addIdArg( args, id ); break; case 'S': tr_bencDictAddStr( &top, "method", "torrent-stop" ); - if( strcmp( optarg, "all" ) ) - tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); + addIdArg( args, id ); + break; + case 't': tr_strlcpy( id, optarg, sizeof( id ) ); + addArg = FALSE; + break; + case 'u': tr_bencDictAddStr( &top, "method", "session-set" ); + tr_bencDictAddInt( args, "speed-limit-up", numarg( optarg ) ); + tr_bencDictAddInt( args, "speed-limit-up-enabled", 1 ); + break; + case 'U': tr_bencDictAddStr( &top, "method", "session-set" ); + tr_bencDictAddInt( args, "speed-limit-up-enabled", 0 ); break; case 'v': tr_bencDictAddStr( &top, "method", "torrent-verify" ); - if( strcmp( optarg, "all" ) ) - tr_rpc_parse_list_str( tr_bencDictAdd( args, "ids" ), optarg, strlen(optarg) ); + addIdArg( args, id ); break; case 'w': tr_bencDictAddStr( &top, "method", "session-set" ); tr_bencDictAddStr( args, "download-dir", absolutify(buf,sizeof(buf),optarg) ); @@ -252,9 +255,8 @@ readargs( int argc, char ** argv ) case 'X': tr_bencDictAddStr( &top, "method", "session-set" ); tr_bencDictAddInt( args, "pex-allowed", 0 ); break; - default: + default: fprintf( stderr, "got opt [%d]\n", (int)c ); showUsage( ); - addArg = FALSE; break; } -- 2.40.0