Home > Software design >  Error when trying to execute man command with execv function : "man: can't execute cat: No
Error when trying to execute man command with execv function : "man: can't execute cat: No

Time:01-05

I am writing code for simple shell in C, and for some unknown reason I am getting error when trying to execute man command, while commands like ls, cat or other works fine. I want to have function for searching path of command.

This is error:

man: can't execute cat: No such file or directory
man: command exited with status 255: (cd /usr/share/man && /usr/lib/man-db/zsoelim) | (cd /usr/share/man && /usr/lib/man-db/manconv -f UTF-8:ISO-8859-1 -t ISO-8859-1//IGNORE) | (cd /usr/share/man && tbl) | (cd /usr/share/man && nroff -mandoc -rLL=88n -rLT=88n -Tutf8)
#include<string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdio.h>

char *searchPath(char *cmd) {
    int poljelen = 2;
    char **stringovi = malloc(poljelen * sizeof(char*));
    char *path = getenv("PATH");

    int i = 0;
    while((stringovi[i] = strsep(&path, ":")) != NULL) {
        i  ;
        if (i >= poljelen) {
            poljelen = poljelen   i;
            stringovi = realloc(stringovi, poljelen * sizeof(char*));
            if (stringovi == NULL) {
                fprintf(stderr, "%s", "Alloc error\n");
                exit(0);
            }
        }
    }

    stringovi[i] = '\0';
    i = 0;
    while(*stringovi[i] != '\0') {
        int pathlen = strlen(stringovi[i]);
        int cmdlen = strlen(cmd);
        char path[pathlen   cmdlen   2];

        strcpy(path, stringovi[i]);
        strcat(path, "/");
        strcat(path, cmd);
        if (access(path, F_OK) == 0) {
            char *pathname = malloc(sizeof(char) * (pathlen   cmdlen   2));
            if (!pathname) {
                return NULL;
            }
            strcpy(pathname, path);
            pathname[strlen(pathname)] = '\0';
            return pathname;
        }
        else {
            i  ;
            continue;
        }
    }

    return NULL;
}

int main() {
    char *tokens[3];
    tokens[0] = "man"; //if you put here "ls"
    tokens[1] = "ls";  // and here "-al" its working
    tokens[2] = NULL;
    char *pathh = searchPath(tokens[0]);

    if (pathh == NULL) {
        fprintf(stderr, "Error: command not found\n");
        return 1;
    }

    char stringg[strlen(pathh)   1];
    strcpy(stringg, pathh);

    pid_t childP;
    int status = 0;
    childP = fork();
    if (childP == 0) {
        if (execv(stringg, tokens) == -1) {
            fprintf(stderr, "Error: execv failed: %s\n", strerror(errno));
            exit(1);
        }
    }
    else if (childP == -1) {
        fprintf(stderr, "Error: fork failed: %s\n", strerror(errno));
        return 1;
    }
    else {
        waitpid(childP, &status, WUNTRACED);
    }
}

CodePudding user response:

Your use of strsep() corrupts your PATH environment variable.

Per the Linux strsep() man page:

... this function finds the first token in the string *stringp, that is delimited by one of the bytes in the string delim. This token is terminated by overwriting the delimiter with a null byte ('\0') ...

By calling strsep() with the value returned from getenv("PATH") you corrupt your PATH environment variable, leaving it as only the first component of the original value.

You should make a copy of the value returned from getenv("PATH") and split that into tokens.

  • Related