Bad 'ls' Behavior in a Custom Simple Shell

I have a problem that seems to be slipping past my knowledge. I am writing a simple shell to learn about some of the programming systems for internships at Unisys. In my shell, it seems that all the commands I try work in addition to lsand even now detect the command wc. lsand it wcworks when I type it on my own, but if I give him the arguments, it will not work and will give me an error in saying No such file or directory.

here is my code:

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

#define BUF_SIZE 1024
#define DELIMS " -\r\t\n"

/****************************************************************
 *  Capture input from the user. Returns the input from the
 *  standard input file descriptor.
 ***************************************************************/
char * getInput (char **buffer, size_t buflen)
{
    size_t bufsize = BUF_SIZE;
    *buffer = malloc(sizeof(char) * bufsize + 1);   // allocate space for the buffer

    if (!*buffer)
    {
        fprintf(stderr, "Shell: buffer allocation error\n");
        exit(EXIT_FAILURE);
    }

    printf("$$ ");

    fflush(NULL);

    int bytesRead = getline(&(*buffer), &bufsize, stdin);
    if (bytesRead < 0)
    {
        printf("Getline error\n");
        exit(EXIT_FAILURE);
    }

    return *buffer; // Not capturing return value right now
 }

/****************************************************************
 *  Tokenize the buffer input from stdin
 ***************************************************************/
char ** splitLine(char *line)
{
    int bufsize = BUF_SIZE;
    int pos = 0;
    char **tokens = malloc (sizeof(char) * BUF_SIZE + 1);
    char *token;

    if (!tokens)
    {
        fprintf(stderr, "Shell: buffer allocation error\n");
        exit(EXIT_FAILURE);
    }

    /* Tokenize the line */
    token = strtok(line, DELIMS);
    while (token != NULL)
    {
        tokens[pos] = token;
        pos++;
        if (pos > bufsize)
        {
            bufsize += BUF_SIZE;
            tokens = realloc(tokens, bufsize * sizeof(char) + 1);
            if (!tokens)
            {
                fprintf(stderr, "Shell: buffer allocation error\n");
                exit(EXIT_FAILURE);
            }
        }
        token = strtok(NULL, DELIMS);   // continue grabbing tokens
    }

    tokens[pos] = NULL;
    return tokens;
}

/****************************************************************
 *  Main function
 ***************************************************************/
int main (int argc, char **argv)
{
    char *buf;     // buffer to hold user input from standard input stream.
    pid_t pid;          // Parent id of the current process
    int status;

    /* Loop while the user is getting input */
    while (getInput(&buf, sizeof(buf)))
    {
        char **args = splitLine(buf);
        int i = 0;

        /* Print tokens just to check if we are processing them correctly */
        while (1)
        {
            char *token = args[i++];
            if (token != NULL)
                printf("Token #%d: %s\n", i, token);
            else
                break;
        }

        fflush(NULL);

        /* Fork and execute command in the shell */
        pid = fork();
        switch(pid)
        {
            case -1:
            {
                /* Failed to fork */
                fprintf(stderr, "Shell cannot fork: %s\n", strerror(errno));
                continue;
            }
            case 0:
            {
                /* Child so run the command */
                execvp(args[0], args);        // Should not ever return otherwise there was an error
                fprintf(stderr, "Shell: couldn't execute %s: %s\n   ", buf, strerror(errno));
                exit(EX_DATAERR);
            }
        }

        /* Suspend execution of calling process until receiving a status message from the child process
            or a signal is received. On return of waitpid, status contains the termination
            information about the process that exited. The pid parameter specifies the set of child
            process for which to wait for */
        if ((pid = waitpid(pid, &status, 0) < 0))
        {
            fprintf(stderr, "Shell: waitpid error: %s\n", strerror(errno));
        }

        free(args);
    }

    free(buf);

    exit(EX_OK);
}

For example, I tried the following commands with output:

ls -la (ISSUE)

$$ ls -la
Token #1: ls
Token #2: la
ls: la: No such file or directory
$$ 

wc -l (ISSUE)

$$ wc -l
Token #1: wc
Token #2: l
wc: l: open: No such file or directory

Ls

$$ ls
Token #1: ls
Makefile    driver      driver.dSYM main.c      main.o
$$ 

ps -la

$$ ps -la
Token #1: ps
Token #2: la
  UID   PID  PPID CPU PRI NI      VSZ    RSS WCHAN  STAT   TT       TIME COMMAND
    0  2843  2405   0  31  0  2471528      8 -      Us   s000    0:00.08 login 
  501  2845  2843   0  31  0  2463080   1268 -      S    s000    0:01.08 -bash
  501  4549  2845   0  31  0  2454268    716 -      S+   s000    0:00.01 ./driv
    0  4570  4549   0  31  0  2435020    932 -      R+   s000    0:00.00 ps la
$$

, which the

$$ which which
Token #1: which
Token #2: which
/usr/bin/which

which -a which

$$ which -a which 
Token #1: which
Token #2: a
Token #3: which
/usr/bin/which

and even finally man getline

GETLINE(3)               BSD Library Functions Manual               GETLINE(3)

NAME
     getdelim, getline -- get a line from a stream

LIBRARY
     Standard C Library (libc, -lc)
.
.
.

- , ?

+4
1

"-" DELIMS.

.

, , , . const char* delims . , - , .

+3

Source: https://habr.com/ru/post/1617538/


All Articles