support non-interactive command processing
- app is now configured in setup_app function - added process_command() to api - support piped input and -c argument - fix memleaks
This commit is contained in:
parent
dbf3e11473
commit
7bc9078e00
|
|
@ -85,13 +85,12 @@ static char** command_completion(const char* text, int start, int end) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_commands() {
|
void setup_app(CLI::App *app) {
|
||||||
CLI::App app{"pcloudcc-lneely"};
|
app->fallthrough();
|
||||||
app.fallthrough();
|
app->footer("Type 'help' or '?' for a list of supported commands.");
|
||||||
app.footer("Type 'help' or '?' for a list of supported commands.");
|
|
||||||
|
|
||||||
// top-level commands
|
// top-level commands
|
||||||
app.add_subcommand("help", "Show help")->alias("?")->callback([] {
|
app->add_subcommand("help", "Show help")->alias("?")->callback([] {
|
||||||
std::cout << "Supported commands are:" << std::endl
|
std::cout << "Supported commands are:" << std::endl
|
||||||
<< " help(?): Show this help message" << std::endl
|
<< " help(?): Show this help message" << std::endl
|
||||||
<< " crypto(c):" << std::endl
|
<< " crypto(c):" << std::endl
|
||||||
|
|
@ -104,13 +103,13 @@ void process_commands() {
|
||||||
<< " finalize(f): Kill daemon and quit" << std::endl
|
<< " finalize(f): Kill daemon and quit" << std::endl
|
||||||
<< " quit(q): Exit this program" << std::endl;
|
<< " quit(q): Exit this program" << std::endl;
|
||||||
});
|
});
|
||||||
auto crypto_cmd = app.add_subcommand("crypto", "Crypto-related commands")->alias("c");
|
auto crypto_cmd = app->add_subcommand("crypto", "Crypto-related commands")->alias("c");
|
||||||
crypto_cmd->require_subcommand();
|
crypto_cmd->require_subcommand();
|
||||||
auto sync_cmd = app.add_subcommand("sync", "Sync-related commands")->alias("s");
|
auto sync_cmd = app->add_subcommand("sync", "Sync-related commands")->alias("s");
|
||||||
sync_cmd->require_subcommand();
|
sync_cmd->require_subcommand();
|
||||||
|
|
||||||
// finalize command
|
// finalize command
|
||||||
app.add_subcommand("finalize", "Finalize and exit")->alias("f")->callback([] {
|
app->add_subcommand("finalize", "Finalize and exit")->alias("f")->callback([] {
|
||||||
char *errm = NULL;
|
char *errm = NULL;
|
||||||
size_t errm_size = 0;
|
size_t errm_size = 0;
|
||||||
rpc_call(FINALIZE, "", &errm, &errm_size);
|
rpc_call(FINALIZE, "", &errm, &errm_size);
|
||||||
|
|
@ -119,15 +118,15 @@ void process_commands() {
|
||||||
exit(0);
|
exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.add_subcommand("quit", "Quit the program")->alias("q")->callback([] {
|
app->add_subcommand("quit", "Quit the program")->alias("q")->callback([] {
|
||||||
exit(0);
|
exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// crypto start
|
// crypto start
|
||||||
auto start_crypto_cmd = crypto_cmd->add_subcommand("start", "Start crypto");
|
auto start_crypto_cmd = crypto_cmd->add_subcommand("start", "Start crypto");
|
||||||
std::string start_crypto_pwd;
|
static std::string start_crypto_pwd;
|
||||||
start_crypto_cmd->add_option("password", start_crypto_pwd, "Crypto password")->required();
|
start_crypto_cmd->add_option("password", start_crypto_pwd, "Crypto password")->required();
|
||||||
start_crypto_cmd->callback([&] {
|
start_crypto_cmd->callback([] {
|
||||||
char *errm = NULL;
|
char *errm = NULL;
|
||||||
size_t errm_size = 0;
|
size_t errm_size = 0;
|
||||||
if(int result = rpc_call(STARTCRYPTO, start_crypto_pwd.c_str(), &errm, &errm_size) != 0) {
|
if(int result = rpc_call(STARTCRYPTO, start_crypto_pwd.c_str(), &errm, &errm_size) != 0) {
|
||||||
|
|
@ -144,7 +143,7 @@ void process_commands() {
|
||||||
crypto_cmd->add_subcommand("stop", "Stop crypto")->callback([] {
|
crypto_cmd->add_subcommand("stop", "Stop crypto")->callback([] {
|
||||||
char *errm = NULL;
|
char *errm = NULL;
|
||||||
size_t errm_size = 0;
|
size_t errm_size = 0;
|
||||||
if(int result = rpc_call(STOPCRYPTO, "", &errm, &errm_size) == 0) {
|
if(int result = rpc_call(STOPCRYPTO, "", &errm, &errm_size) != 0) {
|
||||||
std::cout << "Stop Crypto failed: "<< (errm ? errm : "no message") << std::endl;
|
std::cout << "Stop Crypto failed: "<< (errm ? errm : "no message") << std::endl;
|
||||||
if (errm) { free(errm); }
|
if (errm) { free(errm); }
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -187,9 +186,10 @@ void process_commands() {
|
||||||
} else {
|
} else {
|
||||||
std::cout << "No synchronized folders found." << std::endl;
|
std::cout << "No synchronized folders found." << std::endl;
|
||||||
}
|
}
|
||||||
free(flist);
|
if(flist) { free(flist); }
|
||||||
} else {
|
} else {
|
||||||
std::cout << "failed to read folder list from shm" << std::endl;
|
std::cout << "failed to read folder list from shm" << std::endl;
|
||||||
|
if(flist) { free(flist); }
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(errm) { free(errm); }
|
if(errm) { free(errm); }
|
||||||
|
|
@ -198,10 +198,10 @@ void process_commands() {
|
||||||
|
|
||||||
// sync add
|
// sync add
|
||||||
auto sync_add_cmd = sync_cmd->add_subcommand("add", "Add sync folder");
|
auto sync_add_cmd = sync_cmd->add_subcommand("add", "Add sync folder");
|
||||||
std::string localpath, remotepath;
|
static std::string localpath, remotepath;
|
||||||
sync_add_cmd->add_option("localpath", localpath, "Local Path")->required();
|
sync_add_cmd->add_option("localpath", localpath, "Local Path")->required();
|
||||||
sync_add_cmd->add_option("remotepath", remotepath, "Remote Path")->required();
|
sync_add_cmd->add_option("remotepath", remotepath, "Remote Path")->required();
|
||||||
sync_add_cmd->callback([&] {
|
sync_add_cmd->callback([] {
|
||||||
char *errm = NULL;
|
char *errm = NULL;
|
||||||
size_t errmsz = 0;
|
size_t errmsz = 0;
|
||||||
|
|
||||||
|
|
@ -222,9 +222,9 @@ void process_commands() {
|
||||||
|
|
||||||
// sync remove
|
// sync remove
|
||||||
auto sync_remove_cmd = sync_cmd->add_subcommand("remove", "Remove sync folder (use ls to get folder ID)")->alias("rm");
|
auto sync_remove_cmd = sync_cmd->add_subcommand("remove", "Remove sync folder (use ls to get folder ID)")->alias("rm");
|
||||||
std::string syncrm_fid;
|
static std::string syncrm_fid;
|
||||||
sync_remove_cmd->add_option("folderid", syncrm_fid, "Folder ID")->required();
|
sync_remove_cmd->add_option("folderid", syncrm_fid, "Folder ID")->required();
|
||||||
sync_remove_cmd->callback([&] {
|
sync_remove_cmd->callback([] {
|
||||||
char *errm = NULL;
|
char *errm = NULL;
|
||||||
size_t errmsz = 0;
|
size_t errmsz = 0;
|
||||||
const char *folderid = syncrm_fid.c_str();
|
const char *folderid = syncrm_fid.c_str();
|
||||||
|
|
@ -239,6 +239,23 @@ void process_commands() {
|
||||||
if(errm) { free(errm); }
|
if(errm) { free(errm); }
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_command(const std::string &command) {
|
||||||
|
CLI::App app = CLI::App{"pcloudcc-lneely"};
|
||||||
|
setup_app(&app);
|
||||||
|
try {
|
||||||
|
app.parse(command);
|
||||||
|
return 0;
|
||||||
|
} catch (const CLI::ParseError &e) {
|
||||||
|
std::cerr << "Invalid command: '" << command << "'" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_commands() {
|
||||||
|
CLI::App app = CLI::App{"pcloudcc-lneely"};
|
||||||
|
setup_app(&app);
|
||||||
|
|
||||||
// enable command history and auto-completion
|
// enable command history and auto-completion
|
||||||
using_history();
|
using_history();
|
||||||
|
|
@ -266,7 +283,7 @@ void process_commands() {
|
||||||
args.push_back(arg);
|
args.push_back(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
invs << "Invalid command: '" << "line"
|
invs << "Invalid command: '" << line
|
||||||
<< "'. Type 'help' or '?' to get a list of valid commands.";
|
<< "'. Type 'help' or '?' to get a list of valid commands.";
|
||||||
if (!args.empty()) {
|
if (!args.empty()) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,13 @@
|
||||||
#ifndef CONTROL_TOOLS_H
|
#ifndef CONTROL_TOOLS_H
|
||||||
#define CONTROL_TOOLS_H
|
#define CONTROL_TOOLS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace control_tools {
|
namespace control_tools {
|
||||||
|
|
||||||
void process_commands();
|
void process_commands();
|
||||||
int daemonize(bool do_commands);
|
int daemonize(bool do_commands);
|
||||||
|
int process_command(const std::string &command);
|
||||||
|
|
||||||
} // namespace control_tools
|
} // namespace control_tools
|
||||||
|
|
||||||
|
|
|
||||||
54
main.cpp
54
main.cpp
|
|
@ -58,31 +58,21 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
po::options_description desc("Allowed options");
|
po::options_description desc("Allowed options");
|
||||||
desc.add_options()("help,h", "Show this help message.")(
|
desc.add_options()
|
||||||
"username,u", po::value<std::string>(&username),
|
("help,h", "Show this help message.")
|
||||||
"pCloud account name.")(
|
("username,u", po::value<std::string>(&username), "pCloud account name.")
|
||||||
"password,p", po::bool_switch(&passwordsw),
|
("password,p", po::bool_switch(&passwordsw), "Ask for pCloud account password.")
|
||||||
"Ask for pCloud account password.")(
|
("tfa_code,t", po::value<std::string>(&tfa_code), "pCloud tfa code")
|
||||||
"tfa_code,t", po::value<std::string>(&tfa_code),
|
("trusted_device,r", po::bool_switch(&trusted_device), "Trust this device.")
|
||||||
"pCloud tfa code")(
|
("crypto,c", po::bool_switch(&crypto), "Ask for crypto password.")
|
||||||
"trusted_device,r", po::bool_switch(&trusted_device),
|
("passascrypto,y", po::value<std::string>(), "User password is the same as crypto password.")
|
||||||
"Trust this device.")(
|
("daemonize,d", po::bool_switch(&daemon), "Run the process as a background daemon.")
|
||||||
"crypto,c", po::bool_switch(&crypto),
|
("commands ,o", po::bool_switch(&commands), "Keep parent process alive and process commands. ")
|
||||||
"Ask for crypto password.")(
|
("mountpoint,m", po::value<std::string>(), "Specify where pCloud filesystem is mounted.")
|
||||||
"passascrypto,y", po::value<std::string>(),
|
("commands_only,k", po::bool_switch(&commands_only), "Open command prompt to interact with running daemon.")
|
||||||
"User password is the same as crypto password.")(
|
("command,c", po::value<std::string>(), "Execute a single command and exit.")
|
||||||
"daemonize,d", po::bool_switch(&daemon),
|
("newuser,n", po::bool_switch(&newuser), "Register a new pCloud user account.")
|
||||||
"Run the process as a background daemon.")(
|
("savepassword,s", po::bool_switch(&save_pass), "Save user password in the database.");
|
||||||
"commands ,o", po::bool_switch(&commands),
|
|
||||||
"Keep parent process alive and process commands. ")(
|
|
||||||
"mountpoint,m", po::value<std::string>(),
|
|
||||||
"Specify where pCloud filesystem is mounted.")(
|
|
||||||
"commands_only,k", po::bool_switch(&commands_only),
|
|
||||||
"Open command prompt to interact with running daemon.")(
|
|
||||||
"newuser,n", po::bool_switch(&newuser),
|
|
||||||
"Register a new pCloud user account.")(
|
|
||||||
"savepassword,s", po::bool_switch(&save_pass),
|
|
||||||
"Save user password in the database.");
|
|
||||||
|
|
||||||
po::command_line_parser parser{argc, argv};
|
po::command_line_parser parser{argc, argv};
|
||||||
po::positional_options_description p;
|
po::positional_options_description p;
|
||||||
|
|
@ -102,6 +92,20 @@ int main(int argc, char **argv) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_piped_input = !isatty(STDIN_FILENO);
|
||||||
|
if (has_piped_input && !vm.count("help")) {
|
||||||
|
std::string line;
|
||||||
|
if (std::getline(std::cin, line) && !line.empty()) {
|
||||||
|
return ct::process_command(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("command")) {
|
||||||
|
std::string command = vm["command"].as<std::string>();
|
||||||
|
return ct::process_command(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((!vm.count("username"))) {
|
if ((!vm.count("username"))) {
|
||||||
std::cout << "Username option is required, specify with "
|
std::cout << "Username option is required, specify with "
|
||||||
<< "-u or --username." << std::endl;
|
<< "-u or --username." << std::endl;
|
||||||
|
|
|
||||||
|
|
@ -191,11 +191,12 @@ char *ppath_private(char *name) {
|
||||||
if (!path)
|
if (!path)
|
||||||
return NULL;
|
return NULL;
|
||||||
rpath = psync_strcat(path, "/", name, NULL);
|
rpath = psync_strcat(path, "/", name, NULL);
|
||||||
free(path);
|
|
||||||
if (stat(rpath, &st) && mkdir(path, PSYNC_DEFAULT_POSIX_FOLDER_MODE)) {
|
if (stat(rpath, &st) && mkdir(path, PSYNC_DEFAULT_POSIX_FOLDER_MODE)) {
|
||||||
psync_free(rpath);
|
psync_free(rpath);
|
||||||
|
free(path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
free(path);
|
||||||
return rpath;
|
return rpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ key_t pshm_get_key() {
|
||||||
return (key_t)-1;
|
return (key_t)-1;
|
||||||
}
|
}
|
||||||
snprintf(path, sizeof(path), "%s/.pcloud/data.db", home);
|
snprintf(path, sizeof(path), "%s/.pcloud/data.db", home);
|
||||||
|
free(home);
|
||||||
return ftok(path, 'A');
|
return ftok(path, 'A');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -610,9 +610,8 @@ psync_rsa_publickey_t prsa_load_public(const unsigned char *keydata,
|
||||||
// function gets the actual key length from the ASN.1 header, trims any bytes
|
// function gets the actual key length from the ASN.1 header, trims any bytes
|
||||||
// that exceed that length, and writes the trimmed key and length to keydata
|
// that exceed that length, and writes the trimmed key and length to keydata
|
||||||
// and keylen.
|
// and keylen.
|
||||||
static unsigned char* trim_der_key(const unsigned char *keydata, size_t *keylen) {
|
static void trim_der_key(unsigned char *keydata, size_t *keylen) {
|
||||||
size_t len, header_size, correct_len;
|
size_t len, header_size, correct_len;
|
||||||
unsigned char tag;
|
|
||||||
unsigned char *p = (unsigned char *)keydata;
|
unsigned char *p = (unsigned char *)keydata;
|
||||||
const unsigned char *end;
|
const unsigned char *end;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -621,17 +620,16 @@ static unsigned char* trim_der_key(const unsigned char *keydata, size_t *keylen)
|
||||||
end = keydata + *keylen;
|
end = keydata + *keylen;
|
||||||
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
header_size = p - keydata;
|
header_size = p - keydata;
|
||||||
correct_len = header_size + len;
|
correct_len = header_size + len;
|
||||||
trimmed = malloc(correct_len);
|
trimmed = malloc(correct_len);
|
||||||
if (!trimmed) return NULL;
|
if (!trimmed) return;
|
||||||
|
|
||||||
memcpy(trimmed, keydata, correct_len);
|
memcpy(trimmed, keydata, correct_len);
|
||||||
|
memcpy(keydata, trimmed, correct_len);
|
||||||
|
free(trimmed);
|
||||||
*keylen = correct_len;
|
*keylen = correct_len;
|
||||||
|
|
||||||
return trimmed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
psync_rsa_privatekey_t prsa_load_private(const unsigned char *keydata, size_t keylen) {
|
psync_rsa_privatekey_t prsa_load_private(const unsigned char *keydata, size_t keylen) {
|
||||||
|
|
@ -639,7 +637,7 @@ psync_rsa_privatekey_t prsa_load_private(const unsigned char *keydata, size_t ke
|
||||||
mbedtls_rsa_context *rsa;
|
mbedtls_rsa_context *rsa;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
trim_der_key(keydata, &keylen);
|
trim_der_key((unsigned char *)keydata, &keylen);
|
||||||
|
|
||||||
mbedtls_pk_init(&ctx);
|
mbedtls_pk_init(&ctx);
|
||||||
ret = mbedtls_pk_parse_key(&ctx, keydata, keylen, NULL, 0, rng_get, &rng);
|
ret = mbedtls_pk_parse_key(&ctx, keydata, keylen, NULL, 0, rng_get, &rng);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue