PAX
view release on metacpan or search on metacpan
lib/PAX/AppImage.pm view on Meta::CPAN
? { status => 'built' }
: { status => 'not_built', reason => 'C launcher compile failed' };
}
# _launcher_source($image)
# Renders the C source for the app-image launcher, including embedded asset
# extraction and Unix-socket request forwarding.
# Input: image metadata hash reference.
# Output: C source string.
sub _launcher_source {
my ($image) = @_;
my $socket = _c_string($image->{socket_path});
my $entrypoint = _c_string($image->{entrypoint});
my $perl5lib = _c_string(join ':', @{ $image->{lib_dirs} // [] });
my $asset_root = _c_string($image->{asset_root});
my $asset_table = _asset_table_c($image->{assets} // []);
return <<"C";
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
struct pax_asset {
const char *path;
const unsigned char *data;
unsigned long len;
};
$asset_table
static void ensure_parent_dirs(const char *path) {
char tmp[4096];
size_t len = strlen(path);
if (len >= sizeof(tmp)) return;
memcpy(tmp, path, len + 1);
for (char *p = tmp + 1; *p; p++) {
if (*p == '/') {
*p = 0;
mkdir(tmp, 0700);
*p = '/';
}
}
}
static void extract_embedded_assets(void) {
if (pax_asset_count == 0) return;
mkdir($asset_root, 0700);
for (unsigned long i = 0; i < pax_asset_count; i++) {
char path[4096];
snprintf(path, sizeof(path), "%s/%s", $asset_root, pax_assets[i].path);
ensure_parent_dirs(path);
FILE *out = fopen(path, "wb");
if (!out) continue;
fwrite(pax_assets[i].data, 1, pax_assets[i].len, out);
fclose(out);
}
setenv("PAX_EMBEDDED_ASSET_ROOT", $asset_root, 1);
}
static void json_string(FILE *out, const char *s) {
fputc('"', out);
for (; *s; s++) {
if (*s == '"' || *s == '\\\\') { fputc('\\\\', out); fputc(*s, out); }
else if (*s == '\\n') fputs("\\\\n", out);
else fputc(*s, out);
}
fputc('"', out);
}
static int fallback_exec(int argc, char **argv) {
extract_embedded_assets();
if (strlen($perl5lib) > 0) {
const char *old = getenv("PERL5LIB");
char merged[8192];
if (old && strlen(old) > 0) snprintf(merged, sizeof(merged), "%s:%s", $perl5lib, old);
else snprintf(merged, sizeof(merged), "%s", $perl5lib);
setenv("PERL5LIB", merged, 1);
}
char **next = calloc((size_t)argc + 2, sizeof(char *));
if (!next) return 111;
next[0] = "perl";
next[1] = $entrypoint;
for (int i = 1; i < argc; i++) next[i + 1] = argv[i];
execvp("perl", next);
perror("execvp perl");
return 111;
}
int main(int argc, char **argv) {
extract_embedded_assets();
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) return fallback_exec(argc, argv);
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, $socket, sizeof(addr.sun_path) - 1);
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) return fallback_exec(argc, argv);
FILE *stream = fdopen(fd, "r+");
if (!stream) return fallback_exec(argc, argv);
fputs("{\\"argv\\":[", stream);
for (int i = 1; i < argc; i++) {
if (i > 1) fputc(',', stream);
json_string(stream, argv[i]);
}
fputs("],\\"cwd\\":", stream);
char cwd[4096];
if (getcwd(cwd, sizeof(cwd))) json_string(stream, cwd); else json_string(stream, ".");
fputs("}\\n", stream);
fflush(stream);
char buf[8192];
while (fgets(buf, sizeof(buf), stream)) {
if (strncmp(buf, "__PAX_EXIT__:", 13) == 0) return atoi(buf + 13);
fputs(buf, stdout);
}
return 0;
( run in 0.785 second using v1.01-cache-2.11-cpan-71847e10f99 )