Working with processes

Tasks

Task 1. Write and test under a debugger a simple shell (it should allow to run commands without arguments).

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

int main() {
    char *line = NULL;
    size_t len;
    ssize_t nread;
    int status = 0;
    while ((nread = getline(&line, &len, stdin)) != -1) {
        if (line[nread-1] == '\n')
            line[nread-1] = '\0';

        if (fork()) {
            // parent
            wait(&status);
        } else {
            //child
            execl(line, line, NULL);
            printf("command not found: %s\n", line);
            return 1;
        }
    }
    return 0;
}

Task 2. Extend the shell so that it prints a prompt, uses $PATH and can pass arguments to commands.

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

int main() {
    char *line = NULL;
    size_t len;
    ssize_t nread;
    int status = 0;
    while (1) {
        // prompt
        if (status != 0 && WIFEXITED(status))
            printf("(\033[31m%d\033[0m) ", WEXITSTATUS(status));
        printf("[%s]> ", get_current_dir_name());

        // read the line and strip newline
        nread = getline(&line, &len, stdin);
        if (nread == -1)
            break;
        if (line[nread-1] == '\n')
            line[nread-1] = '\0';

        // change spaces into zero bytes
        // and initialize argv
        char *argv[100] = { 0 };
        char *p = line;
        int i = 0;
        while (*p) {
            argv[i] = p;
            ++i;
            while (*p && *p != ' ')
                ++p;
            if (*p == ' ')
                *p = '\0';
            ++p;
        }
        if (fork()) {
            // parent
            wait(&status);
        } else {
            //child
            execvp(argv[0], argv);
            printf("command not found: %s\n", argv[0]);
            return 1;
        }
    }
    return 0;
}

Task 3. Extend the shell so that it can change the current directory.