A clone of btpd with my configuration changes.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

234 satır
7.9 KiB

  1. #include "btcli.h"
  2. #include "utils.h"
  3. void
  4. usage_list(void)
  5. {
  6. printf(
  7. "List torrents.\n"
  8. "\n"
  9. "Usage: list [-a] [-i] [-f <format>]\n"
  10. " list torrent ...\n"
  11. "\n"
  12. "Arguments:\n"
  13. "torrent ...\n"
  14. "\tThe torrents to list. Running 'btcli list' without any arguments\n"
  15. "\tor options is equivalent to running 'btcli list -ai'.\n"
  16. "\n"
  17. "Options:\n"
  18. "-a\n"
  19. "\tList active torrents.\n"
  20. "\n"
  21. "-i\n"
  22. "\tList inactive torrents.\n"
  23. "\n"
  24. );
  25. exit(1);
  26. }
  27. struct item {
  28. unsigned num, peers;
  29. char *name, *dir, *label;
  30. char hash[SHAHEXSIZE];
  31. char st;
  32. long long cgot, csize, totup, downloaded, uploaded, rate_up, rate_down;
  33. uint32_t torrent_pieces, pieces_have, pieces_seen;
  34. BTPDQ_ENTRY(item) entry;
  35. };
  36. struct items {
  37. int count;
  38. char **argv;
  39. int ntps;
  40. struct ipc_torrent *tps;
  41. BTPDQ_HEAD(item_tq, item) hd;
  42. };
  43. void
  44. itm_insert(struct items *itms, struct item *itm)
  45. {
  46. struct item *p;
  47. BTPDQ_FOREACH(p, &itms->hd, entry)
  48. if (strcmp(itm->name, p->name) < 0)
  49. break;
  50. if (p != NULL)
  51. BTPDQ_INSERT_BEFORE(p, itm, entry);
  52. else
  53. BTPDQ_INSERT_TAIL(&itms->hd, itm, entry);
  54. }
  55. static void
  56. list_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg)
  57. {
  58. struct items *itms = arg;
  59. struct item *itm = calloc(1, sizeof(*itm));
  60. if (objerr != IPC_OK)
  61. diemsg("list failed for '%s' (%s).\n", itms->argv[obji],
  62. ipc_strerror(objerr));
  63. itms->count++;
  64. itm->num = (unsigned)res[IPC_TVAL_NUM].v.num;
  65. itm->peers = (unsigned)res[IPC_TVAL_PCOUNT].v.num;
  66. itm->st = tstate_char(res[IPC_TVAL_STATE].v.num);
  67. if (res[IPC_TVAL_NAME].type == IPC_TYPE_ERR)
  68. asprintf(&itm->name, "%s", ipc_strerror(res[IPC_TVAL_NAME].v.num));
  69. else
  70. asprintf(&itm->name, "%.*s", (int)res[IPC_TVAL_NAME].v.str.l,
  71. res[IPC_TVAL_NAME].v.str.p);
  72. if (res[IPC_TVAL_DIR].type == IPC_TYPE_ERR)
  73. asprintf(&itm->dir, "%s", ipc_strerror(res[IPC_TVAL_DIR].v.num));
  74. else
  75. asprintf(&itm->dir, "%.*s", (int)res[IPC_TVAL_DIR].v.str.l,
  76. res[IPC_TVAL_DIR].v.str.p);
  77. if (res[IPC_TVAL_LABEL].type == IPC_TYPE_ERR)
  78. asprintf(&itm->label, "%s", ipc_strerror(res[IPC_TVAL_LABEL].v.num));
  79. else
  80. asprintf(&itm->label, "%.*s", (int)res[IPC_TVAL_LABEL].v.str.l,
  81. res[IPC_TVAL_LABEL].v.str.p);
  82. bin2hex(res[IPC_TVAL_IHASH].v.str.p, itm->hash, 20);
  83. itm->cgot = res[IPC_TVAL_CGOT].v.num;
  84. itm->csize = res[IPC_TVAL_CSIZE].v.num;
  85. itm->totup = res[IPC_TVAL_TOTUP].v.num;
  86. itm->downloaded = res[IPC_TVAL_SESSDWN].v.num;
  87. itm->uploaded = res[IPC_TVAL_SESSUP].v.num;
  88. itm->rate_up = res[IPC_TVAL_RATEUP].v.num;
  89. itm->rate_down = res[IPC_TVAL_RATEDWN].v.num;
  90. itm->torrent_pieces = (uint32_t)res[IPC_TVAL_PCCOUNT].v.num;
  91. itm->pieces_seen = (uint32_t)res[IPC_TVAL_PCSEEN].v.num;
  92. itm->pieces_have = (uint32_t)res[IPC_TVAL_PCGOT].v.num;
  93. itm_insert(itms, itm);
  94. }
  95. void
  96. print_items(struct items* itms, char *format)
  97. {
  98. struct item *p;
  99. char *it;
  100. BTPDQ_FOREACH(p, &itms->hd, entry) {
  101. if(format) {
  102. for (it = format; *it; ++it) {
  103. switch (*it) {
  104. case '%':
  105. ++it;
  106. switch (*it) {
  107. case '%': putchar('%'); break;
  108. case '#': printf("%u", p->num); break;
  109. case '^': printf("%lld", p->rate_up); break;
  110. case 'A': printf("%u", p->pieces_seen); break;
  111. case 'D': printf("%lld", p->downloaded); break;
  112. case 'H': printf("%u", p->pieces_have); break;
  113. case 'P': printf("%u", p->peers); break;
  114. case 'S': printf("%lld", p->csize); break;
  115. case 'U': printf("%lld", p->uploaded); break;
  116. case 'T': printf("%u", p->torrent_pieces); break;
  117. case 'd': printf("%s", p->dir); break;
  118. case 'g': printf("%lld", p->cgot); break;
  119. case 'h': printf("%s", p->hash); break;
  120. case 'l': printf("%s", p->label); break;
  121. case 'n': printf("%s", p->name); break;
  122. case 'p': print_percent(p->cgot, p->csize); break;
  123. case 'r': print_ratio(p->totup, p->csize); break;
  124. case 's': print_size(p->csize); break;
  125. case 't': printf("%c", p->st); break;
  126. case 'u': printf("%lld", p->totup); break;
  127. case 'v': printf("%lld", p->rate_down); break;
  128. case '\0': continue;
  129. }
  130. break;
  131. case '\\':
  132. ++it;
  133. switch (*it) {
  134. case 'n': putchar('\n'); break;
  135. case 't': putchar('\t'); break;
  136. case '\0': continue;
  137. }
  138. break;
  139. default: putchar(*it); break;
  140. }
  141. }
  142. } else {
  143. printf("%-40.40s %4u %c. ", p->name, p->num, p->st);
  144. print_percent(p->cgot, p->csize);
  145. print_size(p->csize);
  146. print_ratio(p->totup, p->csize);
  147. printf("\n");
  148. }
  149. }
  150. }
  151. static struct option list_opts [] = {
  152. { "format", required_argument, NULL, 'f' },
  153. { "help", no_argument, NULL, 'H' },
  154. {NULL, 0, NULL, 0}
  155. };
  156. void
  157. cmd_list(int argc, char **argv)
  158. {
  159. int ch, inactive = 0, active = 0;
  160. char *format = NULL;
  161. enum ipc_err code;
  162. enum ipc_twc twc;
  163. enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME,
  164. IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT, IPC_TVAL_PCOUNT,
  165. IPC_TVAL_PCCOUNT, IPC_TVAL_PCSEEN, IPC_TVAL_PCGOT, IPC_TVAL_SESSUP,
  166. IPC_TVAL_SESSDWN, IPC_TVAL_RATEUP, IPC_TVAL_RATEDWN, IPC_TVAL_IHASH,
  167. IPC_TVAL_DIR, IPC_TVAL_LABEL };
  168. size_t nkeys = ARRAY_COUNT(keys);
  169. struct items itms;
  170. while ((ch = getopt_long(argc, argv, "aif:", list_opts, NULL)) != -1) {
  171. switch (ch) {
  172. case 'a':
  173. active = 1;
  174. break;
  175. case 'f':
  176. format = optarg;
  177. break;
  178. case 'i':
  179. inactive = 1;
  180. break;
  181. default:
  182. usage_list();
  183. }
  184. }
  185. argc -= optind;
  186. argv += optind;
  187. if (argc > 0) {
  188. if (inactive || active)
  189. usage_list();
  190. itms.tps = malloc(argc * sizeof(*itms.tps));
  191. for (itms.ntps = 0; itms.ntps < argc; itms.ntps++) {
  192. if (!torrent_spec(argv[itms.ntps], &itms.tps[itms.ntps]))
  193. exit(1);
  194. }
  195. } else {
  196. itms.ntps = 0;
  197. itms.tps = NULL;
  198. }
  199. if (inactive == active)
  200. twc = IPC_TWC_ALL;
  201. else if (inactive)
  202. twc = IPC_TWC_INACTIVE;
  203. else
  204. twc = IPC_TWC_ACTIVE;
  205. btpd_connect();
  206. itms.count = 0;
  207. itms.argv = argv;
  208. BTPDQ_INIT(&itms.hd);
  209. if (itms.tps == NULL)
  210. code = btpd_tget_wc(ipc, twc, keys, nkeys, list_cb, &itms);
  211. else
  212. code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms);
  213. if (code != IPC_OK)
  214. diemsg("command failed (%s).\n", ipc_strerror(code));
  215. if (format == NULL)
  216. printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME");
  217. print_items(&itms, format);
  218. }