/* * This file Copyright (C) 2008-2014 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * */ #include #include /* isspace */ #include #include #include #include /* strcmp */ #include #define CURL_DISABLE_TYPECHECK /* otherwise -Wunreachable-code goes insane */ #include #include #include #include #include #include #include #include #include #include #include #define MY_NAME "transmission-remote" #define DEFAULT_HOST "localhost" #define DEFAULT_PORT atoi (TR_DEFAULT_RPC_PORT_STR) #define DEFAULT_URL TR_DEFAULT_RPC_URL_STR "rpc/" #define ARGUMENTS TR_KEY_arguments #define MEM_K 1024 #define MEM_B_STR "B" #define MEM_K_STR "KiB" #define MEM_M_STR "MiB" #define MEM_G_STR "GiB" #define MEM_T_STR "TiB" #define DISK_K 1000 #define DISK_B_STR "B" #define DISK_K_STR "kB" #define DISK_M_STR "MB" #define DISK_G_STR "GB" #define DISK_T_STR "TB" #define SPEED_K 1000 #define SPEED_B_STR "B/s" #define SPEED_K_STR "kB/s" #define SPEED_M_STR "MB/s" #define SPEED_G_STR "GB/s" #define SPEED_T_STR "TB/s" /*** **** **** Display Utilities **** ***/ static void etaToString (char * buf, size_t buflen, int64_t eta) { if (eta < 0) tr_snprintf (buf, buflen, "Unknown"); else if (eta < 60) tr_snprintf (buf, buflen, "%" PRId64 " sec", eta); else if (eta < (60 * 60)) tr_snprintf (buf, buflen, "%" PRId64 " min", eta / 60); else if (eta < (60 * 60 * 24)) tr_snprintf (buf, buflen, "%" PRId64 " hrs", eta / (60 * 60)); else tr_snprintf (buf, buflen, "%" PRId64 " days", eta / (60 * 60 * 24)); } static char* tr_strltime (char * buf, int seconds, size_t buflen) { int days, hours, minutes, total_seconds; char b[128], d[128], h[128], m[128], s[128], t[128]; if (seconds < 0) seconds = 0; total_seconds = seconds; days = seconds / 86400; hours = (seconds % 86400) / 3600; minutes = (seconds % 3600) / 60; seconds = (seconds % 3600) % 60; tr_snprintf (d, sizeof (d), "%d %s", days, days==1?"day":"days"); tr_snprintf (h, sizeof (h), "%d %s", hours, hours==1?"hour":"hours"); tr_snprintf (m, sizeof (m), "%d %s", minutes, minutes==1?"minute":"minutes"); tr_snprintf (s, sizeof (s), "%d %s", seconds, seconds==1?"second":"seconds"); tr_snprintf (t, sizeof (t), "%d %s", total_seconds, total_seconds==1?"second":"seconds"); if (days) { if (days >= 4 || !hours) tr_strlcpy (b, d, sizeof (b)); else tr_snprintf (b, sizeof (b), "%s, %s", d, h); } else if (hours) { if (hours >= 4 || !minutes) tr_strlcpy (b, h, sizeof (b)); else tr_snprintf (b, sizeof (b), "%s, %s", h, m); } else if (minutes) { if (minutes >= 4 || !seconds) tr_strlcpy (b, m, sizeof (b)); else tr_snprintf (b, sizeof (b), "%s, %s", m, s); } else tr_strlcpy (b, s, sizeof (b)); tr_snprintf (buf, buflen, "%s (%s)", b, t); return buf; } static char* strlpercent (char * buf, double x, size_t buflen) { return tr_strpercent (buf, x, buflen); } static char* strlratio2 (char * buf, double ratio, size_t buflen) { return tr_strratio (buf, buflen, ratio, "Inf"); } static char* strlratio (char * buf, int64_t numerator, int64_t denominator, size_t buflen) { double ratio; if (denominator != 0) ratio = numerator / (double)denominator; else if (numerator != 0) ratio = TR_RATIO_INF; else ratio = TR_RATIO_NA; return strlratio2 (buf, ratio, buflen); } static char* strlmem (char * buf, int64_t bytes, size_t buflen) { if (!bytes) tr_strlcpy (buf, "None", buflen); else tr_formatter_mem_B (buf, bytes, buflen); return buf; } static char* strlsize (char * buf, int64_t bytes, size_t buflen) { if (bytes < 0) tr_strlcpy (buf, "Unknown", buflen); else if (bytes == 0) tr_strlcpy (buf, "None", buflen); else tr_formatter_size_B (buf, bytes, buflen); return buf; } enum { TAG_SESSION, TAG_STATS, TAG_DETAILS, TAG_FILES, TAG_LIST, TAG_PEERS, TAG_PIECES, TAG_PORTTEST, TAG_TORRENT_ADD, TAG_TRACKERS }; static const char* getUsage (void) { return MY_NAME" "LONG_VERSION_STRING"\n" "A fast and easy BitTorrent client\n" "https://transmissionbt.com/\n" "\n" "Usage: " MY_NAME " [host] [options]\n" " " MY_NAME " [port] [options]\n" " " MY_NAME " [host:port] [options]\n" " " MY_NAME " [http(s?)://host:port/transmission/] [options]\n" "\n" "See the man page for detailed explanations and many examples."; } /*** **** **** Command-Line Arguments **** ***/ static tr_option opts[] = { { 'a', "add", "Add torrent files by filename or URL", "a", 0, NULL }, { 970, "alt-speed", "Use the alternate Limits", "as", 0, NULL }, { 971, "no-alt-speed", "Don't use the alternate Limits", "AS", 0, NULL }, { 972, "alt-speed-downlimit", "max alternate download speed (in "SPEED_K_STR")", "asd", 1, "" }, { 973, "alt-speed-uplimit", "max alternate upload speed (in "SPEED_K_STR")", "asu", 1, "" }, { 974, "alt-speed-scheduler", "Use the scheduled on/off times", "asc", 0, NULL }, { 975, "no-alt-speed-scheduler", "Don't use the scheduled on/off times", "ASC", 0, NULL }, { 976, "alt-speed-time-begin", "Time to start using the alt speed limits (in hhmm)", NULL, 1, "