aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2017-05-31 14:09:34 +0200
committerMarc André Tanner <mat@brain-dump.org>2017-05-31 15:37:25 +0200
commitfae92a04cdfd5ebe8e07865446732b0287f4553a (patch)
tree8b505f958be45f0eff5ce5bec869402714ede975
parent2599e5c9be9fa8ef12ff92cff85f0c72be2b1aeb (diff)
downloadvis-fae92a04cdfd5ebe8e07865446732b0287f4553a.tar.gz
vis-fae92a04cdfd5ebe8e07865446732b0287f4553a.tar.xz
build: cleanup self contained executable
Set $PATH and $TERMINFO_DIRS environment variables, use chdir(2) to simplify extraction logic, improve error handling.
-rw-r--r--Dockerfile2
-rw-r--r--Makefile16
-rwxr-xr-xconfigure11
-rw-r--r--vis-single.c191
4 files changed, 120 insertions, 100 deletions
diff --git a/Dockerfile b/Dockerfile
index 105fd6b..72644e6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,7 +6,7 @@
# docker cp vis:/tmp/vis/vis .
# make vis-single
# docker cp vis:/tmp/vis/vis-single .
-FROM alpine:edge
+FROM alpine:3.6
ENV DIR /tmp/vis
WORKDIR $DIR
RUN apk update && apk add musl-dev fortify-headers gcc make libtermkey-dev ncurses-dev ncurses-static lua5.3-dev lua5.3-lpeg lua-lpeg-dev acl-dev libarchive-dev xz-dev xz bzip2-dev
diff --git a/Makefile b/Makefile
index b71238a..7950865 100644
--- a/Makefile
+++ b/Makefile
@@ -73,17 +73,17 @@ vis-digraph: vis-digraph.c
${CC} ${CFLAGS} ${CFLAGS_AUTO} ${CFLAGS_STD} ${CFLAGS_EXTRA} $< ${LDFLAGS} ${LDFLAGS_STD} ${LDFLAGS_AUTO} -o $@
vis-single-payload.inc: $(EXECUTABLES) lua/*
- echo '#ifndef VIS_SINGLE_PAYLOAD_H' > vis-single-payload.inc
- echo '#define VIS_SINGLE_PAYLOAD_H' >> vis-single-payload.inc
- echo 'unsigned char vis_single_payload[] = {' >> vis-single-payload.inc
- tar c $(EXECUTABLES) $$(find lua -name '*.lua') | xz | od -t x1 -A none -v | \
- sed 's/\([0-9a-f]\+\)/0x\1,/g;$$s/,$$/ };/' >> vis-single-payload.inc
- echo '#endif' >> vis-single-payload.inc
-
-vis-single: vis-single.c vis-single-payload.inc
for e in $(ELF); do \
${STRIP} "$$e"; \
done
+ echo '#ifndef VIS_SINGLE_PAYLOAD_H' > $@
+ echo '#define VIS_SINGLE_PAYLOAD_H' >> $@
+ echo 'static unsigned char vis_single_payload[] = {' >> $@
+ tar c $(EXECUTABLES) $$(find lua -name '*.lua') | xz | od -t x1 -A none -v | \
+ sed 's/\([0-9a-f]\+\)/0x\1,/g;$$s/,$$/ };/' >> $@
+ echo '#endif' >> $@
+
+vis-single: vis-single.c vis-single-payload.inc
${CC} ${CFLAGS} ${CFLAGS_AUTO} ${CFLAGS_STD} ${CFLAGS_EXTRA} $< ${LDFLAGS} ${LDFLAGS_STD} ${LDFLAGS_AUTO} -larchive -lacl -lbz2 -llzma -o $@
debug: clean
diff --git a/configure b/configure
index 56b204b..67f7dfd 100755
--- a/configure
+++ b/configure
@@ -137,7 +137,6 @@ case "$arg" in
--docdir=*) DOCDIR=${arg#*=} ;;
--mandir=*) MANDIR=${arg#*=} ;;
--environment-only) environmentonly=yes ;;
---static) static=yes ;;
--enable-help|--enable-help=yes) help=yes ;;
--disable-help|--enable-help=no) help=no ;;
--enable-curses|--enable-curses=yes) curses=yes ;;
@@ -245,15 +244,7 @@ tryflag CFLAGS -fPIE
tryflag CFLAGS_AUTO -fstack-protector-all
tryldflag LDFLAGS -Wl,-z,now
tryldflag LDFLAGS -Wl,-z,relro
-# in theory it should be perfectly fine to produce a staticically linked PIE
-# however in practice it is not yet properly supported by gcc:
-#
-# cc -fPIE -pie --static
-#
-# will always add a PT_INTERP referencing the dynamic loader/linker
-if test "$static" != "yes" || tryldflag LDFLAGS_AUTO -Wl,--no-dynamic-linker ; then
- tryldflag LDFLAGS_AUTO -pie
-fi
+tryldflag LDFLAGS_AUTO -pie
printf "creating config.mk... "
diff --git a/vis-single.c b/vis-single.c
index b6296c0..dc6fe9f 100644
--- a/vis-single.c
+++ b/vis-single.c
@@ -1,18 +1,30 @@
-#define _GNU_SOURCE
-
+#include <sys/wait.h>
#include <ftw.h>
+#include <limits.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sys/wait.h>
#include <unistd.h>
-#include <archive.h>
#include <archive_entry.h>
-#include <sys/acl.h>
+#include <archive.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
#include "vis-single-payload.inc"
-int copy_data(struct archive *ar, struct archive *aw) {
+#ifndef VIS_TMP
+#define VIS_TMP "/tmp/.vis-single-XXXXXX"
+#endif
+
+#ifndef VIS_TERMINFO
+#define VIS_TERMINFO "/etc/terminfo:/lib/terminfo:/usr/share/terminfo:" \
+ "/usr/lib/terminfo:/usr/local/share/terminfo:/usr/local/lib/terminfo"
+#endif
+
+static int copy_data(struct archive *ar, struct archive *aw) {
int r;
const void *buff;
size_t size;
@@ -36,116 +48,133 @@ int copy_data(struct archive *ar, struct archive *aw) {
return ARCHIVE_OK;
}
-int extract(const char *path) {
- struct archive *a;
+static int extract(void) {
+ struct archive *in = NULL, *out = NULL;
struct archive_entry *entry;
- struct archive *ext;
- char * abs_path = NULL;
- const char * term;
- char * termenv;
int r = ARCHIVE_FAILED;
- if ((a = archive_read_new()) == NULL)
+ if (!(in = archive_read_new()))
return ARCHIVE_FAILED;
- if ((r = archive_read_support_filter_xz(a)) != ARCHIVE_OK)
- goto out10;
+ if ((r = archive_read_support_filter_xz(in)) != ARCHIVE_OK)
+ goto err;
- if ((r = archive_read_support_format_tar(a)) != ARCHIVE_OK)
- goto out10;
+ if ((r = archive_read_support_format_tar(in)) != ARCHIVE_OK)
+ goto err;
- if ((ext = archive_write_disk_new()) == NULL) {
+ if (!(out = archive_write_disk_new())) {
r = ARCHIVE_FAILED;
- goto out10;
+ goto err;
}
- if ((r = archive_read_open_memory(a, vis_single_payload, sizeof(vis_single_payload))) != ARCHIVE_OK) {
- fprintf(stderr, "archive_read_open_memory() failed: %s\n", archive_error_string(a));
- goto out20;
+ if ((r = archive_read_open_memory(in, vis_single_payload, sizeof(vis_single_payload))) != ARCHIVE_OK) {
+ fprintf(stderr, "archive_read_open_memory() failed: %s\n", archive_error_string(in));
+ goto err;
}
- while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
- if (asprintf(&abs_path, "%s/%s", path, archive_entry_pathname(entry)) == -1)
- goto out20;
-
- archive_entry_set_pathname(entry, abs_path);
- free(abs_path);
-
- if ((r = archive_write_header(ext, entry)) != ARCHIVE_OK) {
- fprintf(stderr, "archive_write_header() failed: %s\n", archive_error_string(ext));
- goto out20;
+ while (archive_read_next_header(in, &entry) == ARCHIVE_OK) {
+ if ((r = archive_write_header(out, entry)) != ARCHIVE_OK) {
+ fprintf(stderr, "archive_write_header() failed: %s\n", archive_error_string(out));
+ goto err;
}
- if ((r = copy_data(a, ext)) != ARCHIVE_OK)
- goto out20;
+ if ((r = copy_data(in, out)) != ARCHIVE_OK)
+ goto err;
- if ((r = archive_write_finish_entry(ext)) != ARCHIVE_OK) {
- fprintf(stderr, "archive_write_finish_entry() failed: %s\n", archive_error_string(ext));
- goto out20;
+ if ((r = archive_write_finish_entry(out)) != ARCHIVE_OK) {
+ fprintf(stderr, "archive_write_finish_entry() failed: %s\n", archive_error_string(out));
+ goto err;
}
}
-out20:
- archive_write_close(ext);
- archive_write_free(ext);
+err:
+ if (out) {
+ archive_write_close(out);
+ archive_write_free(out);
+ }
-out10:
- archive_read_close(a);
- archive_read_free(a);
+ if (in) {
+ archive_read_close(in);
+ archive_read_free(in);
+ }
- return ARCHIVE_OK;
+ return r;
}
-int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
- return remove(fpath);
+static int unlink_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
+ return remove(path);
}
int main(int argc, char **argv) {
- char tmp_dirname_template[] = "/tmp/.vis-single-XXXXXX";
- const char *tmp_dirname;
- char *abs_path = NULL;
- const char *term;
- char *termenv = NULL;
- int child_pid, statval, rc = EXIT_FAILURE;
-
- if ((tmp_dirname = mkdtemp(tmp_dirname_template)) == NULL) {
- perror ("mkdtemp: Could not create tmp directory");
- goto out10;
+ char exe[256], cwd[PATH_MAX], path[PATH_MAX];
+ int rc = EXIT_FAILURE;
+
+ if (!getcwd(cwd, sizeof(cwd))) {
+ perror("getcwd");
+ return rc;
}
- if (extract(tmp_dirname) != ARCHIVE_OK)
- goto out20;
+ char tmp_dirname_template[] = VIS_TMP;
+ const char *tmp_dirname = mkdtemp(tmp_dirname_template);
- if (asprintf(&abs_path, "%s/vis", tmp_dirname) == -1)
- goto out20;
+ if (!tmp_dirname) {
+ perror("mkdtemp");
+ return rc;
+ }
- child_pid = fork();
- if (child_pid == -1) {
- fprintf(stderr, "could not fork!\n");
- goto out30;
- } else if (child_pid == 0) {
- if ((term = getenv("TERM")) == NULL) {
- puts("TERM is not defined!");
- goto out30;
- }
+ char *old_path = getenv("PATH");
+ if (snprintf(path, sizeof(path), "%s%s%s", tmp_dirname,
+ old_path ? ":" : "", old_path ? old_path : "") < 0) {
+ goto err;
+ }
+
+ if (setenv("PATH", path, 1) == -1 ||
+ setenv("TERMINFO_DIRS", VIS_TERMINFO, 0) == -1) {
+ perror("setenv");
+ goto err;
+ }
- if (asprintf(&termenv, "TERM=%s", term) == -1)
- goto out30;
- char *env[] = { termenv, NULL };
- execve(abs_path, argv, env);
+ if (chdir(tmp_dirname) == -1) {
+ perror("chdir");
+ goto err;
}
- waitpid(child_pid, &statval, WUNTRACED|WCONTINUED);
- rc = WEXITSTATUS(statval);
+ if (extract() != ARCHIVE_OK)
+ goto err;
+
+ if (chdir(cwd) == -1) {
+ perror("chdir");
+ goto err;
+ }
-out30:
- free(abs_path);
- free(termenv);
+ if (snprintf(exe, sizeof(exe), "%s/vis", tmp_dirname) < 0)
+ goto err;
-out20:
- nftw(tmp_dirname, unlink_cb, 64, FTW_DEPTH|FTW_PHYS);
+ int child_pid = fork();
+ if (child_pid == -1) {
+ perror("fork");
+ goto err;
+ } else if (child_pid == 0) {
+ execv(exe, argv);
+ perror("execv");
+ return EXIT_FAILURE;
+ }
+
+ for (;;) {
+ int status;
+ int w = waitpid(child_pid, &status, 0);
+ if (w == -1) {
+ perror("waitpid");
+ break;
+ }
+ if (w == child_pid) {
+ rc = WEXITSTATUS(status);
+ break;
+ }
+ }
-out10:
+err:
+ nftw(tmp_dirname, unlink_cb, 64, FTW_DEPTH|FTW_PHYS|FTW_MOUNT);
return rc;
}