non interactive command processing (#123)
* 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
f437fe840e
commit
27977765e8
|
|
@ -39,8 +39,6 @@
|
|||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "control_tools.h"
|
||||
|
||||
#include "pclsync_lib.h"
|
||||
#include "pclsync/pshm.h"
|
||||
#include "pclsync/pfoldersync.h"
|
||||
|
|
@ -53,196 +51,6 @@ namespace cc = console_client;
|
|||
|
||||
namespace control_tools {
|
||||
|
||||
static const int STOP = 0;
|
||||
|
||||
int list_sync_folders() {
|
||||
int ret;
|
||||
char *errm;
|
||||
size_t errmsz;
|
||||
int result;
|
||||
psync_folder_list_t *flist;
|
||||
psync_folder_t *folder;
|
||||
int rval;
|
||||
|
||||
errm = NULL;
|
||||
errmsz = 0;
|
||||
rval = 0;
|
||||
|
||||
result = rpc_call(LISTSYNC, "", &ret, &errm, &errmsz);
|
||||
|
||||
if (result != 0) {
|
||||
std::cout << "List Sync Folders failed. return is " << ret
|
||||
<< " and message is " << (errm ? errm : "no message")
|
||||
<< std::endl;
|
||||
rval = result;
|
||||
}
|
||||
|
||||
if(pshm_read((void**)&flist, NULL)) {
|
||||
const int id_width = 12;
|
||||
const int path_width = 30;
|
||||
|
||||
if(flist->foldercnt > 0) {
|
||||
std::cout << std::left << std::setw(id_width) << "Folder ID"
|
||||
<< std::setw(path_width) << "Local Path"
|
||||
<< std::setw(path_width) << "Remote Path" << std::endl;
|
||||
std::cout << std::string(id_width, '-')
|
||||
<< std::string(path_width - 1, '-')
|
||||
<< std::string(path_width - 1, '-') << std::endl;
|
||||
for (uint32_t i = 0; i < flist->foldercnt; i++) {
|
||||
folder = &flist->folders[i];
|
||||
std::cout << std::left << std::setw(id_width) << folder->folderid
|
||||
<< std::setw(path_width) << folder->localpath
|
||||
<< std::setw(path_width) << folder->remotepath << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "No synchronized folders found." << std::endl;
|
||||
rval = ret;
|
||||
}
|
||||
rval = ret;
|
||||
|
||||
free(flist);
|
||||
} else {
|
||||
std::cout << "failed to read folder list from shm" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(errm) {
|
||||
free(errm);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int start_crypto(const char *pass) {
|
||||
int ret;
|
||||
char *errm;
|
||||
size_t errm_size;
|
||||
|
||||
int result = rpc_call(STARTCRYPTO, pass, &ret, &errm, &errm_size);
|
||||
|
||||
if (result != 0 || ret != 0) {
|
||||
std::cout << "Start Crypto failed. return is " << ret << " and message is "
|
||||
<< (errm ? errm : "no message") << std::endl;
|
||||
} else {
|
||||
std::cout << "Crypto started. " << std::endl;
|
||||
}
|
||||
if (errm)
|
||||
free(errm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int stop_crypto() {
|
||||
int ret;
|
||||
char *errm;
|
||||
size_t errm_size;
|
||||
|
||||
int result = rpc_call(STOPCRYPTO, "", &ret, &errm, &errm_size);
|
||||
if (result != 0) {
|
||||
std::cout << "Stop Crypto failed. return is " << ret << " and message is "
|
||||
<< (errm ? errm : "no message") << std::endl;
|
||||
} else {
|
||||
std::cout << "Crypto Stopped. " << std::endl;
|
||||
}
|
||||
|
||||
if (errm)
|
||||
free(errm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int remove_sync_folder(const char *folderid) {
|
||||
int ret;
|
||||
char *errm;
|
||||
size_t errmsz;
|
||||
int result;
|
||||
int rval;
|
||||
|
||||
errm = NULL;
|
||||
errmsz = 0;
|
||||
rval = 0;
|
||||
|
||||
result = rpc_call(STOPSYNC, folderid, &ret, &errm, &errmsz);
|
||||
if (result != 0) {
|
||||
std::cout << "Remove Sync Folder failed with unknown error. return is "
|
||||
<< ret << " and message is " << (errm ? errm : "no message")
|
||||
<< std::endl;
|
||||
rval = result;
|
||||
} else {
|
||||
std::cout << "Successfully removed sync folder with folderid " << folderid
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if(errm) {
|
||||
free(errm);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
// TODO: should add support for specifying sync type. Need a better
|
||||
// CLI processing solution first.
|
||||
int add_sync_folder(std::string localpath, std::string remotepath) {
|
||||
int ret;
|
||||
char *errm;
|
||||
size_t errmsz;
|
||||
int result;
|
||||
int rval;
|
||||
|
||||
errm = NULL;
|
||||
errmsz = 0;
|
||||
rval = 0;
|
||||
|
||||
std::string combinedPaths = localpath + '|' + remotepath;
|
||||
result = rpc_call(ADDSYNC, combinedPaths.c_str(), &ret, &errm, &errmsz);
|
||||
|
||||
if (result != 0) {
|
||||
if (result == -1) {
|
||||
std::cout << "Add Sync Folders failed: remote folder " << remotepath
|
||||
<< " not found." << std::endl;
|
||||
} else {
|
||||
std::cout << "Add Sync Folders failed with unknown error. return is "
|
||||
<< ret << " and message is " << (errm ? errm : "no message")
|
||||
<< std::endl;
|
||||
}
|
||||
rval = result;
|
||||
} else {
|
||||
rval = ret;
|
||||
}
|
||||
|
||||
if(errm) {
|
||||
free(errm);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int finalize() {
|
||||
int ret;
|
||||
char *errm;
|
||||
size_t errm_size;
|
||||
|
||||
rpc_call(FINALIZE, "", &ret, &errm, &errm_size);
|
||||
std::cout << "Exiting ..." << std::endl;
|
||||
|
||||
if (errm){
|
||||
free(errm);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void help() {
|
||||
std::cout << "Supported commands are:" << std::endl
|
||||
<< " help(?): Show this help message" << std::endl
|
||||
<< " crypto(c):" << std::endl
|
||||
<< " start <crypto pass>: Unlock crypto folder" << std::endl
|
||||
<< " stop: Lock crypto folder" << std::endl
|
||||
<< " sync(s):" << std::endl
|
||||
<< " list(ls): List sync folders" << std::endl
|
||||
<< " add <localpath> <remotepath>: Add sync folder" << std::endl
|
||||
<< " remove(rm) <folderid>: Remove sync folder" << std::endl
|
||||
<< " finalize(f): Kill daemon and quit" << std::endl
|
||||
<< " quit(q): Exit this program" << std::endl;
|
||||
}
|
||||
|
||||
static char* command_generator(const char* text, int state) {
|
||||
static int list_index, len;
|
||||
static const char* commands[] = {
|
||||
|
|
@ -256,85 +64,204 @@ static char* command_generator(const char* text, int state) {
|
|||
nullptr
|
||||
};
|
||||
|
||||
// If this is a new word to complete, initialize
|
||||
if (!state) {
|
||||
list_index = 0;
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
// Return the next name which partially matches
|
||||
while (const char* command = commands[list_index++]) {
|
||||
if (strncmp(command, text, len) == 0) {
|
||||
return strdup(command); // Caller frees this with free()
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr; // No more matches
|
||||
}
|
||||
|
||||
static char** command_completion(const char* text, int start, int end) {
|
||||
// If this is the start of line, complete commands
|
||||
if (start == 0) {
|
||||
return rl_completion_matches(text, command_generator);
|
||||
}
|
||||
|
||||
// Otherwise, don't complete
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void process_commands() {
|
||||
CLI::App app{"pcloudcc-lneely"};
|
||||
app.fallthrough();
|
||||
app.footer("Type 'help' or '?' for a list of supported commands.");
|
||||
static char** command_completion(const char* text, int start, int end) {
|
||||
if (start == 0) {
|
||||
return rl_completion_matches(text, command_generator);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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(help);
|
||||
auto crypto_cmd =
|
||||
app.add_subcommand("crypto", "Crypto-related commands")->alias("c");
|
||||
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
|
||||
<< " start <crypto pass>: Unlock crypto folder" << std::endl
|
||||
<< " stop: Lock crypto folder" << std::endl
|
||||
<< " sync(s):" << std::endl
|
||||
<< " list(ls): List sync folders" << std::endl
|
||||
<< " add <localpath> <remotepath>: Add sync folder" << std::endl
|
||||
<< " remove(rm) <folderid>: Remove sync folder" << std::endl
|
||||
<< " 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");
|
||||
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();
|
||||
app.add_subcommand("finalize", "Finalize and exit")->alias("f")->callback([] {
|
||||
finalize();
|
||||
exit(0);
|
||||
});
|
||||
app.add_subcommand("quit", "Quit the program")->alias("q")->callback([] {
|
||||
|
||||
// finalize command
|
||||
app->add_subcommand("finalize", "Finalize and exit")->alias("f")->callback([] {
|
||||
char *errm = NULL;
|
||||
size_t errm_size = 0;
|
||||
rpc_call(FINALIZE, "", &errm, &errm_size);
|
||||
std::cout << "Exiting ..." << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
exit(0);
|
||||
});
|
||||
|
||||
// crypto subcommands
|
||||
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;
|
||||
start_crypto_cmd->add_option("password", start_crypto_pwd, "Crypto password")
|
||||
->required();
|
||||
start_crypto_cmd->callback([&] { start_crypto(start_crypto_pwd.c_str()); });
|
||||
|
||||
crypto_cmd->add_subcommand("stop", "Stop crypto")->callback(stop_crypto);
|
||||
|
||||
// sync subcommands
|
||||
sync_cmd->add_subcommand("list", "List sync folders")
|
||||
->alias("ls")
|
||||
->callback(list_sync_folders);
|
||||
|
||||
auto sync_add_cmd = sync_cmd->add_subcommand("add", "Add sync folder");
|
||||
std::string syncadd_lpath, syncadd_rpath;
|
||||
sync_add_cmd->add_option("localpath", syncadd_lpath, "Local Path")->required();
|
||||
sync_add_cmd->add_option("remotepath", syncadd_rpath, "Remote Path")->required();
|
||||
sync_add_cmd->callback([&] {
|
||||
add_sync_folder(syncadd_lpath, syncadd_rpath);
|
||||
static std::string start_crypto_pwd;
|
||||
start_crypto_cmd->add_option("password", start_crypto_pwd, "Crypto password")->required();
|
||||
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) {
|
||||
std::cout << "Start Crypto failed: " << (errm ? errm : "no message") << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
return result;
|
||||
}
|
||||
std::cout << "Crypto started." << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
return 0;
|
||||
});
|
||||
|
||||
auto sync_remove_cmd =
|
||||
sync_cmd->add_subcommand("remove", "Remove sync folder (use ls to get folder ID)")->alias("rm");
|
||||
std::string syncrm_fid;
|
||||
sync_remove_cmd->add_option("folderid", syncrm_fid, "Folder ID")->required();
|
||||
sync_remove_cmd->callback([&] { remove_sync_folder(syncrm_fid.c_str()); });
|
||||
// crypto stop
|
||||
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) {
|
||||
std::cout << "Stop Crypto failed: "<< (errm ? errm : "no message") << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
return result;
|
||||
}
|
||||
|
||||
std::cout << "Crypto Stopped." << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
return 0;
|
||||
});
|
||||
|
||||
// sync list
|
||||
sync_cmd->add_subcommand("list", "List sync folders")->alias("ls")->callback([] {
|
||||
char *errm = NULL;
|
||||
size_t errmsz = 0;
|
||||
|
||||
if(int result = rpc_call(LISTSYNC, "", &errm, &errmsz) != 0) {
|
||||
std::cout << "List Sync Folders failed: " << (errm ? errm : "no message") << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
return result;
|
||||
}
|
||||
|
||||
psync_folder_list_t *flist = NULL;
|
||||
if(pshm_read((void**)&flist, NULL)) {
|
||||
const int id_width = 12;
|
||||
const int path_width = 30;
|
||||
|
||||
if(flist->foldercnt > 0) {
|
||||
std::cout << std::left << std::setw(id_width) << "Folder ID"
|
||||
<< std::setw(path_width) << "Local Path"
|
||||
<< std::setw(path_width) << "Remote Path" << std::endl;
|
||||
std::cout << std::string(id_width, '-')
|
||||
<< std::string(path_width - 1, '-')
|
||||
<< std::string(path_width - 1, '-') << std::endl;
|
||||
for (uint32_t i = 0; i < flist->foldercnt; i++) {
|
||||
psync_folder_t *folder = &flist->folders[i];
|
||||
std::cout << std::left << std::setw(id_width) << folder->folderid
|
||||
<< std::setw(path_width) << folder->localpath
|
||||
<< std::setw(path_width) << folder->remotepath << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "No synchronized folders found." << std::endl;
|
||||
}
|
||||
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); }
|
||||
return 0;
|
||||
});
|
||||
|
||||
// sync add
|
||||
auto sync_add_cmd = sync_cmd->add_subcommand("add", "Add sync folder");
|
||||
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([] {
|
||||
char *errm = NULL;
|
||||
size_t errmsz = 0;
|
||||
|
||||
std::string combinedPaths = localpath + '|' + remotepath;
|
||||
if(int result = rpc_call(ADDSYNC, combinedPaths.c_str(), &errm, &errmsz) != 0) {
|
||||
if (result == -1) {
|
||||
std::cout << "Add Sync Folders failed: remote folder " << remotepath << " not found." << std::endl;
|
||||
} else {
|
||||
std::cout << "Add Sync Folders failed:" << (errm ? errm : "no message") << std::endl;
|
||||
}
|
||||
if (errm) { free(errm); }
|
||||
return result;
|
||||
}
|
||||
|
||||
if(errm) { free(errm); }
|
||||
return 0;
|
||||
});
|
||||
|
||||
// sync remove
|
||||
auto sync_remove_cmd = sync_cmd->add_subcommand("remove", "Remove sync folder (use ls to get folder ID)")->alias("rm");
|
||||
static std::string syncrm_fid;
|
||||
sync_remove_cmd->add_option("folderid", syncrm_fid, "Folder ID")->required();
|
||||
sync_remove_cmd->callback([] {
|
||||
char *errm = NULL;
|
||||
size_t errmsz = 0;
|
||||
const char *folderid = syncrm_fid.c_str();
|
||||
|
||||
if(int result = rpc_call(STOPSYNC, folderid, &errm, &errmsz) != 0) {
|
||||
std::cout << "Remove Sync Folder failed: " << (errm ? errm : "no message") << std::endl;
|
||||
if (errm) { free(errm); }
|
||||
return result;
|
||||
}
|
||||
std::cout << "Successfully removed sync folder with folderid " << folderid << std::endl;
|
||||
|
||||
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();
|
||||
rl_attempted_completion_function = command_completion;
|
||||
|
||||
// command loop
|
||||
rl_attempted_completion_function = command_completion;
|
||||
while (true) {
|
||||
char* line_read = readline("pcloud> ");
|
||||
if (!line_read) break;
|
||||
|
|
@ -350,10 +277,14 @@ void process_commands() {
|
|||
std::vector<std::string> args;
|
||||
std::istringstream iss(line);
|
||||
std::string arg;
|
||||
std::ostringstream invs;
|
||||
|
||||
while (iss >> arg) {
|
||||
args.push_back(arg);
|
||||
}
|
||||
|
||||
invs << "Invalid command: '" << line
|
||||
<< "'. Type 'help' or '?' to get a list of valid commands.";
|
||||
if (!args.empty()) {
|
||||
try {
|
||||
auto *subcom = app.get_subcommand(args[0]);
|
||||
|
|
@ -361,20 +292,13 @@ void process_commands() {
|
|||
std::cout << "Usage for '" << args[0] << "':" << std::endl;
|
||||
std::cout << subcom->help() << std::endl;
|
||||
} else {
|
||||
std::cout
|
||||
<< "Invalid command: '" << line
|
||||
<< "'. Type 'help' or '?' to get a list of valid commands."
|
||||
<< std::endl;
|
||||
std::cout << invs.str() << std::endl;
|
||||
}
|
||||
} catch (...) {
|
||||
std::cout << "Invalid command: '" << line
|
||||
<< "'. Type 'help' or '?' to get a list of valid commands."
|
||||
<< std::endl;
|
||||
std::cout << invs.str() << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "Invalid command: '" << line
|
||||
<< "'. Type 'help' or '?' to get a list of valid commands."
|
||||
<< std::endl;
|
||||
std::cout << invs.str() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@
|
|||
#ifndef CONTROL_TOOLS_H
|
||||
#define CONTROL_TOOLS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace control_tools {
|
||||
|
||||
int start_crypto(const char *pass);
|
||||
int stop_crypto();
|
||||
int finalize();
|
||||
int daemonize(bool do_commands);
|
||||
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,7 +637,7 @@ 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);
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@
|
|||
// specified sockpath. it may write an error message and error message
|
||||
// size to out and out_size, and a "ret" value to ret (i think this is
|
||||
// redundant maybe...)
|
||||
static int socket_connect(const char *sockpath, char **out, size_t *out_size,
|
||||
int *ret) {
|
||||
static int socket_connect(const char *sockpath, char **out, size_t *out_size) {
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
const char *error_msg;
|
||||
|
|
@ -87,7 +86,6 @@ static int socket_connect(const char *sockpath, char **out, size_t *out_size,
|
|||
error_msg = "Unable to create unix socket";
|
||||
*out = strdup(error_msg);
|
||||
*out_size = strlen(error_msg) + 1;
|
||||
*ret = POVERLAY_SOCKET_CREATE_FAILED;
|
||||
return POVERLAY_SOCKET_CREATE_FAILED;
|
||||
}
|
||||
|
||||
|
|
@ -98,43 +96,36 @@ static int socket_connect(const char *sockpath, char **out, size_t *out_size,
|
|||
error_msg = "Unable to connect to UNIX socket";
|
||||
*out = strdup(error_msg);
|
||||
*out_size = strlen(error_msg) + 1;
|
||||
*ret = POVERLAY_SOCKET_CONNECT_FAILED;
|
||||
return POVERLAY_SOCKET_CONNECT_FAILED;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int write_request(int fd, int msgtype, const char *value, char **out,
|
||||
size_t *out_size, int *ret) {
|
||||
static int write_request(int fd, int msgtype, const char *value, char **out, size_t *out_size) {
|
||||
uint64_t bytes_written;
|
||||
int rc;
|
||||
int len;
|
||||
int size;
|
||||
char *buf;
|
||||
const char *err;
|
||||
rpc_message_t *request;
|
||||
char *curbuf;
|
||||
int len = strlen(value);
|
||||
int size = sizeof(rpc_message_t) + len + 1;
|
||||
char *buf = (char *)malloc(size);
|
||||
|
||||
*ret = 0; // Initialize ret to 0
|
||||
|
||||
len = strlen(value);
|
||||
size = sizeof(rpc_message_t) + len + 1;
|
||||
buf = (char *)malloc(size);
|
||||
request = (rpc_message_t *)buf;
|
||||
// prepare the message
|
||||
rpc_message_t *request = (rpc_message_t *)buf;
|
||||
memset(request, 0, size);
|
||||
request->type = msgtype;
|
||||
strncpy(request->value, value, len + 1);
|
||||
request->length = size;
|
||||
bytes_written = 0;
|
||||
curbuf = (char *)request;
|
||||
|
||||
while (bytes_written < request->length && *ret == 0) {
|
||||
rc = write(fd, curbuf, (request->length - bytes_written));
|
||||
// write to the socket
|
||||
char *curbuf = (char *)request;
|
||||
int writeerr = 0;
|
||||
while (bytes_written < request->length && !writeerr) {
|
||||
int rc = write(fd, curbuf, (request->length - bytes_written));
|
||||
if (rc <= 0) {
|
||||
if (errno != EINTR) {
|
||||
err = "failed to write to socket.";
|
||||
const char *err = "failed to write to socket.";
|
||||
*out = strdup(err);
|
||||
*ret = POVERLAY_WRITE_SOCK_ERR;
|
||||
*out_size = strlen(err) + 1;
|
||||
writeerr = POVERLAY_WRITE_SOCK_ERR;
|
||||
}
|
||||
} else {
|
||||
bytes_written += rc;
|
||||
|
|
@ -142,91 +133,86 @@ static int write_request(int fd, int msgtype, const char *value, char **out,
|
|||
}
|
||||
}
|
||||
|
||||
if (*ret == 0 && bytes_written != request->length) {
|
||||
err = "Communication error";
|
||||
// return error if only partial data written
|
||||
if (!writeerr && bytes_written != request->length) {
|
||||
const char *err = "communication error";
|
||||
*out = strdup(err);
|
||||
*out_size = strlen(err) + 1;
|
||||
*ret = POVERLAY_WRITE_COMM_ERR;
|
||||
writeerr = POVERLAY_WRITE_COMM_ERR;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return *ret;
|
||||
return writeerr;
|
||||
}
|
||||
|
||||
static int read_response(int fd, char **out, size_t *out_size, int *ret) {
|
||||
rpc_message_t *msg;
|
||||
ssize_t bytes_read;
|
||||
static int read_response(int fd, char **out, size_t *out_size) {
|
||||
|
||||
msg = (rpc_message_t *)malloc(POVERLAY_BUFSIZE);
|
||||
rpc_message_t *msg = (rpc_message_t *)malloc(POVERLAY_BUFSIZE);
|
||||
if (msg == NULL) {
|
||||
const char *error_msg = "Memory allocation failed";
|
||||
*out = strdup(error_msg);
|
||||
*out_size = strlen(error_msg) + 1;
|
||||
*ret = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_read = read(fd, msg, POVERLAY_BUFSIZE);
|
||||
ssize_t bytes_read = read(fd, msg, POVERLAY_BUFSIZE);
|
||||
if (bytes_read <= 0) {
|
||||
const char *error_msg = (bytes_read == 0) ? "Connection closed" : "Read error";
|
||||
free(msg);
|
||||
*out = strdup(error_msg);
|
||||
*out_size = strlen(error_msg) + 1;
|
||||
*ret = -1;
|
||||
free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (char *)malloc(msg->length);
|
||||
memcpy(*out, msg->value, msg->length);
|
||||
*out_size = msg->length;
|
||||
*ret = msg->type;
|
||||
|
||||
free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpc_get_state(pCloud_FileState *state, char *path) {
|
||||
char *errm = NULL;
|
||||
size_t errm_size = 0;
|
||||
int rep = 0;
|
||||
char *errm;
|
||||
size_t errm_size;
|
||||
|
||||
if (!rpc_call(4, path /*IN*/, &rep, &errm, &errm_size)) {
|
||||
if ((rep = rpc_call(4, path, &errm, &errm_size) == 0)) {
|
||||
debug(D_NOTICE, "rpc_get_state responese rep[%d] path[%s]", rep, path);
|
||||
if (errm)
|
||||
if (errm) {
|
||||
debug(D_NOTICE, "The error is %s", errm);
|
||||
if (rep == 10)
|
||||
}
|
||||
if (rep == 10) {
|
||||
*state = FileStateInSync;
|
||||
else if (rep == 12)
|
||||
} else if (rep == 12) {
|
||||
*state = FileStateInProgress;
|
||||
else if (rep == 11)
|
||||
} else if (rep == 11) {
|
||||
*state = FileStateNoSync;
|
||||
else
|
||||
} else {
|
||||
*state = FileStateInvalid;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
debug(D_ERROR, "rpc_get_state ERROR rep[%d] path[%s]", rep, path);
|
||||
}
|
||||
if(errm) {
|
||||
free(errm);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// path contains the input argument(s).
|
||||
int rpc_call(int id, const char *path, int *ret, char **errm, size_t *errmsz) {
|
||||
int result;
|
||||
int sockfd;
|
||||
int rpc_call(int id, const char *path, char **errm, size_t *errmsz) {
|
||||
int result = 0;
|
||||
int sockfd = -1;
|
||||
|
||||
sockfd = -1;
|
||||
result = 0;
|
||||
*errm = NULL;
|
||||
*errmsz = 0;
|
||||
*ret = 0;
|
||||
|
||||
sockfd = socket_connect(PRPC_SOCK_PATH, errm, errmsz, ret);
|
||||
sockfd = socket_connect(PRPC_SOCK_PATH, errm, errmsz);
|
||||
if (sockfd >= 0) {
|
||||
if ((result = write_request(sockfd, id, path, errm, errmsz, ret)) == 0) {
|
||||
result = read_response(sockfd, errm, errmsz, ret);
|
||||
if ((result = write_request(sockfd, id, path, errm, errmsz)) == 0) {
|
||||
result = read_response(sockfd, errm, errmsz);
|
||||
}
|
||||
close(sockfd);
|
||||
} else {
|
||||
result = -1;
|
||||
}
|
||||
return *ret; // always 0 on success
|
||||
return result; // always 0 on success
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ typedef enum _pCloud_FileState {
|
|||
} pCloud_FileState;
|
||||
|
||||
int rpc_get_state(pCloud_FileState *, char *);
|
||||
int rpc_call(int id, const char *, int *, char **, size_t *);
|
||||
int rpc_call(int id, const char *path, char **errm, size_t *errmsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue