dush_1986
asked on
Created my own shell need help processing a sequence of commands/programs separated by ";"
Ok i have created my own shell but i am having trouble creating it to process a sequence of commands/programs separated by ";"
This is sofar what i have could you please just tell me what to add to my code to make this work?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
pid_t myFork();
int readArgs(const char*,char*[]);
int main (int argc, char *argv[]){
pid_t pid;
char line [255];
char *argList[20];
int ampersand, status, i;
printf ("This program executes commands and \n");
printf ("progams for you \n");
while(1){
printf ("To exit, enter CTR-C, or enter\n");
printf ("a program name with its arguments> ");
fgets(line,255,stdin);
ampersand=readArgs(line,ar gList);
if ((pid = myFork ()) == -1){
perror("impossible to fork");
exit(1);
}
if (pid>0) //This is the parent
if (ampersand) //Background execution
printf("Process [%d]\n", pid);
else{
waitpid(pid, &status,0);
printf("My child has terminated\n");
}
else //this is the child
if (execvp(argList[0], argList)==-1){
perror("child Process");
exit(22);
}
}
exit(0);
}
pid_t myFork(){
static int count=0;
count++;
if (count<=20)
return(fork());
else
return(-1);
}
int readArgs(const char *line, char *argList[]){
static int yes=0;
int i=0, offset=0;
char name[50];
int found=0;
while (yes & argList[i] !=NULL)
free(argList[i++]);
i=0; //reset i to ZERO
while(sscanf(line+offset, "%s", name)==1){
argList[i] = (char *)malloc(strlen(name)+1);
strcpy(argList[i++],name);
while(line[offset]==' ') offset++; //skip blanks
offset += strlen(name);
}
if (!strcmp(argList[i-1], "&")){
argList[i-1] = NULL;
found = 1;
}
else{
if (argList[i-1][strlen(argLi st[i-1])-1 ]=='&'){
argList[i-1][strlen(argLis t[i-1])-1] ='\0';
found = 1;
}
argList[i] = NULL;
}
yes=1;
return(found);
}
Thanx
This is sofar what i have could you please just tell me what to add to my code to make this work?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
pid_t myFork();
int readArgs(const char*,char*[]);
int main (int argc, char *argv[]){
pid_t pid;
char line [255];
char *argList[20];
int ampersand, status, i;
printf ("This program executes commands and \n");
printf ("progams for you \n");
while(1){
printf ("To exit, enter CTR-C, or enter\n");
printf ("a program name with its arguments> ");
fgets(line,255,stdin);
ampersand=readArgs(line,ar
if ((pid = myFork ()) == -1){
perror("impossible to fork");
exit(1);
}
if (pid>0) //This is the parent
if (ampersand) //Background execution
printf("Process [%d]\n", pid);
else{
waitpid(pid, &status,0);
printf("My child has terminated\n");
}
else //this is the child
if (execvp(argList[0], argList)==-1){
perror("child Process");
exit(22);
}
}
exit(0);
}
pid_t myFork(){
static int count=0;
count++;
if (count<=20)
return(fork());
else
return(-1);
}
int readArgs(const char *line, char *argList[]){
static int yes=0;
int i=0, offset=0;
char name[50];
int found=0;
while (yes & argList[i] !=NULL)
free(argList[i++]);
i=0; //reset i to ZERO
while(sscanf(line+offset, "%s", name)==1){
argList[i] = (char *)malloc(strlen(name)+1);
strcpy(argList[i++],name);
while(line[offset]==' ') offset++; //skip blanks
offset += strlen(name);
}
if (!strcmp(argList[i-1], "&")){
argList[i-1] = NULL;
found = 1;
}
else{
if (argList[i-1][strlen(argLi
argList[i-1][strlen(argLis
found = 1;
}
argList[i] = NULL;
}
yes=1;
return(found);
}
Thanx
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I started to debug your program and ended up in writing a new one :-) In the following program "input" variable in main() represents the format which you are trying to parse (i am not mistaken).
The general idea is that in the main program tokenize my input on ";". Hence each token will represent a program name and its respective arguments which will be taken care by construct_cmd function.
Each command is represented by a Command struct. Which is the output of construct_cmd function. A Command Struct contains all what your program needs i.e. program name, its arguments and a boolean
idicating whether it should run in background or not.
Have a look at it. If you dont understand feel free to ask.
typedef enum bool
{
false,
true
}bool;
typedef struct
{
char *cmd_name;
char **args;
int nargs;
bool run_in_bg;
}Command;
void free_cmd(Command *cmd2free);
void print_cmd(Command *cmd2print);
Command *construct_cmd(const char *cmd);
int main(int argc, char *argv[])
{
char *input = strdup("prog p1_o1 p1_o2 p1_o3 &; prog2 p2_o1 ; prog3; prog4 &");
char *buf;
char *str;
Command *cmds[10];
int i = 0;
char *tok;
int ncmds = 0;
// create a modifiable copy of input
str = strdup(input);
tok = strtok_r(str, ";", &buf);
for (i = 0; tok != NULL; i++)
{
cmds[i] = construct_cmd(tok);
tok = strtok_r(NULL, ";", &buf);
}
ncmds = i;
// print all cmds
for (i = 0; i < ncmds; i++)
print_cmd(cmds[i]);
// free all cmds
for (i = 0; i < ncmds; i++)
free_cmd(cmds[i]);
free(str);
free(input);
return 0;
}
Command *construct_cmd(const char *cmd_str)
{
char *tok;
char *buf;
int nalloc = 2;
char **cmd_args;
int i = 0;
Command *cmd = (Command *)malloc(sizeof(Command));
memset(cmd, 0, sizeof(Command));
cmd_args = (char **)malloc(nalloc * sizeof(char *));
// create a modifiable copy of cmd
char *str = strdup(cmd_str);
// a command is given as <prog_name> <option_list>
// so now tokenize str on the basis of spaces
tok = strtok_r(str, " ", &buf);
// first token is always the program name
cmd->cmd_name = strdup(tok);
// the rest are its arguments
tok = strtok_r(NULL, " ", &buf);
while (tok != NULL)
{
// special case
if (strcmp(tok, "&") == 0)
cmd->run_in_bg = true;
else
{
if (i == nalloc)
{
nalloc *= 2;
cmd_args = (char **)realloc(cmd_args, nalloc * sizeof(char *));
}
cmd_args[i++] = strdup(tok);
}
tok = strtok_r(NULL, " ", &buf);
}
cmd->nargs = i;
if (cmd->nargs > 0)
{
// deallocate extra cmd_args elements
for (i = i; i < nalloc; i++)
free(cmd_args[i]);
cmd->args = cmd_args;
}
free(str);
return cmd;
}
void print_cmd(Command *cmd2print)
{
int i;
printf("===Command===\n");
printf("Name = %s\n", cmd2print->cmd_name);
printf("Nargs = %d\n", cmd2print->nargs);
printf("RunInBg = %s\n", cmd2print->run_in_bg==true
for (i = 0; i < cmd2print->nargs; i++)
printf("arg[%d] = %s\n", i, cmd2print->args[i]);
printf("=============\n");
}
void free_cmd(Command *cmd2free)
{
int i;
free(cmd2free->cmd_name);
for (i = 0; i < cmd2free->nargs; i++)
free(cmd2free->args[i]);
free(cmd2free->args);
free(cmd2free);
}
sibtay,
you should not give full answers to homework questions (see https://www.experts-exchange.com/help.jsp#hi130)
But there is no problem helping and guiding to an answer.
you should not give full answers to homework questions (see https://www.experts-exchange.com/help.jsp#hi130)
But there is no problem helping and guiding to an answer.
> static int yes=0;
> while (yes & argList[i] !=NULL)
> free(argList[i++]);
I asume you do this because you got errors the first time you free argList? It is better to initialize argList before you use it.
char *argList[20];
...
argList[0]=NULL;