diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-02-28 01:06:35 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-02-28 01:06:35 -0500 |
commit | 511deab4f22a6c25f33cce1e206b656d520ab7e6 (patch) | |
tree | 669591ef38f61f0dc842e96b86aa1533f274269f | |
parent | b6587f1d905e308cab713b1d5545e4667c80d6e4 (diff) | |
download | spmc-511deab4f22a6c25f33cce1e206b656d520ab7e6.tar.gz |
Improvements:
* Refactored a few function names
* Can read package metadata
* Can delete packages
* Can download! and install packages at the same time
* Can prompt the user before proceeding
-rw-r--r-- | include/conf.h | 3 | ||||
-rw-r--r-- | include/install.h | 12 | ||||
-rw-r--r-- | include/metadata.h | 8 | ||||
-rw-r--r-- | include/purge.h | 7 | ||||
-rw-r--r-- | include/spm.h | 1 | ||||
-rw-r--r-- | include/user_input.h | 1 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/config_global.c | 6 | ||||
-rw-r--r-- | src/install.c | 105 | ||||
-rw-r--r-- | src/internal_cmd.c | 34 | ||||
-rw-r--r-- | src/metadata.c | 40 | ||||
-rw-r--r-- | src/purge.c | 93 | ||||
-rw-r--r-- | src/spm.c | 37 | ||||
-rw-r--r-- | src/user_input.c | 29 |
14 files changed, 284 insertions, 93 deletions
diff --git a/include/conf.h b/include/conf.h index 99d550d..fa27b16 100644 --- a/include/conf.h +++ b/include/conf.h @@ -20,7 +20,10 @@ typedef struct { char *datadir; char *mandir; char *sysconfdir; + char *tmpdir; char *localstatedir; + char *dbdir; // $localstate/db + char *dbrecdir; // $localstate/db/records } SPM_Hierarchy; typedef struct { diff --git a/include/install.h b/include/install.h index 94a49df..1b1aa42 100644 --- a/include/install.h +++ b/include/install.h @@ -1,12 +1,10 @@ #ifndef SPM_INSTALL_H #define SPM_INSTALL_H -int metadata_remove(const char *_path); -void install_show_package(ManifestPackage *package); -int install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package); -int install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name); -int is_installed(SPM_Hierarchy *fs, char *package_name); -int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages); - +void spm_install_show_package(ManifestPackage *package); +int spm_install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package); +int spm_install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name); +int spm_check_installed(SPM_Hierarchy *fs, char *package_name); +int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages); #endif //SPM_INSTALL_H diff --git a/include/metadata.h b/include/metadata.h index bb864f6..d91c1f1 100644 --- a/include/metadata.h +++ b/include/metadata.h @@ -1,12 +1,16 @@ #ifndef SPM_METADATA_H #define SPM_METADATA_H +#include "conf.h" #define SPM_METADATA_VERIFY 0 << 1 #define SPM_METADATA_NO_VERIFY 1 << 1 typedef int (ReaderFn)(size_t line, char **); -char **metadata_filelist_read(const char *filename); -char **metadata_read(const char *filename, int no_verify); +char **spm_metadata_read(const char *filename, int no_verify); +int spm_metadata_remove(const char *_path); + +// TODO: Can this somehow get hooked into spm_metadata_read()? +ConfigItem **spm_descriptor_read(const char *filename); #endif //SPM_METADATA_H diff --git a/include/purge.h b/include/purge.h new file mode 100644 index 0000000..0debd4b --- /dev/null +++ b/include/purge.h @@ -0,0 +1,7 @@ +#ifndef SPM_REMOVE_H +#define SPM_REMOVE_H + +int spm_purge(SPM_Hierarchy *fs, const char *_package_name); +int spm_do_purge(SPM_Hierarchy *fs, StrList *packages); + +#endif //SPM_REMOVE_H diff --git a/include/spm.h b/include/spm.h index 690d1f9..a0fc16e 100644 --- a/include/spm.h +++ b/include/spm.h @@ -50,6 +50,7 @@ #include "mirrors.h" #include "user_input.h" #include "install.h" +#include "purge.h" #define SYSERROR stderr, "%s:%s:%d: %s\n", basename(__FILE__), __FUNCTION__, __LINE__, strerror(errno) diff --git a/include/user_input.h b/include/user_input.h index 4e051ed..61d56ee 100644 --- a/include/user_input.h +++ b/include/user_input.h @@ -2,6 +2,7 @@ #define SPM_USER_INPUT_H int spm_user_yesno(int answer, int empty_input_is_yes); +int spm_prompt_user(const char *msg, int empty_input_is_yes); void spm_user_yesno_test(); #endif //SPM_USER_INPUT_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 06065a8..bac2769 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable(spm shlib.c user_input.c metadata.c + purge.c ) target_link_libraries(spm crypto ssl curl) diff --git a/src/config_global.c b/src/config_global.c index fb97a61..ee42935 100644 --- a/src/config_global.c +++ b/src/config_global.c @@ -169,6 +169,9 @@ SPM_Hierarchy *spm_hierarchy_init(char *basepath) { fs->localstatedir = join((char *[]) {fs->rootdir, "var", NULL}, DIRSEPS); fs->sysconfdir = join((char *[]) {fs->rootdir, "etc", NULL}, DIRSEPS); fs->mandir = join((char *[]) {fs->datadir, "man", NULL}, DIRSEPS); + fs->tmpdir = join((char *[]) {fs->rootdir, "tmp", NULL}, DIRSEPS); + fs->dbdir = join((char *[]) {fs->localstatedir, "db", NULL}, DIRSEPS); + fs->dbrecdir = join((char *[]) {fs->dbdir, "records", NULL}, DIRSEPS); return fs; } @@ -186,6 +189,9 @@ void spm_hierarchy_free(SPM_Hierarchy *fs) { free(fs->localstatedir); free(fs->sysconfdir); free(fs->mandir); + free(fs->tmpdir); + free(fs->dbdir); + free(fs->dbrecdir); free(fs); } diff --git a/src/install.c b/src/install.c index 2655626..93d07b0 100644 --- a/src/install.c +++ b/src/install.c @@ -1,39 +1,10 @@ /** * @file install.c */ +#include <url.h> #include "spm.h" -extern const char *METADATA_FILES[]; - -/** - * SPM packages contain metadata files that are not useful post-install and would amount to a lot of clutter. - * This function removes these data files from a directory tree - * @param _path - * @return success=0, error=-1 - */ -int metadata_remove(const char *_path) { - if (exists(_path) != 0) { - perror(_path); - fprintf(SYSERROR); - return -1; - } - - for (int i = 0; METADATA_FILES[i] != NULL; i++) { - char path[PATH_MAX]; - sprintf(path, "%s%c%s", _path, DIRSEP, METADATA_FILES[i]); - if (exists(path) != 0) { - continue; - } - if (unlink(path) < 0) { - perror(path); - fprintf(SYSERROR); - return -1; - } - } - return 0; -} - -void install_show_package(ManifestPackage *package) { +void spm_install_show_package(ManifestPackage *package) { if (package == NULL) { fprintf(stderr, "ERROR: package was NULL\n"); return; @@ -48,7 +19,7 @@ void install_show_package(ManifestPackage *package) { * @param _package name of archive to install (not a path) * @return success=0, exists=1, error=-1 (general), -2 (unable to create `destroot`) */ -int install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) { +int spm_install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) { char *package = strdup(_package); if (!package) { @@ -71,6 +42,35 @@ int install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) { printf("Extracting archive: %s\n", package); } + if (strstr(package, "://") != NULL) { + if (exists(fs->tmpdir) != 0) { + mkdirs(fs->tmpdir, 0755); + } + long response = 0; + char *url = strdup(package); + char *tmp_package = join_ex(DIRSEPS, fs->tmpdir, basename(package), NULL); + size_t tmp_package_len = strlen(tmp_package); + + if (tmp_package_len > strlen(package)) { + char *tmp = realloc(package, (strlen(package) + 1) * sizeof(char)); + if (tmp == NULL) { + perror("cannot realloc package path"); + return -1; + } + package = tmp; + } + strcpy(package, tmp_package); + + if (exists(tmp_package) != 0) { + if ((response = fetch(url, package)) >= 400) { + fprintf(stderr, "HTTP(%ld): %s\n", response, http_response_str(response)); + return -1; + } + } + free(url); + free(tmp_package); + } + if (tar_extract_archive(package, tmpdir) != 0) { fprintf(stderr, "%s: %s\n", package, strerror(errno)); free(package); @@ -81,7 +81,7 @@ int install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) { return 0; } -int install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name) { +int spm_install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name) { RuntimeEnv *rt = runtime_copy(__environ); char *records_topdir = join((char *[]) {fs->localstatedir, "db", "records", NULL}, DIRSEPS); char *records_pkgdir = join((char *[]) {records_topdir, package_name, NULL}, DIRSEPS); @@ -122,14 +122,15 @@ int install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name) return 0; } -int is_installed(SPM_Hierarchy *fs, char *package_name) { +int spm_check_installed(SPM_Hierarchy *fs, char *package_name) { char *records_topdir = join((char *[]) {fs->localstatedir, "db", "records", NULL}, DIRSEPS); char *records_pkgdir = join((char *[]) {records_topdir, package_name, NULL}, DIRSEPS); + char *descriptor = join((char *[]) {records_pkgdir, SPM_META_DESCRIPTOR, NULL}, DIRSEPS); char *filelist = join((char *[]) {records_pkgdir, SPM_META_FILELIST, NULL}, DIRSEPS); char **data = NULL; - if (exists(records_pkgdir) != 0) { + if ((exists(records_pkgdir) || exists(descriptor) || exists(descriptor)) != 0) { free(records_topdir); free(records_pkgdir); free(descriptor); @@ -137,7 +138,7 @@ int is_installed(SPM_Hierarchy *fs, char *package_name) { return 0; // does not exist } - data = metadata_read(filelist, SPM_METADATA_VERIFY); + data = spm_metadata_read(filelist, SPM_METADATA_VERIFY); if (data == NULL) { free(records_topdir); free(records_pkgdir); @@ -147,7 +148,6 @@ int is_installed(SPM_Hierarchy *fs, char *package_name) { } for (size_t i = 0; data[i] != NULL; i++) { - printf("%zu: %s\n", i, data[i]); free(data[i]); } free(data); @@ -166,7 +166,7 @@ int is_installed(SPM_Hierarchy *fs, char *package_name) { * @param packages * @return 0=success, -1=failed to create storage, -2=denied by user */ -int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { +int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { size_t num_requirements = 0; ManifestPackage **requirements = NULL; char source[PATH_MAX]; @@ -202,24 +202,13 @@ int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { // Install packages printf("Requested package(s):\n"); for (size_t i = 0; requirements !=NULL && requirements[i] != NULL; i++) { - install_show_package(requirements[i]); + spm_install_show_package(requirements[i]); } if (SPM_GLOBAL.prompt_user) { - int user_choice; - int status_choice; - printf("\nProceed with installation? [Y/n] "); - while ((user_choice = getchar())) { - status_choice = spm_user_yesno(user_choice, 1); - if (status_choice == 0) { // No - exit(-2); - } else if (status_choice == 1) { // Yes - break; - } else { // Only triggers when spm_user_yesno's second argument is zero - puts("Please answer 'y' or 'n'..."); - } + if (spm_prompt_user("Proceed with installation?", 1) == 0) { + exit(-2); } - puts(""); } printf("Installing package(s):\n"); @@ -227,15 +216,15 @@ int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { for (size_t i = 0; requirements != NULL && requirements[i] != NULL; i++) { char *package_path = join((char *[]) {requirements[i]->origin, SPM_GLOBAL.repo_target, requirements[i]->archive, NULL}, DIRSEPS); - if (is_installed(fs, requirements[i]->name)) { + if (spm_check_installed(fs, requirements[i]->name)) { printf(" -> %s is already installed\n", requirements[i]->name); free(package_path); continue; } - install_show_package(requirements[i]); - install(fs, tmpdir, package_path); - install_package_record(fs, tmpdir, requirements[i]->name); + spm_install_show_package(requirements[i]); + spm_install(fs, tmpdir, package_path); + spm_install_package_record(fs, tmpdir, requirements[i]->name); num_installed++; free(package_path); } @@ -256,7 +245,7 @@ int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { if (SPM_GLOBAL.verbose) { printf("Removing metadata\n"); } - metadata_remove(source); + spm_metadata_remove(source); // Copy temporary directory to destination if (SPM_GLOBAL.verbose) { @@ -273,4 +262,4 @@ int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { } rmdirs(tmpdir); return 0; -}
\ No newline at end of file +} diff --git a/src/internal_cmd.c b/src/internal_cmd.c index 08bc158..47a0532 100644 --- a/src/internal_cmd.c +++ b/src/internal_cmd.c @@ -141,7 +141,7 @@ int mkmanifest_interface(int argc, char **argv) { * */ void mkruntime_interface_usage(void) { - printf("usage: mkruntime {root_dir}"); + printf("usage: mkruntime {root_dir}\n"); } /** @@ -162,20 +162,15 @@ int mkruntime_interface(int argc, char **argv) { } char *root = argv[1]; - char *spm_bindir = join((char *[]) {root, "bin", NULL}, DIRSEPS); - char *spm_includedir = join((char *[]) {root, "include", NULL}, DIRSEPS); - char *spm_libdir = join((char *[]) {root, "lib", NULL}, DIRSEPS); - char *spm_datadir = join((char *[]) {root, "share", NULL}, DIRSEPS); - char *spm_mandir = join((char *[]) {spm_datadir, "man", NULL}, DIRSEPS); - char *spm_localstatedir = join((char *[]) {root, "var", NULL}, DIRSEPS); - char *spm_pkgconfigdir = join((char *[]) {spm_libdir, "pkgconfig", NULL}, DIRSEPS); - - runtime_set(rt, "SPM_BIN", spm_bindir); - runtime_set(rt, "SPM_INCLUDE", spm_includedir); - runtime_set(rt, "SPM_LIB", spm_libdir); - runtime_set(rt, "SPM_DATA", spm_datadir); - runtime_set(rt, "SPM_MAN", spm_mandir); - runtime_set(rt, "SPM_LOCALSTATE", spm_localstatedir); + SPM_Hierarchy *fs = spm_hierarchy_init(root); + char *spm_pkgconfigdir = join((char *[]) {fs->libdir, "pkgconfig", NULL}, DIRSEPS); + + runtime_set(rt, "SPM_BIN", fs->bindir); + runtime_set(rt, "SPM_INCLUDE", fs->includedir); + runtime_set(rt, "SPM_LIB", fs->libdir); + runtime_set(rt, "SPM_DATA", fs->datadir); + runtime_set(rt, "SPM_MAN", fs->mandir); + runtime_set(rt, "SPM_LOCALSTATE", fs->localstatedir); runtime_set(rt, "SPM_PKGCONFIG", spm_pkgconfigdir); runtime_set(rt, "SPM_META_DEPENDS", SPM_META_DEPENDS); runtime_set(rt, "SPM_META_PREFIX_BIN", SPM_META_PREFIX_BIN); @@ -188,7 +183,7 @@ int mkruntime_interface(int argc, char **argv) { runtime_set(rt, "MANPATH", "$SPM_MAN:$MANPATH"); runtime_set(rt, "PKG_CONFIG_PATH", "$SPM_PKGCONFIG:$PKG_CONFIG_PATH"); - char *spm_ccpath = join((char *[]) {spm_bindir, "gcc"}, DIRSEPS); + char *spm_ccpath = join((char *[]) {fs->bindir, "gcc"}, DIRSEPS); if (exists(spm_ccpath) == 0) { runtime_set(rt, "CC", "$SPM_BIN/gcc"); } @@ -198,14 +193,9 @@ int mkruntime_interface(int argc, char **argv) { runtime_export(rt, NULL); runtime_free(rt); - free(spm_bindir); - free(spm_includedir); - free(spm_libdir); - free(spm_datadir); - free(spm_mandir); - free(spm_localstatedir); free(spm_pkgconfigdir); free(spm_ccpath); + spm_hierarchy_free(fs); return 0; } diff --git a/src/metadata.c b/src/metadata.c index d2bb078..e4dcfc6 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -1,5 +1,7 @@ #include "spm.h" +extern const char *METADATA_FILES[]; + static int verify_filelist(size_t lineno, char **a) { if (lineno == 0) { if (strncmp((*a), SPM_PACKAGE_HEADER_FILELIST, strlen(SPM_PACKAGE_HEADER_FILELIST)) != 0) { @@ -54,11 +56,11 @@ static int reader_metadata(size_t lineno, char **line) { /** * Detect the type of metadata based on file name and execute the appropriate function against each line * in the file. Verification can be disabled by passing a non-zero value as the second argument. - * @param _filename + * @param filename * @param no_verify SPM_METADATA_VERIFY or SPM_METADATA_NO_VERIFY * @return array of strings (line endings removed) */ -char **metadata_read(const char *_filename, int no_verify) { +char **spm_metadata_read(const char *_filename, int no_verify) { char *filename = strdup(_filename); char **data = NULL; char **result = NULL; @@ -126,3 +128,37 @@ char **metadata_read(const char *_filename, int no_verify) { return result; } + +/** + * SPM packages contain metadata files that are not useful post-install and would amount to a lot of clutter. + * This function removes these data files from a directory tree + * @param _path + * @return success=0, error=-1 + */ +int spm_metadata_remove(const char *_path) { + if (exists(_path) != 0) { + perror(_path); + fprintf(SYSERROR); + return -1; + } + + for (int i = 0; METADATA_FILES[i] != NULL; i++) { + char path[PATH_MAX]; + sprintf(path, "%s%c%s", _path, DIRSEP, METADATA_FILES[i]); + if (exists(path) != 0) { + continue; + } + if (unlink(path) < 0) { + perror(path); + fprintf(SYSERROR); + return -1; + } + } + return 0; +} + +ConfigItem **spm_descriptor_read(const char *filename) { + ConfigItem **result = config_read(filename); + return result; +} + diff --git a/src/purge.c b/src/purge.c new file mode 100644 index 0000000..997df51 --- /dev/null +++ b/src/purge.c @@ -0,0 +1,93 @@ +#include "spm.h" + +/** + * Remove a package + * @param fs `SPM_Hierarchy` + * @param _package_name + * @return + */ +int spm_purge(SPM_Hierarchy *fs, const char *_package_name) { + size_t files_count = 0; + char **_files_orig = NULL; + char *path = NULL; + char *package_name = strdup(_package_name); + char *package_topdir = join((char *[]) {fs->dbrecdir, package_name, NULL}, DIRSEPS); + char *descriptor = join((char *[]) {package_topdir, SPM_META_DESCRIPTOR, NULL}, DIRSEPS); + char *filelist = join((char *[]) {package_topdir, SPM_META_FILELIST, NULL}, DIRSEPS); + + if (spm_check_installed(fs, package_name) == 0) { + // package is not installed in this root + free(package_name); + free(package_topdir); + free(descriptor); + free(filelist); + return 1; + } + + ConfigItem **desc = spm_descriptor_read(descriptor); + char *name = config_get(desc, "name")->value; + char *version = config_get(desc, "version")->value; + char *revision = config_get(desc, "revision")->value; + + printf("Removing package: %s-%s-%s\n", name, version, revision); + _files_orig = spm_metadata_read(filelist, SPM_METADATA_VERIFY); + for (size_t i = 0; _files_orig[i] != NULL; i++) { + files_count++; + } + + for (size_t i = 0; _files_orig[i] != NULL; i++) { + path = calloc(PATH_MAX, sizeof(char)); + path = join((char *[]) {fs->rootdir, _files_orig[i], NULL}, DIRSEPS); + if (SPM_GLOBAL.verbose) { + printf(" -> %s\n", path); + } + if (exists(path) != 0) { + printf("%s does not exist\n", path); + } else { + remove(path); + } + free(path); + } + rmdirs(package_topdir); + + free(package_name); + free(package_topdir); + free(descriptor); + free(filelist); + config_free(desc); + return 0; +} + +/** + * Remove packages + * @param fs `SPM_Hierarchy` + * @param packages `StrList` + * @return + */ +int spm_do_purge(SPM_Hierarchy *fs, StrList *packages) { + int status_remove = 0; + + printf("Removing package(s):\n"); + for (size_t i = 0; i < strlist_count(packages); i++) { + char *package = strlist_item(packages, i); + if (spm_check_installed(fs, package) == 0) { + printf("%s is not installed\n", package); + return -1; + } + printf("-> %s\n", package); + } + + if (SPM_GLOBAL.prompt_user) { + if (spm_prompt_user("Proceed with removal?", 1) == 0) { + return -2; + } + } + + for (size_t i = 0; i < strlist_count(packages); i++) { + if ((status_remove = spm_purge(fs, strlist_item(packages, i))) != 0) { + printf("Failed"); + break; + } + } + return status_remove; +}
\ No newline at end of file @@ -5,6 +5,7 @@ #include <errno.h> #include "spm.h" +int RUNTIME_REMOVE = 0; int RUNTIME_INSTALL = 0; int RUNTIME_ROOTDIR = 0; int RUNTIME_LIST = 0; @@ -131,6 +132,22 @@ int main(int argc, char *argv[], char *arge[]) { strcpy(rootdir, arg_next); i++; } + else if (strcmp(arg, "-R") == 0 || strcmp(arg, "--remove") == 0) { + RUNTIME_REMOVE = 1; + for (int p = 0; i < argc; p++) { + i++; + if (startswith(argv[i], "-") == 0 || startswith(argv[i], "--") == 0) { + i--; + break; + } + if ((argc - i) == 0) { + fprintf(stderr, "-R|--remove requires at least one package\n"); + usage(program_name); + exit(1); + } + strlist_append(packages, argv[i]); + } + } else if (strcmp(arg, "-I") == 0 || strcmp(arg, "--install") == 0) { RUNTIME_INSTALL = 1; for (int p = 0; i < argc; p++) { @@ -165,10 +182,14 @@ int main(int argc, char *argv[], char *arge[]) { show_global_config(); } - if (RUNTIME_ROOTDIR && !RUNTIME_INSTALL) { + if (!RUNTIME_ROOTDIR && RUNTIME_INSTALL) { fprintf(stderr, "-r|--root requires -I|--install\n"); usage(program_name); exit(1); + } else if (!RUNTIME_ROOTDIR && RUNTIME_REMOVE) { + fprintf(stderr, "-r|--root requires -R|--remove\n"); + usage(program_name); + exit(1); } if (isempty(rootdir)) { @@ -190,9 +211,21 @@ int main(int argc, char *argv[], char *arge[]) { runtime_set(rt, "SPM_LOCALSTATE", rootfs->localstatedir); runtime_apply(rt); + if (RUNTIME_REMOVE) { + int status_remove = 0; + if ((status_remove = spm_do_purge(rootfs, packages)) == -1) { + exit(1); + } + else if (status_remove == -2) { + // user said no when asked to proceed + exit(2); + } + + } + if (RUNTIME_INSTALL) { int status_install = 0; - if ((status_install = do_install(rootfs, mf, packages)) == -1) { + if ((status_install = spm_do_install(rootfs, mf, packages)) == -1) { // failed to create temporary destination root exit(1); } diff --git a/src/user_input.c b/src/user_input.c index 061fb2e..3f358fa 100644 --- a/src/user_input.c +++ b/src/user_input.c @@ -25,6 +25,35 @@ int spm_user_yesno(int answer, int empty_input_is_yes) { return result; } +int spm_prompt_user(const char *msg, int empty_input_is_yes) { + int user_choice = 0; + int status_choice = 0; + char ch_yes = 'y'; + char ch_no = 'n'; + + if (empty_input_is_yes) { + ch_yes = 'Y'; + } else { + ch_no = 'N'; + } + + printf("\n%s [%c/%c] ", msg, ch_yes, ch_no); + while ((user_choice = getchar())) { + status_choice = spm_user_yesno(user_choice, 1); + if (status_choice == 0) { // No + break; + } else if (status_choice == 1) { // Yes + break; + } else { // Only triggers when spm_user_yesno's second argument is zero + puts("Please answer 'y' or 'n'..."); + } + } + puts(""); + + return status_choice; +} + + void spm_user_yesno_test() { int choice; int status; |