//code for foo (run executable as ./a.out)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char **argv) {
pid_t pid;
pid = fork();
int i = 1;
char *parms[] = {"test2", "5", NULL}; //test executable named test2
if(pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
else if(pid == 0) {
printf("Child pid is %d\n", pid);
i = execv("test2", parms); //exec call to test with a param of 5
}
else {
wait(NULL);
}
printf("I is now %d\n", i); //i is still 1 here, why?
return 0;
}
Hey everybody, I am trying to learn a little bit about fork and execv() calls. I make my foo.c program above make a call to a file I have named test.c. I fork a child and have the child make a call to execv, which will just add 10 to the parameter read in. I am unsure of why the variable does not change, at the bottom of my foo.c function. Does the call need to be a pointer or return an address? Any help would be greatly appreciated. Thanks
Code for test.c (executable named test2)
#include <stdio.h>
int main(int argc, char ** argv[]) {
int i = atoi(argv[1]);
i = i +10;
printf("I in test is %d\n", i);
return i;
}
You only call execv() in the child process. The exec() family functions never return if it runs successfully. See evec(3):
The exec() functions only return if an error has occurred. The return value is -1, and errno is set to indicate the error.
You printed the value of i in the parent process, it never changed in the parent process.
To get the exit status from the child process, you can make use of wait() or waitpid():
else {
int waitstatus;
wait(&waitstatus);
i = WEXITSTATUS(waitstatus);
}
Related
I'm trying to better understand exec() - so I have the following script in testing.c
#include <stdio.h>
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char ** argv)
{
if(argc < 2) {
fprintf(stderr,"Error:: Expecting an Argument!\n");
exit(-1);
}
pid_t pid;
pid = fork();
if (pid==0) {
execlp("./testing","testing",NULL);
fprintf(stderr, "I want to get to here...\n");
exit(-1);
}
wait(NULL);
printf("Parent and child done\n");
return 0;
}
The block below is the output after I execute with ./testing one:
Error:: Expecting an Argument!
Parent and child done
In reading how exec() works, I was expecting to be able to fprintf after my execlp call since it should be returning -1, I'm wondering if I need to be setting an errno or something or being more explicity about throwing something so that execlp recoginize the error?
If the execlp function successfully starts the given program, it does not return. The current program image gets replaced with the program image of the new program. So even if the new program exits with status -1, it still doesn't go back to the program that called execlp.
If you want to get the exit status of the child process, pass the address of an int to wait and read that:
int main(int argc, char ** argv)
{
if(argc < 2) {
fprintf(stderr,"Error:: Expecting an Argument!\n");
exit(-1);
}
pid_t pid;
pid = fork();
if (pid == -1 {
perror("fork failed");
exit(-1);
} else if (pid == 0) {
execlp("./testing","testing",NULL);
perror("execlp failed");
exit(-1);
}
int status;
wait(&status);
printf("child exit status: %d\n", WEXITSTATUS(status));
printf("Parent and child done\n");
return 0;
}
The output:
Error:: Expecting an Argument!
Parent and child done
is from
(first line) child process tries to run but no command line parameter.
(second line) parent process finishes
I am trying to write a program that will fork, then open a file and execute it. The file it should execute is called child and it has been compiled. When I type ./child, it runs. However, when I run this program it does not execute the child program and I am prompted with the error message I put in "Execution failed". What I am doing wrong?
This is my parent class
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int main (int argc, char **argv)
{
pid_t parent = getpid();
pid_t pid = fork();
if (pid == -1)
{
// error, failed to fork()
}
else if (pid > 0)
{
int status;
waitpid(pid, &status, 0);
}
else
{
int var = execvp("./child", NULL);
if(var < 0)
{
printf("Execution failed");
}
}
exit(0); // exec never returns
}
This is the child
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
printf ("Im the child");
exit (0);
}
I actually don't know what you are doing wrong. After a copy and a compilation (and several warning complains) your code runs fine (GCC 7.2).
Obviously, child must be in the same working directory in which you run your main executable (the one that forks).
But probably I would write that code in this way, but I'm not an expert in forking:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
extern int errno;
int main () {
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
if (pid == 0) {
int ret = execl("./child", "", (char *)NULL);
if(ret < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
} else {
wait(NULL);
}
return 0;
}
At least it tells you which error execl has encountered.
I'm trying my hand at some reverse engineering, and I'm a bit stumped on how to do in-memory patching. My target binary is a simple Hello World app that's signed. So while I can easily patch the binary, gatekeeper blows up (as it should).
The string is in-memory, so I thought I'd just use posix_spawn() with POSIX_SPAWN_START_SUSPENDED, patch the memory of the process with xnumem, and resume it. For some reason, that seems to fail as well. My test code;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <spawn.h>
#include <sys/wait.h>
#include "xnumem.h"
extern char **environ;
void run_cmd(char *cmd)
{
pid_t pid;
char *argv[] = {NULL};
int status;
printf("Run command: %s\n", cmd);
status = posix_spawn(&pid, cmd, NULL, NULL, argv, environ);
if (status == 0) {
printf("Child pid: %i\n", pid);
if (waitpid(pid, &status, 0) != -1) {
printf("Child exited with status %i\n", status);
} else {
perror("waitpid");
}
} else {
printf("posix_spawn: %s\n", strerror(status));
}
}
int main (int argc, const char * argv[]) {
char *arg;
arg = "./hello-world";
run_cmd(arg);
return 0;
}
I don't seem to be getting any errors, just a loop of;
Run command: ./hello-world
Child pid: 53209
Run command: ./hello-world
Child pid: 53210
...
and then it terminates.
Can someone point me in the right direction? How can I start a process in a suspended state, alter its memory, and resume without tripping gatekeeper?
I have a binary file that contains a program with function written in C inside that looks like:
int main()
{
int a, b;
foo(a,b);
return 0;
}
And now I want to execute that program by using fork() and execve() in another program called "solver".
int main(int argc, char* argv[])
{
pid_t process;
process = fork();
if(process==0)
{
if(execve(argv[0], (char**)argv, NULL) == -1)
printf("The process could not be started\n");
}
return 0;
}
Is that a good way? Because it compiles, but I'm not sure whether the arguments of function inside "worker" program receive variables passed by command line to "solver" program
I believe you are trying to achieve something like that:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
static char *sub_process_name = "./work";
int main(int argc, char *argv[])
{
pid_t process;
process = fork();
if (process < 0)
{
// fork() failed.
perror("fork");
return 2;
}
if (process == 0)
{
// sub-process
argv[0] = sub_process_name; // Just need to change where argv[0] points to.
execv(argv[0], argv);
perror("execv"); // Ne need to check execv() return value. If it returns, you know it failed.
return 2;
}
int status;
pid_t wait_result;
while ((wait_result = wait(&status)) != -1)
{
printf("Process %lu returned result: %d\n", (unsigned long) wait_result, status);
}
printf("All children have finished.\n");
return 0;
}
./work will be launched with the same arguments as your original program.
Can someone pls explain why the output of the following program is 1 and not 2?
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int x = 1;
int *y = &x;
pid_t pid = fork();
if (pid == 0) {
*y = 2;
exit(0);
} else {
wait(NULL);
printf("father: %d\n", x);
}
return 1;
}
fork doesn't create a thread, it creates a whole new process.
The address space of the child is a copy of the parent's one, they don't share it.
Modifications done by the parent are not visible from the child, and vice-versa, unless the specifically set something up to do so (via shared memory segments for instance).