I am trying to execute "sudo conntrack -E -p udp -e NEW" command and then pipe the output of this command to "logger" command, but this doesnt work. anything obvious that is going wrong?
so parent is the "sudo conntrack...." which forks the child "logger ..."
void main () {
pid_t pid;
int status;
int j=0;
int exe_process;
FILE *prt1;
FILE *prt2;
int fd[2];
char *arg[]={ "sudo", "/usr/sbin/conntrack", "-E", "-p", "udp", "-e", "NEW", NULL };
char *arg1[]={ "/usr/bin/logger", "-t", "log-conntrack", "-p", "daemon.notice", NULL };
if (pipe(fd) < 0)
printf("pipe error\n");
if ((pid = fork()) < 0) /* fork a child process */
{
printf("ERROR: forking child process failed\n");
exit(1);
}
else if (pid > 0) /* for the parent process: */
{
printf("In parent process %d\n",getpid());
close(fd[0]);
if (execvp("/usr/sbin/conntrack", arg) < 0) /* execute the command */
{
printf("ERROR: exec failed\n");
exit(1);
}
prt1=fdopen(fd[1], "ab");
}
else /* for the child: */
{
printf("In parent child %d\n",getpid());
close(fd[1]);
prt2=fdopen(fd[0], "rb");
if (execvp("/usr/bin/logger", arg1) < 0) /* execute the command */
{
printf("ERROR: exec failed\n");
exit(1);
}
}
}
That's pretty much correct but the main problem is that you need dup() instead of what you are trying to do with fdopen. dup will redirect stdin/stdout the way you want.
else if (pid > 0) /* for the parent process: */
{
printf("In parent process %d\n",getpid());
close(fd[0]);
close(1);
dup(fd[1]);
if (execvp("/usr/sbin/conntrack", arg) < 0) /* execute the command */
{
printf("ERROR: exec failed\n");
exit(1);
}
//prt1=fdopen(fd[1], "ab");
}
And in the child:
close(0);
dup(fd[0]);
Related
Hi I'm having a bit of trouble with my pipe execute function, where I want a shell in C to be able to execute a pipe. arg1 is the input before the pipe and arg2 is the command after the pipe. I want the program to terminate after ctr -d but it seems to quit without it, the moment the code is executed. An example of my input is ls | wc, where arg1 = ls and arg2 = wc. Any help/ pointers will be greatly appreciated, thank you.
int executepipe (char ** arg1, char ** arg2) {
int fds[2];
int child=-1;
int status = pipe(fds);
if (status < 0)
{
printf("\npipe error");
return -1;
}
int pid =-1;
pid= fork();
while(1){
if (pid < 0) { //error!
perror("fork");
exit(1);
}
//child
if (pid == 0){// child process (command after the pipe)
//signal(SIGINT, SIG_DFL);
//signal(SIGQUIT, SIG_DFL);
close(fds[1]);//nothing more to be written
dup2(fds[0], 0);
execvp(arg2[0], arg2);
//if errors exist execv wouldn't have been invoked
perror("cannot execute command");
exit(1);
}
else { // parent process (command before the pipe)
close(fds[0]);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
dup2(fds[1], 1);
close(fds[1]);
execvp(arg1[0], arg1);
//if errors exist execv wouldn't have been invoked
perror("cannot execute command");
exit(1);
}
if ( wait(&child) == -1 ){
perror("wait");}
}
return 0;
};
i am trying to create a shell program to execute piped command. When i call ls from forked child & wc from parent it works fine. but if i call wc also from forked child parent keeps on waiting (i don't know why this is happening).
void execPiped(char** Args,char** pipedArgs)
{
int pfds[2];
pipe(pfds);
pid_t pid1 = fork();
if (pid1 == -1)
{
printf("\nFailed forking child..");
return;
}
else if (pid1 == 0) //CHILD 1 EXECUTING
{
close(1); //close STDOUT
dup(pfds[1]); //set pfds as STDOUT
close(pfds[0]); //we don't need this
if (execvp(Args[0], Args) < 0)
{
printf("\nCould not execute command..");
exit(1);
}
}
else {
pid_t pid2 = fork();
if (pid2 == -1)
{
printf("\nFailed forking child..");
return;
}
else if (pid2 == 0) //CHILD 2 EXECUTING
{
close(0); //close STDIN
dup(pfds[0]); //set pfds as STDIN
close(pfds[1]); //we don't need this
if (execvp(pipedArgs[0], pipedArgs) < 0)
{
printf("\nCould not execute command..");
exit(1);
}
}
else { //Parent Executing
//Wating for Children to exit
wait(NULL);
wait(NULL);
}
return;
}
}
I have an assignment for which I have to create C programm which has to do the following: The mother proccess has to send via pipe to the child proccess the result of the command ps hax -o user | sort | uniq -c. The child proccess has to take this result and write it to a file users.log.
This is the code I have written:
int main(int argc, char **argv)
{
int file_number;
pid_t pid, pid_2, pid_3, pid_4;
int n, pd[2],fd[2], zd[2];
char line[MAXLINE];
if ( pipe(pd) < 0 || pipe(fd) < 0 || pipe(zd) < 0)
{
perror("cannot create pipe."); // failure on create pipe
exit(1);
}
if ( (pid = fork()) < 0)
{
perror("cannot fork"); // failure on creating child proccess
exit(1);
}
else if ( pid > 0) // mother proccess
{
dup2(zd[1], STDOUT_FILENO);
close(zd[0]);
close(zd[1]);
if ( (pid_4 = fork()) < 0)
{
perror("cannot fork.");
exit(1);
}
else if (pid_4 > 0)
{
dup2(pd[1], STDOUT_FILENO);
close(pd[0]);
close(pd[1]);
close(fd[0]);
close(fd[1]);
execl("/bin/ps", "ps", "hax", "-o", "user", (char *)0);
}
if ( (pid_2 = fork()) < 0)
{
perror("cannot fork.");
exit(1);
}
else if (pid_2 == 0)
{
dup2(pd[0], 0);
dup2(fd[1], 1);
close(pd[0]);
close(pd[1]);
close(fd[0]);
close(fd[1]);
execl("/bin/sort", "sort", "", (char *)0);
}
if ( (pid_3 = fork()) < 0)
{
perror("cannot fork.");
exit(1);
}
else if (pid_3 == 0)
{
dup2(fd[0], 0);
close(pd[0]);
close(pd[1]);
close(fd[0]);
close(fd[1]);
execl("/bin/uniq", "uniq", "-c", (char *)0);
}
close(pd[0]);
close(pd[1]);
close(fd[0]);
close(fd[1]);
pid_t terminated;
int stat;
while ((terminated = wait(&stat)) > 0)
{
printf("Child %d terminated.\n", terminated);
}
}
else // child proccess
{
FILE *fptr = fopen("users.log", "a+");
if (fptr == NULL)
fprintf(stderr, "could not open file.\n");
file_number = fileno(fptr); // getting the file descriptor of fptr
dup2(zd[0], STDIN_FILENO);
close(zd[1]);
close(zd[0]);
n = read(zd[0], line, MAXLINE);
printf("Output: (%.*s)\n", n, line);
write(file_number, line, n);
}
return 0;
}
Running the code seems not to produce the desired result. Nothing is written to the file and I get this error:
Signal 17 (CHLD) caught by hax (procps-ng version 3.3.10).
hax:display.c:66: please report this bug
What am I missing here?
I have written the below method to fork and execute commands separated by multiple pipes( test with : ls -lrt | grep "check" | wc -l . However it is not resulting in any output, could any one please spot my mistake. Thanks.
void execCmd (pInfo *info)
{
int i, j, k, m;
struct comType *comm, *comm1, *comm2;
if(info->noOfPipes > 2)
{
// DOES NOT WORK
printf("Start\n");
comm=&(info->cArr[0]);
comm2=&(info->cArr[(info->ppNum)-1]);
int fds[2];
pipe(fds);
pid_t pid = fork();
if(pid == -1)
{
perror("fork failed");
exit(1);
}
if(pid == 0)
{
printf("1st child execution here\n");
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(comm->cmd,comm->parms);
}
for (k=1;k<=((info->ppNum)-1);k++)
{
printf("For loop executionn number %d",k);
comm1=&(info->cArr[k]);
printf ("comm 1 : %s\n",comm1->cmd);
pid = fork();
if(pid == -1)
{
perror("fork failed");
exit(1);
}
if(pid == 0)
{
//2nd to n-1 child process
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
execvp(comm1->cmd,comm1->parms);
}
wait(NULL);
}
pid = fork();
if(pid == -1)
{
perror("fork failed");
exit(1);
}
if(pid == 0)
{
//nth child process
printf("Last child execution\n");
close(fds[1]);
dup2(fds[0], STDIN_FILENO);
close(fds[0]);
execvp(comm2->cmd,comm2->parms);
}
close(fds[0]);
close(fds[1]);
wait(NULL);
wait(NULL);
}
}
This following code should give you an idea how to implement the pipelining:
#define STDIN 0
#define STDOUT 1
void exec_cmd(struct comType cmd) {
execvp(cmd->cmd, cmd->params);
}
void pipeCmds(struct comType* cmds) {
int fd[cmds_length * 2] = {0};
pid_t pid = 0;
for (int i = 0; i < cmds_length; i++) {
if (pid = fork() == 0) {
//child: make this cmd's output the other cmd's input
pipe(fd + (2*i) );
close(STDOUT);
dup(fd[i]);
if(i > 0) {
close(STDIN);
dup(fd[i-1]);
}
exec_cmd(cmds[i]);
close(fd[i]);
}
}
}
Note that the main idea is that each command is executed in a separate process (via fork) and the output goes to the next command's input rather than to the default stdout(with file descriptor 1), and the same for the input - stdin (file descriptor 0).
I am implementing a shell in C. This is the function i use for piping. When i put "ls | a" in the code (i.e. pipe a valid command with invalid one),It doesnt exit the child process like it should. How do i make it go back to main function?
same thing happens when i do ps | ls or ps | pwd etc. but ls | ps works the same as in bash. i know ls | ps or ps | ls dont make sense but atleast they should give same output as bash.
void exec3(char **args, char **args2){
int fd[2];
pid_t pid,pid1;
int status;
pipe(fd);
int e=0;
if ((pid = fork()) < 0) {
printf("*** ERROR: forking child process failed\n");
exit(1);
}
else if ((pid1 = fork()) < 0) {
printf("*** ERROR: forking child process failed\n");
exit(1);
}
else if (pid == 0 && pid1!=0){
printf("in 1\n");
close(1);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
if(execvp(args[0],args)<0){
printf("**error in exec");
close(fd[0]);
close(fd[1]);
exit(1);
}
//printf("exiting 1\n");
exit(0);
}
else if (pid1 == 0 && pid!=0) {
printf("in 2\n");
close(0);
dup(fd[0]);
close(fd[1]);
close(fd[0]);
if((e=execvp(args2[0],args2))<0){
printf("**error in exec2 ");
close(fd[0]);
close(fd[1]);
exit(1);
}
exit(0);
}
else {
close(fd[0]);
close(fd[1]);
fflush(stdout) ;
while (wait(&status) != pid);
while (wait(&status) != pid1);
}
}
You are close to the solution. Look at how popen() is implemented, that is what you are trying to do.