How do you spawn another process in C? - c

How do you run an external program and pass it command line parameters using C? If you have to use operating system API, include a solution for Windows, Mac, and Linux.

It really depends on what you're trying to do, exactly, as it's:
OS dependent
Not quite clear what you're trying to do.
Nevertheless, I'll try to provide some information for you to decide.
On UNIX, fork() creates a clone of your process from the place where you called fork. Meaning, if I have the following process:
#include <unistd.h>
#include <stdio.h>
int main()
{
printf( "hi 2 u\n" );
int mypid = fork();
if( 0 == mypid )
printf( "lol child\n" );
else
printf( "lol parent\n" );
return( 0 );
}
The output will look as follows:
hi 2 u
lol child
lol parent
When you fork() the pid returned in the child is 0, and the pid returned in the parent is the child's pid. Notice that "hi2u" is only printed once... by the parent.
execve() and its family of functions are almost always used with fork(). execve() and the like overwrite the current stackframe with the name of the application you pass to it. execve() is almost always used with fork() where you fork a child process and if you're the parent you do whatever you need to keep doing and if you're the child you exec a new process. execve() is also almost always used with waitpid() -- waitpid takes a pid of a child process and, quite literally, waits until the child terminates and returns the child's exit status to you.
Using this information, you should be able to write a very basic shell; one that takes process names on the command line and runs processes you tell it to. Of course, shells do more than that, like piping input and output, but you should be able to accomplish the basics using fork(), execve() and waitpid().
NOTE: This is *nix specific! This will NOT work on Windows.
Hope this helped.

If you want to perform more complicated operations, like reading the output of the external program, you may be better served by the popen system call. For example, to programmatically access a directory listing (this is a somewhat silly example, but useful as an example), you could write something like this:
#include <stdio.h>
int main()
{
int entry = 1;
char line[200];
FILE* output = popen("/usr/bin/ls -1 /usr/man", "r");
while ( fgets(line, 199, output) )
{
printf("%5d: %s", entry++, line);
}
}
to give output like this
1: cat1
2: cat1b
3: cat1c
4: cat1f
5: cat1m
6: cat1s
...

#include <stdlib.h>
int main()
{
system("echo HAI");
return 0;
}

I want to give a big warning to not use system and 100% never use system when you write a library. It was designed 30 years ago when multithreading was unknown to the toy operating system called Unix. And it is still not useable even when almost all programs are multithreaded today.
Use popen or do a fork+execvp, all else is will give you hard to find problems with signal handling, crashs in environment handling code etc. It's pure evil and a shame that the selected and most rated answer is promoting the use of "system". It's more healthy to promote the use of Cocain on the workplace.

On UNIX, I think you basically need to fork it if you want the spawned process to run detached from your the spawing one : For instance if you don't want your spawned process to be terminate when you quit your spawning process.
Here is a page that explains all the subtle differences between Fork, System, Exec.
If you work on Win,Mac and linux, I can recommend you the Qt Framework and its QProcess object, but I don't know if that's an option for you. The great advantages is that you will be able to compile the same code on windows linux and mac :
QString program = "./yourspawnedprogram";
QProcess * spawnedProcess = new QProcess(parent);
spawnedProcess->start(program);
// or spawnedProcess->startDetached(program);
And for extra, you can even kill the child process from the mother process,
and keep in communication with it through a stream.

One solution is the system function defined in stdlib.h
int system(const char *string);
system api example

If you need to check/read/parse the output of your external command, I would suggest to use popen() instead of system().

Speaking of platform-dependent recipes, on Windows use CreateProcess, on Posix (Linux, Mac) use fork + execvp. But system() should cover your basic needs and is part of standard library.

Related

why a shell creates a new process for each command?

I am trying to program a shell in C , and I found that each command is executed in a new process, my question is why do we make a new process to execute the command? can't we just execute the command in the current process?
It's because of how the UNIX system was designed, where the exec family of calls replace the current process. Therefore you need to create a new process for the exec call if you want the shell to continue afterward.
When you execute a command, one of the following happens:
You're executing a builtin command
You're executing an executable program
An executable program needs many things to work: different memory sections (stack, heap, code, ...), it is executed with a specific set of privileges, and many more things are happening.
If you run this new executable program in your current process, you're going to replace the current program (your shell) with the new one. It works perfectly fine but when the new executable program is done, you cannot go back to your shell since it's not in memory anymore. This is why we create a new process and run the executable program in this new process. The shell waits for this new process to be done, then it collects its exit status and prompts you again for a new command to execute.
can't we just execute the command in the current process?
Sure we can, but that would then replace the shell program with the program of the command called. But that's probably not something you want in this particular application. There are in fact, many situations in which replacing the process program via execve is a the most straightforward way to implement something. But in the case of a shell, that's likely not what you want.
You should not think processes to be something to be avoided or "feared". As a matter of fact, segregating different things into different processes is the foundation of reliability and security features. Processes are (mostly) isolated from each other, so if a process gets terminated for whatever reason (bug, crash, etc.) this in the first degree affects only that particular process.
Here's something to try out:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int segfault_crash()
{
fprintf(stderr, "I will SIGSEGV...\n");
fputs(NULL, stderr);
return 0;
}
int main(int argc, char *argv)
{
int status = -1;
pid_t const forked_pid = fork();
if( -1 == forked_pid ){
perror("fork: ");
return 1;
}
if( 0 == forked_pid ){
return segfault_crash();
}
waitpid(forked_pid, &status, 0);
if( WIFSIGNALED(status) ){
fprintf(stderr, "Child process %lld terminated by signal %d\n",
(long long)forked_pid,
(int)WTERMSIG(status) );
} else {
fprintf(stderr, "Child process %lld terminated normally\n",
(long long)forked_pid);
}
return 0;
}
This little program forks itself, then calls a function that deliberately performs undefined behavior, that on commonplace systems triggers some kind of memory protection fault (Access Violation on Windows, Segmentation Fault on *nix systems). But because this crash has been isolated into dedicated process, the parent process (and also siblings) are not crashing together with it.
Furthermore processes may drop their privileges, limit themselves to only a subset of system calls, and be moved into namespaces/containers, each of which prevents a bug in the process to damage the rest of the system. This is how modern browsers (for example) implement sandboxing, to improve security.

how to call pkill in c program without using "system() library function"

In the below program, I've used system library function to execute "pkill" command. Is there any system call available for pkill(Because PID is unknown). I don't want to use "system" library function. Please let me know how to do it
#include <stdio.h>
int main()
{
char test[1024] = "pkill -15 radio";
system(test);
return 0;
}
The system call for sending signals to processes is kill; however, you need the process id for. If you intend to launch the program to be killed from within your application, too, use fork together with one of the exec-functions and you have it. Otherwise, you will most likely have to iterate over the /proc/* subdirectories.

C Fork program output explanation

I have a program in C which utilizes the fork() system call:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void doit(void)
{
pid_t pid;
fork();
fork();
printf("Unix System Programming\n");
return;
}
int main(void)
{
doit();
printf("WTF\n");
exit(0);
}
Now, this program gives me 8 lines of output. I think that is because of two forks 2^2 = 4 Times * 2 Print Statement = 8 Times. If I am wrong, please correct me and explain why.
Now, the question is why am I getting different outputs on each run? Let's say I execute this code: the first time I get output
Unix System Programming
WTF
Unix System Programming
Unix System Programming
Unix System Programming
WTF
WTF
WTF
and the 2nd time I get:
Unix System Programming
WTF
Unix System Programming
Unix System Programming
WTF
Unix System Programming
WTF
WTF
And third time again different. Why does this happen? I am clueless; kindly explain in detail.
When you fork a new process, the parent and child both run concurrently. The order that they execute their respective printf() statements is unpredictable -- sometimes the parent will print first, sometimes the child will.
You might understand better if you included the PID in the output, so you could see which process is printing each line. SO change it to:
printf("%d: Unix System Programming\n", getpid());
and
printf("%d: WTF\n", getpid());
What you should see is that each process prints Unix System Programming before WTF, but the order of processes will be mixed up.
The outputs that you are seeing are from different processes. Once fork has succeeded, you get a different child process (as well as the parent process). Since they are from different processes, you can't guarantee when one process gets its turn and executes. So the outputs of different processes get intermixed and the order might be different at each run.
If you want to make sure that parent and child processes run in some specific order then you have to synchronize them, which is typically a lot more work than just forking. (It will probably require a wait operation or the use of pipes — depending on the nature of synchronization that you want.)

Win XP, C program: Query regarding int main() for child process

I am creating a child process and passing some arguments to it.
Now, the child process starts execution from the next line of code, but will I have to write another int main () separately for the child process, as below, or would it just use the already written code for int main() of the parent process?
createProcess(All required arguments);
if (pid == child_process)
{
int main ()
{
......
}
}
ENV: WinXP, VS2005
NOTE: The above code just describes the flow and may have syntax errors.
Are you confusing Windows CreateProcess with UNIX fork()? The two operating systems are different in the way that processes are created. With Windows you have to execute an exe file from the beginning, you can't continue as the child process after CreateProcess as you can with fork on UNIX. Your statement "the child process starts execution from the next line of code" is mistaken for Windows.
Mind you, your code would be illegal on UNIX as well, you can't have two functions called main, and you can't have nested functions in C.
Please read the documentation of CreateProcess() again.
The function takes the filename of the program to run in the new process. The nested function you're showing is not valid C.

When to use system() and when to use execv*()?

I need to execute a unix command with different args in a loop. Now I wonder if I should use execvp(), passing in the cmd and the args, or use system, building a string consisting of cmd + args?
Well, the other answers are mostly correct.
System, while not only forks and then execs, it doesn't exec your process, it runs the default shell, passing your program as an argument.
So, unless you really want a shell (for parameter parsing and the like) it is much more efficient to do something like:
int i = fork();
if ( i != 0 ) {
exec*(...); // whichever flavor fits the bill
} else {
wait(); // or something more sophisticated
}
The exec family of functions will replace the current process with a new one, whilst system will fork off the new process, and then wait for it to finish. Which one to use depends on what you want.
Since you're doing this in a loop, I guess you don't want to replace the original process. Therefore, I suggest you try to go with system.
I'd use execvp only if I can't achieve what I want with system. Note that to get the equivalent of system, you need execvp, fork and some signal handling as well.

Resources