File node.c of Package nodejs-common

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#ifdef HAVE_LIBALTERNATIVES_H
#include <libalternatives.h>
#endif

const unsigned min_version = 4;
const unsigned max_version = 42;
const char *default_version = "-default";

const char * const supported_execs[] = {
	"node",
	"npm",
	"npx",
	"corepack",
	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);
	}

#ifdef HAVE_LIBALTERNATIVES_H
	// if we want default version and not using update-alternatives
	if (version == default_version)
	{
		// should not return, and if it does, it probably means
		// we should fall back to using node-default fallback.
		libalts_exec_default(argv);
		// some programs parse stderr, so let's be quiet here.
		//fputs("Falling back to using -default symlink.\n", stderr);
	}
#endif

	/* 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;
}

openSUSE Build Service is sponsored by