Results 1 to 5 of 5
Hello,
I have been working on this for last 5 days and have not slept properly.
been stressed out.
The problem I have so far is when I put an ...
- 08-29-2009 #1Just Joined!
- Join Date
- Aug 2009
- Posts
- 6
problem with redirection stdout to a file.
Hello,
I have been working on this for last 5 days and have not slept properly.
been stressed out.
The problem I have so far is when I put an input through fgets
say, " shell> /bin/ls > a.out" and then the program gets numb(it is supposed to have another input btw).
When I got out of the program using Ctrl+C,I found there was a "a.out" file created successfully.
I can not figure why the program was stuck.
Can you guys please help me with this.
Thank you in advance.
the source code is as follow.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
//#include <limits.h>
int bg_symbol;
int rd_symbol;
int pp_symbol;
//int file_out_d;
char *rd_pointer;
char *pipe_pointer;
char filename[80];
int out_redirect(char *file_name);
int my_system(char **argv,int numberToken);//char *str);
int tokenize(char *str,char *argv[]); //return token number counted
int main(void)
{
char buffer[256];
char *argv[64];
char curDir[255];
int token;
bg_symbol=0;
while(1){
if(bg_symbol==0)
wait(NULL);
rd_symbol=0;
while(1){
if(bg_symbol==0)
wait(NULL);
rd_symbol=0;
pp_symbol=0;
memset(buffer,0,256);
//get current working directory
getcwd(curDir,255);
//print out
printf("%s > ",curDir);
if(fgets(buffer,256,stdin) == NULL){
fflush(stdin);
continue;
}
if(buffer[strlen(buffer) -1 ] =='\n')
buffer[strlen(buffer)-1] = 0;
if(buffer[0] == '\0' || buffer[0] == ' '){
fflush(NULL);
continue;
}
if(strcmp(buffer,"exit") ==0) return EXIT_SUCCESS;
token=tokenize(buffer,&argv[0]);
out_redirect(filename);
my_system(&argv[0],token);
}
return 0;
}
int tokenize(char *str,char **argv)
{
int i=0,j=0;
char temp[80];
char temp2[80];
int quotation=0;
strcpy(temp,str);
for(i=0;i<=strlen(temp);i++){
switch(temp[i]){
case 92:
if(temp[i+1] == '\0')
break;
if(temp[i+1] == 34){
temp[j++]='"';
}
break;
case 34:
temp2[j++]='^';
quotation++;
break;
case '>':
if(quotation%2==0){
if(temp[i-1] != ' ') //*(str+j++)=' ';
temp2[j++]=' ';
temp2[j++]='>';
if(temp[i+1] == '\0') {
temp[j]='\0';
break;
}
if(temp[i+1] != ' ') //*(str+j++) =' ';
temp2[j++]=' ';
}else{
temp2[j++]='>';
}
case '&':
if(quotation%2==0){
bg_symbol = 1;
}
temp2[j++]=' ';
break;
default:
temp2[j++]=temp[i];
break;
}
if(temp[i] == '\0'){
temp2[j]='\0';
break;
}
}
////////find symbol > and then replace it with \0
////////also apply redirection
strcpy(temp,temp2);
if((rd_pointer = strchr(temp,'>')) != NULL && quotation%2==0)
{
*rd_pointer = 0;
strcpy(filename,strtok(rd_pointer+1," \t"));
rd_symbol = 1;
}
if((rd_pointer = strchr(temp2,'>')) != NULL)
*rd_pointer = 0;
////////////////////tokenize from here
i=0;
if(quotation>0){
argv[i] = strtok(temp2,"^");
i++;
}else{
argv[i] = strtok(temp2," \t");
i++;
}
argv[1] = basename(argv[0]);
i++;
for(;;i++){
argv[i] = strtok(NULL," \t");
if(argv[i] == NULL) break;
}
argv[i] = NULL;
////////////////////finish tokenize
return i;
}
int my_system(char **argv,int token)
{
char **arg;
int file;
pid_t pid,status;
arg=argv;
//file = open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_I WUSR);
if((pid=fork()) == 0){
if(rd_symbol==1){
//fflush(stdout);
// dup2(file,STDOUT_FILENO);
// close(file);
close(1);
}
//execv(arg[0],&arg[1]);
system("ls");
perror("error");
exit(1);
}else if(pid < 0){ //success, child process
printf("Unable to create child process,exiting.\n");
exit(-1);
}else{
close(file);
close(1);
}
if(bg_symbol == 1){
printf("[+%d]\n",pid);
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
}else{
wait(&status);
if(WIFEXITED(status)){
printf("normal termination with status %d\n",WEXITSTATUS(status));
}
}
return 0;
}
int out_redirect(char *file_name)
{
int err,file_out_d;
if(file_name == NULL)
return 0;
if((file_out_d = open(file_name,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_ IWUSR))<0)
return -1;
if(dup2(file_out_d,1) == -1){
err=errno;
close(file_out_d);
errno=err;
return -1;
}
return close(file_out_d);
}
- 08-29-2009 #2
The problem description is not clear. What does and then the program gets numb mean?
Also, that's a lot of code for a would-be helper to parse. And it's hard to read because it's not formatted as code.
I recommend two things:
- Always put code in code tags (click on the # while editing), and
- Only post the portion(s) where you think the problem is.
Also, not related to your question, but as a general programming practice, I avoid using a constant more than once, since you can inadvertently change it one place which would cause a problem elsewhere. For example, do this:Code:memset(buffer, 0, sizeof(buffer));
- 08-30-2009 #3Just Joined!
- Join Date
- Aug 2009
- Posts
- 6
thank you for reply btw.
the problem i am thinking of is after forking it seems like it stops working.
say, if i enter
"
shell > /bin/ls > a.out
"
it supposed to create a file "a.out" and redirect stdout to the file just created.
and then it should continue getting another input showing "shell >" to users.
but it stops after entering the command "/bin/ls > a.out".(but it actually generated the file and put a stdout into a file already but just stops continuing the program)
it works fine without entered '>' symbol.
thank you for reply jackson.
- 08-31-2009 #4
Ah... I see the problem, I think...
First off, I just want to say it wasn't clear what you were writing, at first. You're writing the shell, right?
Here's the thing: after you read your command from the user, you parse it, then you redirect output, and then you run the command. But you never undo the output redirection. Thus, the next command prompt written to stdout (file descriptor 1) still goes to that file ./a.out.
There are different ways you could deal with this. One way shells commonly deal with this is to fork before doing file descriptor manipulation, so that the effects of fdup2() only apply to the new process. But if, for whatever reason, you needed to do fdup2() in the main thread, you could undo it later by first fdup2()ing stdout to another file descriptor, then back again in the main thread, after the fork(). The former seems like the better approach to me...
It seems you actually have some code in there to do this - I haven't looked carefully enough to see why it's commented out...
- 09-01-2009 #5Just Joined!
- Join Date
- Aug 2009
- Posts
- 6
Thank you tetsujin.
I solved it with your help.
it seems like as you said.
I did open file descriptor in the main and did close it for only 1 processor. so it does take stdout since file descriptor(1) was open.
One more question, why the child process lost **argv variable point if i define **argv variable in the main and then pass it to the my_system function which acutally does fork().
it seems like before i fork the variable actually point to the string what i entered with fgets but as soon as fork(), it seemed like it lost its point so it did point different string which was unexpected.
I solved this problem with define **argv in the my_system function but i do not know why...lol.


Reply With Quote