~emersion/mrsh-dev

Add command -v builtin. v1 PROPOSED

dragnel: 1
 Add command -v builtin.

 4 files changed, 117 insertions(+), 0 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/mrsh-dev/patches/5490/mbox | git am -3
Learn more about email & git

[PATCH] Add command -v builtin. Export this patch

---

This add only the -v behaviour for now. I'd like to contribute again so
let me know anything wrong, indent style, big C mistakes or whatever.

 builtin/builtin.c |   1 +
 builtin/command.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 include/builtin.h |   1 +
 meson.build       |   1 +
 4 files changed, 117 insertions(+)
 create mode 100644 builtin/command.c

diff --git a/builtin/builtin.c b/builtin/builtin.c
index 0f0c563..20ed598 100644
--- a/builtin/builtin.c
@@ -18,6 +18,7 @@ static const struct builtin builtins[] = {
	{ ":", builtin_colon, true },
	{ "alias", builtin_alias, false },
	{ "cd", builtin_cd, false },
	{ "command", builtin_command, false },
	{ "eval", builtin_eval, true },
	{ "exit", builtin_exit, true },
	{ "export", builtin_export, true },
diff --git a/builtin/command.c b/builtin/command.c
new file mode 100644
index 0000000..ee77516
--- /dev/null
@@ -0,0 +1,114 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <limits.h>
#include <mrsh/getopt.h>
#include <mrsh/shell.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "builtin.h"

static const char command_usage[] = "usage: command [-v|-V|-p] command_name [argument...]\n";

int builtin_command(struct mrsh_state *state, int argc, char *argv[]) {
    const char *look_alias = NULL;
    const char *look_fn = NULL;
    const char *path = NULL;
    const char *command_name;

    mrsh_optind = 0;
    int opt;
    int len_command_name = 0;
    int len_full_path = 0;
    struct stat check_file;

    while ((opt = mrsh_getopt(argc, argv, ":vVp")) != -1) {
        switch (opt) {
            case 'v':
                // first alias, then function, then PATH
                if(argc != 3) return 1;
                command_name = argv[mrsh_optind];
                len_command_name = strlen(command_name);

                look_alias = mrsh_hashtable_get(&state->aliases,command_name);
                if(look_alias != NULL){
                    printf("%s\n",command_name);
                    return 0;
                }

                look_fn = mrsh_hashtable_get(&state->functions,command_name);
                if(look_fn != NULL){
                    printf("%s\n",command_name);
                    return 0;
                }

                const char *default_path = "/bin:/usr/bin";  
                char *used_path;

                path = mrsh_env_get(state, "PATH", NULL);

                if(path == NULL) {
                    fprintf(stderr, "command: $PATH doesn't exists, searching in /bin:/usr/bin\n");
                    used_path = (char *)default_path;
                }
                else
                {
                    used_path = malloc(strlen(path));
                    strncpy(used_path,path,strlen(path)+1);
                }

                char *full_path = NULL;
                char *p = NULL;
                for (;;used_path = NULL) {
                    p = strtok(used_path,":");

                    if (p == NULL)
                        break;

                    len_full_path = strlen(p) + 1 + len_command_name + 1;
                    full_path = malloc(len_full_path);
                    if(full_path == NULL)
                    {
                        fprintf(stderr,"PANIC out of memory\n");
                        return 666;
                    }

                    strncpy(full_path,p,strlen(p)+1);
                    strncat(full_path,"/",1);
                    strncat(full_path,command_name,len_command_name);
                    full_path[len_full_path] = '\0'; 

                    if(lstat(full_path,&check_file) == 0)
                    {
                        if(check_file.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
                        {
                            printf("%s\n",full_path);
                            free(full_path);
                            return 0;
                        }
                    }

                    free(full_path);
                    full_path = NULL;
                }

                return 0x42;

            case 'V':
                fprintf(stderr, "command: `-p` and no arg not yet implemented\n");
                return 1;
            case 'p': // use getconf or not ?
                // not implemented
                break;
            default:
                fprintf(stderr, "command: unknown option -- %c\n", mrsh_optopt);
                fprintf(stderr, command_usage);
                return 1;
        }
    }

    return 0;
}

diff --git a/include/builtin.h b/include/builtin.h
index 8a848c8..491a739 100644
--- a/include/builtin.h
+++ b/include/builtin.h
@@ -10,6 +10,7 @@ void print_escaped(const char *value);

int builtin_alias(struct mrsh_state *state, int argc, char *argv[]);
int builtin_cd(struct mrsh_state *state, int argc, char *argv[]);
int builtin_command(struct mrsh_state *state, int argc, char *argv[]);
int builtin_colon(struct mrsh_state *state, int argc, char *argv[]);
int builtin_dot(struct mrsh_state *state, int argc, char *argv[]);
int builtin_eval(struct mrsh_state *state, int argc, char *argv[]);
diff --git a/meson.build b/meson.build
index 41494c4..84931fb 100644
--- a/meson.build
+++ b/meson.build
@@ -75,6 +75,7 @@ lib_mrsh = library(
		'builtin/alias.c',
		'builtin/builtin.c',
		'builtin/cd.c',
                'builtin/command.c',
		'builtin/colon.c',
		'builtin/dot.c',
		'builtin/eval.c',
-- 
2.20.1
View this thread in the archives