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;
|
||||
}
|
||||
|
||||
void process_commands() {
|
||||
CLI::App app{"pcloudcc-lneely"};
|
||||
app.fallthrough();
|
||||
app.footer("Type 'help' or '?' for a list of supported commands.");
|
||||
void setup_app(CLI::App *app) {
|
||||
app->fallthrough();
|
||||
app->footer("Type 'help' or '?' for a list of supported 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
|
||||
<< " help(?): Show this help message" << std::endl
|
||||
<< " crypto(c):" << std::endl
|
||||
|
|
@ -104,13 +103,13 @@ void process_commands() {
|
|||
<< " finalize(f): Kill daemon and quit" << 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();
|
||||
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();
|
||||
|
||||
// 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;
|
||||
size_t errm_size = 0;
|
||||
rpc_call(FINALIZE, "", &errm, &errm_size);
|
||||
|
|
@ -119,15 +118,15 @@ void process_commands() {
|
|||
exit(0);
|
||||
});
|
||||
|
||||
app.add_subcommand("quit", "Quit the program")->alias("q")->callback([] {
|
||||
app->add_subcommand("quit", "Quit the program")->alias("q")->callback([] {
|
||||
exit(0);
|
||||
});
|
||||
|
||||
// crypto start
|
||||
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->callback([&] {
|
||||
start_crypto_cmd->callback([] {
|
||||
char *errm = NULL;
|
||||
size_t 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([] {
|
||||
char *errm = NULL;
|
||||
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;
|
||||
if (errm) { free(errm); }
|
||||
return result;
|
||||
|
|
@ -187,9 +186,10 @@ void process_commands() {
|
|||
} else {
|
||||
std::cout << "No synchronized folders found." << std::endl;
|
||||
}
|
||||
free(flist);
|
||||
if(flist) { free(flist); }
|
||||
} else {
|
||||
std::cout << "failed to read folder list from shm" << std::endl;
|
||||
if(flist) { free(flist); }
|
||||
return -1;
|
||||
}
|
||||
if(errm) { free(errm); }
|
||||
|
|
@ -198,10 +198,10 @@ void process_commands() {
|
|||
|
||||
// sync add
|
||||
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("remotepath", remotepath, "Remote Path")->required();
|
||||
sync_add_cmd->callback([&] {
|
||||
sync_add_cmd->callback([] {
|
||||
char *errm = NULL;
|
||||
size_t errmsz = 0;
|
||||
|
||||
|
|
@ -222,9 +222,9 @@ void process_commands() {
|
|||
|
||||
// sync remove
|
||||
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->callback([&] {
|
||||
sync_remove_cmd->callback([] {
|
||||
char *errm = NULL;
|
||||
size_t errmsz = 0;
|
||||
const char *folderid = syncrm_fid.c_str();
|
||||
|
|
@ -239,6 +239,23 @@ void process_commands() {
|
|||
if(errm) { free(errm); }
|
||||
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
|
||||
using_history();
|
||||
|
|
@ -266,7 +283,7 @@ void process_commands() {
|
|||
args.push_back(arg);
|
||||
}
|
||||
|
||||
invs << "Invalid command: '" << "line"
|
||||
invs << "Invalid command: '" << line
|
||||
<< "'. Type 'help' or '?' to get a list of valid commands.";
|
||||
if (!args.empty()) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -29,10 +29,13 @@
|
|||
#ifndef CONTROL_TOOLS_H
|
||||
#define CONTROL_TOOLS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace control_tools {
|
||||
|
||||
void process_commands();
|
||||
int daemonize(bool do_commands);
|
||||
int process_command(const std::string &command);
|
||||
|
||||
} // namespace control_tools
|
||||
|
||||
|
|
|
|||
54
main.cpp
54
main.cpp
|
|
@ -58,31 +58,21 @@ int main(int argc, char **argv) {
|
|||
|
||||
try {
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()("help,h", "Show this help message.")(
|
||||
"username,u", po::value<std::string>(&username),
|
||||
"pCloud account name.")(
|
||||
"password,p", po::bool_switch(&passwordsw),
|
||||
"Ask for pCloud account password.")(
|
||||
"tfa_code,t", po::value<std::string>(&tfa_code),
|
||||
"pCloud tfa code")(
|
||||
"trusted_device,r", po::bool_switch(&trusted_device),
|
||||
"Trust this device.")(
|
||||
"crypto,c", po::bool_switch(&crypto),
|
||||
"Ask for crypto password.")(
|
||||
"passascrypto,y", po::value<std::string>(),
|
||||
"User password is the same as crypto password.")(
|
||||
"daemonize,d", po::bool_switch(&daemon),
|
||||
"Run the process as a background daemon.")(
|
||||
"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.");
|
||||
desc.add_options()
|
||||
("help,h", "Show this help message.")
|
||||
("username,u", po::value<std::string>(&username), "pCloud account name.")
|
||||
("password,p", po::bool_switch(&passwordsw), "Ask for pCloud account password.")
|
||||
("tfa_code,t", po::value<std::string>(&tfa_code), "pCloud tfa code")
|
||||
("trusted_device,r", po::bool_switch(&trusted_device), "Trust this device.")
|
||||
("crypto,c", po::bool_switch(&crypto), "Ask for crypto password.")
|
||||
("passascrypto,y", po::value<std::string>(), "User password is the same as crypto password.")
|
||||
("daemonize,d", po::bool_switch(&daemon), "Run the process as a background daemon.")
|
||||
("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.")
|
||||
("command,c", po::value<std::string>(), "Execute a single command and exit.")
|
||||
("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::positional_options_description p;
|
||||
|
|
@ -102,6 +92,20 @@ int main(int argc, char **argv) {
|
|||
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"))) {
|
||||
std::cout << "Username option is required, specify with "
|
||||
<< "-u or --username." << std::endl;
|
||||
|
|
|
|||
|
|
@ -191,11 +191,12 @@ char *ppath_private(char *name) {
|
|||
if (!path)
|
||||
return NULL;
|
||||
rpath = psync_strcat(path, "/", name, NULL);
|
||||
free(path);
|
||||
if (stat(rpath, &st) && mkdir(path, PSYNC_DEFAULT_POSIX_FOLDER_MODE)) {
|
||||
psync_free(rpath);
|
||||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
free(path);
|
||||
return rpath;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ key_t pshm_get_key() {
|
|||
return (key_t)-1;
|
||||
}
|
||||
snprintf(path, sizeof(path), "%s/.pcloud/data.db", home);
|
||||
free(home);
|
||||
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
|
||||
// that exceed that length, and writes the trimmed key and length to keydata
|
||||
// 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;
|
||||
unsigned char tag;
|
||||
unsigned char *p = (unsigned char *)keydata;
|
||||
const unsigned char *end;
|
||||
int ret;
|
||||
|
|
@ -621,17 +620,16 @@ static unsigned char* trim_der_key(const unsigned char *keydata, size_t *keylen)
|
|||
end = keydata + *keylen;
|
||||
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||
if (ret != 0) {
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
header_size = p - keydata;
|
||||
correct_len = header_size + len;
|
||||
trimmed = malloc(correct_len);
|
||||
if (!trimmed) return NULL;
|
||||
|
||||
if (!trimmed) return;
|
||||
memcpy(trimmed, keydata, correct_len);
|
||||
memcpy(keydata, trimmed, correct_len);
|
||||
free(trimmed);
|
||||
*keylen = correct_len;
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
psync_rsa_privatekey_t prsa_load_private(const unsigned char *keydata, size_t keylen) {
|
||||
|
|
@ -639,8 +637,8 @@ psync_rsa_privatekey_t prsa_load_private(const unsigned char *keydata, size_t ke
|
|||
mbedtls_rsa_context *rsa;
|
||||
int ret;
|
||||
|
||||
trim_der_key(keydata, &keylen);
|
||||
|
||||
trim_der_key((unsigned char *)keydata, &keylen);
|
||||
|
||||
mbedtls_pk_init(&ctx);
|
||||
ret = mbedtls_pk_parse_key(&ctx, keydata, keylen, NULL, 0, rng_get, &rng);
|
||||
if(unlikely(ret)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue