aboutsummaryrefslogtreecommitdiff
path: root/snag
diff options
context:
space:
mode:
Diffstat (limited to 'snag')
-rw-r--r--snag/main.c4
-rw-r--r--snag/pkg_db.c97
-rw-r--r--snag/pkg_db.h10
3 files changed, 82 insertions, 29 deletions
diff --git a/snag/main.c b/snag/main.c
index 9804f99..ff7ac64 100644
--- a/snag/main.c
+++ b/snag/main.c
@@ -18,12 +18,12 @@ void subcmd_install(char* pkgs[], size_t count) {
for (int i = 0; i < count; ++i) {
char* pkgid = pkgs[i];
- fprintf(stderr, "package: %s\n", pkgid);
// load package description
package_info_t info;
- if (load_package_info(&info, pkgid)) {
+ if (load_package_info(pkgid, &info)) {
printf("Installing %s - %s\n", info.attrs.name, info.attrs.desc);
+ run_package_install(&info);
}
}
}
diff --git a/snag/pkg_db.c b/snag/pkg_db.c
index ad9eff3..032c089 100644
--- a/snag/pkg_db.c
+++ b/snag/pkg_db.c
@@ -8,23 +8,26 @@
#include <errno.h>
#include <sys/wait.h>
-#define PKG_DB "../packages"
-#define PKG_DB_LEN (sizeof(PKG_DB) - 1)
#define PKG_INFO_CMD "./get_pkg_attrs.sh"
+#define PKG_INST_CMD "./run_pkg_install.sh"
-bool load_package_info(package_info_t* info, char* pkgid) {
+// note: fixed location of package database for now
+const char pkg_db[] = "../packages";
+const size_t pkg_db_len = sizeof(pkg_db) - 1;
+
+bool load_package_info(char* pkgid, package_info_t* info) {
memset(info, 0, sizeof(*info));
size_t pkgid_len = strlen(pkgid);
// construct package description directory path and ensure it exists
- // pkg_dir = "PKG_DB/pkgid"
- size_t pkg_dir_len = PKG_DB_LEN + pkgid_len + 1;
+ // pkg_dir = "pkg_db/pkgid"
+ size_t pkg_dir_len = pkg_db_len + pkgid_len + 1;
char* pkg_dir = emalloc(pkg_dir_len + 1, "pkg_dir");
{
- memcpy(pkg_dir, PKG_DB, PKG_DB_LEN);
- pkg_dir[PKG_DB_LEN] = '/';
- memcpy(pkg_dir + PKG_DB_LEN + 1, pkgid, pkgid_len);
+ memcpy(pkg_dir, pkg_db, pkg_db_len);
+ pkg_dir[pkg_db_len] = '/';
+ memcpy(pkg_dir + pkg_db_len + 1, pkgid, pkgid_len);
pkg_dir[pkg_dir_len] = '\0';
if (access(pkg_dir, F_OK) != 0) {
eprintf("Package '%s' not found\n", pkgid);
@@ -41,7 +44,8 @@ bool load_package_info(package_info_t* info, char* pkgid) {
memcpy(info->script_path, pkg_dir, pkg_dir_len);
info->script_path[pkg_dir_len] = '/';
memcpy(&info->script_path[pkg_dir_len + 1], pkgid, pkgid_len);
- memcpy(&info->script_path[script_path_len - 3], ".sh", 4);
+ memcpy(&info->script_path[script_path_len - 3], ".sh", 3);
+ info->script_path[script_path_len] = '\0';
free(pkg_dir);
if (access(info->script_path, F_OK) != 0) {
eprintf("Package '%s' broken, doesn't have description script\n", pkgid);
@@ -50,15 +54,15 @@ bool load_package_info(package_info_t* info, char* pkgid) {
}
}
- // PIPE and FORK to run get pkg attrs script
+ // PIPE and FORK to run pkg attrs script
int pipefds[2] = {0};
if (pipe(pipefds) < 0) error_out("failed to pipe: %s", strerror(errno));
pid_t pid = fork();
if (pid < 0) error_out("failed to fork: %s", strerror(errno));
- // child proc
if (pid == 0) {
- // write my stdout the the pipe
+ // child proc
+ // write my stdout to the pipe
close(pipefds[0]);
dup2(pipefds[1], STDOUT_FILENO);
close(pipefds[1]);
@@ -66,36 +70,85 @@ bool load_package_info(package_info_t* info, char* pkgid) {
char* argv[] = { PKG_INFO_CMD, info->script_path, NULL };
char* envp[] = { NULL };
execve(PKG_INFO_CMD, argv, envp);
+ // what are you still doing here?
error_out("execve failed");
- }
+ } else {
+ // parent proc, close write end of pipe
+ close(pipefds[1]);
+ }
// wait for child to finish
int wstatus;
if (waitpid(pid, &wstatus, 0) < 0) error_out("waitpid failed: %s", strerror(errno));
if (WEXITSTATUS(wstatus) != 0) error_out("failed to execute get pkg attr script");
- // read all bytes from pipe
- ssize_t bytes_read = read(pipefds[0], info->package_attrs, sizeof(info->package_attrs));
- if (bytes_read < 0) error_out("Failed to read from pipe");
+ // read all bytes from pipe into attr buffer
+ ssize_t bytes_read = read(pipefds[0], info->attrs.buffer, sizeof(info->attrs.buffer));
+ if (bytes_read < 0) error_out("failed to read from pipe: %s", strerror(errno));
+ close(pipefds[0]);
- // read attributes from pipe data
+ // read attributes from attr buffer
+ // attribute format: type (char), data value (null terminated str)
+ // todo(jqj): switch over to dynamically allocated buffer
for (int i = 0; i < bytes_read;) {
- char atype = info->package_attrs[i];
+ char atype = info->attrs.buffer[i];
i++;
switch (atype) {
case 'i':
- info->attrs.id = &info->package_attrs[i];
+ info->attrs.id = &info->attrs.buffer[i];
break;
case 'n':
- info->attrs.name = &info->package_attrs[i];
+ info->attrs.name = &info->attrs.buffer[i];
break;
case 'd':
- info->attrs.desc = &info->package_attrs[i];
+ info->attrs.desc = &info->attrs.buffer[i];
break;
}
- for(;info->package_attrs[i] && i < bytes_read; i++);
+ for(;info->attrs.buffer[i] && i < bytes_read; i++);
i++;
}
return true;
}
+
+void run_package_install(const package_info_t* info) {
+
+ // PIPE and FORK to run install script
+ int pipefds[2] = {0};
+ if (pipe(pipefds) < 0) error_out("failed to pipe: %s", strerror(errno));
+ pid_t pid = fork();
+ if (pid < 0) error_out("failed to fork: %s", strerror(errno));
+
+ if (pid == 0) {
+ // child proc
+ // write my stdout and stderr to the pipe
+ close(pipefds[0]);
+ dup2(pipefds[1], STDOUT_FILENO);
+ dup2(pipefds[1], STDERR_FILENO);
+ close(pipefds[1]);
+ // exec into install script
+ char* argv[] = { PKG_INST_CMD, info->script_path, NULL };
+ char* envp[] = { NULL };
+ execve(PKG_INST_CMD, argv, envp);
+ // what are you still doing here?
+ error_out("execve failed");
+ } else {
+ // parent proc, close write end of pipe
+ close(pipefds[1]);
+ }
+
+ // read from the pipe until EOF
+ char buf[4096];
+ ssize_t bytes_read = 0;
+ while ((bytes_read = read(pipefds[0], buf, sizeof(buf))) > 0) {
+ // print build out, can log and stuff in future
+ printf("%.*s", (int)bytes_read, buf);
+ }
+ if (bytes_read < 0) error_out("failed to read from pipe: %s", strerror(errno));
+ close(pipefds[0]);
+
+ // reap the child to finish
+ int wstatus;
+ if (waitpid(pid, &wstatus, 0) < 0) error_out("waitpid failed: %s", strerror(errno));
+ if (WEXITSTATUS(wstatus) != 0) error_out("failed to execute install script");
+}
diff --git a/snag/pkg_db.h b/snag/pkg_db.h
index 464380b..0a67043 100644
--- a/snag/pkg_db.h
+++ b/snag/pkg_db.h
@@ -4,21 +4,21 @@
#include <stdbool.h>
// loads and allocates package attributes for the info struct. does not do
-// excessive validation, so this should be fine when loading package data in
-// bulk.
-
+// excessive validation, so this should be fine when loading lots of package
+// data
typedef struct {
char* id;
char* name;
char* desc;
+ char buffer[4069];
} package_attrs_t;
typedef struct {
char* script_path;
- char package_attrs[4069];
package_attrs_t attrs;
} package_info_t;
-bool load_package_info(package_info_t* info, char* pkgid);
+bool load_package_info(char* pkgid, package_info_t* info);
+void run_package_install(const package_info_t* info);
#endif