How to find pid using execlp()? - c

The getpid() gives me PID of a process. But now I want to find the PID using the execlp() command and also print the PID. But I am unable to solve it. Help.
#include <stdio.h> //my code so far
#include <unistd.h>
#include <sys/types.h>
int main()
{
execlp("/usr/include","/usr/include",getpid(),(char *)0);
}

I think your missing a step in your design. You are trying to use execlp() to call a library function getpid() and this just won't work. If you need to get the PID of the process through a call to execlp() then you need a program to call.
So start by creating a simple program that prints out its PID:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf( "%s %d\n", argv[1], getpid()) ;
}
Call this printpid.c and compile it to an executable called printpid. Then you can have a program that does this:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
pid_t pid = fork() ;
if ( pid == 0 )
{
execlp("./printpid", "printpid", "child", (char *)0) ;
} else {
execlp("./printpid", "printpid", "parent", (char *)0) ;
}
return 0 ;
}
Compile this to be an executable called forkprocess say and make sure that it and the printpid program are in the same directory. When you run forkprocess it runs printpid twice and printpid displays the PID of the process. To make it clear what is going on I'm passing a parameter to printpid to show if it's being called from the parent process or the child process created by the call to fork().

Related

How to enable the usage of fork(), wait() and execv()

I have an assignment to do which requires me to use fork(), wait and execv(). However, every time I try to use them I get an error that they aren't defined. Here is my code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
fork();
printf("Hello world!\n");
return 0;
}
Here is the errors I get:
I would appreciate it if anyone could help.

How to call execl (or simlar) and set signal handlers for the child process?

I am trying to write a program, caller, which traps SIGINT with sigaction, and calls an external program, prog.
I understand how to use sigaction on a simple program, but I don't know how to use it to set signal handlers for other processes (called by execl, for example).
The following is a MWE:
caller.c is this:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
void got_sig(int sig) {
printf("SIGNAL caught: %d\n",sig);
}
int main () {
struct sigaction sa;
(void) sigfillset(&sa.sa_mask);
sa.sa_handler = got_sig;
sa.sa_flags=0;
sigaction(SIGINT,&sa,NULL);
printf("\n");
execl("./prog", "./prog", (char*) NULL);
}
prog.c is this:
#include <stdio.h>
#include <unistd.h>
int main() {
for(int i=0; ; i++) {
sleep(1);
printf("epoch: %d\n",i);
}
}
But when I run caller, I see the output of prog.c, and hitting ^C does stop the prorgam (the signal is not trapped).
I suppose this is related to how execl works (it creates a new process, which does not inherit the parents' signal handlers -- is this right?)
So, how can I accomplish what I am trying to do?
Thank you!
execl("./prog", "./prog", "./prog", (char*) NULL);
Or if it's not working, check out here: https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html

How to redirect signal to child process from parent process?

I am trying to understand processes in C. I currently want to create shell-like structure which - after pressing a shortcut like Ctrl+C or Ctrl+Z will kill all its subprocesses but will stay alive. My code looks like this:
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
init_signals();
pid = fork();
if(pid > 0){
//Parent Process
wait(NULL);
} else {
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
Problem here is that, when I press Ctrl+C, parent redirects it to child and kills it but when I press Ctrl+Z (even though child process is stopped) parent still hangs on wait(NULL). Any suggestions on how to fix this?
You can check here how to use wait in C . Long story short:
The wait system-call puts the process to sleep and waits for a child-process to end. It then fills in the argument with the exit code of the child-process (if the argument is not NULL).
wait doesn't get signaled until the child process ends, so just by sending the child to sleep there is no reason for the main process to continue. If you want any setup where the main process still works while the child does as well (including when it sleeps!) you can't wait on the child.
Wouldn't make sense for a shell either - it's always active in the background. Instead you need a better handler on main - like waiting on a condition. That way, when sending a child to sleep, you can signal the condition and keep going.
Apart from the solution at https://stackoverflow.com/a/49346549/5694959 I would like to suggest one more solution as to handle signals for parent process only.This way parent will execute signal handler and default action will be performed for child process. Use waitpid() to get the status of child.
waitpid(pid, NULL, WUNTRACED);
Now parent will resume its execution when child process changes its state i.e. either terminated or stopped.
Update your code as follows:
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
pid = fork();
if(pid > 0){
//Parent Process
init_signals();
waitpid(pid, NULL, WUNTRACED);
printf("I think this is what you are expecting...\n");
} else {
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
Just one thing to keep in mind that please make sure that parent process
has handled signal before you press ctrl + c or ctrl + z otherwise, default action of signal will be performed for parent as well.

How to use memory when calling fork()

I'm learning about the fork() function. When I run the following code :
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int getpid(void);
pid_t fork(void);
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
sleep(1);//wait for parent process changing pid.
printf("Child:%d\nAddress:%p\n",pid,&pid);
exit(0);
}
printf("Parent:%d\nAddress:%p\n",pid,&pid);
pid=10;
exit(0);
}
the program always output like this:(the addresses of pid are same.)
Parent:31244
Address:0x7ffe5f3cd344
Child:0
Address:0x7ffe5f3cd344
If parent and child used the same memory, why did not the pid of child process change to 10 ? (Ubuntu & gcc 6.2.0)
Thanks for help :)

Set display before indicate path into (execlp)

I need to work with multiple displays in execlp calls (). I'm trying this:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("calling to execlp:\n\n");
execlp("DISPLAY=:0 /usr/bin/qtdisplay","qtdisplay", "-r", NULL);
execlp("DISPLAY=:1 /usr/bin/qtdisplay","qtdisplay", "-r", NULL);
printf("fail!");
exit(0);
}
But this fails, with the following message: execlp: No such file or directory
Is there any way to work with the displays?
Try system() instead, it'll start a new child process and call exec() from there. Also, it handles shell command-line constructs by calling a shell and handing your shell construct to that shell, like this:
system("DISPLAY=:0; /usr/bin/qtdisplay -r");
Also, learn to check return codes from functions like this, and do some sane action (like print an error message):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int rc;
rc = system("DISPLAY=:0; /usr/bin/qtdisplay -r");
if (rc == -1) {
perror("error starting qtdisplay on :0");
exit(1);
}
rc = system("DISPLAY=:1; /usr/bin/qtdisplay -r");
if (rc == -1) {
perror("error starting qtdisplay on :1");
exit(1);
}
exit(0);
}
If you want these two commands to be run in parallel (not one after the other), you should use command-lines like this:
system("DISPLAY=:0; /usr/bin/qtdisplay -r &");

Resources