A clone of btpd with my configuration changes.

209 行
4.4 KiB

  1. #include <stdarg.h>
  2. #include "btcli.h"
  3. const char *btpd_dir;
  4. struct ipc *ipc;
  5. void
  6. diemsg(const char *fmt, ...)
  7. {
  8. va_list ap;
  9. va_start(ap, fmt);
  10. vfprintf(stderr, fmt, ap);
  11. va_end(ap);
  12. exit(1);
  13. }
  14. void
  15. btpd_connect(void)
  16. {
  17. if ((errno = ipc_open(btpd_dir, &ipc)) != 0)
  18. diemsg("cannot open connection to btpd in %s (%s).\n", btpd_dir,
  19. strerror(errno));
  20. }
  21. enum ipc_err
  22. handle_ipc_res(enum ipc_err code, const char *cmd, const char *target)
  23. {
  24. switch (code) {
  25. case IPC_OK:
  26. break;
  27. case IPC_COMMERR:
  28. diemsg("error in communication with btpd.\n");
  29. default:
  30. fprintf(stderr, "btcli %s '%s': %s.\n", cmd, target,
  31. ipc_strerror(code));
  32. }
  33. return code;
  34. }
  35. void
  36. print_percent(long long part, long long whole)
  37. {
  38. printf("%5.1f%% ", floor(1000.0 * part / whole) / 10);
  39. }
  40. void
  41. print_rate(long long rate)
  42. {
  43. if (rate >= 999.995 * (1 << 10))
  44. printf("%6.2fMB/s ", (double)rate / (1 << 20));
  45. else
  46. printf("%6.2fkB/s ", (double)rate / (1 << 10));
  47. }
  48. void
  49. print_size(long long size)
  50. {
  51. if (size >= 999.995 * (1 << 20))
  52. printf("%6.2fG ", (double)size / (1 << 30));
  53. else
  54. printf("%6.2fM ", (double)size / (1 << 20));
  55. }
  56. void
  57. print_ratio(long long part, long long whole)
  58. {
  59. printf("%7.2f ", (double)part / whole);
  60. }
  61. char
  62. tstate_char(enum ipc_tstate ts)
  63. {
  64. switch (ts) {
  65. case IPC_TSTATE_INACTIVE:
  66. return 'I';
  67. case IPC_TSTATE_START:
  68. return '+';
  69. case IPC_TSTATE_STOP:
  70. return '-';
  71. case IPC_TSTATE_LEECH:
  72. return 'L';
  73. case IPC_TSTATE_SEED:
  74. return 'S';
  75. }
  76. diemsg("unrecognized torrent state.\n");
  77. }
  78. int
  79. torrent_spec(char *arg, struct ipc_torrent *tp)
  80. {
  81. char *p;
  82. tp->u.num = strtoul(arg, &p, 10);
  83. if (*p == '\0') {
  84. tp->by_hash = 0;
  85. return 1;
  86. }
  87. if ((p = mi_load(arg, NULL)) == NULL) {
  88. fprintf(stderr, "btcli: bad torrent '%s' (%s).\n", arg,
  89. strerror(errno));
  90. return 0;
  91. }
  92. tp->by_hash = 1;
  93. mi_info_hash(p, tp->u.hash);
  94. free(p);
  95. return 1;
  96. }
  97. static struct {
  98. const char *name;
  99. void (*fun)(int, char **);
  100. void (*help)(void);
  101. } cmd_table[] = {
  102. { "add", cmd_add, usage_add },
  103. { "del", cmd_del, usage_del },
  104. { "kill", cmd_kill, usage_kill },
  105. { "list", cmd_list, usage_list },
  106. { "rate", cmd_rate, usage_rate },
  107. { "start", cmd_start, usage_start },
  108. { "stop", cmd_stop, usage_stop },
  109. { "stat", cmd_stat, usage_stat }
  110. };
  111. int ncmds = sizeof(cmd_table) / sizeof(cmd_table[0]);
  112. static void
  113. usage(void)
  114. {
  115. printf(
  116. "btcli is the btpd command line interface.\n"
  117. "\n"
  118. "Usage: btcli [main options] command [command options]\n"
  119. "\n"
  120. "Main options:\n"
  121. "-d dir\n"
  122. "\tThe btpd directory.\n"
  123. "\n"
  124. "--help [command]\n"
  125. "\tShow this text or help for the specified command.\n"
  126. "\n"
  127. "Commands:\n"
  128. "add\t- Add torrents to btpd.\n"
  129. "del\t- Remove torrents from btpd.\n"
  130. "kill\t- Shut down btpd.\n"
  131. "list\t- List torrents.\n"
  132. "rate\t- Set up/download rate limits.\n"
  133. "start\t- Activate torrents.\n"
  134. "stat\t- Display stats for active torrents.\n"
  135. "stop\t- Deactivate torrents.\n"
  136. "\n"
  137. "Note:\n"
  138. "Torrents can be specified either with its number or its file.\n"
  139. "\n"
  140. );
  141. exit(1);
  142. }
  143. static struct option base_opts [] = {
  144. { "help", no_argument, NULL, 'H' },
  145. {NULL, 0, NULL, 0}
  146. };
  147. int
  148. main(int argc, char **argv)
  149. {
  150. int ch, help = 0;
  151. if (argc < 2)
  152. usage();
  153. while ((ch = getopt_long(argc, argv, "+d:", base_opts, NULL)) != -1) {
  154. switch (ch) {
  155. case 'd':
  156. btpd_dir = optarg;
  157. break;
  158. case 'H':
  159. help = 1;
  160. break;
  161. default:
  162. usage();
  163. }
  164. }
  165. argc -= optind;
  166. argv += optind;
  167. if (argc == 0)
  168. usage();
  169. if (btpd_dir == NULL)
  170. if ((btpd_dir = find_btpd_dir()) == NULL)
  171. diemsg("cannot find the btpd directory.\n");
  172. optind = 0;
  173. int found = 0;
  174. for (int i = 0; !found && i < ncmds; i++) {
  175. if (strcmp(argv[0], cmd_table[i].name) == 0) {
  176. found = 1;
  177. if (help)
  178. cmd_table[i].help();
  179. else
  180. cmd_table[i].fun(argc, argv);
  181. }
  182. }
  183. if (!found)
  184. usage();
  185. return 0;
  186. }