aboutsummaryrefslogblamecommitdiffstats
path: root/src/actions.c
blob: 3293e537c91a06301d42ab98365acf2a36fba246 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                


                                             





                                                                                
                    
                   
                     
 

               
                                         
               
                       

                                                         

                                     
                                          
              
   
        

                          
   
                        
                        
                                  
           


                                        


                          
   
                                              



                            
                                                                 
               
                           
                                                        
               
   
                          
                                           
                                                          
               
   
                                     

                  
                                                
              
   
                
                                    
           


                                        
               
        
                          

              
 

















                                                                      
                                          
     
   

                




                                                   
            

 
                                        

                          
              

   
                         

                            




















                                                                                  
                                            

                   
     





                                                                     
                                          
                 
     

                
                                                                                             

                                  
                           










                                                                        

                            

                                  
                  
           

                
            

 
                                        

                          
              
   
 
                                     
                                                 
 
                    
                               
               
   
                       

                       
                                                                               

                  
                                     
          
               
                                                                                           

                         


















                                                                      
                                                                                                 
          


                        
                         

                
                              

                  
                                
   
       
                
                      
           


                      
            

 
                                          


                                                                        
   

                          


              
                                  
                                                                              
                
                                                 

                

                                            
                                           
                             



                                       
                  








                                                  

 
                                        
               
                       









                                                    
                                                        
                                                                                   


                                                                         





                                                   
            
 

                                           

                          
              







                                                                               
                                                                 

















                                                              
                                       














                             
              
                  



                                      


                  
            
 


















































                                                             
/* 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, MIN, MAX)                                                       \
    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 [...]");
}