How can I make a process of a program? - c

Hey I have to write a small process launcher for uni.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
pid_t pid;
if((pid = fork()) < 0){
return 0;
}
else if(pid == 0){
if(execvp(*argv, argv) < 0){
return 0;
}
}
return 0;
}
This is my program. I want to call it like ./process-launcher firefox --browser to start a new firefox process.
I think when I start the programm like this there should be a process of firefox in my system monitoring but it isn't
How do I get this?
Compiling with:
clang -o process-launcher process-launcher.c

What is in *argv? Your launcher name...
So when executing your code as is, you only relaunch your launcher...
Solution: ++argv;, it will pass the second parameter to execvp:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
pid_t pid;
if((pid = fork()) < 0){
return 0;
}
else if(pid == 0){
++argv;
printf("execvp(%s, ...)\n", *argv);
if(execvp(*argv, argv) < 0){
return 0;
}
}
return 0;
}

Related

execve failed to overlay process

I am new to parallel processing and was attempting to use fork() to create a new child process where I would like to overlay this process by using execve. It happened to me that execve("_filename",array, NULL) sometimes works but most of the time, it failed to overlay the process and return -1; I tried to run other's sample code but it failed on my laptop so I am wondering if this is because of my mac's configuration? I am really new to this topic and hope I can find help here, thanks!
Here is the program I am attempting to run:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char **argv) {
// populate arraay with random numbers
int child_status;
pid_t pid;
int i;
pid = fork();
char *array[3] = {"Hello", "There", "Test"};
if (pid == 0) {
pid = execve("Process4", array, NULL);
exit(0);
}
int num = -1;
printf("What is 2 + 2");
while (num != 4) {
scanf("%d", &num);
if (num == 4) {
printf("You win \n");
} else {
printf("%i incorrect - try again ", num);
printf("\r\b\r");
}
}
wait(&child_status);
return (0);
}
And for Process4, I wrote below:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int secs = 0;
int main(int argc, char **argv) {
int i;
if (argc > 0) {
printf("The arguments supplied are:\n");
for (i = 0; i < argc; i++) {
printf("%s\t", argv[i]);
}
} else {
printf("argument list is empty.\n");
}
int j;
printf("\n");
while (secs < 10) {
printf("Time:%i\n", secs);
fflush(0);
sleep(1);
secs++;
printf("\r\b\r");
}
return 0;
}
My process4 should be able to receive the parameters passed in (as an array in the second argument) and start the timer.
Thanks in advance for the help.
The array to specify the arguments for execve() must be terminated by NULL.
Try
char *array[] = {"Hello", "There", "Test", NULL};
instead of
char *array[3] = {"Hello", "There", "Test"};

Can't get execvp to execute file

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.

fork() and exec() run in parallel in C

I am trying to run three execv("./test",execv_str) in parallel. And I need to print out success message when each of execv() completes successfully.
But now I get result as following:
username#username:~/Desktop/$./test -p
SUCCESS
SUCCESS
SUCCESS
username#username:~/Desktop/$ TESTING
TESTING
TESTING
The expected result will be:
username#username:~/Desktop/$./test -p
TESTING
SUCCESS
TESTING
SUCCESS
TESTING
SUCCESS
username#username:~/Desktop/$
Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int fork_execv()
{
int status;
pid_t pid;
pid = fork();
/* Handling Child Process */
if(pid == 0){
char* execv_str[] = {"./test", NULL};
if (execv("./test",execv_str) < 0){
status = -1;
perror("ERROR\n");
}
}
/* Handling Child Process Failure */
else if(pid < 0){
status = -1;
perror("ERROR\n");
}
return status;
}
int main(int argc, char *argv[]){
if (argc == 1){
sleep(5);
printf("TESTING\n");
}
else{
int i;
for(i = 0; i < 3; ++i){
if (fork_execv() != -1){
printf("SUCCESS\n");
}
}
}
}
How to modify my code to make it work?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int fork_execv()
{
int status;
pid_t pid;
pid = fork();
/* Handeling Chile Process */
if(pid == 0){
char* execv_str[] = {"./test", NULL};
if (execv("./test",execv_str) < 0){
status = -1;
perror("ERROR\n");
}
}
/* Handeling Chile Process Failure */
else if(pid < 0){
status = -1;
perror("ERROR\n");
}
return pid;
}
void handler(int sig){
printf("SUCCESS\n");
}
int main(int argc, char *argv[]){
if (argc == 1){
sleep(5);
printf("TESTING\n");
}
else{
int i;
pid_t process_id;
for(i = 0; i < 3; ++i){
if ((process_id = fork_execv()) != -1){
if(process_id != 0){
signal(SIGCHLD, handler);
waitpid(process_id, NULL, 0);
}
}
}
}
}
Here what I would do. After the fork, I return the pid, check if it isn't 0 (so we are in the father process) and make the father wait for the son. To print "success", I bind the SIGCHLD signal that is triggered when a child process ends. Note that this is a little overkill and put print after the waitpid would have done the job. (But I like to bind signal.)

C: Trying to implement unnamed pipes

I'm trying to make a program that simlutates the terminal's nameless pipes. For example, if I want to run the command:
ls –l | grep ‘10’
would be:
./pipes ls -l - grep '10'
(I use - instead of |).
However, my program doesn't work because execvp fails (bad adress). This seems impossible to me. What am I doing wrong? Any help would be welcome!
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
void np_exec(char* cmd, char** argv)
{
int fd[2];
while(*(++argv) != NULL)
{
pipe(fd);
int pid = fork(); //parent executes
if(pid < 0)
{
printf("Error forking");
exit(1);
}
if(pid != 0) // parent
{
dup2(fd[1],1);
close(fd[0]);
if (execvp(cmd, *argv) == -1)
{
perror("execvp failed");
}
}
else
{
dup2(fd[0],0);
close(fd[1]);
}
}
}
int main(int argc, char** argv)
{
assert(strcmp(argv[argc-1], "-"));
int i;
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "-"))
{
argv[i] = NULL;
np_exec(argv[1], &argv[1]);
argv = &argv[i];
argc -= i;
i = 0;
}
}
char* args[argc];
args[argc-1] = NULL;
for (i = 1; i < argc; ++i) {
args[i-1] = argv[i];
}
if (execvp(args[0], args) == -1)
perror("execvp failed");
return;
}
Replace:
if (execvp(cmd, *argv) == -1)
by:
if (execvp(cmd, argv) == -1)
Notes:
a) is the warnign level you use high enough?
b) you must add a "#include" for "execvp". In this way, the compiler will find by itself this error.
c) last return statement must be "return 0". Again, compiler must warning you of this subject.

execve won't run executable assembly file

I'm trying to create a c program that takes an executable and its arguments and runs them using execve, and then does some other stuff that shouldn't matter. The problem I'm having is that execve won't work when calling it on an exectuable assembly file. I think the problem is with my path because I can get the unix shell commands to work, but I can't get executables in the current directory (using ./spy ./executableName where spy is the name of my c program) to run. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
extern char **environ;
int main(int argc, char* const argv[]) {
pid_t pid;
char filename[50];
char* arglist[argc];
int i = 1,count = 0;
int status;
strcpy(filename, "/bin/");
strcat(filename,argv[1]);
for(i = 1; i< argc; i++)
arglist[i-1] = argv[i];
arglist[argc-1] = 0;
arglist[0] = filename;
if (argc == 1) {
fprintf(stderr,"usage : %s <prog> ...\n",argv[0]);
return -1;
}
pid = fork();
if(pid == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
if(execve(filename, arglist, 0) < 0)
fprintf(stdout,"Invalid file.");
}
else {
while(1) {
waitpid(pid,&status,0);
if (WIFEXITED(status))
break;
ptrace(PTRACE_SINGLESTEP, pid,NULL, NULL);
count++;
}
}
return 0;
}
From the source you posted it looks as if you were always prefixing the name passed as parameter with /bin/. So if the file isn't in /bin/ it can not be found, nor run.
Just change these two lines:
strcpy(filename, "/bin/");
strcat(filename,argv[1]);
to be:
strcpy(filename,argv[1]);
Note that having applied this modification the program to be run needs to be specified with its full path.
So to run ls you need to do specfify /bin/ls as parameter to the program.
Some other comments:
So avoid buffer a overflow for long path/file names change:
char filename[50];
to be:
char filename[PATH_MAX];
To get more detailed information on why an execve() might have failed change:
if(execve(filename, arglist, 0) < 0)
fprintf(stdout,"Invalid file.");
to be:
if(execve(filename, arglist, (char*) 0) < 0)
perror("execve() failed");
To detect a possible failure of forking do change:
pid = fork();
to become:
if (-1 == (pid = fork())) then
{
perror("fork() failed");
}
else

Resources