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

Thank you in advance for the help We are expected to write a the above program i

ID: 3595783 • Letter: T

Question

Thank you in advance for the help

We are expected to write a the above program in C Language via linux terminal.

Here is the shellp.h file:

#ifndef SHELLP_H
#define SHELLP_H

enum Kind {
noCMD,exitCMD,cdCMD,pwdCMD,linkCMD,rmCMD,basicCMD,pipelineCMD
};

typedef struct Stage {
int _nba;
char** _args;
// Feel free to add fields as needed
} Stage;

typedef struct Command {
char* _com;
enum Kind _kind;
int _mode;
char* _input;
char* _output;
char** _args;
int _nba;
Stage** _stages;
int _nbs;
// Feel free to add fields as needed
} Command;

#define TRUE 1
#define FALSE 0


// A pipeline "object" contains
// 1. An array of nbStages stages
// 2. A mode flag to determine whether
// - the pipeline input is redirected
// - the pipeline output is redirected
// Each stage is a structure that encapsulates
// - The number of arguments
// - Each argument (in string form)
// BY DEFAULT THE MAIN PROGRAM CALLS THE PRINT METHOD OF THE COMMAND
// OBJECT. So you can see how the pipeline description is represented/stored
// Your objective:
// * Implement the execute method to create and execute the entire pipeline.
// Hint: all the systems calls seen in class will be useful (fork/exec/open/close/pipe/....)
// Good Luck!

#endif

Here is the shellp.c file:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "shellp.h"

char *strdup(const char *s);

// Check the bottom of this file to locate the method you must implement.
// You do not need to read all provided code, but you are encouraged to
// do so if you want to experiment/understand more details about the program.

#define R_NONE 0 /* No redirections */
#define R_INP 1 /* input redirection bit */
#define R_OUTP 2 /* output redirection bit */
#define R_APPD 4 /* append redirection bit */

#define MAXRD 255

Stage* allocStage(int nba,char** args);
void freeStage(Stage*);
void printStage(Stage*);
Command* addCommandStage(Command* c,Stage* s);

int extractRedirect(char* buf,int* len,int* mode,char* input,char* output);

char* skipWS(char* arg);
char* cutWord(char* arg);
int trimString(char* buf,int len);

Command* allocCommand(char* c)
{
Command* r = (Command*)calloc(1,sizeof(Command));
r->_com = NULL;
r->_kind = noCMD;
r->_mode = R_NONE;
return r;
}
void freeCommand(Command* c)
{
if (c->_com) free(c->_com);
if (c->_input) free(c->_input);
if (c->_output) free(c->_output);
for(int i=0;i < c->_nba;i++)
if (c->_args[i]) free(c->_args[i]);
free(c->_args);
for(int j=0;j<c->_nbs;j++)
freeStage(c->_stages[j]);
if (c->_stages) free(c->_stages);
free(c);
}

Command* setCommand(Command* c,enum Kind k,char* com)
{
c->_kind = k;
if (c->_com) free(c->_com);
c->_com = strdup(com);
return c;
}
Command* setCommandArgs(Command* c,int nb,char** args)
{
c->_nba = nb + 1;
c->_args = (char**)malloc(sizeof(char*)*c->_nba);
for(int i=0;i<nb;i++)
c->_args[i] = strdup(args[i]);
c->_args[nb] = NULL;
return c;
}

Command* addCommandStage(Command* c,Stage* s)
{
printf("New stage:");
printStage(s);

c->_stages = realloc(c->_stages,sizeof(Stage*)*(c->_nbs + 1));
c->_nbs += 1;
c->_stages[c->_nbs - 1] = s;
return c;
}

void printCommand(Command* c)
{
if (c->_mode & R_INP)
printf("< [%s] ",c->_input);
if (c->_mode & R_OUTP)
printf("> [%s] ",c->_output);
if (c->_mode & R_APPD)
printf(">> [%s] ",c->_output);
printf("CORE: %s ",c->_com);
for(int i=0;i<c->_nba;i++)
printf(" args[%d] = %s ",i,c->_args[i]);
printf("Stages:");
for(int i=0;i < c->_nbs;i++)
printStage(c->_stages[i]);
printf(" ");
}


Command* makeCommand()
{
char buffer[1024];
int i = 0;
char ch,*ptr;
printf("%%");fflush(stdout);
while(i < sizeof(buffer) && (ch = getchar()) != ' ' && ch != EOF)
buffer[i++] = ch;

buffer[i] = 0;
ptr = buffer+i-1;
while(ptr>=buffer && isspace(*ptr)) ptr--,i--;
*++ptr = 0;
Command* c = allocCommand(ptr);
if(ch==EOF)
return setCommand(c,exitCMD,"exit");
else {
int mode = R_NONE;
char input[1024];
char output[1024];
*input = *output = 0;
int len = strlen(buffer);
int ok = extractRedirect(buffer,&len,&mode,input,output);
c->_mode = mode;
c->_input = strdup(input);
c->_output = strdup(output);
len = trimString(buffer,len);
if (ok) {
char* sc = skipWS(buffer);
char* ec = cutWord(sc);
if (strcmp(sc,"cd")==0) {
char* a0 = skipWS(ec);
char* a1 = cutWord(a0);
char* args[1] = {a0};
return setCommandArgs(setCommand(c,cdCMD,sc),1,args);
} else if (strcmp(sc,"pwd")==0) {
return setCommand(c,pwdCMD,sc);
} else if (strcmp(sc,"ln") == 0) {
char* a0 = skipWS(ec);
char* a1 = skipWS(cutWord(a0));
char* a2 = cutWord(a1);
char* args[2] = {a0,a1};
return setCommandArgs(setCommand(c,linkCMD,sc),2,args);
} else if (strcmp(sc,"rm") == 0) {
char* a0 = skipWS(ec);
char* a1 = cutWord(a0);
char* args[1] = {a0};
return setCommandArgs(setCommand(c,rmCMD,sc),1,args);
} else if (strcmp(sc,"exit") == 0) {
return setCommand(c,exitCMD,sc);
} else {
if (*sc) {
if (strchr(ec,'|') != NULL) {
// This is a pipeline.
char* args[512];
args[0] = sc;
char* arg = skipWS(ec);
int nba = 1;
setCommand(c,pipelineCMD,"");
while(arg && *arg) {
char* p = *arg == '|' ? arg : 0;
if (p) {
*p = 0;
addCommandStage(c,allocStage(nba,args));
args[0] = arg = skipWS(p+1);
arg = cutWord(arg);
nba = 1;
} else {
args[nba++] = arg;
arg = skipWS(cutWord(arg));
}
}
return addCommandStage(c,allocStage(nba,args));
} else {
char* args[1024];
args[0] = sc;
char* arg = ec;
int nba = 1;
while(arg && *arg) {
args[nba++] = arg;
arg = skipWS(cutWord(arg));
assert(nba < 1024);
}
return setCommandArgs(setCommand(c,basicCMD,args[0]),nba,args);
}
}
}
}
return c;
}
}

#define IS_REDIR(ch) ((ch) == '<' || (ch)=='>')

/* The routine extracts any redirects and replaces those parts of the command
by whitespaces
*/

int extractRedirect(char* buf,int* len,int* mode,char* input,char* output)
{
int i = 0;
char* ptr = buf;
while(ptr && *ptr) {
if (IS_REDIR(*ptr)) {
if (ptr[0]== '<') {
if (*mode & R_INP) {
printf("Ambiguous input redirect ");
return 0;
} else {
*ptr++ = ' ';
i = 0;
while(isspace(*ptr)) ptr++;
while(isalnum(*ptr) || ispunct(*ptr)) {
if (i>=MAXRD) {
printf("redirect filename too long ");
return 0;
}
input[i++] = *ptr;
*ptr++ = ' ';
}
input[i] = 0;
*mode = *mode | R_INP;
}
} else if (ptr[0]=='>' && ptr[1]=='>') {
if (*mode & (R_APPD | R_OUTP)) {
printf("Ambiguous output redirect ");
return 0;
} else {
ptr[0] = ' ';
ptr[1] = ' ';
ptr += 2;
i = 0;
while(isspace(*ptr)) ptr++;
while(isalnum(*ptr) || ispunct(*ptr)) {
if (i>=MAXRD) {
printf("redirect filename too long ");
return 0;
}
output[i++] = *ptr;
*ptr++ = ' ';
}
output[i] = 0;
*mode = *mode | R_APPD;
}
} else {
if (*mode & (R_APPD | R_OUTP)) {
printf("Ambiguous output redirect ");
return 0;
} else {
assert(ptr[0]=='>');
*ptr++ = ' ';
i = 0;
while(isspace(*ptr)) ptr++;
while(isalnum(*ptr) || ispunct(*ptr)) {
if (i>=MAXRD) {
printf("redirect filename too long ");
return 0;
}
output[i++] = *ptr;
*ptr++ = ' ';
}
output[i] = 0;
*mode = *mode | R_OUTP;
}
}
}
else ptr++;
}
return 1;
}


char* skipWS(char* arg)
{
while(arg && *arg && isspace(*arg)) arg++;
if(arg && *arg=='"') arg++;
return arg;
}

char* cutWord(char* arg)
{
while(arg && *arg && !isspace(*arg)) arg++;
if(*(arg-1)=='"') arg--;
if (arg && *arg) *arg++ = 0;
return arg;
}

int trimString(char* buf,int len)
{
char* ptr = buf + len - 1;
while(ptr>=buf && isspace(*ptr))
ptr--,len--;
*++ptr = 0;
return len;
}

// ================================================================================
// This part of the file contains the PipelineCommand object that you must modify
// ================================================================================
Stage* allocStage(int nba,char** args)
{
Stage* s = (Stage*)calloc(1,sizeof(Stage));
s->_nba = nba + 1;
s->_args = (char**)calloc(s->_nba,sizeof(char*));
for(int i=0;i<nba;i++)
s->_args[i] = strdup(args[i]);
return s;
}

void freeStage(Stage* s)
{
for(int i=0;i<s->_nba;i++)
if (s->_args[i] != NULL) free(s->_args[i]);
free(s->_args);
free(s);
}

void printStage(Stage* s)
{
printf(" (%d)[",s->_nba);
for(int i=0;i<s->_nba;i++)
if (s->_args[i] != NULL)
printf("%s ",s->_args[i]);
else printf("null ");
printf("] ");
}


// ================================================================================
// Write the pipelining logic here.
// ================================================================================


int setupCommandPipeline(Command* c)
{
// TODO: Implement the pipeline commmand.
return 1;
}

// ================================================================================
// Write the basic command logic here.
// ================================================================================


int basicExecute(char* com,int mode,char* input,char* output,char** args)
{
//TODO: Implement the basic command logic here.
return 1;
}

int executeCommand(Command* c)
{
switch(c->_kind) {
case cdCMD: {
int st = chdir(c->_args[0]);
if (st==-1)
printf("cd error: [%s] ",strerror(errno));
return TRUE;
}break;
case pwdCMD: {
char buf[1024];
char* ptr = getcwd(buf,sizeof(buf));
if (ptr)
printf("cwd: %s ",buf);
return TRUE;
}break;
case exitCMD:
return FALSE;
case linkCMD: {
int rv = link(c->_args[0],c->_args[1]);
if (rv!=0)
printf("link error [%s] ",strerror(errno));
return TRUE;
}break;
case rmCMD: {
int rv = unlink(c->_args[0]);
if (rv!=0)
printf("rm error: [%s] ",strerror(errno));
return TRUE;
}break;
case basicCMD: {
return basicExecute(c->_com,c->_mode,c->_input,c->_output,c->_args);
}break;
case pipelineCMD: {
setupCommandPipeline(c);
return TRUE;
}break;
default:
printf("oops.... ");
return TRUE;
}
}

int main(int argc,char* argv[])
{
int loop = 1;
while(loop) {
Command* com = makeCommand();
printCommand(com);
loop = executeCommand(com);
freeCommand(com);
}
return 0;
}

Exercise 2. Pipeline command (60 points) A pipeline is a sequence of external programs chained together to form a single construction. The chaining occurs when the standard output of stage i of the pipeline is fed to the standard input of stage i +1. Consider that each stage of the pipeline consist of an external command (as in question 1) that can take a collection of arguments. Its input is coming from a pipe fed by the previous pipeline stage and its output feeds the next stage of the pipeline. Your specific task is to implement the following function of shel1p.c: int setupCommandPipeline (Command* c) C // TODO: Implement the pipeline commmand return 1; The command object is an abstract data type defined in the header file and reproduced in Figure 1. The Figure defines two structures. The Command structure specifies the entire pipeline. The arguments to each stage are embedded in the_stages array and the array in the Command are not used for pipelines. Pipeline example] Consider the following pipeline for counting the number of occurrences of each word in a text docu- ment: cat whitman.txt tr -s [:space:] "In" I tr -d [:punct:] I tr A-Z a-z sort I uniq -c I sort -nr > counts.txt It contains 7 stages: 1. Send to standard output the content of the filewhitman.txt. 2 Replace every sequence of consecutive spaces by a single line-feed, and send the result to standard output 3. Delete all punctuation characters from the standard input and sends remaining characters to standard output 4 Replace the uppercase letters in the standard input with lowercase letters in the standard output 5 Sort the lines of the standard input alphabetically and print the sorted list to the standard output 6 Collapse adjacent matching lines to a single copy preceded by the number of copies 7. Sort the lines of the standard input in reverse numerical order and prints the sorted list to the standard output Note how the number of arguments varies from stage to stage (stage 5 has no arguments, stages 1, 6, and 7 have a single argument, stages 3, and 4have twoarguments, and stage 2 has three arguments). Also note howthe entirepipeline output is redirected to afile. The Command instance passed to setupCommandPipeline contains an exact descrijption of the pipeline. Note how redirections are global to the pipeline and not local to a stage Your code must setup the pipes connecting all the processes that implement the pipeline The parent process (the shell) must orchestrate the creation of all the processes and their coordination through the pipes as well as possibly setting up the redirections. It may be necessary to add additional fields to the Command and or Stage structures.

Explanation / Answer

shellp.c

====================================================================================

shellp.h

#ifndef SHELLP_H
#define SHELLP_H

enum Kind {
noCMD,exitCMD,cdCMD,pwdCMD,linkCMD,rmCMD,basicCMD,pipelineCMD
};

typedef struct Stage {
int _nba;
char** _args;
// Feel free to add fields as needed
} Stage;

typedef struct Command {
char* _com;
enum Kind _kind;
int _mode;
char* _input;
char* _output;
char** _args;
int _nba;
Stage** _stages;
int _nbs;
// Feel free to add fields as needed
} Command;

#define TRUE 1
#define FALSE 0

#endif

============================================================================

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote