2019-02-01 16:58:55 +01:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2021-05-31 18:33:47 +02:00
|
|
|
#ifdef HAVE_LIBALTERNATIVES_H
|
|
|
|
#include <libalternatives.h>
|
|
|
|
#endif
|
|
|
|
|
2019-02-01 16:58:55 +01:00
|
|
|
const unsigned min_version = 4;
|
2019-12-30 14:51:11 +01:00
|
|
|
const unsigned max_version = 42;
|
2019-02-01 16:58:55 +01:00
|
|
|
const char *default_version = "-default";
|
|
|
|
|
|
|
|
const char * const supported_execs[] = {
|
|
|
|
"node",
|
|
|
|
"npm",
|
|
|
|
"npx",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void __attribute__((noreturn)) printInvalidVersion(const char *version) {
|
|
|
|
fprintf(stderr, "Invalid node version: %s\n", version);
|
|
|
|
exit(-2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
if (argc < 1) {
|
|
|
|
fprintf(stderr, "Invalid parameters ... no basename?\n");
|
|
|
|
return 128;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify we are called with supported name */
|
|
|
|
const char *program_name = basename(argv[0]);
|
|
|
|
const char * const * bn = supported_execs;
|
|
|
|
|
|
|
|
for (; *bn!=NULL; bn++) {
|
|
|
|
if (strcmp(*bn, program_name) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*bn == NULL) {
|
|
|
|
fprintf(stderr, "Invalid program called: '%s'\n", program_name);
|
|
|
|
return 129;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify we have one of probably supported versions */
|
|
|
|
const char *version = getenv("NODE_VERSION");
|
|
|
|
char *endptr = 0;
|
|
|
|
if (version == NULL || strcmp(version, default_version) == 0)
|
|
|
|
version = default_version;
|
|
|
|
|
|
|
|
unsigned long node_ver = strtoul(version, &endptr, 10);
|
|
|
|
|
|
|
|
if (*endptr == '\0' &&
|
|
|
|
( node_ver < min_version || node_ver > max_version))
|
|
|
|
{
|
|
|
|
printInvalidVersion(version);
|
|
|
|
}
|
|
|
|
else if (*endptr != '\0' && version != default_version)
|
|
|
|
{
|
|
|
|
printInvalidVersion(version);
|
|
|
|
}
|
|
|
|
|
2021-05-31 18:33:47 +02:00
|
|
|
#ifdef HAVE_LIBALTERNATIVES_H
|
|
|
|
// if we want default version and not using update-alternatives
|
|
|
|
if (version == default_version)
|
|
|
|
{
|
2021-06-11 13:27:52 +02:00
|
|
|
// should not return, and if it does, it probably means
|
|
|
|
// we should fall back to using node-default fallback.
|
|
|
|
libalts_exec_default(argv);
|
2021-06-18 21:31:35 +02:00
|
|
|
// some programs parse stderr, so let's be quiet here.
|
|
|
|
//fputs("Falling back to using -default symlink.\n", stderr);
|
2021-05-31 18:33:47 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-02-01 16:58:55 +01:00
|
|
|
/* Generate our program path and check that we can execute it */
|
|
|
|
char *program_path, *program;
|
|
|
|
if (asprintf(&program, "%s%s", *bn, version) == -1 ||
|
|
|
|
asprintf(&program_path, "/usr/bin/%s", program) == -1) {
|
|
|
|
|
|
|
|
fputs("Memory allocation error... terminating\n", stderr);
|
|
|
|
return 130;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (access(program_path, X_OK) != 0) {
|
|
|
|
perror(program_path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
argv[0] = program;
|
|
|
|
|
|
|
|
execv(program_path, argv);
|
|
|
|
perror("execv failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|