#include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef PATH_MAX #define PATH_MAX 4096 #endif #include "vis-single-payload.inc" #ifndef VIS_TMP_DIR #define VIS_TMP_DIR "/tmp" #endif #ifndef VIS_TMP #define VIS_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 lzma_stream strm = LZMA_STREAM_INIT; static int libtar_xzopen(const char *pathname, int flags, ...) { int ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED); if (ret != LZMA_OK) { fprintf(stderr, "lzma_stream_decoder error: %d\n", ret); return ret; } strm.next_in = vis_single_payload; strm.avail_in = sizeof(vis_single_payload); return ret; } static int libtar_xzclose(int fd) { lzma_end(&strm); return 0; } static ssize_t libtar_xzread(int fd, void *buf, size_t count) { strm.next_out = buf; strm.avail_out = count; int ret = lzma_code(&strm, LZMA_FINISH); if (ret != LZMA_OK && ret != LZMA_STREAM_END) { fprintf(stderr, "lzma_code error: %d\n", ret); return -1; } return count - strm.avail_out; } tartype_t xztype = { libtar_xzopen, libtar_xzclose, libtar_xzread, }; int extract(char *directory) { TAR *tar; if (tar_open(&tar, NULL, &xztype, O_RDONLY, 0, 0) == -1) { perror("tar_open"); return -1; } if (tar_extract_all(tar, directory) != 0) { perror("tar_extract_all"); return -1; } if (tar_close(tar) != 0) { perror("tar_close"); return -1; } return 0; } 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) { int rc = EXIT_FAILURE; char exe[256], path[PATH_MAX], tmp_dirname[PATH_MAX]; char *tmpdir = getenv("TMPDIR"); if (snprintf(tmp_dirname, sizeof(tmp_dirname), "%s/%s", tmpdir ? tmpdir : VIS_TMP_DIR, VIS_TMP) < 0) { perror("snprintf"); return rc; } if (!mkdtemp(tmp_dirname)) { perror("mkdtemp"); return rc; } 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 (extract(tmp_dirname) != 0) goto err; if (snprintf(exe, sizeof(exe), "%s/vis", tmp_dirname) < 0) goto err; 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; } signal(SIGINT, SIG_IGN); for (;;) { int status; int w = waitpid(child_pid, &status, 0); if (w == -1) { perror("waitpid"); break; } if (w == child_pid) { rc = WEXITSTATUS(status); break; } } err: nftw(tmp_dirname, unlink_cb, 64, FTW_DEPTH|FTW_PHYS|FTW_MOUNT); return rc; }