~emersion/mrsh

869fba0814b0c9256de536714f8ccbcf0369b391 — Simon Ser 25 days ago 0da902c
Make expand_path return allocated memory

Gets rid of one PATH_MAX use.
M builtin/command.c => builtin/command.c +6 -3
@@ 47,9 47,10 @@ static int verify_command(struct mrsh_state *state, const char *command_name,
		}
	}

	const char *expanded = expand_path(state, command_name, true, default_path);
	char *expanded = expand_path(state, command_name, true, default_path);
	if (expanded != NULL) {
		printf("%s\n", expanded);
		free(expanded);
		return 0;
	}



@@ 62,8 63,8 @@ static int run_command(struct mrsh_state *state, int argc, char *argv[],
		return mrsh_run_builtin(state, argc - _mrsh_optind, &argv[_mrsh_optind]);
	}

	const char *path = expand_path(state, argv[0], true, default_path);
	if (!path) {
	char *path = expand_path(state, argv[0], true, default_path);
	if (path == NULL) {
		fprintf(stderr, "%s: not found\n", argv[0]);
		return 127;
	}


@@ 81,6 82,8 @@ static int run_command(struct mrsh_state *state, int argc, char *argv[],
		exit(126);
	}

	free(path);

	struct mrsh_process *proc = process_create(state, pid);
	return job_wait_process(proc);
}

M builtin/dot.c => builtin/dot.c +2 -1
@@ 19,7 19,7 @@ int builtin_dot(struct mrsh_state *state, int argc, char *argv[]) {
		return 1;
	}

	const char *path = expand_path(state, argv[1], false, false);
	char *path = expand_path(state, argv[1], false, false);
	if (!path) {
		fprintf(stderr, "%s: not found\n", argv[1]);
		if (!state->interactive) {


@@ 34,6 34,7 @@ int builtin_dot(struct mrsh_state *state, int argc, char *argv[]) {
			argv[1], strerror(errno));
		goto error;
	}
	free(path);

	struct mrsh_parser *parser = mrsh_parser_with_fd(fd);
	struct mrsh_program *program = mrsh_parse_program(parser);

M builtin/exec.c => builtin/exec.c +1 -1
@@ 17,7 17,7 @@ int builtin_exec(struct mrsh_state *state, int argc, char *argv[]) {
		return 0;
	}

	const char *path = expand_path(state, argv[_mrsh_optind], false, false);
	char *path = expand_path(state, argv[_mrsh_optind], false, false);
	if (path == NULL) {
		fprintf(stderr, "exec: %s: command not found\n", argv[_mrsh_optind]);
		return 127;

M builtin/hash.c => builtin/hash.c +3 -1
@@ 1,6 1,7 @@
#include <mrsh/builtin.h>
#include <shell/path.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "builtin.h"
#include "mrsh_getopt.h"


@@ 41,11 42,12 @@ int builtin_hash(struct mrsh_state *state, int argc, char *argv[]) {
			continue;
		}

		const char *path = expand_path(state, utility, true, false);
		char *path = expand_path(state, utility, true, false);
		if (path == NULL) {
			fprintf(stderr, "hash: command not found: %s\n", utility);
			return 1;
		}
		free(path);
	}

	return 0;

M builtin/type.c => builtin/type.c +3 -2
@@ 42,9 42,10 @@ int builtin_type(struct mrsh_state *state, int argc, char *argv[]) {
			continue;
		}

		const char *path = expand_path(state, name, true, false);
		if (path) {
		char *path = expand_path(state, name, true, false);
		if (path != NULL) {
			fprintf(stdout, "%s is %s\n", name, path);
			free(path);
			continue;
		}


M include/shell/path.h => include/shell/path.h +1 -1
@@ 10,7 10,7 @@
 * used instead of the $PATH variable. Fully qualified paths are returned
 * as-is.
 */
const char *expand_path(struct mrsh_state *state, const char *file, bool exec,
char *expand_path(struct mrsh_state *state, const char *file, bool exec,
	bool default_path);

#endif

M shell/path.c => shell/path.c +10 -8
@@ 8,10 8,10 @@
#include "shell/path.h"
#include "mrsh_limit.h"

const char *expand_path(struct mrsh_state *state, const char *file, bool exec,
char *expand_path(struct mrsh_state *state, const char *file, bool exec,
		bool default_path) {
	if (strchr(file, '/')) {
		return file;
		return strdup(file);
	}

	char *pathe;


@@ 39,19 39,20 @@ const char *expand_path(struct mrsh_state *state, const char *file, bool exec,
		}
	}

	static char path[PATH_MAX + 1];
	char *path = NULL;
	char *basedir = strtok(pathe, ":");
	while (basedir) {
		int blen = strlen(basedir);
	while (basedir != NULL) {
		size_t blen = strlen(basedir);
		if (blen == 0) {
			goto next;
		}
		bool slash = basedir[blen - 1] == '/';
		size_t n = snprintf(path, sizeof(path), "%s%s%s",
				basedir, slash ? "" : "/", file);
		if (n >= sizeof(path)) {
		size_t n = snprintf(NULL, 0, "%s%s%s", basedir, slash ? "" : "/", file);
		path = realloc(path, n + 1);
		if (path == NULL) {
			goto next;
		}
		snprintf(path, n + 1, "%s%s%s", basedir, slash ? "" : "/", file);
		if (access(path, exec ? X_OK : R_OK) != -1) {
			free(pathe);
			return path;


@@ 59,6 60,7 @@ const char *expand_path(struct mrsh_state *state, const char *file, bool exec,
next:
		basedir = strtok(NULL, ":");
	}
	free(path);
	free(pathe);
	return NULL;
}

M shell/task/simple_command.c => shell/task/simple_command.c +3 -1
@@ 46,7 46,7 @@ static int run_process(struct mrsh_context *ctx, struct mrsh_simple_command *sc,
	// The pipeline is responsible for creating the job
	assert(ctx->job != NULL);

	const char *path = expand_path(ctx->state, argv[0], true, false);
	char *path = expand_path(ctx->state, argv[0], true, false);
	if (!path) {
		fprintf(stderr, "%s: not found\n", argv[0]);
		return 127;


@@ 107,6 107,8 @@ static int run_process(struct mrsh_context *ctx, struct mrsh_simple_command *sc,
		exit(127);
	}

	free(path);

	struct mrsh_process *process = init_child(ctx, pid);
	return job_wait_process(process);
}