i wrote a function that simulate cp function (copy in bash ) , basically this function takes a file as an input and copies it to a dest file :
cp sourceFile destFile .
the cp function can run in fore ground or in back ground if there was a '&' at the end of the line (cp sourceFile destFile &
)
in order to support this i used fork , and the son basically copies the file , and he father if the command was fore ground waits for the child , else if the command is back ground we don't wait ( we add it to certain list )
my problem is when the command runs in fore ground after the son finishes the code exit the cp function then returns , but when it exits the cp function it prints something , and i don't want this to happen :(
( example at the end )
my function :
void CopyCommand::execute() {
char *buff = new char[1024]();
int fdRead = open(args[1], O_RDONLY);
if (fdRead == -1) {
perror("smash error: open failed");
return;
}
int fdWrite = open(args[2], O_WRONLY | O_TRUNC);
if (fdWrite ==-1) {
fdWrite = open(args[2], O_WRONLY | O_CREAT, 0666);
if (fdWrite == -1) {
perror("smash error: open failed");
return;
}
}
PID = fork();
if (PID == 0) {
setpgrp();
int count = read(fdRead, buff, 1); /// read from the file fd1 into fd2
while (count != -1) {
if (!count) {
break;
}
if (write(fdWrite, buff, 1) == -1) {
perror("smash error: write failed");
return; // not sure if we should return
}
count = read(fdRead, buff, 1);
if (count == -1) {
perror("smash error: read failed");
return;
}
}
return ;
} if (PID > 0) { // if i am the father then i will :
if (isBackground) {
// if cp command is running in the background then add it to the jobs list
SmallShell::getInstance().SmallShellGetJobs()->removeFinishedJobs();
SmallShell::getInstance().Jobs_List.addJob(SmallShell::getInstance().currentCommand, false);
cout << "smash: " << args[1] << " was copied to " << args[2] << endl;
return;
} else {
int status;
waitpid(PID, &status, WUNTRACED);
cout << "smash: " << args[1] << " was copied to " << args[2] << endl;
return;
}
} else {
perror("smash error: fork failed");
}
}
what happens : for example the input is :
cp test_src_1.txt test_newdest_1.txt
the output would be :
outside of cp function :(
smash: test_src_1.txt was copied to test_newdest_1.txt
fork
doesn't work the way you think it does. The child process exists until it's terminated, and inherits things like the parent's call stack; when you return
in the child process, you're just going to the calling function.
You need to use exit
or something in the same family. For example:
if (PID == 0) {
setpgrp();
int count = read(fdRead, buff, 1); /// read from the file fd1 into fd2
while (count != -1) {
if (!count) {
break;
}
if (write(fdWrite, buff, 1) == -1) {
perror("smash error: write failed");
exit(0); // not sure if we should return
}
count = read(fdRead, buff, 1);
if (count == -1) {
perror("smash error: read failed");
exit(1);
}
}
exit(1) ;
}