Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

with the provided segments of codes that need to be completed in command.h file:

ID: 3777323 • Letter: W

Question

with the provided segments of codes that need to be completed

in command.h file:

#define MAX_CHAR_LINE 1024
#define MAX_NO_ARGS 10
#define MAX_COMMANDS 10

struct command
{
char *comm;
char *args[MAX_NO_ARGS+2]; //the first item is the command itself and the last is NULL
int no_args; //actual number of arguments excluding the first item, command name, and the last item, NULL.
int order; //the order of the command 0, 1, ...
};

in exec_commands.c file:

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

#include "command.h"


/*
* This function should execute all of the commands in mycommands[],
* properly setting up the pipes between them.
* This means, for example, that the output of mycommands[0] will be
* the input of mycommands[1], and the output of mycommands[1] will
* be the input of mycommands[2], etc.
*
* This function should create the required pipes and then use
* execute_command to create the individual processes.
*/
void execute_commands(struct command mycommands[], int no_commands)
{
   return;
}

/*
* This function calls fork and executes a single command. It uses dup2 as
* appropriate to redirect stdin and stdout to fd_in and fd_out.
*
* Arguments:
*   command: The command to be executed
*   args: An array of strings containing the arguments to the command
*   argc: The number of arguments stored in args
*   fd_in: The filedescriptor that should be used as stdin for
*   the command
*   fd_out: The filedescriptor that should be used as stdout for
*   the command
*/
int execute_command(char *command, int argc, char *args[], int fd_in, int fd_out )
{
   return 0;
}

in exec_commands.h file:

void execute_commands(struct command mycommands[], int no_commands);
int execute_command(char *command, int argc, char *args[], int fd_in, int fd_out );

in get_commands.c file:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "command.h"

/*
* This is a trim function for strings. You pass it a string,
* and it removes any starting and trailing whitespace.
* It returns a pointer to the trimmed string.
*/
char *mytrim(char *s)
{
if (s == NULL)
   return s;
while (isspace((unsigned char) *s))
   s++;

if (*s) {
   char *p = s;
   while (*p)
   p++;
   while (isspace((unsigned char) *(--p)));
   p[1] = '';
}

return s;
}

/*
* Parse the commands found in line and store them in the
* array of struct command data structures mycommands
*/
int get_commands(char *line, struct command mycommands[])
{
int i = 0;
int j = 0;
int k = 0;


/*
* Step 1: Parse the line based on the | character and split up each
* separate command into its own entry in the mycommands array.
* Note that this stores the entire command, with its arguments, in
* the comm entry of the struct command. This is wrong, because the
* arguments should be stored in their own array. We'll fix it later.
*/
while (1) {
   char *tmp;
   if (i == 0) {
   tmp = mytrim(strtok(line, "|"));
   } else {
   tmp = mytrim(strtok(NULL, "|"));
   }

   if (tmp == NULL)
   break;

   mycommands[i].comm = tmp;
   mycommands[i].order = i;
   i++;
}

/*
* Step 2: Go through each of the commands and parse their
* arguments. This splits the commands by space and/or tab
* in order to get the arguments.
*/
for (j = 0; j < i; j++) {
   k = 0;
   while (1) {
   char *tmp;
   if (k == 0) {
       tmp = mytrim(strtok(mycommands[j].comm, " "));
   } else {
       tmp = mytrim(strtok(NULL, " "));
   }

   mycommands[j].args[k] = tmp;

   if (tmp == NULL) {
       break;
   }

   k++;
   }
   mycommands[j].comm = mycommands[j].args[0];
   mycommands[j].no_args = k - 1;
}

return i;
}

in get_commands.h file:

int get_commands(char* line, struct command mycommands[]);
char *mytrim(char *s);

in shell.c file:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "command.h"
#include "get_commands.h"
#include "exec_commands.h"

int main()
{
char *prompt = "cmps405> ";
char line[MAX_CHAR_LINE];
struct command mycommands[MAX_COMMANDS];
int no_co = 0;

while (1) {
   // Print the prompt and get a line of input from the user
   printf("%s", prompt);
   fgets(line, MAX_CHAR_LINE, stdin);

   // Check if the user typed "exit"
   if (strcmp(mytrim(line), "exit") == 0) {
   break;
   }

   // Check if the user entered a blank line
   if (strcmp(mytrim(line), "") == 0) {
   continue;
   }

   // Parse the commands
   no_co = get_commands(line, mycommands);

   // Execute the commands
   execute_commands(mycommands, no_co);
}
return 0;
}

Description This homework is the second phase in developing a basic shell (Command Line Interpreter). In the previous homework you coded the first phase, parsing commands In the second phase, you are required to code the execution of the parsed commands. You are given a skeleton code, including a working code of phase 1, and required to build on it to achieve this task. The user entry is still a number of commands with their arguments, if an separated by pipes if any. The output should be the result of the executed commands Functionality In the skeleton of the given code, you need to code the function to execute the commands execute commands and replace the call to the print commands function with the call to this function. The function prototype is void execute commands (struct command mycommands 1, int no commands This function Creates pipes if needed Determines the input and output file descriptors of a command based on the command's order X> Calls a function execute command to execute a command at a time. This function has the prototype statement int fd in, int fd out int execute command (char *command, int argc, char args The execute command function forks a child which does the following Decides if dup2 is needed for any of the standard input or output based on the values of f d in and fd out Uses execvp to execute the command When the function execute command is called for every command in the array mycommands it starts waiting for all of them to finish

Explanation / Answer

If my understanding of your requirement is correct, is this the code below you want? If not let me know i'll modify it accordingly. I have given you exec_commands.c file below which forks and executes the commands given by the user one at a time.

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

#include "command.h"


/*
* This function should execute all of the commands in mycommands[],
* properly setting up the pipes between them.
* This means, for example, that the output of mycommands[0] will be
* the input of mycommands[1], and the output of mycommands[1] will
* be the input of mycommands[2], etc.
*
* This function should create the required pipes and then use
* execute_command to create the individual processes.
*/
void execute_commands(struct command mycommands[], int no_commands)
{
int i=0;
int cPids[no_commands];
int fd[2];
int status;
   for(i=0;i<no_commands;i++)
   {
       switch(cPids[i]=fork()){
       pipe(fd);
       case 0: //child process
           close(fd[0]);
           execute_command(mycommands[i].comm,mycommands[i].no_args,mycommands[i].args,fd[0],fd[1]);
      
           break;
       case -1:
           printf("Error while executing the command %s ", mycommands[i].comm);
           break;
       default:
           close(fd[1]);
           while (wait(&status) != cPids[i])
           break;
       }
   }
    return;
}

/*
* This function calls fork and executes a single command. It uses dup2 as
* appropriate to redirect stdin and stdout to fd_in and fd_out.
*
* Arguments:
*    command: The command to be executed
*    args: An array of strings containing the arguments to the command
*    argc: The number of arguments stored in args
*    fd_in: The filedescriptor that should be used as stdin for
*           the command
*    fd_out: The filedescriptor that should be used as stdout for
*            the command
*/
int execute_command(char *command, int argc, char *args[], int fd_in, int fd_out )
{
   int n;
   if(fd_out==2)
       dup2(fd_out,n);

   execvp(command,args);
    return 0;
}