Set fork()'s child into foreground, and exit parent - c

I am trying to change the PID of a process in Linux.
Then the idea is to use fork() to spawn a child, and give the control of the terminal to this child, then exit from parent.
The result would be a new process with new process PID without interrupting the execution flow.
I've coded the following PoC, but it doesn't work. If I don't use wait() on the parent, the child process doesn't take control of the terminal. I mean, it continues outputting but the stdin is not attached to the child, is owned by bash.
#include <string.h>
#include <stdio.h>
#include <asm/ptrace.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/sched.h>
#include <stdlib.h>
#include <signal.h>
int main(void) {
int i = 0, ret = 0;
pid_t pid = 0;
printf("PID = %d\n", getpid());
pid = fork();
if (pid == -1) {
return -1;
}
if (pid != 0) {
printf("Parent PGID = %d\n", getpgid(0));
printf("Parent PGID for 0 = %d\n", tcgetpgrp(0));
signal(SIGTTOU, SIG_IGN);
for (i = 0; i < 3; i++) {
ret = tcsetpgrp(i, pid);
}
exit(0);
}
setpgid(0, 0);
printf("Child PGID = %d\n", getpgid(0));
printf("Child PGID for 0 = %d\n", tcgetpgrp(0));
for (i = 0; 1; i++) {
printf("iter = %d, PID = %d\n", i, getpid());
usleep(300000);
}
return 0;
}
Thanks in advance.

Related

How do I make it so that processes are created parallel to each other rather than one after another?

I need help in modifying this code. Right now, it creates a process, and then waits for its termination. After which, another process is created, and then it waits for its termination. I want to modify it so that it creates both processes at the same time and executes them parallel to each other. The code is:
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char * argv[]) {
pid_t pid;
int status;
pid = fork();
if (pid != 0) {
while (pid != wait( & status));
} else {
sleep(5);
exit(5);
}
pid = fork();
if (pid != 0) {
while (pid != wait( & status));
} else {
sleep(1);
exit(1);
}
}
Here's code that should do the job:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
pid_t pid = fork();
if (pid != 0)
printf("Child 1 PID = %d\n", pid);
else
{
sleep(5);
exit(5);
}
pid = fork();
if (pid != 0)
{
printf("Child 2 PID = %d\n", pid);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("Child %d exited with status 0x%.4X\n", corpse, status);
}
else
{
sleep(1);
exit(1);
}
return 0;
}
One time when I ran it, I got the output:
Child 1 PID = 49582
Child 2 PID = 49583
Child 49583 exited with status 0x0100
Child 49582 exited with status 0x0500
If you preferred, you could move the wait() loop and its variable declarations after the if structures and immediately before the return 0; at the end. That would give you better symmetry. You could even wrap up the child creation phase into a function called twice:
static void procreate(int kidnum, int naptime)
{
int pid = fork();
if (pid != 0)
printf("Child %d PID = %d (nap time = %d)\n", kidnum, pid, naptime);
else
{
sleep(naptime);
exit(naptime);
}
}
and then in main() you'd just have two calls to procreate() and the wait loop:
int main(void)
{
procreate(1, 5);
procreate(2, 1);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("Child PID %d exited with status 0x%.4X\n", corpse, status);
return 0;
}

How do find the granchild pid in C?

I am trying to code a toy process manager and was wondering how do I find the grandchild pids when one of my children pids dies. I.e. how to deal with the "Readiness protocol".
systemd has the "Type=forking" option, which as far as I understand, waits for the forked pid to die and then assumes that one of the forked pid's children is the actual "daemon" to monitor.
My code so far is as following, but I am missing the XXX
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
int
main (int argc, const char *argv[])
{
printf("sup stared\n");
int pid;
prctl(PR_SET_CHILD_SUBREAPER);
pid = fork();
if (pid == 0) {
setpgid(0, 0);
printf("service started, pid: %d, pgid: %d\n",
getpid(), getpgid(0));
int dpid;
dpid = fork();
if (dpid == 0) {
printf("daemon started, pid: %d, pgid: %d\n",
getpid(), getpgid(0));
while (1);
}
printf("service exiting\n");
return 0;
} else {
printf("service pid: %d\n", pid);
int rc;
rc = waitpid(pid, NULL, 0);
printf("service exited? %d\n", rc);
int dpid;
dpid = XXcX();
printf("daemon, %d\n", dpid);
}
return 0;
}

How to make parent process wait for child processes to finish?

I have an assignment which gives me this code to transform into a code that makes the parent process wait for all children processes to finish.
PS: the first code has 4 processes and needs to use waitpid to solve this.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t p = fork();
pid_t k = fork();
if(p>0){
printf("p=%d: PID = %d\n", p, getpid());
sleep(45);
exit(0);
}
else if(p==0){
printf("p=%d: PID = %d\n", p, getpid());
exit(0);
}
else if(p<0){
printf("ERRO! p=%d\n", p);
exit(p);
}
}
I've tried this, but I think that this only works for only 1 child process and not for a lot of them.
int main(){
pid_t p = fork();
pid_t k = fork();
if(p<0){
printf("fodeu");
exit(p);
}
else if(p==0){
printf("");
exit(0);
}
else{
for(i=0;i<4;i++){
int returnstatus;
waitpid(p,&returnstatus,0);
if(returnstatus == 0){
printf("o processo filho correu normalmente");
}
else if(returnstatus == 1){
printf("o processo filho ardeu");
}
}
}
}
This won't do your assignment, but I hope it is advice enough to get
you going. The assignment appear to be a riddle around fork(), your
teacher has good taste :-)
fork() is different. It returns twice.
In the parent it returns the process ID of the created process.
In the child it returns 0; a process can always determine its PID using getpid()
Actually, the assignment is not good taste. Usually code using `fork()
never lets any branch escape into enclosing code to avoid complete
bullshit. Like so,
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid = fork();
if (pid == 0 /*child*/) {
printf("PID %d (child) doing work\n", pid);
sleep(5);
exit(0); // don't let it continue (leak) into parent code
}
else if (pid > 0 /*parent*/) {
int status;
pid_t terminated;
printf("PID %d (parent) waiting for child PID %d\n", getpid(), pid);
terminated = waitpid(pid, &status, 0);
if (terminated == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status))
printf("child exited normally with status %d\n", WEXITSTATUS(status));
else
printf("hm. child died otherwise. see 'man waidpid' for more\n");
}
return 0;
}
With this in mind, look at these two innocent looking lines,
pid_t p = fork(); // two processes after this
pid_t k = fork(); // executed by **two** processes, again duplicating
So, after these two lines we have four processes executing the rest of
the code in parallel. This is the point where brains explode. What
does the leaked child of the k line do when it asks what p's value
is?
Look at the output of this little program, to see what's the effect of
leaking.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
printf("MAIN PID %d\n", getpid());
fork();
fork();
printf("PID %d, PPID %d\n", getpid(), getppid());
return 0;
}
This is one way to do it; there will be numerous others.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static void wait_for_kids(void);
int main(void)
{
pid_t p = fork();
pid_t k = fork();
if (p > 0)
{
printf("p=%d: PID = %d\n", p, getpid());
sleep(5);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else if (p == 0)
{
printf("p=%d: PID = %d\n", p, getpid());
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else
{
printf("ERROR! p=%d\n", p);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(p);
}
/*NOTREACHED*/
}
static void wait_for_kids(void)
{
int corpse;
int status;
int pid = getpid();
while ((corpse = waitpid(0, &status, 0)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", pid, corpse, status);
}
Example output:
p=43445: PID = 43444
p=43445: PID = 43446
p=0: PID = 43445
p=0: PID = 43447
43447: p = 0, k = 0 - exiting
43445: child 43447 exited with status 0x0000
43445: p = 0, k = 43447 - exiting
43446: p = 43445, k = 0 - exiting
43444: child 43445 exited with status 0x0000
43444: child 43446 exited with status 0x0000
43444: p = 43445, k = 43446 - exiting

how can I send a signal between a child and a parent processes in linux

I have two cods the first one is for the parent which sends a signal (SIGUSER1) to the child and when the child receive it he should print that he received it.
Parent code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand(int);
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
FILE *fp1;
fp1 = fopen("cpid.txt", "w+");
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
fprintf(fp1, "%d\n", cpid);
// kill(cpid, SIGUSR1);//id, signal, send
sigset(SIGUSR2, sighand);
return 0;
}
void sighand(int the_sig){
if (the_sig == SIGUSR2){
printf("sigusr2 received");
exit(1);
}
}
Child code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand1(int);
int main()
{
FILE *fp1;
int pid;
fp1 = fopen("cpid.txt", "r");
fscanf(fp1, "%d,", &pid);
sigset(SIGUSR1,sighand1);
while(1) {
printf("Waiting..");
sigpause(SIGUSR1);
}
return 0;
}
void sighand1(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received");
exit(1);
}
}
When I start the code it prints that the process (child) was created then when I send a signal it wont do any thing the child stuck in a loop or the wait and the parent wont do anything can any one tell me where did i go wrong in my code or logic.
Your code has several problems:
You try to pass some pid through a file, but you can use the getppid() function (get parent id)
You have some child code, but it is not called
no signal is launched
So your code can be corrected this way:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void parent_handler(int the_sig)
{
if (the_sig == SIGUSR2){
printf("sigusr2 received in parent\n");
}
}
void child_handler(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received in child\n");
kill(getppid(), SIGUSR2);
exit(1);
}
}
int child_function()
{
/* prepare to receive signal */
sigset(SIGUSR1,child_handler);
while(1) {
printf("Waiting..");
fflush(stdout);
/* wait for signal */
sigpause(SIGUSR1);
}
return 0;
}
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
child_function();
return 0;
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
/* child will never reach this point */
sleep(1);
/* prepare parent to received signal */
sigset(SIGUSR2, parent_handler);
/* send signal to child */
kill(cpid, SIGUSR1);
sleep(1);
return 0;
}

Calling every child process at once to kill?

I have to write an program which will generate a random amount of processes, and then will kill them one after one, after they all were created.
My problem is that I can't stop the child processes after being created.
Also, I try to call the termination-output to stdout from a child process, but don't really know how to solve it (because pid = 0 is for every child process).
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
//int status;
srand(time(NULL));
int amount = (rand())%9+1;
pid_t fatherid = getpid();
printf("Hello I am a parent process, my PID is %d and I will now create %d children.\n",fatherid,amount);
pid_t pid = 1;
pid_t pidarr[amount];
for(int i = 0;i<amount;i++){
if(pid != 0){
pid = fork();
pidarr[i] = pid;
if(pid ==0){
printf("Hello I am a child process, my PID is %d and my parent has the PID %d.\n",getpid(),fatherid);
}
sleep(1);
}
}
if(pid != 0){
wait(NULL);
}
for(int i = (amount-1);i >= 0;i--){
if(pidarr[(i-1)] != 0){
printf("Hello I am a child process %d, I will terminate now.\n",getpid());
}
sleep(rand()%4);
if(pid != 0){
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
}
if(pid != 0){
printf("All child processes were terminated. I will terminate myself now.\n");
}
return EXIT_SUCCESS;
}
the following code shows how to handle fork and child processes.
the code compiles cleanly, is tested and works
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
int main( void )
{
//int status;
srand(time(NULL));
int amount = (rand())%9+1;
pid_t fatherid = getpid();
printf("Hello I am a parent process, my PID is %d and I will now create %d children.\n",fatherid,amount);
pid_t pid;
pid_t pidarr[amount];
for(int i = 0;i<amount;i++)
{
pid = fork();
if( -1 == pid )
{ //then, fork() error
perror( "fork() failed" );
exit(1);
}
// implied else, fork() successful
//pidarr[i] = pid;
if(!pid )
{ // then child process
printf("Hello I am a child process, my PID is %d and my parent has the PID %d.\n",getpid(),fatherid);
exit(0); // exit child process
}
// implied else, parent process
pidarr[i] = pid;
sleep(1);
} // end for
for(int i = (amount-1); i >= 0; i--)
{
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
printf("All child processes were terminated. I will terminate myself now.\n");
return(0);
} // end function: main
I am not sure about other parts of your logic (e.g. the if clause inside the fork loop), but
if(pid != 0){
wait(NULL);
}
looks suspiciously as of the parent process waits for a child to exit so that it doesn't get to the code which would kill the children at all (unless they exit on their own, but then the killing seems pointless).
Some issues in your code:
1) As #Peter Schneider points out,
parent process waits for a child to exit so that it doesn't get to the code which would kill the children
So first of all, you have to get rid of:
if(pid != 0){
wait(NULL);
}
2) The for loop that kills the children has to be executed only by the parent process, so the if clause embraces the for:
if(pid != 0){
for(int i = (amount-1);i >= 0;i--){
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
}
3) The child processes have to wait doing something until parent kills them, so append the following else clause to the above if:
else{
while(1){
printf("I am a child process %d. Will sleep for 2 senconds\n",getpid());
sleep(2);
}
}
4) the following code makes no sense, because when children are killed they simply stop working.
if(pidarr[(i-1)] != 0){
printf("Hello I am a child process %d, I will terminate now.\n",getpid());
}
If you want children to do something when the signal from kill() gets to them, you will have to use signals.

Resources