ALNMOO
asked on
execvp and wiat BUG
Ive got this code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main (void) {
char **chargv;
char inbuf[MAX_BUFFER];
char inbuf2[MAX_BUFFER];
int argnum;
for( ; ; ) {
printf(">>");
gets(inbuf);
strcpy(inbuf2,inbuf);
if (strcmp(inbuf, QUIT_STRING) == 0)
exit(0);/*return 0;*/
argnum = makeargv(inbuf2, " ", &chargv);
/*printf("%d\n",argnum);
printf("%s\n",*(chargv+arg num-1));*/
if( (argnum >0) && (strcmp(*(chargv+argnum-1) ,"&"))==0) {
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
strcpy(*(chargv+argnum-1), "\0");
execvp(chargv[0], chargv);
}
printf("Running in Background\n");
/*wait(NULL);*/
}
else if ( (argnum >0) && (strcmp(*(chargv+argnum-1) ,"&"))!=0) {
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg num-1));
execvp(chargv[0], chargv);
}
wait(NULL);
printf("Running in Forgound\n");
}
}
}
int makeargv(const char *s, const char *delimiters, char ***argvp) {
int error;
int i;
int numtokens;
const char *snew;
char *t;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
/* create argument array for ptrs to the tokens */
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
-----
the problem is when I execute a line with & for the first time
>>sleep 20 &
I can never execute one in forground again! any help
try this when u run the prog and u will know what I mean...
>>sleep 10
>>sleep 10 &
>>sleep 10
thanks :)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main (void) {
char **chargv;
char inbuf[MAX_BUFFER];
char inbuf2[MAX_BUFFER];
int argnum;
for( ; ; ) {
printf(">>");
gets(inbuf);
strcpy(inbuf2,inbuf);
if (strcmp(inbuf, QUIT_STRING) == 0)
exit(0);/*return 0;*/
argnum = makeargv(inbuf2, " ", &chargv);
/*printf("%d\n",argnum);
printf("%s\n",*(chargv+arg
if( (argnum >0) && (strcmp(*(chargv+argnum-1)
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
strcpy(*(chargv+argnum-1),
execvp(chargv[0], chargv);
}
printf("Running in Background\n");
/*wait(NULL);*/
}
else if ( (argnum >0) && (strcmp(*(chargv+argnum-1)
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg
execvp(chargv[0], chargv);
}
wait(NULL);
printf("Running in Forgound\n");
}
}
}
int makeargv(const char *s, const char *delimiters, char ***argvp) {
int error;
int i;
int numtokens;
const char *snew;
char *t;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
/* create argument array for ptrs to the tokens */
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
-----
the problem is when I execute a line with & for the first time
>>sleep 20 &
I can never execute one in forground again! any help
try this when u run the prog and u will know what I mean...
>>sleep 10
>>sleep 10 &
>>sleep 10
thanks :)
the exec.. functions replace the memory image of the current program and dont return to the program that called them.
ASKER
I know that's why I fork a child to run it
If the exec*() call succedes, the new process image replaces the current process. I.e. successful calls to the exec functions do not return because the system overlays the calling process with the new process.
If the exec*() functions returns to the calling process image, an error has occurred; the return value is -1 , and the function sets errno to indicate the error.
Have a look, on your OS, at exec(2) (man exec, or man 2 exec) for complete reference.
If the exec*() functions returns to the calling process image, an error has occurred; the return value is -1 , and the function sets errno to indicate the error.
Have a look, on your OS, at exec(2) (man exec, or man 2 exec) for complete reference.
Oh.Sorry.
Didnt see the fork call.
Didnt see the fork call.
ASKER
take a look please :)
---
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg num-1));
execvp(chargv[0], chargv);
}
--------
noly a forked chiled calls exec*()
---
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg
execvp(chargv[0], chargv);
}
--------
noly a forked chiled calls exec*()
ASKER
:)
fine you've seen it :)
fine you've seen it :)
Thanx. :~)
My suggestions on this one would only be subjective as i dont have linux here.
My suggestions on this one would only be subjective as i dont have linux here.
ASKER
thanks any way
A few suggestions:
cast the return of malloc() in your makeargv function.
if( (argnum >0) && (strcmp(*(chargv+argnum-1) ,"&"))==0) {
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
strcpy(*(chargv+argnum-1), "\0");
execvp(chargv[0], chargv);
}
printf("Running in Background\n");
/*wait(NULL);*/
}
//this part executed by parent
else if ( (argnum >0) && (strcmp(*(chargv+argnum-1) ,"&"))!=0) {
//this part not executed as "&" has been chopped off to ""
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg num-1));
execvp(chargv[0], chargv);
}
wait(NULL);//waits for child.
So,the parent wont execute anything as it is waiting on the child.
cast the return of malloc() in your makeargv function.
if( (argnum >0) && (strcmp(*(chargv+argnum-1)
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
strcpy(*(chargv+argnum-1),
execvp(chargv[0], chargv);
}
printf("Running in Background\n");
/*wait(NULL);*/
}
//this part executed by parent
else if ( (argnum >0) && (strcmp(*(chargv+argnum-1)
//this part not executed as "&" has been chopped off to ""
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg
execvp(chargv[0], chargv);
}
wait(NULL);//waits for child.
So,the parent wont execute anything as it is waiting on the child.
It wont execute the wait() also.
Ignore my prev. comment
Ignore my prev. comment
ASKER
now imtrying to use
waitpid() insted of wait...
it's not working as well!
waitpid() insted of wait...
it's not working as well!
>gets(inbuf);
NEVER use gets ... replace it with fgets
fgets ( inbuf, MAX_LEN, stdin );
>the problem is when I execute a line with & for the first time
>>>sleep 20 &
>I can never execute one in forground again! any help
Do you mean the exec'ed process ? If yes, then I dont think you can bring it to foreground again ... well you can but it will be a bit difficult ... you will have to associate a controlling tty with that process ....
What exactly are you trying to achieve ?
NEVER use gets ... replace it with fgets
fgets ( inbuf, MAX_LEN, stdin );
>the problem is when I execute a line with & for the first time
>>>sleep 20 &
>I can never execute one in forground again! any help
Do you mean the exec'ed process ? If yes, then I dont think you can bring it to foreground again ... well you can but it will be a bit difficult ... you will have to associate a controlling tty with that process ....
What exactly are you trying to achieve ?
ASKER
thanks sunny
I mean a now process...
can I know why I should not uses gets! :)
thanks
I mean a now process...
can I know why I should not uses gets! :)
thanks
from gets man page
BUGS
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.
BUGS
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.
I am still not sure of what you are doing
pls take a step by step example of each and every step and each and every command that you execute on the command line
>the problem is when I execute a line with & for the first time
Is a bit unclear
pls take a step by step example of each and every step and each and every command that you execute on the command line
>the problem is when I execute a line with & for the first time
Is a bit unclear
ok, I get an idea
this is the output I receive
========================== ========== ========== ========== ===
sleep: invalid time interval `&
'
Try `sleep --help' for more information.
Running in Forgound
>>^[[A
Running in Forgound
>>sleep 20&
20&
sleep: invalid time interval `20&
'
Try `sleep --help' for more information.
>>sleep 20 &
&
sleep: invalid time interval `&
'
Try `sleep --help' for more information.
Running in Forgound
>>sleep 10 &
&
sleep: invalid time interval `&
'
Try `sleep --help' for more information.
Running in Forgound
>>
Running in Forgound
>>
this is the output I receive
==========================
sleep: invalid time interval `&
'
Try `sleep --help' for more information.
Running in Forgound
>>^[[A
Running in Forgound
>>sleep 20&
20&
sleep: invalid time interval `20&
'
Try `sleep --help' for more information.
>>sleep 20 &
&
sleep: invalid time interval `&
'
Try `sleep --help' for more information.
Running in Forgound
>>sleep 10 &
&
sleep: invalid time interval `&
'
Try `sleep --help' for more information.
Running in Forgound
>>
Running in Forgound
>>
changing gets to fgets made some difference however things are a bit crazy still ... everything says running in foreground ...
command parsing needs a bit more efforts
What is the objective of the program ?
command parsing needs a bit more efforts
What is the objective of the program ?
ASKER
leave a space b/w & and any char b4 it...
the objective is the to make a command interpriter :)...
the objective is the to make a command interpriter :)...
After you type a command with an '&',
give the next command as "q" to quit the current process and see if you can run in foreground again or not.
give the next command as "q" to quit the current process and see if you can run in foreground again or not.
ASKER
ankuratvb
it quits and returns to the shell!
it quits and returns to the shell!
Ok.
if( (argnum >0) && (strcmp(*(chargv+argnum-1) ,"&"))==0) {
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
strcpy(*(chargv+argnum-1), "\0");
execvp(chargv[0], chargv);
}
printf("Running in Background\n");
/*wait(NULL);*/
}
else if ( (argnum >0) && (strcmp(*(chargv+argnum-1) ,"&"))!=0) {
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg num-1));
execvp(chargv[0], chargv);
}
wait(NULL);//try removing this wait call.I guess(i cant execute this) your parent process blocks here.
printf("Running in Forgound\n");
if( (argnum >0) && (strcmp(*(chargv+argnum-1)
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
strcpy(*(chargv+argnum-1),
execvp(chargv[0], chargv);
}
printf("Running in Background\n");
/*wait(NULL);*/
}
else if ( (argnum >0) && (strcmp(*(chargv+argnum-1)
if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0)) {
printf("%s\n",*(chargv+arg
execvp(chargv[0], chargv);
}
wait(NULL);//try removing this wait call.I guess(i cant execute this) your parent process blocks here.
printf("Running in Forgound\n");
ASKER
OH GOD
I did it finally
------------
the code
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main (void) {
char **chargv, *cmd;
char inbuf[MAX_BUFFER];
int FLAG, i;
while(1) {
printf("RBMax>>");
gets(inbuf); /* gets user input */
cmd = strtok(inbuf, ";"); /* tokinze input using ";" as delemeter */
while(cmd != NULL) {
if (strcmp(cmd, QUIT_STRING) == 0) /* exit if q */
exit(0);
FLAG = 0; /* sets the run in background to 0 */
for(i = 0; i < strlen(cmd); i++) /*search the input for "&" */
if (cmd[i] == '&') { /* if found */
FLAG = 1; /* sets the flag to 1 */
cmd[i] = ' '; /* replace & with ' ' */
} /* end if */
if ((fork() == 0) && (makeargv(cmd, " ", &chargv) > 0))
{
execvp(chargv[0], chargv);
printf("Bad command or file name.\n"); /* will be printed if execvp was not executed correctly */
exit(-77);
}
cmd = strtok(NULL, ";"); /* get next token */
if (FLAG == 0) /* if to be run in forground */
wait(NULL);
} /* end of while */
} /* end of while */
}
int makeargv(const char *s, const char *delimiters, char ***argvp) {
int error;
int i;
int numtokens;
const char *snew;
char *t;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
/* create argument array for ptrs to the tokens */
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
------
the problem was I did not make sure that a child is kill if exec* was not executed correctly....
WHAT A BUG :):)
I did it finally
------------
the code
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main (void) {
char **chargv, *cmd;
char inbuf[MAX_BUFFER];
int FLAG, i;
while(1) {
printf("RBMax>>");
gets(inbuf); /* gets user input */
cmd = strtok(inbuf, ";"); /* tokinze input using ";" as delemeter */
while(cmd != NULL) {
if (strcmp(cmd, QUIT_STRING) == 0) /* exit if q */
exit(0);
FLAG = 0; /* sets the run in background to 0 */
for(i = 0; i < strlen(cmd); i++) /*search the input for "&" */
if (cmd[i] == '&') { /* if found */
FLAG = 1; /* sets the flag to 1 */
cmd[i] = ' '; /* replace & with ' ' */
} /* end if */
if ((fork() == 0) && (makeargv(cmd, " ", &chargv) > 0))
{
execvp(chargv[0], chargv);
printf("Bad command or file name.\n"); /* will be printed if execvp was not executed correctly */
exit(-77);
}
cmd = strtok(NULL, ";"); /* get next token */
if (FLAG == 0) /* if to be run in forground */
wait(NULL);
} /* end of while */
} /* end of while */
}
int makeargv(const char *s, const char *delimiters, char ***argvp) {
int error;
int i;
int numtokens;
const char *snew;
char *t;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
/* create argument array for ptrs to the tokens */
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
------
the problem was I did not make sure that a child is kill if exec* was not executed correctly....
WHAT A BUG :):)
ASKER
OH GOD
I did it finally
------------
the code
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main (void) {
char **chargv, *cmd;
char inbuf[MAX_BUFFER];
int FLAG, i;
while(1) {
printf(">>");
gets(inbuf); /* gets user input */
cmd = strtok(inbuf, ";"); /* tokinze input using ";" as delemeter */
while(cmd != NULL) {
if (strcmp(cmd, QUIT_STRING) == 0) /* exit if q */
exit(0);
FLAG = 0; /* sets the run in background to 0 */
for(i = 0; i < strlen(cmd); i++) /*search the input for "&" */
if (cmd[i] == '&') { /* if found */
FLAG = 1; /* sets the flag to 1 */
cmd[i] = ' '; /* replace & with ' ' */
} /* end if */
if ((fork() == 0) && (makeargv(cmd, " ", &chargv) > 0))
{
execvp(chargv[0], chargv);
printf("Bad command or file name.\n"); /* will be printed if execvp was not executed correctly */
exit(-77);
}
cmd = strtok(NULL, ";"); /* get next token */
if (FLAG == 0) /* if to be run in forground */
wait(NULL);
} /* end of while */
} /* end of while */
}
int makeargv(const char *s, const char *delimiters, char ***argvp) {
int error;
int i;
int numtokens;
const char *snew;
char *t;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
/* create argument array for ptrs to the tokens */
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
------
the problem was I did not make sure that a child is kill if exec* was not executed correctly....
WHAT A BUG :):)
I did it finally
------------
the code
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main (void) {
char **chargv, *cmd;
char inbuf[MAX_BUFFER];
int FLAG, i;
while(1) {
printf(">>");
gets(inbuf); /* gets user input */
cmd = strtok(inbuf, ";"); /* tokinze input using ";" as delemeter */
while(cmd != NULL) {
if (strcmp(cmd, QUIT_STRING) == 0) /* exit if q */
exit(0);
FLAG = 0; /* sets the run in background to 0 */
for(i = 0; i < strlen(cmd); i++) /*search the input for "&" */
if (cmd[i] == '&') { /* if found */
FLAG = 1; /* sets the flag to 1 */
cmd[i] = ' '; /* replace & with ' ' */
} /* end if */
if ((fork() == 0) && (makeargv(cmd, " ", &chargv) > 0))
{
execvp(chargv[0], chargv);
printf("Bad command or file name.\n"); /* will be printed if execvp was not executed correctly */
exit(-77);
}
cmd = strtok(NULL, ";"); /* get next token */
if (FLAG == 0) /* if to be run in forground */
wait(NULL);
} /* end of while */
} /* end of while */
}
int makeargv(const char *s, const char *delimiters, char ***argvp) {
int error;
int i;
int numtokens;
const char *snew;
char *t;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;
/* create argument array for ptrs to the tokens */
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
------
the problem was I did not make sure that a child is kill if exec* was not executed correctly....
WHAT A BUG :):)
ASKER
thanks all for the help :)
Can either be PAQ/Refund or a split ... There were some helpful suggestions but real problem was solved by the asker
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.