0

I am currently working on a simple shell program in C, but I am facing an issue with the return status of my code. The problem is that the shell should return 0 upon successful execution of a command, but it always returns 1, even when the command runs correctly.

I have provided the relevant parts of the code below:

  • main function The main function handles the overall flow of the shell program. It repeatedly prompts for user input, executes commands using exe_cmd, and frees allocated memory using the memory function. I'm unable to identify the specific reason for the return status issue here.
#include "shell.h"
/**
 * main - entry point
 *
 * Return: 0  if succ
 *
 */
int main(void)
{
    char *input;
    char **args;
    int stat;

    do
    {
        if (isatty(STDIN_FILENO))
            write(1, "ous&zoh$ ", 9); /*prompt*/
        input = read_line();
        if (input == NULL)
        {
            exit(EXIT_FAILURE);
        }
        args = break_line(input);
        if (args == NULL)
        {
            perror("Error");
            free(input);
            exit(EXIT_FAILURE);
        }
        stat = exe_cmd(args);
        memory(input, args);
    }
    while (stat != -1); /*Continue until -1 : run until user type exit*/

    return (0);
}
  • read_line function

This function reads input from the user. It works as expected and doesn't seem to contribute to the return status problem.

#include "shell.h"

/**
 * read_line - read input from user
 *
 * Return: buffer
 */
char *read_line()
{
    char *buffer = NULL;
    size_t len = 0;
    ssize_t char_read;

    char_read = getline(&buffer, &len, stdin);

    if (char_read == -1)
    {
        if (isatty(STDIN_FILENO))
            perror("error");
        if (buffer != NULL)
            free(buffer);
        return (NULL);
    }

    return (buffer);
}
  • exe_cmd function

This function executes a command passed as arguments. I have thoroughly reviewed this function, and it seems to execute the commands correctly. However, it might be the source of the problem with the return status.

#include "shell.h"

/**
 * exe_cmd - executes cmd
 *
 * @args: arg for cmd
 *
 * Return: 0 if scc or -1 if error
 */
int exe_cmd(char **args)
{
    pid_t pid;
    int stat;
    int exe;
    int exit_stat;

    if (args == NULL || args[0] == NULL)
        return (0);

    if (_strcmp(args[0], "exit") == 0)
        return (-1);
    pid = fork();
    if (pid == 0)
    {
        exe = execvp(args[0], args);

        if (exe == -1)
        {
            perror("error");
            exit(EXIT_FAILURE);
        }
    } else if (pid > 0)
    {
        wait(&stat);
        if (WIFEXITED(stat))
        {
            exit_stat = WEXITSTATUS(stat);
            return (exit_stat);
        }
        else
        {
            perror("error");
            return (-1);
        }
    }
    else
    {
        perror("eroor");
        return (-1);
    }
    return (0);
}
  • break_line function

This function takes a line of input and breaks it into an array of arguments. I suspect the issue may be related to this function as it dynamically allocates memory using _realloc, but I can't pinpoint the exact problem.

#include "shell.h"

/**
 * break_line - break a line into array
 *
 * @line: line that will user give
 *
 * Return: args
 */
char **break_line(char *line)
{
    char **args = NULL;
    char *token;
    size_t size = 0;
    size_t i;

    if (line == NULL)
        return (NULL);

    token = strtok(line, DEL);
    for (i = 0; token != NULL; i++)
    {
        if (i == size)
        {
            size = size + 10;
            args = _realloc(args, 8 * (size + 1), 8);
            if (args == NULL)
                return (NULL);
        }
        args[i] = token;
        token = strtok(NULL, DEL);
    }
    args[i] = NULL;
    return (args);
}
  • memory function

This function is used to free the memory allocated for the input line and arguments. The issue is not likely to be in this function, as its purpose is memory management.

#include "shell.h"

/**
 * memory - to free al memory allocated
 * @line : line to be free
 * @args: args to be free
 */


void memory(char *line, char **args)
{
    if (line != NULL)
        free(line);
    if (args != NULL)
        free(args);
}
  • _realloc function that i use in break line function

This function is used to reallocate memory blocks. It seems to be working correctly and has no direct relation to the return status issue.

#include <stdlib.h>
#include "shell.h"

/**
 * *_realloc - reallocates a memory block using malloc and free
 * @ptr: pointer to the memory previsouly allocated by malloc
 * @old_size: size of the allocated memory for ptr
 * @new_size: new size of the new memory block
 * Return: pointer to the newly allocated memory block
 */
void *_realloc(void *ptr, unsigned int old_size, unsigned int new_size)
{
    char *ptr1;
    char *old_ptr;
    unsigned int i;

    if (new_size == old_size)
        return (ptr);

    if (new_size == 0 && ptr)
    {
        free(ptr);
        return (NULL);
    }

    if (!ptr)
        return (malloc(new_size));

    ptr1 = malloc(new_size);
    if (!ptr1)
        return (NULL);

    old_ptr = ptr;

    if (new_size < old_size)
    {
        for (i = 0; i < new_size; i++)
            ptr1[i] = old_ptr[i];
    }

    if (new_size > old_size)
    {
        for (i = 0; i < old_size; i++)
            ptr1[i] = old_ptr[i];
    }

    free(ptr);
    return (ptr1);
}
  • header file
#ifndef SHELL_H
#define SHELL_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

#define DEL " \t\r\n\a"


char *read_line();
char **break_line(char *line);
int exe_cmd(char **args);
void memory(char *line, char **args);
void *_realloc(void *ptr, unsigned int old_size, unsigned int new_size);

/*string.h*/
int _strcmp(char *s1, char *s2);

#endif

I am reaching out for assistance to identify the root cause of the problem. I suspect it might be related to how the return status is being handled within the exe_cmd function or the dynamic memory allocation in the break_line function.

Any insights or suggestions to resolve the issue and improve the shell program would be greatly appreciated. Thank you in advance for your help!

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Do we really need all this code just to answer this specific problem? Please narrow it down to just the part specific to the incorrect return value. – Barmar Jul 26 '23 at 15:48
  • 1
    Try printing a different error message before each `exit(EXIT_FAILURE);`. Then you'll know where the problem is, and you can debug that. – Barmar Jul 26 '23 at 15:50
  • 2
    This would also be a good time to learn how to use a debugger. https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ – Barmar Jul 26 '23 at 15:51
  • Tangential note (nothing to do with the exit status of your shell): You have: `exe = execvp(args[0], args); if (exe == -1)` —— There is no point in testing or capturing the return value from `execvp()`. If the call succeeds, it does not return; if it returns, it failed. Simply report the error and exit. – Jonathan Leffler Jul 26 '23 at 16:53
  • Note that you should not, in general, create function, variable, tag or macro names that start with an underscore. Part of [C11 §7.1.3 Reserved identifiers](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) says: — _All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use._ — _All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces._ See also [What does double underscore (`__const`) mean in C?](https://stackoverflow.com/q/1449181) – Jonathan Leffler Jul 26 '23 at 16:54
  • In due course, when you have processes that can be run in the background, you'll need to capture the PID returned by `wait()` because the command that terminates might not be the the one you just ran but some prior process run in the background. It's not a bad idea to capture and test the result anyway. – Jonathan Leffler Jul 26 '23 at 16:57
  • Why are you providing your own `_realloc()` function when the standard library already provides a `realloc()` that does substantially the same thing, but can be expected to be better tuned, and which you can reasonably assume to be bug-free? – John Bollinger Jul 26 '23 at 17:09
  • `if (p != NULL) free(p);` is an antipattern. It is perfectly safe (and has no effect) to free a null pointer, so at minimum that is excessively verbose. But it also conveys the impression that non-null pointers must be safe to free, which is not inherently true. Instead, just `free(p)` unconditionally. – John Bollinger Jul 26 '23 at 17:16

0 Answers0