A clone of btpd with my configuration changes.

303 line
8.7 KiB

  1. #include "btpd.h"
  2. #include <getopt.h>
  3. #include <time.h>
  4. int btpd_daemon_phase = 2;
  5. int first_btpd_comm[2];
  6. int pidfd;
  7. void
  8. first_btpd_exit(char code)
  9. {
  10. write(first_btpd_comm[1], &code, 1);
  11. close(first_btpd_comm[0]);
  12. close(first_btpd_comm[1]);
  13. }
  14. static void
  15. writepid(void)
  16. {
  17. int nw;
  18. char pidtxt[100];
  19. nw = snprintf(pidtxt, sizeof(pidtxt), "%ld", (long)getpid());
  20. ftruncate(pidfd, 0);
  21. write(pidfd, pidtxt, nw);
  22. }
  23. static void
  24. setup_daemon(int daemonize, const char *dir)
  25. {
  26. char c;
  27. pid_t pid;
  28. struct timespec ts;
  29. if (snprintf(NULL, 0, "btpd") != 4)
  30. btpd_err("snprintf doesn't work.\n");
  31. if (evtimer_gettime(&ts) != 0)
  32. btpd_err("evtimer_gettime failed (%s).\n", strerror(errno));
  33. if (dir == NULL) {
  34. if ((dir = find_btpd_dir()) == NULL)
  35. btpd_err("Cannot find the btpd directory.\n");
  36. if (dir[0] != '/')
  37. btpd_err("Got non absolute path '%s' from system environment.\n",
  38. dir);
  39. btpd_dir = dir;
  40. }
  41. if (mkdir(dir, 0777) == -1 && errno != EEXIST)
  42. btpd_err("Couldn't create home '%s' (%s).\n", dir, strerror(errno));
  43. if (chdir(dir) != 0)
  44. btpd_err("Couldn't change working directory to '%s' (%s).\n", dir,
  45. strerror(errno));
  46. if (mkdir("torrents", 0777) == -1 && errno != EEXIST)
  47. btpd_err("Couldn't create torrents subdir (%s).\n", strerror(errno));
  48. if (btpd_dir == NULL) {
  49. char wd[PATH_MAX];
  50. if (getcwd(wd, PATH_MAX) == NULL)
  51. btpd_err("Couldn't get working directory (%s).\n",
  52. strerror(errno));
  53. if ((btpd_dir = strdup(wd)) == NULL)
  54. btpd_err("Out of memory.\n");
  55. }
  56. if (daemonize) {
  57. if (pipe(first_btpd_comm) < 0)
  58. btpd_err("Failed to create pipe (%s).\n", strerror(errno));
  59. if ((pid = fork()) < 0)
  60. btpd_err("fork() failed (%s).\n", strerror(errno));
  61. if (pid != 0) {
  62. read(first_btpd_comm[0], &c, 1);
  63. exit(c);
  64. }
  65. btpd_daemon_phase--;
  66. if (setsid() < 0)
  67. btpd_err("setsid() failed (%s).\n", strerror(errno));
  68. if ((pid = fork()) < 0)
  69. btpd_err("fork() failed (%s).\n", strerror(errno));
  70. if (pid != 0)
  71. exit(0);
  72. }
  73. if ((pidfd = open("pid", O_CREAT|O_WRONLY, 0666)) == -1)
  74. btpd_err("Couldn't open 'pid' (%s).\n", strerror(errno));
  75. if (lockf(pidfd, F_TLOCK, 0) == -1)
  76. btpd_err("Another instance of btpd is probably running in %s.\n", dir);
  77. writepid();
  78. }
  79. static void
  80. usage(void)
  81. {
  82. printf(
  83. "btpd is the BitTorrent Protocol Daemon.\n"
  84. "\n"
  85. "Usage: btpd [-d dir] [-p port] [more options...]\n"
  86. "\n"
  87. "Options:\n"
  88. "-4\n"
  89. "\tUse IPv4. If given in conjunction with -6, "
  90. "both versions are used.\n"
  91. "\n"
  92. "-6\n"
  93. "\tUse IPv6. By default IPv4 is used.\n"
  94. "\n"
  95. "--bw-in n\n"
  96. "\tLimit incoming BitTorrent traffic to n kB/s.\n"
  97. "\tDefault is 0 which means unlimited.\n"
  98. "\n"
  99. "--bw-out n\n"
  100. "\tLimit outgoing BitTorrent traffic to n kB/s.\n"
  101. "\tDefault is 0 which means unlimited.\n"
  102. "\n"
  103. "-d dir\n"
  104. "\tThe directory in which to run btpd. Default is '$HOME/.btpd'.\n"
  105. "\n"
  106. "--empty-start\n"
  107. "\tStart btpd without any active torrents.\n"
  108. "\n"
  109. "--help\n"
  110. "\tShow this text.\n"
  111. "\n"
  112. "--ip addr\n"
  113. "\tLet the tracker distribute the given address instead of the one\n"
  114. "\tit sees btpd connect from.\n"
  115. "\n"
  116. "--ipcprot mode\n"
  117. "\tSet the protection mode of the command socket.\n"
  118. "\tThe mode is specified by an octal number. Default is 0600.\n"
  119. "\n"
  120. "--logfile file\n"
  121. "\tWhere to put the logfile. By default it's put in the btpd dir.\n"
  122. "\n"
  123. "--max-peers n\n"
  124. "\tLimit the amount of peers to n.\n"
  125. "\n"
  126. "--max-uploads n\n"
  127. "\tControls the number of simultaneous uploads.\n"
  128. "\tThe possible values are:\n"
  129. "\t\tn < -1 : Choose n >= 2 based on --bw-out (default).\n"
  130. "\t\tn = -1 : Upload to every interested peer.\n"
  131. "\t\tn = 0 : Dont't upload to anyone.\n"
  132. "\t\tn > 0 : Upload to at most n peers simultaneously.\n"
  133. "\n"
  134. "--no-daemon\n"
  135. "\tKeep the btpd process in the foregorund and log to std{out,err}.\n"
  136. "\tThis option is intended for debugging purposes.\n"
  137. "\n"
  138. "-p n, --port n\n"
  139. "\tListen at port n. Default is 6881.\n"
  140. "\n"
  141. "--prealloc n\n"
  142. "\tPreallocate disk space in chunks of n kB. Default is 2048.\n"
  143. "\tNote that n will be rounded up to the closest multiple of the\n"
  144. "\ttorrent piece size. If n is zero no preallocation will be done.\n"
  145. "\n"
  146. "--numwant n\n"
  147. "\tSet the number of peers to fetch on each request. Default is 50.\n"
  148. "\n");
  149. exit(1);
  150. }
  151. static int longval = 0;
  152. static struct option longopts[] = {
  153. { "port", required_argument, NULL, 'p' },
  154. { "bw-in", required_argument, &longval, 1 },
  155. { "bw-out", required_argument, &longval, 2 },
  156. { "prealloc", required_argument, &longval, 3 },
  157. { "max-uploads", required_argument, &longval, 4 },
  158. { "max-peers", required_argument, &longval, 5 },
  159. { "no-daemon", no_argument, &longval, 6 },
  160. { "logfile", required_argument, &longval, 7 },
  161. { "ipcprot", required_argument, &longval, 8 },
  162. { "empty-start", no_argument, &longval, 9 },
  163. { "ip", required_argument, &longval, 10 },
  164. { "logmask", required_argument, &longval, 11 },
  165. { "numwant", required_argument, &longval, 12 },
  166. { "help", no_argument, &longval, 128 },
  167. { NULL, 0, NULL, 0 }
  168. };
  169. int
  170. main(int argc, char **argv)
  171. {
  172. char *dir = NULL, *log = NULL;
  173. int daemonize = 1, opt4 = 0, opt6 = 0;
  174. for (;;) {
  175. switch (getopt_long(argc, argv, "46d:p:", longopts, NULL)) {
  176. case -1:
  177. goto args_done;
  178. case '4':
  179. opt4 = 1;
  180. break;
  181. case '6':
  182. opt6 = 1;
  183. break;
  184. case 'd':
  185. dir = optarg;
  186. break;
  187. case 'p':
  188. net_port = atoi(optarg);
  189. break;
  190. case 0:
  191. switch (longval) {
  192. case 1:
  193. net_bw_limit_in = atoi(optarg) * 1024;
  194. break;
  195. case 2:
  196. net_bw_limit_out = atoi(optarg) * 1024;
  197. break;
  198. case 3:
  199. cm_alloc_size = atoi(optarg) * 1024;
  200. break;
  201. case 4:
  202. net_max_uploads = atoi(optarg);
  203. break;
  204. case 5:
  205. net_max_peers = atoi(optarg);
  206. break;
  207. case 6:
  208. daemonize = 0;
  209. break;
  210. case 7:
  211. log = optarg;
  212. break;
  213. case 8:
  214. ipcprot = strtol(optarg, NULL, 8);
  215. break;
  216. case 9:
  217. empty_start = 1;
  218. break;
  219. case 10:
  220. tr_ip_arg = optarg;
  221. break;
  222. case 11:
  223. btpd_logmask = atoi(optarg);
  224. break;
  225. case 12:
  226. net_numwant = (unsigned)atoi(optarg);
  227. break;
  228. default:
  229. usage();
  230. }
  231. break;
  232. case '?':
  233. default:
  234. usage();
  235. }
  236. }
  237. args_done:
  238. argc -= optind;
  239. argv += optind;
  240. if (opt6) {
  241. net_ipv6 = 1;
  242. if (!opt4)
  243. net_ipv4 = 0;
  244. }
  245. if (argc > 0)
  246. usage();
  247. setup_daemon(daemonize, dir);
  248. if (evloop_init() != 0)
  249. btpd_err("Failed to initialize evloop (%s).\n", strerror(errno));
  250. btpd_init();
  251. if (daemonize) {
  252. if (freopen("/dev/null", "r", stdin) == NULL)
  253. btpd_err("freopen of stdin failed (%s).\n", strerror(errno));
  254. if (freopen(log == NULL ? "log" : log, "a", stderr) == NULL)
  255. btpd_err("Couldn't open '%s' (%s).\n", log, strerror(errno));
  256. if (dup2(fileno(stderr), fileno(stdout)) < 0)
  257. btpd_err("dup2 failed (%s).\n", strerror(errno));
  258. first_btpd_exit(0);
  259. }
  260. setlinebuf(stdout);
  261. setlinebuf(stderr);
  262. btpd_daemon_phase = 0;
  263. if (!empty_start)
  264. active_start();
  265. else
  266. active_clear();
  267. evloop();
  268. btpd_err("Exit from evloop with error (%s).\n", strerror(errno));
  269. return 1;
  270. }