void btpd_connect(void) { if ((errno = ipc_open(btpd_dir, &ipc)) != 0) diemsg("cannot open connection to btpd in %s (%s).\n", btpd_dir, strerror(errno)); }
void cmd_kill(CGI *cgi) { enum ipc_err code; btpd_connect(); if ((code = btpd_die(ipc)) != 0) diemsg("command failed (%s).\n", ipc_strerror(code)); }
enum ipc_err handle_ipc_res(enum ipc_err code, const char *cmd, const char *target) { switch (code) { case IPC_OK: break; case IPC_COMMERR: diemsg("error in communication with btpd.\n"); default: printf("btpdcgi: %s '%s': %s.\n", cmd, target, ipc_strerror(code)); } return code; }
int main(int argc, char **argv) { int ch, help = 0; while ((ch = getopt_long(argc, argv, "+d:", base_opts, NULL)) != -1) { switch (ch) { case 'd': btpd_dir = optarg; break; case 'H': help = 1; break; default: usage(); } } argc -= optind; argv += optind; if (btpd_dir == NULL) if ((btpd_dir = find_btpd_dir()) == NULL) diemsg("cannot find the btpd directory.\n"); if (argc == 0) { cmd_list(argc, argv); cmd_stat(argc, argv); return 0; } optind = 0; int found = 0; for (int i = 0; !found && i < ARRAY_COUNT(cmd_table); i++) { if (strcmp(argv[0], cmd_table[i].name) == 0) { found = 1; if (help) cmd_table[i].help(); else cmd_table[i].fun(argc, argv); } } if (!found) usage(); return 0; }
char tstate_char(enum ipc_tstate ts) { switch (ts) { case IPC_TSTATE_INACTIVE: return 'I'; case IPC_TSTATE_START: return '+'; case IPC_TSTATE_STOP: return '-'; case IPC_TSTATE_LEECH: return 'L'; case IPC_TSTATE_SEED: return 'S'; } diemsg("unrecognized torrent state.\n"); }
char* tstate_str(enum ipc_tstate ts) { switch (ts) { case IPC_TSTATE_INACTIVE: return "inactive"; case IPC_TSTATE_START: return "start"; case IPC_TSTATE_STOP: return "stop"; case IPC_TSTATE_LEECH: return "leech"; case IPC_TSTATE_SEED: return "seed"; } return "n/a"; diemsg("unrecognized torrent state.\n"); }
void cmd_add(int argc, char **argv) { int ch, topdir = 0, start = 1, nfile, nloaded = 0; size_t dirlen = 0, labellen = 0; char *dir = NULL, *name = NULL, *glabel = NULL, *label; while ((ch = getopt_long(argc, argv, "NTd:l:n:", add_opts, NULL)) != -1) { switch (ch) { case 'N': start = 0; break; case 'T': topdir = 1; break; case 'd': dir = optarg; if ((dirlen = strlen(dir)) == 0) diemsg("bad option value for -d.\n"); break; case 'l': glabel = optarg; if ((labellen = strlen(dir)) == 0) diemsg("bad option value for -l.\n"); break; case 'n': name = optarg; break; default: usage_add(); } } argc -= optind; argv += optind; if (argc < 1 || dir == NULL) usage_add(); btpd_connect(); char *mi; size_t mi_size; enum ipc_err code; char dpath[PATH_MAX]; struct iobuf iob; for (nfile = 0; nfile < argc; nfile++) { if ((mi = mi_load(argv[nfile], &mi_size)) == NULL) { fprintf(stderr, "error loading '%s' (%s).\n", argv[nfile], strerror(errno)); continue; } iob = iobuf_init(PATH_MAX); iobuf_write(&iob, dir, dirlen); if (topdir && !mi_simple(mi)) { size_t tdlen; const char *td = benc_dget_mem(benc_dget_dct(mi, "info"), "name", &tdlen); iobuf_swrite(&iob, "/"); iobuf_write(&iob, td, tdlen); } iobuf_swrite(&iob, "\0"); if ((errno = make_abs_path(iob.buf, dpath)) != 0) { fprintf(stderr, "make_abs_path '%s' failed (%s).\n", dpath, strerror(errno)); iobuf_free(&iob); continue; } if(NULL == glabel) label = benc_dget_str(mi, "announce", NULL); else label = glabel; code = btpd_add(ipc, mi, mi_size, dpath, name, label); if ((code == IPC_OK) && start) { struct ipc_torrent tspec; tspec.by_hash = 1; mi_info_hash(mi, tspec.u.hash); code = btpd_start(ipc, &tspec); } if (code != IPC_OK) { fprintf(stderr, "command failed for '%s' (%s).\n", argv[nfile], ipc_strerror(code)); } else { nloaded++; } iobuf_free(&iob); } if (nloaded != nfile) { diemsg("error loaded %d of %d files.\n", nloaded, nfile); } }
/* getopt * int getopt(int argc, char *const argv[], const char *optstring); * * extern char *optarg; * extern int optind, opterr, optopt; */ int get_short_opt_arg(int argc, char **argv) { // first char is +, it will stop at first nonoption arg // first char is -, it will return nonoption with oc == 1 // after +/- or nothing, next char is colon, then we can distinguish // between invalid option and missing option arguments. // The options argument is a string that specifies the option characters // that are valid for this program. // * An option character in this string can be followed by a colon (‘:’) // to indicate that it takes a required argument. // * If an option character is followed by two colons (‘::’), its argument // is optional; // This is a GNU extension. // Ref: https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html const char *short_options = ":ab:c::h"; int oc; // opterr = 1; // default, getopt print error message for invalid options while (1) { oc = getopt(argc, argv, short_options); if (oc == -1) { // END of getopt break; } switch (oc) { case 'a': case 'h': printf("setting [%c] flag\n", oc); break; case 'b': printf("setting [%c] optarg=[%s]\n", oc, optarg); break; case 'c': // optional opt arg // -c valid, no optarg // -c3 valid, "3" is optarg // -c 3 invalid, optarg == NULL if (optarg == NULL) { printf("setting [%c] with NO optarg\n", oc); } else { printf("setting [%c] with optarg=[%s]\n", oc, optarg); } break; case 1: printf("when optstring[0]=%c, optarg=[%s]\n", short_options[0], optarg); break; case ':': diemsg("%s: option '-%c' %x requries an arguemnts\n", argv[0], optopt, optopt); break; case '?': default: diemsg("%s: option '-%c' %c is invalid: ignore\n", argv[0], oc, optopt); break; } } argc -= optind; argv += optind; showArg(argc, argv); return 0; }
/* getopt_long struct option { const char *name; // name of option, without any dash int has_arg; // enum, no_argument, required_argument, optional_argument int *flag; // if flag == NULL, then getopt_long return VAL. // if flag != NULL, *flag = val, getopt_long return 0 int val; }; array of options, should end with all 0 field. so it could find end of options. */ int get_long_opt_arg(int argc, char **argv) { int isHelp = 0; struct option option_list[] = { {"all", no_argument, NULL, 'a'}, {"bang", required_argument, NULL, 'b'}, {"cee", optional_argument, NULL, 'c'}, {"dii", required_argument, NULL, 1}, {"help", no_argument, &isHelp, 1}, {0, 0, 0, 0} }; char optstring[] = ":ab:c::h"; int oc; while (1) { int option_index; oc = getopt_long(argc, argv, optstring, option_list, &option_index); if (oc == -1) { break; } switch (oc) { case 'b': printf("setting [%c] optarg=[%s]\n", oc, optarg); break; case 'a': printf("setting [%c] flag\n", oc); break; case 'h': printf("setting [%c] flag\n", oc); isHelp = 1; break; case 'c': if (optarg == NULL) { printf("setting [%c] with NO optarg\n", oc); } else { printf("setting [%c] with optarg=[%s]\n", oc, optarg); } break; case 1: printf("find %dth option %s, optarg=[%s]\n", option_index, option_list[option_index].name, optarg); break; case 0: printf("auto setting *flag <= val\n"); break; case ':': diemsg("%s: option '-%c' %x requries an arguemnts\n", argv[0], optopt, optopt); break; case '?': default: diemsg("%s: option '-%c' %c is invalid: ignore\n", argv[0], oc, optopt); break; } } argc -= optind; argv += optind; showArg(argc, argv); return 0; }