diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rwxr-xr-x | res/check_ck | 1 | ||||
-rw-r--r-- | src/actionparser.c | 7 | ||||
-rw-r--r-- | src/actions.c | 24 | ||||
-rw-r--r-- | src/ck.c | 21 | ||||
-rw-r--r-- | src/ckutil.c | 68 | ||||
-rw-r--r-- | src/ckutil.h | 38 | ||||
-rw-r--r-- | src/confparser.c | 17 | ||||
-rw-r--r-- | src/confparser.h | 2 | ||||
-rw-r--r-- | src/dblayer.c | 30 | ||||
-rw-r--r-- | src/dblayer.h | 8 | ||||
-rw-r--r-- | src/engine.c | 62 | ||||
-rw-r--r-- | src/engine.h | 26 | ||||
-rw-r--r-- | tests/add | 81 |
14 files changed, 332 insertions, 56 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b0eeb7e..e38e8e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(ckLib_src ${SRC_DIR}/dblayer.c ${SRC_DIR}/dbhelper.c ${SRC_DIR}/ckutil.c + ${SRC_DIR}/engine.c ) set(ckLib_hdr ${SRC_DIR}/actionparser.h @@ -34,6 +35,7 @@ set(ckLib_hdr ${SRC_DIR}/dblayer.h ${SRC_DIR}/dbhelper.h ${SRC_DIR}/ckutil.h + ${SRC_DIR}/engine.h ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RES_DIR}/cmake) @@ -61,6 +63,7 @@ target_link_libraries (ck ${SQLITE3_LIBRARIES}) set(BIN_TESTS_DIR ${CMAKE_BINARY_DIR}/res/tests) set(PROJECT_TESTING_GROUNDS ${CMAKE_BINARY_DIR}/test_files) configure_file(${TESTS_DIR}/init ${BIN_TESTS_DIR}/init @ONLY) +configure_file(${TESTS_DIR}/add ${BIN_TESTS_DIR}/add @ONLY) # check_ck configure_file(${RES_DIR}/check_ck check_ck @ONLY) diff --git a/res/check_ck b/res/check_ck index 14ec5ba..fc80bd2 100755 --- a/res/check_ck +++ b/res/check_ck @@ -5,4 +5,5 @@ for i in $( ls $DIR ); do ERROR="TEST "$i" FAILED:" PASS="TEST "$i" PASSED" source $DIR/$i + wait $! done diff --git a/src/actionparser.c b/src/actionparser.c index 207a089..0dca98c 100644 --- a/src/actionparser.c +++ b/src/actionparser.c @@ -203,11 +203,10 @@ void get_config(UserOpt *opt) { return; } } - char * defaultConf = "/.ck"; + char * defaultConf = ".ck"; char * home = getenv("HOME"); - opt->confDir = malloc(strlen(defaultConf)+strlen(home)+1); - strcpy(opt->confDir, home); - strcat(opt->confDir, defaultConf); + opt->confDir = malloc(strlen(defaultConf) + 1 /* '/' */ + strlen(home)+1); + str_join_dirname_with_basename(opt->confDir, home, defaultConf); // rewind pos = pos - 1; diff --git a/src/actions.c b/src/actions.c index 77680eb..318c86b 100644 --- a/src/actions.c +++ b/src/actions.c @@ -11,11 +11,13 @@ #include "actions.h" #include "dblayer.h" #include "ckutil.h" +#include "engine.h" int run_INIT(UserOpt * opt, Conf *conf) { + UNUSED(conf); if (db_exists(opt)) { printf("Current configuration file location: %s\n", opt->confDir); - PRINT_ERR("ck is already initialized.\n"); + PRINT_ERR("ck is already initialized."); return 0; } if (init_create_config_file(opt)) { @@ -30,6 +32,7 @@ int run_INIT(UserOpt * opt, Conf *conf) { } AddOpt make_add_options(const int argc, char **argv) { + /* since we are here, the first two argumens must exist */ AddOpt addOpt = { .progName = argv[0], .confPath = NULL, @@ -38,7 +41,6 @@ AddOpt make_add_options(const int argc, char **argv) { .err = ADD_NO_ERR }; - /* the first two argumens have to exist since we are here */ if (!util_is_file_rw(argv[1])) { addOpt.err = ADD_ERR_WRONG_CONFIG; return addOpt; @@ -90,29 +92,34 @@ int run_ADD(UserOpt * opt, Conf *conf) { DB db = open_DB(opt); if (db.ptr == NULL) { if (db.error == SQL_ERR_NO_TABLES) { - PRINT_ERR("The database file is currupted. Run ck init anew.\n"); + PRINT_ERR("The database file is currupted. Run ck init anew."); } + return 0; } AddOpt addOpt = make_add_options(opt->argc, opt->argv); switch (addOpt.err) { case ADD_NO_ERR: break; case ADD_ERR_WRONG_CONFIG: - PRINT_ERR("The config file specified doesn't exist.\n"); + PRINT_ERR("The config file specified doesn't exist."); close_DB(&db); return 0; case ADD_ERR_WRONG_FLAGS: - PRINT_ERR("Flags are: -s for secret and -p for primary.\n"); + PRINT_ERR("Flags are: -s for secret and -p for primary."); close_DB(&db); return 0; } add_print_opts(&addOpt); - if (add_transaction_begin(&db, addOpt.progName, - addOpt.confPath, addOpt.secret, addOpt.prime) == 0) { + if (add_transaction_begin(&db, &addOpt) == 0) { return 0; } - // do the linking close_DB(&db); + engine_add_make_link(&addOpt, conf); + char err[STR_M]; + if (engine_err_message(err)) { + PRINT_ERR(err); + return 0; + } return 1; } @@ -133,6 +140,7 @@ int run_LIST(UserOpt * opt, Conf *conf) { if (db.error == SQL_ERR_NO_TABLES) { printf("no tables\n"); } + return 0; } for (int i = 0; i < opt->argc; i++) { printf("[%d]: %s\n", i, opt->argv[i]); @@ -32,30 +32,39 @@ #include "dblayer.h" #include "ckutil.h" +void free_res(UserOpt *opt, Conf *conf) { + if (opt) { + free_user_opt(opt); + } + if (conf) { + free_conf(conf); + } +} + int main(int argc, char *argv[]) { UserOpt opt; switch(parse_action(argc, argv, &opt)) { case APR_HELP: - free_user_opt(&opt); + free_res(&opt, NULL); print_parser_help(); return 0; case APR_ERR: print_parser_error(&opt); - free_user_opt(&opt); + free_res(&opt, NULL); return 1; case APR_OK: break; } - Conf conf; + Conf conf = {.VC_dir = NULL, .SCRT_dir = NULL}; if (opt.action != CKA_INIT) { if (!db_exists(&opt)) { printf("ck is not initialized in %s.\nRun ck init first.\n", opt.confDir); - free_user_opt(&opt); + free_res(&opt, NULL); return 1; } if (!config_file_parse(&conf, &opt)) { - free_user_opt(&opt); + free_res(&opt, &conf); return 1; } } @@ -71,6 +80,6 @@ int main(int argc, char *argv[]) { default: break; } - free_user_opt(&opt); + free_res(&opt, &conf); return 0; } diff --git a/src/ckutil.c b/src/ckutil.c index fc6d4b0..a77aa01 100644 --- a/src/ckutil.c +++ b/src/ckutil.c @@ -8,8 +8,11 @@ * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ -#include <dirent.h> #include <ctype.h> +#include <dirent.h> +#include <fcntl.h> +#include <libgen.h> +#include <sys/sendfile.h> #include <sys/stat.h> #include <unistd.h> @@ -25,13 +28,15 @@ int util_is_dir(const char *path) { return 1; } -int util_is_str_empty(const char *s) { +void util_replace_slash_with_uscore(char *s) { + int i = 0; while (*s != '\0') { - if (!isspace((unsigned char)*s)) - return 0; + if (*s == '/' && i != 0) { + *s = '_'; + } s++; + i++; } - return 1; } int util_file_exists(const char* path) { @@ -52,3 +57,56 @@ int util_is_file_rw(const char* path) { void util_mkdir(const char *name) { mkdir(name, 0755); } + +int util_move_file(const char *path, const char* dest) { + int srcFile = open(path, O_RDONLY); + int destFile = open(dest, O_WRONLY | O_CREAT); + struct stat st, newSt; + + fstat(srcFile, &st); + sendfile(destFile, srcFile, NULL, st.st_size); + close(srcFile); + + fchmod(destFile, st.st_mode); + + fstat(destFile, &newSt); + if (st.st_size == newSt.st_size) { + unlink(path); + close(destFile); + return 0; + } + close(destFile); + return -1; +} + +int util_symlink_file(const char *path, const char* dest) { + return symlink(path, dest); +} + +void str_make_new_config_name(char *ret, const char *path, + const char *progName) { + char *basec = strdup(path); + char *bname = basename(basec); + + strcpy(ret, progName); + strcat(ret, "_"); + strcat(ret, bname); + free(basec); +} + +void str_join_dirname_with_basename(char *ret, const char *dirname, + const char *basename) { + strcpy(ret, dirname); + strcat(ret, "/"); + strcat(ret, basename); +} + +int str_is_empty(const char *s) { + while (*s != '\0') { + if (!isspace((unsigned char)*s)) { + return 0; + } + s++; + } + return 1; +} diff --git a/src/ckutil.h b/src/ckutil.h index 4c873d6..9955440 100644 --- a/src/ckutil.h +++ b/src/ckutil.h @@ -24,7 +24,9 @@ #include <string.h> #define PRINT_ERR(ERROR) \ - printf("--[ Error ]--\n%s", ERROR); + printf("--[ Error ]--\n%s\n", ERROR); + +#define UNUSED(x) (void)(x) /********************/ /* global constants */ @@ -39,6 +41,23 @@ /* String length - Large */ #define STR_L 400 +/********************/ +/* string functions */ +/********************/ + +/* Create the config name to be used when storing a new config to + * the VC or SCRT dir */ +extern void str_make_new_config_name(char *ret, const char *path, + const char *progName); + +/* Joins the two strings into ret, with a '/' in between */ +extern void str_join_dirname_with_basename(char *ret, const char *path, + const char *progName); + +/* Returns 1 if str contains only whitespace, or nothing, + * else returns 0. */ +extern int str_is_empty(const char *s); + /*********************/ /* utility functions */ /*********************/ @@ -49,13 +68,20 @@ extern int util_is_dir(const char *path); /* Returns 1 if file(or dir) exists, else returns 0. */ extern int util_file_exists(const char *path); +/* Returns 1 if file(or dir) is readable and writable, + * else returns 0. */ extern int util_is_file_rw(const char *path); -extern int util_is_cli_flag(); -/* Returns 1 if str contains only whitespace, or nothing, - * else returns 0. */ -extern int util_is_str_empty(); -extern int util_remove_newlibe(); +extern void util_replace_slash_with_uscore(char *s); +/* Wrapper around mkdir with 0775 permissions */ extern void util_mkdir(const char *path); + +/* Moves file from path, to destination + * keeping the same permissions. + * Only deletes original on successful copy */ +extern int util_move_file(const char *path, const char* dest); + +/* Wrapper around symlink() */ +extern int util_symlink_file(const char *path, const char* dest); #endif // CKUTIL_H diff --git a/src/confparser.c b/src/confparser.c index 0f193e0..80120c8 100644 --- a/src/confparser.c +++ b/src/confparser.c @@ -43,7 +43,7 @@ int read_next_line(char *line, FILE *f) { } ConfVar match_variables(char *line, char matched[]) { - if (line[0] == '#' || util_is_str_empty(line)) { + if (line[0] == '#' || str_is_empty(line)) { return CV_NO_VAL_OR_COMMENT; } #define X(var, str, name) \ @@ -74,7 +74,7 @@ ConfigParserResult parse(Conf *conf, UserOpt *opt) { int flag = 1; char line[STR_L]; char matched[STR_L]; - while (read_next_line(line, confPtr)) { + while (read_next_line(line, confPtr) == 0) { if (strlen(line) > STR_L) { return CPR_WRONG_CONFIG; } @@ -84,7 +84,6 @@ ConfigParserResult parse(Conf *conf, UserOpt *opt) { conf->var = malloc(strlen(matched)+1); \ strcpy(conf->var, matched); \ if (!util_is_dir(matched)) { \ - free(conf->var); \ return CPR_WRONG_##var; \ } \ break; @@ -111,9 +110,10 @@ int config_file_parse(Conf *conf, UserOpt *opt) { switch (parse(conf, opt)) { #define X(var,str,name) \ case CPR_WRONG_##var: \ - printf("Config error:\n" \ + printf("--[ Config error ]--\n" \ "%s: %s\n" \ "defined in config does not exist\n", name, conf->var); \ + free(conf->var); \ return 0; \ break; CONFIG_VARIABLES_TABLE @@ -128,6 +128,15 @@ int config_file_parse(Conf *conf, UserOpt *opt) { } } +void free_conf(Conf *conf) { + if (conf->VC_dir) { + free(conf->VC_dir); + } + if (conf->SCRT_dir) { + free(conf->SCRT_dir); + } +} + int init_create_config_file(UserOpt *opt) { char tmp[200]; if (!util_file_exists(opt->argv[0])) { diff --git a/src/confparser.h b/src/confparser.h index 076cb0f..a07972b 100644 --- a/src/confparser.h +++ b/src/confparser.h @@ -54,5 +54,5 @@ struct ConfigValues { extern int config_file_parse(Conf *conf, UserOpt *opt); extern int init_create_config_file(UserOpt *opt); - +extern void free_conf(Conf *conf); #endif // CONFPARSER_H diff --git a/src/dblayer.c b/src/dblayer.c index bde712b..d9284df 100644 --- a/src/dblayer.c +++ b/src/dblayer.c @@ -157,7 +157,7 @@ int insert_to_program_table(DB *db, const char *name) { rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { - PRINT_ERR("while preparing insert to program sql.\n"); + PRINT_ERR("while preparing insert to program sql."); db->error = SQL_ERR_SQLITE; return -1; } @@ -169,7 +169,7 @@ int insert_to_program_table(DB *db, const char *name) { sqlite3_bind_int(stmt, 1, id); sqlite3_bind_text(stmt, 2, name, strlen(name), 0); if (sqlite3_step(stmt) != SQLITE_DONE) { - PRINT_ERR("while excecuting insert to program sql.\n"); + PRINT_ERR("while excecuting insert to program sql."); db->error = SQL_ERR_SQLITE; return -1; } @@ -185,7 +185,7 @@ int insert_to_config_table(DB *db, const char *path, const int secret, const int dbh_form_query_insert_config(sql); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { - PRINT_ERR("Error while preparing insert to config sql.\n"); + PRINT_ERR("Error while preparing insert to config sql."); db->error = SQL_ERR_SQLITE; return -1; } @@ -199,7 +199,7 @@ int insert_to_config_table(DB *db, const char *path, const int secret, const int sqlite3_bind_int(stmt, 3, secret); sqlite3_bind_int(stmt, 4, prime); if (sqlite3_step(stmt) != SQLITE_DONE) { - PRINT_ERR("Error while excecuting insert to config sql.\n"); + PRINT_ERR("Error while excecuting insert to config sql."); db->error = SQL_ERR_SQLITE; return-1; } @@ -216,14 +216,14 @@ int insert_to_rel_table(DB *db, const int pid, const int cid) { rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { db->error = SQL_ERR_SQLITE; - PRINT_ERR("while preparing insert to rel sql.\n"); + PRINT_ERR("while preparing insert to rel sql."); return -1; } sqlite3_bind_int(stmt, 1, pid); sqlite3_bind_int(stmt, 2, cid); if (sqlite3_step(stmt) != SQLITE_DONE) { db->error = SQL_ERR_SQLITE; - PRINT_ERR("while excecuting insert to rel sql.\n"); + PRINT_ERR("while excecuting insert to rel sql."); return-1; } sqlite3_finalize(stmt); @@ -239,7 +239,7 @@ int program_exists(DB *db, const char* name) { rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { - PRINT_ERR("Error while preparing program_exists sql.\n"); + PRINT_ERR("Error while preparing program_exists sql."); return -2; } sqlite3_bind_text(stmt, 1, name, strlen(name), 0); @@ -252,7 +252,7 @@ int program_exists(DB *db, const char* name) { return id; } -int config_exists(DB *db, const int pid, const char* path) { +int config_exists(DB *db, const char* path) { sqlite3_stmt *stmt; int rc; @@ -261,7 +261,7 @@ int config_exists(DB *db, const int pid, const char* path) { rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { - PRINT_ERR("while preparing config_exists sql.\n"); + PRINT_ERR("while preparing config_exists sql."); return -2; } sqlite3_bind_text(stmt, 1, path, strlen(path), 0); @@ -293,7 +293,7 @@ int program_has_primary_config(DB *db, const int pid) { rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { - PRINT_ERR("while preparing program_has_primary_exists sql.\n"); + PRINT_ERR("while preparing program_has_primary_exists sql."); return -2; } sqlite3_bind_int(stmt, 1, pid); @@ -309,7 +309,7 @@ int program_has_primary_config(DB *db, const int pid) { } int add_get_or_insert_config_to_db(DB *db, const int pid, const char *path, const int secret, const int prime) { - int cid = config_exists(db, pid, path); + int cid = config_exists(db, path); if (cid == -2) { db->error = SQL_ERR_SQLITE; return -1; @@ -340,17 +340,15 @@ int add_get_or_insert_program_to_db(DB *db, const char *name) { return pid; } -int add_transaction_begin(DB *db, const char *progName, - const char* confPath, const int secret, - const int prime) { +int add_transaction_begin(DB *db, const AddOpt * const opt) { __BEGIN_TRANSACTION__ - int pid = add_get_or_insert_program_to_db(db, progName); + int pid = add_get_or_insert_program_to_db(db, opt->progName); if (db->error == SQL_ERR_SQLITE) { PRINT_ERR("Could not insert program to db.\n"); close_DB(db); return 0; } - int cid = add_get_or_insert_config_to_db(db, pid, confPath, secret, prime); + int cid = add_get_or_insert_config_to_db(db, pid, opt->confPath, opt->secret, opt->prime); if (db->error == SQL_ERR_SQLITE) { PRINT_ERR("Could not insert config to db.\n"); close_DB(db); diff --git a/src/dblayer.h b/src/dblayer.h index 40b7dfb..e44ea72 100644 --- a/src/dblayer.h +++ b/src/dblayer.h @@ -17,7 +17,7 @@ #include <sqlite3.h> -#include "actionparser.h" +#include "actions.h" typedef enum SqlErrors SqlError; enum SqlErrors { @@ -55,9 +55,5 @@ extern DB init_make_DB(const UserOpt *opt); /* add */ /*******/ -extern int add_transaction_begin(DB *db, const char *progName, - const char* confPath, const int secret, - const int prime); -extern int add_insert_program_to_db(DB *db, const char * name); -extern int add_insert_config_to_db(DB *db, const int pid, const char *path, const int secret, const int prime); +extern int add_transaction_begin(DB *db, const AddOpt * const opt); #endif /* DBLAYER_H */ diff --git a/src/engine.c b/src/engine.c new file mode 100644 index 0000000..3505fd0 --- /dev/null +++ b/src/engine.c @@ -0,0 +1,62 @@ +/* engine.c - manages the linking and copying of configs ---------------*- C -*- + * + * This file is part of ck, the config keeper + * + * ----------------------------------------------------------------------------- + * + * Copyright (C) 2018 Anastasis Grammenos + * GPLv3 (see LICENCE for the full notice) + * + * ----------------------------------------------------------------------------- + * + * + * + * -------------------------------------------------------------------------- */ +#include "engine.h" + +char engine_err[STR_M] = ""; + +int engine_err_message(char *err) { + if (!str_is_empty(engine_err)) { + if (err) { + strcpy(err, engine_err); + } + return 1; + } + return 0; +} + +int copy_config(char *path); + + +void link_config(const AddOpt *opt, const char* newPath) { + printf("Linking %s -> %s\n", opt->confPath, newPath); + if (util_symlink_file(newPath, opt->confPath) != 0) { + strcpy(engine_err, "Could not link file."); + } +} + +void move_config(const AddOpt *opt, const Conf *conf, char *ret) { + char newName[STR_M]; + str_make_new_config_name(newName, opt->confPath, opt->progName); + char newPath[STR_L]; + str_join_dirname_with_basename(newPath, opt->secret ? conf->SCRT_dir : conf->VC_dir, newName); + printf("Moving %s -> %s\n", opt->confPath, newPath); + strcpy(ret, newPath); + if (util_move_file(opt->confPath, newPath) != 0) { + strcpy(engine_err, "Could not move file."); + } +} + +void engine_add_make_link(const AddOpt *opt, + const Conf *conf) { + char newPath[STR_L]; + move_config(opt, conf, newPath); + if (engine_err_message(NULL)) { + return; + } + link_config(opt, newPath); + if (engine_err_message(NULL)) { + return; + } +} diff --git a/src/engine.h b/src/engine.h new file mode 100644 index 0000000..f3a3b00 --- /dev/null +++ b/src/engine.h @@ -0,0 +1,26 @@ +/* engine.h - manages the linking and copying of configs ---------------*- C -*- + * + * This file is part of ck, the config keeper + * + * ----------------------------------------------------------------------------- + * + * Copyright (C) 2018 Anastasis Grammenos + * GPLv3 (see LICENCE for the full notice) + * + * ----------------------------------------------------------------------------- + * + * + * + * -------------------------------------------------------------------------- */ +#include "actions.h" +#include "ckutil.h" + +/* if engine_err is set return true + * along with a copy of the error message. + * Pass NULL if you don't care about the message */ +extern int engine_err_message(char *err); + +extern void engine_add_make_link(const AddOpt *opt, + const Conf *conf); + + diff --git a/tests/add b/tests/add new file mode 100644 index 0000000..e65cc77 --- /dev/null +++ b/tests/add @@ -0,0 +1,81 @@ +#!/bin/bash +BIN=@CMAKE_BINARY_DIR@ + +# initialize +TEST_LOCATION=@PROJECT_TESTING_GROUNDS@ +mkdir -p $TEST_LOCATION/vc +mkdir $TEST_LOCATION/sec + +exec $BIN/ck conf $BIN init $TEST_LOCATION/vc $TEST_LOCATION/sec & +wait $! + +# setup test configs +echo "Test 1" > $BIN/test1.conf +echo "Test 2" > $BIN/test2.conf +echo "Test 3" > $BIN/test3.conf + +# add configs to ck +exec $BIN/ck conf $BIN add prog1 $BIN/test1.conf -p & +wait $! + +# check db +if [ $(sqlite3 $BIN/ckdb "select name from program where name = 'prog1'" | wc -l) -ne 1 ]; then + echo -e $ERROR"prog1 is not in the db" + exit 1 +fi + +if [ $(sqlite3 $BIN/ckdb "select path from config where path = '"$BIN"/test1.conf'" | wc -l) -ne 1 ]; then + echo -e $ERROR"test1.conf is not in the db" + exit 1 +fi + +# check files +if [ ! -f $TEST_LOCATION/vc/prog1_test1.conf ]; then + echo -e $ERROR"test1.conf failed (add -p)" + exit 1 +fi + +# repeat +exec $BIN/ck conf $BIN add prog2 $BIN/test2.conf -s & +wait $! + +if [ ! -f $TEST_LOCATION/sec/prog2_test2.conf ]; then + echo -e $ERROR"test2.conf failed (add -s)" + exit 1 +fi + +if [ $(sqlite3 $BIN/ckdb "select name from program where name = 'prog2'" | wc -l) -ne 1 ]; then + echo -e $ERROR"prog2 is not in the db" + exit 1 +fi + +if [ $(sqlite3 $BIN/ckdb "select path from config where path = '"$BIN"/test2.conf'" | wc -l) -ne 1 ]; then + echo -e $ERROR"test2.conf is not in the db" + exit 1 +fi + +exec $BIN/ck conf $BIN add prog3 $BIN/test3.conf -p -s & +wait $! + +if [ ! -f $TEST_LOCATION/sec/prog3_test3.conf ]; then + echo -e $ERROR"test3.conf failed (add -p -s)" + exit 1 +fi + +if [ $(sqlite3 $BIN/ckdb "select name from program where name = 'prog3'" | wc -l) -ne 1 ]; then + echo -e $ERROR"prog3 is not in the db" + exit 1 +fi + +if [ $(sqlite3 $BIN/ckdb "select path from config where path = '"$BIN"/test3.conf'" | wc -l) -ne 1 ]; then + echo -e $ERROR"test3.conf is not in the db" + exit 1 +fi + +rm $BIN/ckrc +rm $BIN/ckdb +rm $BIN/test1.conf +rm $BIN/test2.conf +rm $BIN/test3.conf +rm -rf $TEST_LOCATION +echo -e $PASS |