diff --git a/cli/btcli.c b/cli/btcli.c index 78a3313..f1305a2 100644 --- a/cli/btcli.c +++ b/cli/btcli.c @@ -24,6 +24,35 @@ handle_ipc_res(enum ipc_err code, const char *cmd, const char *target) return code; } +void +print_percent(long long part, long long whole) +{ + printf("%5.1f%% ", floor(1000.0 * part / whole) / 10); +} + +void +print_rate(long long rate) +{ + if (rate >= 999.995 * (1 << 10)) + printf("%6.2fMB/s ", (double)rate / (1 << 20)); + else + printf("%6.2fkB/s ", (double)rate / (1 << 10)); +} + +void +print_size(long long size) +{ + if (size >= 999.995 * (1 << 20)) + printf("%6.2fG ", (double)size / (1 << 30)); + else + printf("%6.2fM ", (double)size / (1 << 20)); +} +void +print_ratio(long long part, long long whole) +{ + printf("%7.2f ", (double)part / whole); +} + char tstate_char(enum ipc_tstate ts) { diff --git a/cli/btcli.h b/cli/btcli.h index 96c3f4b..e522f28 100644 --- a/cli/btcli.h +++ b/cli/btcli.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,11 @@ enum ipc_err handle_ipc_res(enum ipc_err err, const char *cmd, char tstate_char(enum ipc_tstate ts); int torrent_spec(char *arg, struct ipc_torrent *tp); +void print_rate(long long rate); +void print_size(long long size); +void print_ratio(long long part, long long whole); +void print_percent(long long part, long long whole); + void usage_add(void); void cmd_add(int argc, char **argv); void usage_del(void); diff --git a/cli/list.c b/cli/list.c index c0888c2..a6ed9d9 100644 --- a/cli/list.c +++ b/cli/list.c @@ -7,6 +7,19 @@ usage_list(void) "List torrents.\n" "\n" "Usage: list [-a] [-i]\n" + " list torrent ...\n" + "\n" + "Arguments:\n" + "torrent ...\n" + "\tThe torrents to list. Running 'btcli list' without any arguments\n" + "\tor options is equivalent to running 'btcli list -ai'.\n" + "\n" + "Options:\n" + "-a\n" + "\tList active torrents.\n" + "\n" + "-i\n" + "\tList inactive torrents.\n" "\n" ); exit(1); @@ -16,11 +29,15 @@ struct item { unsigned num; char *name; char st; + long long cgot, csize, totup; BTPDQ_ENTRY(item) entry; }; struct items { int count; + char **argv; + int ntps; + struct ipc_torrent *tps; BTPDQ_HEAD(item_tq, item) hd; }; @@ -29,7 +46,7 @@ itm_insert(struct items *itms, struct item *itm) { struct item *p; BTPDQ_FOREACH(p, &itms->hd, entry) - if (itm->num < p->num) + if (strcmp(itm->name, p->name) < 0) break; if (p != NULL) BTPDQ_INSERT_BEFORE(p, itm, entry); @@ -42,6 +59,9 @@ list_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg) { struct items *itms = arg; struct item *itm = calloc(1, sizeof(*itm)); + if (objerr != IPC_OK) + errx(1, "list failed for '%s' (%s)", itms->argv[obji], + ipc_strerror(objerr)); itms->count++; itm->num = (unsigned)res[IPC_TVAL_NUM].v.num; itm->st = tstate_char(res[IPC_TVAL_STATE].v.num); @@ -50,21 +70,22 @@ list_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg) else asprintf(&itm->name, "%.*s", (int)res[IPC_TVAL_NAME].v.str.l, res[IPC_TVAL_NAME].v.str.p); + itm->totup = res[IPC_TVAL_TOTUP].v.num; + itm->cgot = res[IPC_TVAL_CGOT].v.num; + itm->csize = res[IPC_TVAL_CSIZE].v.num; itm_insert(itms, itm); } void print_items(struct items* itms) { - int n; struct item *p; BTPDQ_FOREACH(p, &itms->hd, entry) { - n = printf("%u: ", p->num); - while (n < 7) { - putchar(' '); - n++; - } - printf("%c. %s\n", p->st, p->name); + printf("%-40.40s %4u %c. ", p->name, p->num, p->st); + print_percent(p->cgot, p->csize); + print_size(p->csize); + print_ratio(p->totup, p->csize); + printf("\n"); } } @@ -79,7 +100,9 @@ cmd_list(int argc, char **argv) int ch, inactive = 0, active = 0; enum ipc_err code; enum ipc_twc twc; - enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME }; + enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME, + IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT }; + size_t nkeys = sizeof(keys) / sizeof(keys[0]); struct items itms; while ((ch = getopt_long(argc, argv, "ai", list_opts, NULL)) != -1) { switch (ch) { @@ -93,7 +116,22 @@ cmd_list(int argc, char **argv) usage_list(); } } + argc -= optind; + argv += optind; + if (argc > 0) { + if (inactive || active) + usage_list(); + itms.tps = malloc(argc * sizeof(*itms.tps)); + for (itms.ntps = 0; itms.ntps < argc; itms.ntps++) { + if (!torrent_spec(argv[itms.ntps], &itms.tps[itms.ntps])) + exit(1); + + } + } else { + itms.ntps = 0; + itms.tps = NULL; + } if (inactive == active) twc = IPC_TWC_ALL; else if (inactive) @@ -102,11 +140,15 @@ cmd_list(int argc, char **argv) twc = IPC_TWC_ACTIVE; btpd_connect(); - printf("NUM ST NAME\n"); itms.count = 0; + itms.argv = argv; BTPDQ_INIT(&itms.hd); - if ((code = btpd_tget_wc(ipc, twc, keys, 3, list_cb, &itms)) != IPC_OK) + if (itms.tps == NULL) + code = btpd_tget_wc(ipc, twc, keys, nkeys, list_cb, &itms); + else + code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms); + if (code != IPC_OK) errx(1, "%s", ipc_strerror(code)); + printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME"); print_items(&itms); - printf("Listed %d torrent%s.\n", itms.count, itms.count == 1 ? "" : "s"); } diff --git a/cli/stat.c b/cli/stat.c index 1d1b781..c2846c1 100644 --- a/cli/stat.c +++ b/cli/stat.c @@ -1,5 +1,3 @@ -#include - #include "btcli.h" void @@ -8,11 +6,11 @@ usage_stat(void) printf( "Display stats for active torrents.\n" "\n" - "Usage: stat [-i] [-w seconds] [file ...]\n" + "Usage: stat [-i] [-w seconds] [torrent ...]\n" "\n" "Arguments:\n" - "file ...\n" - "\tOnly display stats for the given torrent(s).\n" + "torrent ...\n" + "\tOnly display stats for the given torrents.\n" "\n" "Options:\n" "-i\n" @@ -32,7 +30,7 @@ struct btstat { enum ipc_tstate state; unsigned peers, tr_errors; long long content_got, content_size, downloaded, uploaded, rate_up, - rate_down; + rate_down, tot_up; uint32_t pieces_seen, torrent_pieces; }; @@ -51,6 +49,7 @@ static enum ipc_tval stkeys[] = { IPC_TVAL_PCSEEN, IPC_TVAL_SESSUP, IPC_TVAL_SESSDWN, + IPC_TVAL_TOTUP, IPC_TVAL_RATEUP, IPC_TVAL_RATEDWN, IPC_TVAL_CGOT, @@ -59,30 +58,6 @@ static enum ipc_tval stkeys[] = { static size_t nstkeys = sizeof(stkeys) / sizeof(stkeys[0]); -static void -print_percent(long long part, long long whole) -{ - printf("%5.1f%% ", floor(1000.0 * part / whole) / 10); -} - -static void -print_rate(long long rate) -{ - if (rate >= 999.995 * (1 << 10)) - printf("%6.2fMB/s ", (double)rate / (1 << 20)); - else - printf("%6.2fkB/s ", (double)rate / (1 << 10)); -} - -static void -print_size(long long size) -{ - if (size >= 999.995 * (1 << 20)) - printf("%6.2fG ", (double)size / (1 << 30)); - else - printf("%6.2fM ", (double)size / (1 << 20)); -} - static void print_stat(struct btstat *st) { @@ -91,7 +66,8 @@ print_stat(struct btstat *st) print_rate(st->rate_down); print_size(st->uploaded); print_rate(st->rate_up); - printf("%5u ", st->peers); + print_ratio(st->tot_up, st->content_size); + printf("%4u ", st->peers); print_percent(st->pieces_seen, st->torrent_pieces); if (st->tr_errors > 0) printf("E%u", st->tr_errors); @@ -117,18 +93,14 @@ stat_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg) tot->rate_down += (st.rate_down = res[IPC_TVAL_RATEDWN].v.num); tot->rate_up += (st.rate_up = res[IPC_TVAL_RATEUP].v.num); tot->peers += (st.peers = res[IPC_TVAL_PCOUNT].v.num); + tot->tot_up += (st.tot_up = res[IPC_TVAL_TOTUP].v.num); if ((st.tr_errors = res[IPC_TVAL_TRERR].v.num) > 0) tot->tr_errors++; if (cba->individual) { if (cba->names) printf("%.*s\n", (int)res[IPC_TVAL_NAME].v.str.l, res[IPC_TVAL_NAME].v.str.p); - int n = printf("%u:", st.num); - while (n < 7) { - putchar(' '); - n++; - } - printf("%c. ", tstate_char(st.state)); + printf("%4u %c. ", st.num, tstate_char(st.state)); print_stat(&st); } } @@ -149,10 +121,11 @@ again: if (header == 0) { if (individual) { header = 1; - printf("NUM ST "); + printf(" NUM ST "); } else header = 20; - printf(" HAVE DLOAD RTDWN ULOAD RTUP PEERS AVAIL\n"); + printf(" HAVE DLOAD RTDWN ULOAD RTUP RATIO CONN" + " AVAIL\n"); } bzero(&cba.tot, sizeof(cba.tot)); @@ -165,9 +138,9 @@ again: if (err != IPC_OK) errx(1, ipc_strerror(err)); if (names) - printf("-----\n"); + printf("-------\n"); if (individual) - printf("Total: "); + printf(" "); print_stat(&cba.tot); if (seconds > 0) { sleep(seconds);