customBashShell / src / shell-ast.c
shell-ast.c
Raw
/*
 * shell-ast
 * Manage the abstract syntax tree resulting from parsing
 * command lines from a simple shell grammar.
 *
 * Refactored by Godmar Back for CS 3214 Summer 2020
 * Virginia Tech.
 */
#include <stdio.h>
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>

#include "shell-ast.h"

/* Create new command structure.  Takes ownership of argv. */
struct ast_command * 
ast_command_create(char ** argv, bool dup_stderr_to_stdout)
{
    struct ast_command *cmd = malloc(sizeof *cmd);

    cmd->argv = argv;
    cmd->dup_stderr_to_stdout = dup_stderr_to_stdout;
    return cmd;
}

/* Create a new pipeline */
struct ast_pipeline * ast_pipeline_create(char *iored_input, 
                                          char *iored_output, 
                                          bool append_to_output)
{
    struct ast_pipeline *pipe = malloc(sizeof *pipe);

    list_init(&pipe->commands);
    pipe->iored_output = iored_output;
    pipe->iored_input = iored_input;
    pipe->append_to_output = append_to_output;
    pipe->bg_job = false;
    return pipe;
}

/* Add a new command to this pipeline */
void
ast_pipeline_add_command(struct ast_pipeline *pipe, struct ast_command *cmd)
{
    list_push_back(&pipe->commands, &cmd->elem);
}

/* Create an empty command line */
struct ast_command_line *
ast_command_line_create_empty(void)
{
    struct ast_command_line *cmdline = malloc(sizeof *cmdline);

    list_init(&cmdline->pipes);
    return cmdline;
}

/* Create a command line with a single pipeline */
struct ast_command_line *
ast_command_line_create(struct ast_pipeline *pipe)
{
    struct ast_command_line *cmdline = ast_command_line_create_empty();

    list_push_back(&cmdline->pipes, &pipe->elem);
    return cmdline;
}

/* Print ast_command structure to stdout */
void
ast_command_print(struct ast_command *cmd)
{
    char **p = cmd->argv;

    printf("  Command:");
    while (*p)
        printf(" %s", *p++);

    printf("\n");

    if (cmd->dup_stderr_to_stdout)
        printf("  stderr shall also be redirected\n");
}
  
/* Print ast_pipeline structure to stdout */
void
ast_pipeline_print(struct ast_pipeline *pipe)
{
    int i = 1;

    printf(" Pipeline consists of %ld commands\n", list_size(&pipe->commands));
    for (struct list_elem * e = list_begin(&pipe->commands); 
         e != list_end(&pipe->commands); 
         e = list_next(e)) {
        struct ast_command *cmd = list_entry(e, struct ast_command, elem);

        printf(" %d. ", i++);
        ast_command_print(cmd);
    }

    if (pipe->iored_output)
        printf("  the stdout of the last command %ss to %s\n", 
                pipe->append_to_output ? "append" : "write",
                pipe->iored_output);

    if (pipe->iored_input)
        printf("  stdin of the first command reads from %s\n", pipe->iored_input);

    if (pipe->bg_job)
        printf("  - is a background job\n");
    else
        printf("  - should be started as a regular foreground job\n");
}

/* Print ast_command_line structure to stdout */
void 
ast_command_line_print(struct ast_command_line *cmdline)
{
    printf("Command line\n");
    for (struct list_elem * e = list_begin (&cmdline->pipes); 
         e != list_end (&cmdline->pipes); 
         e = list_next (e)) {
        struct ast_pipeline *pipe = list_entry(e, struct ast_pipeline, elem);

        printf(" ------------- \n");
        ast_pipeline_print(pipe);
    }
    printf("==========================================\n");
}

/* Deallocation functions. */
void 
ast_command_line_free(struct ast_command_line *cmdline)
{
    for (struct list_elem * e = list_begin(&cmdline->pipes); e != list_end(&cmdline->pipes); ) {
        struct ast_pipeline *pipe = list_entry(e, struct ast_pipeline, elem);
        e = list_remove(e);
        ast_pipeline_free(pipe);
    }
    free(cmdline);
}

void 
ast_pipeline_free(struct ast_pipeline *pipe)
{
    for (struct list_elem * e = list_begin(&pipe->commands); e != list_end(&pipe->commands); ) {
        struct ast_command *cmd = list_entry(e, struct ast_command, elem);
        e = list_remove(e);
        ast_command_free(cmd);
    }
    if (pipe->iored_input)
        free(pipe->iored_input);

    if (pipe->iored_output)
        free(pipe->iored_output);

    free(pipe);
}

void 
ast_command_free(struct ast_command * cmd)
{
    char ** p = cmd->argv;
    while (*p) {
        free(*p++);
    }
    free(cmd->argv);
    free(cmd);
}