-1

I'm writing a custom shell and I want to run a shell script with my own shell. I'm trying to check if the less program is installed and if it is, use the less program otherwise use more. However, my shell didn't have the type builtin so I had to create it in order to check if less is installed.

int do_type(int argc, const char **argv) {
    bool found = false;
    char *curr_path;
    char *path;
    char *path_strdup;
    char *path_value;
    char *pathValue;
    pid_t pid;
    pathValue = getenv("PATH");
    path_strdup = strdup(pathValue);
    if (path_strdup == NULL) {
        perror("strdup");
        exit(EXIT_FAILURE);
    }
    path_value = strtok(path_strdup, ":");
    path = path_value;
    while (path && !found) {
        if ((curr_path = malloc(strlen(path) + sizeof(argv[1]))) != NULL) {
            if (curr_path == NULL) {
                fprintf(stderr, "malloc failed!\n");

            }
            strcpy(curr_path, path);
            strcat(curr_path, argv[1]);
            if (file_exist(curr_path)) {
                found = true; // we found the program
            }
            //free(curr_path);
            path = strtok(NULL, ":");
        } else {
            fprintf(stderr, "malloc failed!\n");
            return false;
        }
    }
    if (found)
        printf("%s\n", curr_path, found);
    else
        printf("%s: not found\n", argv[1]);
    return 1;
}

The aboce code will find the less program if it is installed if I run the code in my shell:

$ type /blaha
/blaha: not found
$ type /less
/usr/bin/less
$ type /godoc
/usr/local/go/bin/godoc
$ 

Now I wonder how to perform the check. I've written this script that my shell should execute.

type less > /dev/null
printenv|grep $1|$PAGER

My shell also has the functionality of accepting a conditional if statement so if I can use an exit code 0 or 1 from do_type with my if statement then I can set the PAGER variable to less or more and the whole thing should work. But what should the exit code be for the type builtin? Is it 0 for found (success) and 1 for not found or the other way around? Is there anything else I should think of?

closed as unclear what you're asking by Gilles, Jeff Schaller, Anthon, garethTheRed, Michael Homer Jun 11 '16 at 9:22

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    Does this highly software-development-specific question just boil down to "What does the exit status of type signify?" If so you should cut out the verbiage. It is borderline off-topic as written. – Wildcard Jun 10 '16 at 1:45
  • 1
    I don't understand what the question is here. We don't do programming questions here. If you're looking for a review of your working code, try Code Review. If you have a specific coding problem (I don't see one here), ask on Stack Overflow. – Gilles Jun 11 '16 at 0:10
3

return value

I see that you're using EXIT_FAILURE in your code, therefore you're including stdlib.h. In that header file EXIT_FAILURE and EXIT_SUCCESS are defined as:

#define EXIT_FAILURE    1       /* Failing exit status.  */
#define EXIT_SUCCESS    0       /* Successful exit status.  */

Which is in accordance with typical behaviour of UNIX programs. man type is also useful here, since type is a POSIX command:

EXIT STATUS
       The following exit values shall be returned:

        0    Successful completion.

       >0    An error occurred.

Therefore yes, returning 1 for failure in type is the correct and expected bahaviour.

Moreover, using EXIT_FAILURE and EXIT_SUCCESS in every return instead of the rather confusing return 1 and return false would be better.


if

if evaluates the return value of the command passed to it in the following fashion: if the command returns 0 it considers it as true and executes the then block; if the command returns something that is not 0 the else block is executed (given that that block exists).

Therefore your type (returning 0 for success and 1 for failure) shall work as expected in:

if type less > /dev/null
then
    echo less exists
else
    echo no less we need to use more
fi

One more thing, in your code i'm worried about this part:

if ((curr_path = malloc(strlen(path) + sizeof(argv[1]))) != NULL) {
    if (curr_path == NULL) {
        fprintf(stderr, "malloc failed!\n");

    }

That second if has no chance of being true, ever. You can only get inside the outer block if curr_path != NULL and you're testing for curr_path == NULL. I believe that you want this instead:

if ((curr_path = malloc(strlen(path) + sizeof(argv[1]))) != NULL) {
    ...  /* the actual path matching */
}
else {
    fprintf(stderr, "malloc failed!\n");
}
1

From help type in a bash shell:

type: type [-afptP] name [name ...]
    Display information about command type.

    For each NAME, indicate how it would be interpreted if used as a
    command name.
    ...
    Exit Status:
    Returns success if all of the NAMEs are found; fails if any are not found.

Not the answer you're looking for? Browse other questions tagged or ask your own question.