In a Unix environment with C, modify psh2.c provided below. This program current
ID: 3735403 • Letter: I
Question
In a Unix environment with C, modify psh2.c provided below. This program currently works by taking one argument at a time, until ‘ ’ is the last argument or a maximum of 20 arguments is entered. Then it will run the first argument, arg[0], and will pass the whole array of arguments to the newly forked process.
You need to modify the program such that instead of taking arguments one on each line, it would take the whole string, and chunk it into space-separated arguments and put them into the array of arguments. Then, same as before, it would run the first argument, arg[0], and pass the array of arguments to the process.
You must write a function which would take the input string, and convert it into the array of arguments and return a pointer to it.
Notice that the argument to this function is char* and the return type is char**.
----psh2.c------
/** prompting shell version 2
**
** Solves the `one-shot' problem of version 1
** Uses execvp(), but fork()s first so that the
** shell waits around to perform another command
** New problem: shell catches signals. Run vi, press ^c.
**/
#include <stdio.h>
#include <signal.h>
#define MAXARGS 20 /* cmdline args */
#define ARGLEN 100 /* token length */
main()
{
char *arglist[MAXARGS+1]; /* an array of ptrs */
int numargs; /* index into array */
char argbuf[ARGLEN]; /* read stuff here */
char *makestring(); /* malloc etc */
numargs = 0;
while ( numargs < MAXARGS )
{
printf("Arg[%d]? ", numargs);
if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != ' ' )
arglist[numargs++] = makestring(argbuf);
else
{
if ( numargs > 0 ){ /* any args? */
arglist[numargs]=NULL; /* close list */
execute( arglist ); /* do it */
numargs = 0; /* and reset */
}
}
}
return 0;
}
execute( char *arglist[] )
/*
* use fork and execvp and wait to do it
*/
{
int pid,exitstatus; /* of child */
pid = fork(); /* make new process */
switch( pid ){
case -1:
perror("fork failed");
exit(1);
case 0:
execvp(arglist[0], arglist); /* do it */
perror("execvp failed");
exit(1);
default:
while( wait(&exitstatus) != pid )
;
printf("child exited with status %d,%d ",
exitstatus>>8, exitstatus&0377);
}
}
char *makestring( char *buf )
/*
* trim off newline and create storage for the string
*/
{
char *cp, *malloc();
buf[strlen(buf)-1] = ''; /* trim newline */
cp = malloc( strlen(buf)+1 ); /* get memory */
if ( cp == NULL ){ /* or die */
fprintf(stderr,"no memory ");
exit(1);
}
strcpy(cp, buf); /* copy chars */
return cp; /* return ptr */
}
Explanation / Answer
Below code is working fine in codebloacks. If it gives any issue on your system kindly leave comments.
CODE:
/** prompting shell version 2
**
** Solves the `one-shot' problem of version 1
** Uses execvp(), but fork()s first so that the
** shell waits around to perform another command
** New problem: shell catches signals. Run vi, press ^c.
**/
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#define MAXARGS 20 /* cmdline args */
#define ARGLEN 200 /* token length */
char *arglist[MAXARGS+1];
char *makestring( char *buf )
/*
* trim off newline and create storage for the string
*/
{
char *cp;
buf[strlen(buf)] = ''; /* trim newline */
cp = malloc( strlen(buf)+1 ); /* get memory */
if ( cp == NULL )
{ /* or die */
fprintf(stderr,"no memory ");
exit(1);
}
strcpy(cp, buf); /* copy chars */
return cp; /* return ptr */
}
char **parsearg(char *str)
{
int numargs; /* index into array */
char *token;
numargs = 0;
/* get the first token */
token = strtok(str, " ");
arglist[numargs++] = makestring(token);
/* walk through other tokens */
while(token != NULL)
{
arglist[numargs] = makestring(token);
printf( "%s ", arglist[numargs] );
numargs++;
token = strtok(NULL, " ");
}
return arglist;
}
void execute( char *arglist[] )
/*
* use fork and execvp and wait to do it
*/
{
int pid,exitstatus; /* of child */
pid = fork(); /* make new process */
switch( pid )
{
case -1:
perror("fork failed");
exit(1);
case 0:
execvp(arglist[0], arglist); /* do it */
perror("execvp failed");
exit(1);
default:
while( wait(&exitstatus) != pid );
printf("child exited with status %d,%d ", exitstatus>>8, exitstatus&0377);
}
}
int main()
{
char **arglist; /* an array of ptrs */
char argbuf[ARGLEN]; /* read stuff here */
char *makestring(); /* malloc etc */
printf("Enter Arg List seperated by space [Max 20]: ");
scanf("%[^ ]s", argbuf);
if (argbuf != NULL)
{
arglist = parsearg(argbuf);
execute( arglist );
}
return 0;
}