I'm trying to use the function execlp() to make a child processes run a specific code that I wrote, but I don't understand how the path works.
NOTE: I use export PATH=$PATH:. in the terminal so I don't need to type /.ProgName every time.
The first program is:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
main() {
pid_t childpid;
int i;
int nprocess = 3;
for (i = 0; i < nprocess; ++i) {
if ((childpid = fork()) < 0) {
perror("fork:");
exit(1);
}
if (childpid==0){
printf("I'm the son with ID= %ld\n",(long)getpid());
char *path = "exectest";
if ((execl(path,"0",NULL))<0) printf("\n error exec \n");
}
else
printf("I'm the father with ID= %ld",(long)getpid());
}
}
The second program to be called by the execlp is :
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
void main(){
printf("\n I'm using exec \n");
}
Both programs are in the same directory. The second program is named "exectest" but when I launch the first, I get the error message.
You should compile your second file exectest.c and get executable file which called exectest, because of your first program launch executable file exectest.
Related
Is there a way to obtain the status of a command run with execv without waiting for it with waitpid or wait?
The program I need to do reads other executable program as argument and need to print the status of this program when executed with execv exactly when the command is finished executing, but needs to keep executing after the fork instead of waiting for the program passed as argument to finish executing.
Here is what I have right now which doesn't seem to capture any status:
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio_ext.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/shm.h>
int status;
void child_exit_handler(int signal)
{
int pid = wait(&status);
}
int main(int argc, char *argv[])
{
pid_t pid;
signal(SIGCHLD, child_exit_handler);
for (int i = 1; i < argc; i++)
{
pid = fork();
if (pid == 0)
{
char *cmd[4];
cmd[0] = "sh";
cmd[1] = "-c";
cmd[2] = argv[i];
cmd[3] = NULL;
execv("/bin/bash", cmd);
}
}
if (pid > 0)
{
// do something;
// later do something with status
}
}
I'm writing this program:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
int main(){
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if(pid>0)
{
while(1){
char * command = (char*)malloc(55);
printf("Command: ");
fgets(command,55,stdin);
write(fd[1],&command,55);
wait(NULL);
}
}
else if(pid)
{
char * command = (char*)malloc(55);
read(fd[0],&command,55);
printf("Child command: %s",command);
}
return 0;
}
and when I compile I'll get this error:
I can't figure out what could be. I know that I'm not using all libraries and checking for errors but i think that's not the issue here. Thanks! Have a great day!
My goal is to create N process child with one process father.
I am using two files.The first is named forkn.c which contains this code:
#include <sys/types.h>
#include <wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[] )
{
int status =4;
int i=1;
int wpid;
for (int cpt=0;cpt<atoi(argv[1]);cpt++)
{
if (i>0)
{
i=fork();
if(i>0)
printf("I create process number %d \n",cpt+1);
}
}
//The father process created argv [1] son process. This ensures a single father and argv [1] son process
if(i==0)
{
execl("~/tpBash/tp2/argv[2]","argv[2]",(char*) NULL);
}
if (i>0)
{
for(int cpt=0;cpt<atoi(argv[1]);cpt++)
{
wait(&status) ;
}
printf("I am the father, I waited all my son processes, I finished \n");
}
}
And there is the code of trait2.c:
#include <sys/types.h>
#include <wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int status =4;
printf("I am the child process,my PID is : %d \n",getpid());
exit(status);
}
After i compile :
gcc -std=c99 forkn.c -o forkn
gcc -std=c99 trait2.c -o trait2
And then run the executable file :
./forkn 3 trait2
the first arguments is N (the number of child process to create ) and the second argument is the name of file to execute.
My problem is that the child process does not work.
Any idea please
The problem you are seeing is related to the way you're trying to do string interpolation:
execl("~/tpBash/tp2/argv[2]","argv[2]",(char*) NULL);
I suggest you try snprintf:
char buffer[ENOUGH];
snprintf(buffer, sizeof buffer, "%s/tpBash/.../...%s", home, argv[2]);
execl(buffer, argv[2]...);
Also, the second argument to execl should be argv[2] and not "argv[2]".
I am getting a warning > Implicit declaration of function ‘wait’ < and when I run the program it works correctly, I would like to understand why I am getting this warning?
Thanks in advance
Edit: I forgot to add the library included
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void create (char* program, char** arg_list)
{
/* put your code here */
pid_t childPid;
int status;
if((childPid = fork()) < 0){
printf("Failed to fork() --- exiting...\n");
exit(1);
}
else if (childPid == 0){ // --- inside the child process
if(execvp(program, arg_list) < 0){ // Failed to run the command
printf("*** Failed to exec %s\n", program);
exit(1);
}
}
else{ // --- parent process
while(wait(&status) != childPid)
printf("...\n");
}
}
You are probably missing the headers for wait(2):
#include <sys/types.h>
#include <sys/wait.h>
You need to put:
#include <sys/types.h>
#include <sys/wait.h>
at the top of the program to get the declaration of the function.
This is shown in the man page
I already used execl() in code, and it worked well.
But this time, I really have no idea why it doesn't work.
So here's the code that do not work
#include <unistd.h>
#include <stdio.h>
int main()
{
int i = 896;
printf("please\n");
execl("home/ubuntu/server/LC/admin/admin", (char*)i, NULL);
printf("i have no idea why\n");
return 0;
}
And here's the admin.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int mid = argv[0];
printf("hi from child\n");
printf("%d\n", mid);
return 0;
}
Of course I compiled admin.c to admin, and the path isn't wrong.
>ls
admin admin.c why why.c
>pwd
/home/ubuntu/server/LC/admin
>./admin
hi from child
-1180858374
>./why
please
i have no ida why
Anyone know why it doesn't work?
My C is a bit rusty but your code made many rookie mistakes.
execl will replace the current process if it succeeds. So the last line ("i have no idea why") won't print if the child can launch successfully. Which means...
execl failed and you didn't check for it! Hint: check the typecast to char *.
You cast an int to a char * in the execl call, then again when you launch the child (admin). This is a big no-no in C. It freely allows you to misinterpret types. The only warning is most often a crash. GGC will warn you about it. I don't know about the compiler on AWS.
Check your array's bound! You don't know how many parameters admin was launched with. argv[0] always exist because it contains a representation of the program name. argv[1] may not be defined. Accessing array out-of-bound is an undefined behavior and highly dangerous.
The standard way to start another process in C is to fork the parent, then call one of the functions in the exec family to start the other process.
Consider this instead (I took the liberty to emit different messages to make them clearer).
parent.c
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main()
{
int i = 896;
char str[15];
int pid;
printf("Hello from parent\n");
sprintf(str, "%d", i); // convert the number into string
pid = fork();
if (pid == -1)
{
printf("Fork failed\n");
}
else if (pid == 0)
{
printf("Continue from parent\n");
}
else
{
// start the child process
execl("home/ubuntu/server/LC/admin/admin", str, NULL);
// check if it started properly
if (errno != 0)
{
printf("Error launching child process: %s\n", strerror(errno));
return 1;
}
}
printf("Goodbye from parent\n");
return 0;
}
admin.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char * mid;
// argc is always 1 or more
if (argc >= 2)
mid = argv[1];
else
mid = "<nothing>";
printf("hello from child\n");
printf("argc = %d, argv[1] = %s\n", argc, mid);
return 0;
}