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) {
    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
            path = strtok(NULL, ":");
        } else {
            fprintf(stderr, "malloc failed!\n");
            return false;
    if (found)
        printf("%s\n", curr_path, found);
        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
$ type /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?

  • 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 'SO- stop being evil' Jun 11 '16 at 0:10

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:

       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 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
    echo less exists
    echo no less we need to use more

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");
| improve this answer | |

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.
| improve this answer | |

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