about summary refs log tree commit diff
path: root/cli/list.c
diff options
context:
space:
mode:
authorMarq Schneider <queueRAM@gmail.com>2010-07-29 21:43:07 -0500
committerMarq Schneider <queueRAM@gmail.com>2010-07-29 21:43:07 -0500
commit76c49475cea16512cb319a5222f657254f487cc5 (patch)
treef286b33574d42e02615612df8ff6af2a82938353 /cli/list.c
parent79641da4f277dced59904f76f2dec4c5b4fdcb3c (diff)
downloadbtpd-76c49475cea16512cb319a5222f657254f487cc5.tar.gz
btpd-76c49475cea16512cb319a5222f657254f487cc5.zip
Added custom formats for list operation.
Added printf()-style '%' and '\' sequences for custom list formats.
Updated btcli manpage to reflect change and start -a.

Closes GH-8
Diffstat (limited to 'cli/list.c')
-rw-r--r--cli/list.c110
1 files changed, 91 insertions, 19 deletions
diff --git a/cli/list.c b/cli/list.c
index ce7cc64..cca03a6 100644
--- a/cli/list.c
+++ b/cli/list.c
@@ -6,7 +6,7 @@ usage_list(void)
     printf(
         "List torrents.\n"
         "\n"
-        "Usage: list [-a] [-i]\n"
+        "Usage: list [-a] [-i] [-f <format>]\n"
         "       list torrent ...\n"
         "\n"
         "Arguments:\n"
@@ -26,10 +26,12 @@ usage_list(void)
 }
 
 struct item {
-    unsigned num;
-    char *name;
+    unsigned num, peers;
+    char *name, *dir;
+    char hash[SHAHEXSIZE];
     char st;
-    long long cgot, csize, totup;
+    long long cgot, csize, totup, downloaded, uploaded, rate_up, rate_down;
+    uint32_t torrent_pieces, pieces_have, pieces_seen;
     BTPDQ_ENTRY(item) entry;
 };
 
@@ -63,33 +65,95 @@ list_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg)
         diemsg("list failed for '%s' (%s).\n", itms->argv[obji],
             ipc_strerror(objerr));
     itms->count++;
-    itm->num = (unsigned)res[IPC_TVAL_NUM].v.num;
+    itm->num   = (unsigned)res[IPC_TVAL_NUM].v.num;
+    itm->peers = (unsigned)res[IPC_TVAL_PCOUNT].v.num;
     itm->st = tstate_char(res[IPC_TVAL_STATE].v.num);
     if (res[IPC_TVAL_NAME].type == IPC_TYPE_ERR)
         asprintf(&itm->name, "%s", ipc_strerror(res[IPC_TVAL_NAME].v.num));
     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;
+    if (res[IPC_TVAL_DIR].type == IPC_TYPE_ERR)
+        asprintf(&itm->dir, "%s", ipc_strerror(res[IPC_TVAL_DIR].v.num));
+    else
+        asprintf(&itm->dir, "%.*s", (int)res[IPC_TVAL_DIR].v.str.l,
+            res[IPC_TVAL_DIR].v.str.p);
+    bin2hex(res[IPC_TVAL_IHASH].v.str.p, itm->hash, 20);
+    itm->cgot           = res[IPC_TVAL_CGOT].v.num;
+    itm->csize          = res[IPC_TVAL_CSIZE].v.num;
+    itm->totup          = res[IPC_TVAL_TOTUP].v.num;
+    itm->downloaded     = res[IPC_TVAL_SESSDWN].v.num;
+    itm->uploaded       = res[IPC_TVAL_SESSUP].v.num;
+    itm->rate_up        = res[IPC_TVAL_RATEUP].v.num;
+    itm->rate_down      = res[IPC_TVAL_RATEDWN].v.num;
+    itm->torrent_pieces = (uint32_t)res[IPC_TVAL_PCCOUNT].v.num;
+    itm->pieces_seen    = (uint32_t)res[IPC_TVAL_PCSEEN].v.num;
+    itm->pieces_have    = (uint32_t)res[IPC_TVAL_PCGOT].v.num;
+
     itm_insert(itms, itm);
 }
 
 void
-print_items(struct items* itms)
+print_items(struct items* itms, char *format)
 {
     struct item *p;
+    char *it;
     BTPDQ_FOREACH(p, &itms->hd, entry) {
-        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");
+        if(format) {
+            for (it = format; *it; ++it) {
+                switch (*it) {
+                    case '%':
+                        ++it;
+                        switch (*it) {
+                            case '%': putchar('%');                      break;
+                            case '#': printf("%u",   p->num);            break;
+                            case '^': printf("%lld", p->rate_up);        break;
+
+                            case 'A': printf("%u",   p->pieces_seen);    break;
+                            case 'D': printf("%lld", p->downloaded);     break;
+                            case 'H': printf("%u",   p->pieces_have);    break;
+                            case 'P': printf("%u",   p->peers);          break;
+                            case 'S': printf("%c",   p->st);             break;
+                            case 'U': printf("%lld", p->uploaded);       break;
+                            case 'T': printf("%u",   p->torrent_pieces); break;
+
+                            case 'd': printf("%s",   p->dir);            break;
+                            case 'g': printf("%lld", p->cgot);           break;
+                            case 'h': printf("%s",   p->hash);           break;
+                            case 'n': printf("%s",   p->name);           break;
+                            case 'p': print_percent(p->cgot, p->csize);  break;
+                            case 'r': print_ratio(p->totup, p->csize);   break;
+                            case 's': print_size(p->csize);              break;
+                            case 't': printf("%lld", p->csize);          break;
+                            case 'u': printf("%lld", p->totup);          break;
+                            case 'v': printf("%lld", p->rate_down);      break;
+
+                            case '\0': continue;
+                        }
+                        break;
+                    case '\\':
+                        ++it;
+                        switch (*it) {
+                            case 'n':  putchar('\n'); break;
+                            case 't':  putchar('\t'); break;
+                            case '\0': continue;
+                        }
+                        break;
+                    default: putchar(*it); break;
+                }
+            }
+        } else {
+            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");
+        }
     }
 }
 
 static struct option list_opts [] = {
+    { "format", required_argument, NULL, 'f' },
     { "help", no_argument, NULL, 'H' },
     {NULL, 0, NULL, 0}
 };
@@ -98,17 +162,24 @@ void
 cmd_list(int argc, char **argv)
 {
     int ch, inactive = 0, active = 0;
+    char *format = NULL;
     enum ipc_err code;
     enum ipc_twc twc;
-    enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME,
-       IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT };
+    enum ipc_tval keys[] = { IPC_TVAL_NUM,    IPC_TVAL_STATE,   IPC_TVAL_NAME,
+           IPC_TVAL_TOTUP,   IPC_TVAL_CSIZE,  IPC_TVAL_CGOT,    IPC_TVAL_PCOUNT,
+           IPC_TVAL_PCCOUNT, IPC_TVAL_PCSEEN, IPC_TVAL_PCGOT,   IPC_TVAL_SESSUP,
+           IPC_TVAL_SESSDWN, IPC_TVAL_RATEUP, IPC_TVAL_RATEDWN, IPC_TVAL_IHASH,
+           IPC_TVAL_DIR };
     size_t nkeys = sizeof(keys) / sizeof(keys[0]);
     struct items itms;
-    while ((ch = getopt_long(argc, argv, "ai", list_opts, NULL)) != -1) {
+    while ((ch = getopt_long(argc, argv, "aif:", list_opts, NULL)) != -1) {
         switch (ch) {
         case 'a':
             active = 1;
             break;
+        case 'f':
+            format = optarg;
+            break;
         case 'i':
             inactive = 1;
             break;
@@ -149,6 +220,7 @@ cmd_list(int argc, char **argv)
         code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms);
     if (code != IPC_OK)
         diemsg("command failed (%s).\n", ipc_strerror(code));
-    printf("%-40.40s  NUM ST   HAVE    SIZE   RATIO\n", "NAME");
-    print_items(&itms);
+    if (format == NULL)
+        printf("%-40.40s  NUM ST   HAVE    SIZE   RATIO\n", "NAME");
+    print_items(&itms, format);
 }