/* actions.c - ck actions ----------------------------------------------*- C -*-
*
* This file is part of ck, the config keeper
*
* -----------------------------------------------------------------------------
*
* Copyright (C) 2018 Anastasis Grammenos
* GPLv3 (see LICENCE for the full notice)
*
* -------------------------------------------------------------------------- */
#include "dblayer.h"
#include "cklist.h"
#include "ckerrlog.h"
ERRLOG(action);
int run_INIT(UserOpt * opt, Conf *conf) {
UNUSED(conf);
if (db_exists(opt)) {
ERR("ck is already initialized in %s", opt->confDir);
return -1;
}
if (init_create_config_file(opt)) {
sERR("Cound not create config file.");
return -1;
}
DB db;
if (open_DB(&db, opt)) {
return -1;
}
init_make_tables(&db);
sqlite3_close(db.ptr);
hLOG("Initialized empty ckdb.");
return 0;
}
int run_ADD(UserOpt * opt, Conf *conf) {
DB db;
if (open_DB(&db, opt)) {
return -1;
}
AddOpt addOpt = add_make_options(opt->args);
switch (addOpt.err) {
case ADD_NO_ERR:
break;
case ADD_ERR_WRONG_CONFIG:
ERR("The config file specified doesn't exist or is a link.");
goto error;
case ADD_ERR_WRONG_FLAGS:
ERR("Flags are: -s for secret and -p for primary.");
goto error;
}
add_print_opts(&addOpt);
/* Try adding the new config to the DB */
if (add_transaction_try(&db, &addOpt, conf->home_dir)) {
goto error;
}
if (add_make_link(&addOpt, conf)) {
error:
close_DB(&db);
sERR("Could not complete add transaction.");
return -1;
}
close_DB(&db);
hLOG("ckdb updated succesfully.");
return 0;
}
int run_DEL(UserOpt * opt, Conf *conf) {
UNUSED(conf);
DB db;
if (open_DB(&db, opt)) {
return -1;
}
int rc = -1;
/* Since we are here, args have to be 1 or 2 */
char *pName = list_get(opt->args);
if (!program_exists(&db, pName)) {
ERR("Program %s doesn't exist in the database.", pName);
goto error;
}
/* If there is no next argument */
if (!list_next(opt->args)) {
rc = del_transaction_try(&db, pName, NULL);
}
/* If there are more arguments */
else {
char *cName = list_get(opt->args);
rc = del_transaction_try(&db, pName, cName);
if (rc) {
HELP("Program %s doesn't have a config named %s", pName, cName);
print_suggested_configs(&db, pName);
}
}
error:
close_DB(&db);
if (!rc) {
hLOG("ckdb updated succesfully.");
} else {
sERR("Could not complete delete transaction.");
}
return rc;
}
int run_EDIT(UserOpt *opt, Conf *conf) {
DB db;
if (open_DB(&db, opt)) {
return -1;
}
list_rewind(opt->args);
char confPath[STR_L] = "";
char confName[STR_M] = "";
int secret = 0;
/* Since we are here, args have to be 1 or 2 */
char *pName = list_get(opt->args);
if (!program_exists(&db, pName)) {
ERR("Program %s doesn't exist in the database.", pName);
goto error;
}
/* If there is no next argument */
if (!list_next(opt->args)) {
/* If there is no primary config*/
if (edit_get_prime_config_from_program(&db, pName, confName, &secret) == -1) {
/* If the program has only one config */
if (get_config_number(&db, pName) == 1) {
if (edit_get_config(&db, pName, confName, NULL, &secret)) {
ERR("Coudln't find config file for %s", pName);
goto error;
}
}
/* If the program has many configs */
else {
HELP("Ambiguous config. Please type the config name after the program.");
print_suggested_configs(&db, pName);
goto error;
}
}
}
/* If there are more arguments */
else {
char *cName = list_get(opt->args);
if (edit_get_config(&db, pName, confName, cName, &secret)) {
ERR("Program %s doesn't have a config named %s", pName, cName);
print_suggested_configs(&db, pName);
goto error;
}
}
close_DB(&db);
str_join_dirname_with_basename(confPath, secret ? conf->scrt_dir : conf->vc_dir, confName);
char *editor = getenv("EDITOR");
char command[STR_L] = "";
if (str_is_empty(editor)) {
if (system("which nano > /dev/null 2>&1") != 0) {
ERR("Nano not found. Please set $EDITOR to your desired editor.");
return -1;
}
strcpy(command, "nano");
} else {
strcpy(command, editor);
}
strcat(command, " ");
strcat(command, confPath);
HELP("editing...\n%s", command);
system(command);
return 0;
error:
close_DB(&db);
return -1;
}
int run_LIST(UserOpt *opt, Conf *conf) {
DB db;
if (open_DB(&db, opt)) {
return -1;
}
cklist *the_list = list_make_new();
ListOpt listOpt = list_make_options(opt->args);
if (listOpt.err) {
ERR("Wrong list options.");
goto error;
}
char tmp[STR_L] = "";
switch(listOpt._lt) {
case LT_PATH:
list_get_paths(&db, the_list, listOpt.bName, listOpt.attr, conf->home_dir);
break;
case LT_PROGRAM:
list_get_programs(&db, the_list);
break;
case LT_TREE:
list_get_path_program_tree(&db, the_list, listOpt.bName, listOpt.attr, conf->home_dir);
list_print(the_list);
goto close;
case LT_CKCONF:
strcat(tmp, "ck configuration directory path: ");
strcat(tmp, opt->confDir);
list_add(the_list, tmp);
#define X(var, str, name) \
strcpy(tmp, ""); \
strcat(tmp, name); \
strcat(tmp, ": "); \
strcat(tmp, conf->var); \
list_add(the_list, tmp);
CONFIG_VARIABLES_TABLE;
#undef X
list_print(the_list);
goto close;
case LT_PROG_CONFS:
if (!program_exists(&db, listOpt.pName)) {
ERR("Program %s doesn't exist in the database.", listOpt.pName);
goto error;
}
get_program_paths(&db, the_list, listOpt.pName, listOpt.bName, listOpt.attr, conf->home_dir);
break;
}
switch(listOpt._lst) {
case LST_PLAIN:
list_print(the_list);
break;
case LST_LISP:
list_print_lisp(the_list);
break;
case LST_PYTHON:
list_print_python(the_list);
}
close:
close_DB(&db);
list_free(the_list);
return 0;
error:
close_DB(&db);
list_free(the_list);
return -1;
}
int run_SEARCH(UserOpt *opt, Conf *conf) {
if (system("which grep > /dev/null 2>&1") != 0) {
ERR("No grep avaliable. Please make sure you have grep installed.");
return -1;
}
DB db;
if (open_DB(&db, opt)) {
return -1;
}
cklist *paths = list_make_new();
list_get_paths(&db, paths, 0 /*basename*/, 0/*attributes*/, conf->home_dir);
close_DB(&db);
if (list_size(paths) && list_size(opt->args)) {
do {
FILE *cmd;
char result[STR_L] = "";
char command[STR_L] = "grep -H -n \"";
strcat(command, list_get(opt->args));
strcat(command, "\" ");
strcat(command, list_get(paths));
cmd = popen(command, "r");
if (cmd == NULL) {
list_free(paths);
return -1;
}
while (fgets(result, sizeof(result), cmd)) {
printf("%s", result);
}
pclose(cmd);
} while(list_next(paths));
}
list_free(paths);
return 0;
}
int run_HELP(UserOpt *opt, Conf *conf) {
UNUSED(conf);
char tmp[STR_M] = "";
if (strcmp(list_get(opt->args), "config") == 0) {
print_conf_help();
return 0;
}
if (strcmp(list_get(opt->args), "verbose") == 0) {
print_verbose_help();
return 0;
}
switch(parser_get_action(list_get(opt->args), NULL)) {
#define X(ACTION) \
case CKA_##ACTION: \
HELP("%s", get_possible_action_strings(tmp, CKA_##ACTION)); \
print_##ACTION##_help(); \
return 0;
CK_ACTIONS
#undef X
default:
ERR("Unknown action: %s", list_get(opt->args));
}
return -1;
}
int run_RESTORE(UserOpt *opt, Conf *conf) {
DB db;
if (open_DB(&db, opt)) {
return -1;
}
cklist *from = list_make_new();
cklist *to = list_make_new();
int err_flag = 0;
if (strcmp(list_get(opt->args), "-p") == 0) {
if (list_next(opt->args)) {
if (program_exists(&db, list_get(opt->args))) {
if (restore_configs_exists(&db, conf, list_get(opt->args), from, to)) {
hLOG("Restoring links for %s...", list_get(opt->args));
}
else {
err_flag = 1;
}
}
else {
ERR("Program %s does not exist", list_get(opt->args));
err_flag = 1;
}
}
else {
sERR("-p needs a program name");
err_flag = 1;
}
}
else if (strcmp(list_get(opt->args), "all") == 0) {
if (!list_next(opt->args)) {
if (restore_all_exist(&db, conf, from, to)) {
hLOG("Restoring all links...");
}
else {
err_flag = 1;
}
}
else {
sERR("Wrong argument");
err_flag = 1;
}
}
else {
sERR("Wrong argument");
err_flag = 1;
}
close_DB(&db);
int rc = -1;
if (!err_flag) {
rc = restore_make_links(from, to);
if (rc) {
sERR("Restore failed.");
}
}
list_free(from);
list_free(to);
return rc;
}
/**************/
/* PRINT HELP */
/**************/
void print_INIT_help() {
HELP("ck init VERSION_CONTROL_DIR SECRET_DIR");
}
void print_ADD_help() {
HELP("ck add PROGRAM_NAME CONFIG_PATH [-p] [-s]");
}
void print_DEL_help() {
HELP("ck delete PROGRAM_NAME [CONFIG_BASENAME]");
}
void print_EDIT_help() {
HELP("ck edit PROGRAM_NAME [CONFIG_BASENAME]");
}
void print_LIST_help() {
ckhelp("ck list tree [-a] [-b]");
ckhelp("ck list -p PROGRAM_NAME [-t list-type] [-a] [-b]");
ckhelp("ck list programs [-t list-type] [-a] [-b]");
ckhelp("ck list paths [-t list-type] [-a] [-b]");
ckhelp("ck list ckconf");
report_help();
}
void print_SEARCH_help() {
HELP("ck search SEARCH_TERM");
}
void print_HELP_help() {
HELP("ck help action");
}
void print_RESTORE_help() {
ckhelp("ck restore -p PROGRAM_NAME");
ckhelp("ck restore all");
report_help();
}
void print_conf_help(void) {
HELP("ck [-v|--verbose] [-c|--config DIR] action [...]");
}
void print_verbose_help(void) {
HELP("ck [-v|--verbose] [-c|--config DIR] action [...]");
}