reverse calls order in fork - linux

Warm greetings,
I wrote these lines which display 4 messages corresponding to 'A', 'B', 'C', and 'D' with a for loop and fork. I would like to reverse the calls (output becomes 'D' 'C' 'B' 'A') by making the parent process wait for the children to execute first.
Initial code (right order from A to D):
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i;
for(i=0;i<4;i++){
if (fork()){
break;
}
printf("Mon nom est %c. Je viens du processus %d\n",'A'+i,getpid());
}
return(0);
}
My code for the desired output (from D to A):
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i;
for(i=0;i<4;i++){
if (fork()){
wait(NULL);
break;
}
printf("Mon nom est %c. Je viens du processus %d\n",'A'+i,getpid());
}
return(0);
}
I added wait(NULL) but it doesn't seem to help.
I thank you all in advance!!

Lets trace i between the processes:
P0:i=0; fork(); wait(); exit();
P1: i=0; printf(); i = 1; fork(); wait(); exit();
P2: i=1; printf(); i=2; fork(); wait(); exit();
See the pattern; the parent is always wait()ing and exit()ing without printing. The child prints in the parents place, then becomes the parent of the next generation.
Not to be too picky about style, but even such a small program can benefit from a structured indentation:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
int i;
for (i=0;i<4;i++) {
if (fork()) {
wait(NULL);
break;
}
printf("Mon nom est %c. Je viens du processus %d\n",'A'+i,getpid());
}
return(0);
}

Related

Sigaction doesnt work

I am learning about signals and wrote a simple programs that plays with them.
So i am inputting a number then using fork i create a process.The parent process is supposed to send the number as a signal to the child process,then the child_signal handler is supposed to send back the number squared as a signal.
This is the code.
#include <iostream>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
using namespace std;
void child_handler(int sig_num){
cout<<"Child recieved a signal"<<endl;
pid_t ppid = getppid();
if(kill(ppid,sig_num*sig_num) == -1){
cout<<"Childs signal handler failed to send a signal "<<endl;
}
cout<<"Sent a sgnal to the parent"<<endl;
return;
}
void parent_handler(int sig_num){
cout<<"Parent recieved a signal "<<endl;
cout<<sig_num<<endl;
return;
}
int main(){
int n;
cin>>n;
pid_t pid = fork();
if(pid != 0){
struct sigaction sa2;
memset(&sa2,0,sizeof(sa2));
sa2.sa_handler = parent_handler;
if(sigaction(n,&sa2,NULL) == -1){
cout<<"Parents sigaction failed "<<endl;
}
if(kill(pid,n) == -1){
cout<<"Kill failed "<<endl;
}
cout<<"Sent a signal to the child"<<endl;
waitpid(pid,0,0);
}
else{
struct sigaction sa1;
memset(&sa1,0,sizeof(sa1));
sa1.sa_handler = child_handler;
if(sigaction(n,&sa1,NULL) == -1){
cout<<"Childs sigaction failed eerno:"<<errno<<endl;
}
sleep(20);
return 0;
}
return 0;
}
The output is this.
Sent a signal to the child.
And it doesn't say anything about sigaction.
In your code a child process can receive a signal before setting a handler.

Using cat and execvp

Trying to understand why this section of code using the cat command isn't working with execvp in C.
char *in[5] ={"cat", "file1.txt", ">>", "file2.txt", 0};
execvp(in[0], in);
When I run it displays the contents of file1.txt but then says:
cat: >> No such file or directory.
Then displays the contents of file2.txt
Why wouldn't it recognize the >> operator in this instance?
You can read the "man tee" command which it read from standard input and write to standard output and files. You could achieve this with below example.
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
/*
Implementation of below command:
cat file1.txt > file2.txt
*/
char *cmd1[] = { "/bin/cat", "file1.txt", 0 };
char *cmd2[] = { "tee", "file2.txt", 0 };
static void sigchld_hdl (int sig)
{
int status;
while (waitpid(-1, &status, 0) > 0) {
if(WIFEXITED(status))
printf("Child exited with code %d\n", WEXITSTATUS(status)); }
}
int runcmd(int pfd[])
{
int i=0;
switch (fork()) {
case -1:
perror ("fork");
return 1;
case 0:
dup2(pfd[0], 0);
close(pfd[1]); /* the child does not need this end of the pipe */
execvp(cmd2[0], cmd2);
perror(cmd2[0]);
exit(10);
default: /* parent */
dup2(pfd[1], 1);
close(pfd[0]); /* the parent does not need this end of the pipe */
execvp(cmd1[0], cmd1);
perror(cmd1[0]);
}
sleep(1);
}
int main (int argc, char *argv[])
{
struct sigaction act;
int fd[2];
pipe(fd);
memset (&act, 0, sizeof(act));
act.sa_handler = sigchld_hdl;
if (sigaction(SIGCHLD, &act, 0)) {
perror ("sigaction");
return 1;
}
runcmd(fd);
return 0;
}

How does ptrace work with 2 different processes?

I was reading about ptrace on the net and found that a process can request to trace another process by using PTRACE_ATTACH but apparently all the examples available involve the use of fork().
What I want is to have 2 programs - prg1.c and prg2.c where prg2.c should trace prg1.c. I tried using PTRACE_ATTACH in prg2.c but it seems that the call failed - prg2.c couldn't trace prg1.c . How does ptrace work ? Can anybody explain ?
Code for prg1.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Hello world\n");
sleep(20);
execl("/bin/ls", "ls", NULL);
return 0;
}
Code for prg2.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc , char **argv)
{
int pid = atoi(argv[1]);
int status;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
printf("ptrace attach failed!");
return 0;
}
wait(&status);
sleep(5);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return 0;
}
I have included a sleep() to get the pid of prg1's executable(during that time) using ps -af and give it as an input to the executable of prg2.

Why the program didn't execute some sentences in this C programming or unix programming(execvp() System calls)?

I have the following program, when I run the program, I feel really confused that why my program didn't excute
int num=i;
printf("it is No.%d !",num);
printf("hello , I will excute execvp!");
My program basically create 6 child processes to excute executionbode() function, and then use execvp to overload original program. However, everytime when I run the program, the string "hello, I will execute execvp" never shows up! Also I think those three sentences above also didn't execute in the running program? can someone tell me why? Here is my program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "makeargv.h"
#include "redirection.h"
#include <sys/wait.h>
int executionnode(int i);
int main(){
pid_t childpid;
int i;
int row=6;
for(i=0;i<row;i++)
{ childpid=fork();
if(childpid==0)
continue;
else if (childpid>0)
executionnode(i);
else {
perror("something wrong");
exit(1);
}
}
}
int executionnode(int i){
sleep(i);
printf("hello, I am process:%ld\n",(long)getpid());
wait(NULL);
char *execArgs[] = { "echo", "Hello, World!", NULL };
int num=i;
printf("it is No.%d !",num);
printf("hello , I will excute execvp!");
execvp("echo", execArgs);
}
Can someone tell me why? and how to fix it? I feel it is really strange? Is it because of execvp() functions? I just began to learn operating system,so I am really confused about it! Thank you for helping me!
As user3629249 said you have some confusion. You'll get many children of children of children... and that wait(NULL) is useless :).
I used this structure to got your goal in my OS subject excercises.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#define N 5
int main(int argc, char const *argv[])
{
pid_t pid,pids[N];
int i, num_pids = 0;
int state = 0;
int prior[]={1,3,5,2,4};
pid_t parent_pid = getpid();
printf("Parent pid is %i\n",father_pid);
// This for loop is the key
for (i = 0; i < N && getppid() != parent_pid; i++)
{
if ((pid = fork()) < 0)
{
printf ("fork error\n");
exit(-1);
}
pids[num_pids++] = pid;
}
if (pid == 0) // Child processes
{
printf("I am the child %i\n",getpid());
}
else // Parent process
{
for (i = 0; i < N; i++)
{
int pid_index = prior[i]-1; // Array starts with 0
pid = waitpid(pids[pid_index]);
printf("Children %i ended\n",pids[indice_pid]);
printf("%i alive children\n",N-1-i);
}
}
return 0;
}
This structure works because you save the parent's pid in parent_pid variable and compare the parent of each process pid with getppid(). If this pid is different that parent_pid, this proccess is the parent. In another case the process is a child so it has to stop (these processes don't have to fork). With this way you can get only the forks you need.
The rest of the code is the same: Pid==0 is child process and any other is the parent. You can call executionnode(int i) in child processes block (remember, pid==0 !!! you have a mistake). i variable should have the right value in each call I think.
Good luck!

debugging server's cgi program

i am trying to make a webserver in C which can handle request to dynamic contents.
the webserver part is finish already. i'm trying to execute the following command:
http://localhost:1601/cgi-bin/test?3&7
with the code of program test is as follow:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <wordexp.h>
#define MAXLINE 300
int main(int narg, char * arg[]) {
char *buf, *p;
char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
int n1=0, n2=0;
/* Extract the two arguments */
if ((buf = getenv("QUERY_STRING")) != NULL) {
p = strchr(buf, '&');
*p = '\0';
strcpy(arg1, buf);
strcpy(arg2, p+1);
n1 = atoi(arg1);
n2 = atoi(arg2);
}
/* Make the response body */
sprintf(content, "Welcome to add.com: ");
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
content, n1, n2, n1 + n2);
sprintf(content, "%sThanks for visiting!\r\n", content);
/* Generate the HTTP response */
printf("Content-length: %d\r\n", (int)strlen(content));
printf("Content-type: text/html\r\n\r\n");
printf("%s", content);
if (fork()==0) {
printf("asdfagloiauergauhfgaiudfhg");
execvp("ls",arg);
printf("child of adder error");
}
printf("%s", content);
fflush(stdout);
exit(0);
}
/* $end adder */
It run well. However, i wonder why the child code (the line printf("asdfagloiauergauhfgaiudfhg"); and execvp) didn't print out to the webserver's output. although everything else in test output correctly.
For starters you set the Content-length header to the length of the content, then sent the content, then sent more data in both threads. The browser is within its rights to ignore everything after content-length bytes in the output stream.

Resources