~emersion/mrsh

c6fc68bd180cc9821699736a32ee9201661dad69 — Simon Ser 8 months ago ae41141
builtin/command: implement -p
M builtin/command.c => builtin/command.c +4 -7
@@ 11,7 11,8 @@
static const char command_usage[] = "usage: command [-v|-V|-p] "
	"command_name [argument...]\n";

static int verify_command(struct mrsh_state *state, const char *command_name) {
static int verify_command(struct mrsh_state *state, const char *command_name,
		bool default_path) {
	size_t len_command_name = strlen(command_name);

	const char *look_alias =


@@ 41,7 42,7 @@ static int verify_command(struct mrsh_state *state, const char *command_name) {
		}
	}

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


@@ 74,16 75,12 @@ int builtin_command(struct mrsh_state *state, int argc, char *argv[]) {
		}
	}

	if (default_path) {
		fprintf(stderr, "command: `-p` not yet implemented\n");
		return 1;
	}
	if (verify) {
		if (mrsh_optind != argc - 1) {
			fprintf(stderr, command_usage);
			return 1;
		}
		return verify_command(state, argv[mrsh_optind]);
		return verify_command(state, argv[mrsh_optind], default_path);
	}

	fprintf(stderr, "command: executing not yet implemented\n");

M builtin/dot.c => builtin/dot.c +1 -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);
	const char *path = expand_path(state, argv[1], false, false);
	if (!path) {
		fprintf(stderr, "%s: not found\n", argv[1]);
		if (!state->interactive) {

M builtin/hash.c => builtin/hash.c +1 -1
@@ 41,7 41,7 @@ int builtin_hash(struct mrsh_state *state, int argc, char *argv[]) {
			continue;
		}

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

M builtin/type.c => builtin/type.c +1 -1
@@ 35,7 35,7 @@ int builtin_type(struct mrsh_state *state, int argc, char *argv[]) {
			continue;
		}

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

M include/shell/path.h => include/shell/path.h +7 -3
@@ 4,9 4,13 @@
#include <mrsh/shell.h>
#include <stdbool.h>

/** Searches $PATH for the requested file and returns it if found. If exec is
/* Searches $PATH for the requested file and returns it if found. If exec is
 * true, it will require the file to be executable in order to be considered a
 * match. Fully qualified paths are returned as-is. */
const char *expand_path(struct mrsh_state *state, const char *file, bool exec);
 * match. If default_path is true, the system's default search path will be
 * 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,
	bool default_path);

#endif

M shell/path.c => shell/path.c +28 -9
@@ 8,19 8,38 @@
#include <unistd.h>
#include "shell/path.h"

const char *expand_path(struct mrsh_state *state, const char *file, bool exec) {
const char *expand_path(struct mrsh_state *state, const char *file, bool exec,
		bool default_path) {
	if (strchr(file, '/')) {
		return file;
	}
	static char path[PATH_MAX + 1];
	const char *_pathe = mrsh_env_get(state, "PATH", NULL);
	if (!_pathe) {
		return NULL;
	}
	char *pathe = strdup(_pathe);
	if (!pathe) {
		return NULL;

	char *pathe;
	if (!default_path) {
		const char *_pathe = mrsh_env_get(state, "PATH", NULL);
		if (!_pathe) {
			return NULL;
		}
		pathe = strdup(_pathe);
		if (!pathe) {
			return NULL;
		}
	} else {
		size_t pathe_size = confstr(_CS_PATH, NULL, 0);
		if (pathe_size == 0) {
			return NULL;
		}
		pathe = malloc(pathe_size);
		if (pathe == NULL) {
			return NULL;
		}
		if (confstr(_CS_PATH, pathe, pathe_size) != pathe_size) {
			free(pathe);
			return NULL;
		}
	}

	static char path[PATH_MAX + 1];
	char *basedir = strtok(pathe, ":");
	while (basedir) {
		int blen = strlen(basedir);

M shell/task/simple_command.c => shell/task/simple_command.c +1 -1
@@ 43,7 43,7 @@ static int run_process(struct 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);
	const char *path = expand_path(ctx->state, argv[0], true, false);
	if (!path) {
		fprintf(stderr, "%s: not found\n", argv[0]);
		return TASK_STATUS_ERROR;