/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #define MY_NAME "transmission-remote" #define DEFAULT_HOST "localhost" #define DEFAULT_PORT TR_DEFAULT_RPC_PORT #define DEFAULT_URL TR_DEFAULT_RPC_URL_STR "rpc/" #define ARGUMENTS TR_KEY_arguments #define MEM_K 1024 #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_K_STR "kB" #define DISK_M_STR "MB" #define DISK_G_STR "GB" #define DISK_T_STR "TB" #define SPEED_K 1000 #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; int hours; int minutes; int total_seconds; char b[128]; char d[128]; char h[128]; char m[128]; char s[128]; char 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 != 0) { if (days >= 4 || hours == 0) { tr_strlcpy(b, d, sizeof(b)); } else { tr_snprintf(b, sizeof(b), "%s, %s", d, h); } } else if (hours != 0) { if (hours >= 4 || minutes == 0) { tr_strlcpy(b, h, sizeof(b)); } else { tr_snprintf(b, sizeof(b), "%s, %s", h, m); } } else if (minutes != 0) { if (minutes >= 4 || seconds == 0) { 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 == 0) { 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 char const* 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", false, NULL }, { 970, "alt-speed", "Use the alternate Limits", "as", false, NULL }, { 971, "no-alt-speed", "Don't use the alternate Limits", "AS", false, NULL }, { 972, "alt-speed-downlimit", "max alternate download speed (in "SPEED_K_STR ")", "asd", true, "" }, { 973, "alt-speed-uplimit", "max alternate upload speed (in "SPEED_K_STR ")", "asu", true, "" }, { 974, "alt-speed-scheduler", "Use the scheduled on/off times", "asc", false, NULL }, { 975, "no-alt-speed-scheduler", "Don't use the scheduled on/off times", "ASC", false, NULL }, { 976, "alt-speed-time-begin", "Time to start using the alt speed limits (in hhmm)", NULL, true, "