I am trying to run a new process in background so it will be possible to continue working with parent process.
I used fork then execl. I tried to add to the execl command the argument & but it doesn't work:
execl("newproc","newproc","arg1","&",NULL);
Is there any solution?
The child will run in the background since you used fork. The child will keep running in parallel with the parent (if exec succeeded). If you care about whether the child process succeeded or not (and your code should) you should eventually call waitpid to collect its exit status. Otherwise you should call fork twice and have the intermediate process exit without waiting for the child, so that init adopts the grandchild process.
As #mah said, the & is unnecessary. But another change is needed to that line; execl is a variadic function, and function prototypes therefore don't take care of converting arguments to the correct type. Therefore the final argument should be passed as the correct type - just change it to (char*)NULL.
You mention that your code didn't work. While that could just be because of the spurious &, it may also be because of the first argument. The execl function does not search $PATH for the named program, so unless newproc is actually in the current directory, this execl() invocation will return. When execl returns, that always indicates that there is a problem. The simplest way to solve this is to use execlp() instead of execl(). The alternative approach is to specify an absolute path as the first argument. You can even specify a relative path as the first argument, but this is rarely useful.
The problem is that & is not a command line option to programs. Instead, it is merely special shell syntax which puts a command in the background. The distinguishing feature of background programs is that they are not connected to a terminal, and the terminal is not waiting for the process to complete. The proper function is daemon(). Do a man daemon to read up on how it is used.
& is not a command argument, its a flag that the shell uses to know to run the command in the background. In this case, you're performing the work of the shell... remove the &. Since you state you've called fork(), as long as you're only performing execl() in the child process after fork returns, you're already running in the background.
Related
I am trying to understand the specifications of a C coding project using fork() and execv().
Essentially, I am told I need to either propagate or not propagate the environment variables of the shell to the command I am executing in a child process depending on a binary value.
Though, regardless, I am supposed to pass in any additional environmental variables I am provided to the command I am executing in the child.
This whole idea is new information to me, so I am just trying to understand what exactly this means.
To my understanding, when a child is created using fork(), the environmental variables of the parent process are passed on to the child, and then any additional environmental variable changes can be made as an argument of the execve() function when it is run within the child.
But if this is the case, then the environmental variables are always propagated from the parent/shell anyway right? So what is the difference and how would I not propagate those variables?
Thanks for your time.
You're still in control after the fork() and before the execv().
You can make changes to your child's environment that you don't want to make to your parent -- including calls to unsetenv() -- in that process.
Alternately, you can construct a new environment entirely and pass it in the envp argument to execve().
If you understood fork(2) then you'll know that the parent and the child are exactly the same (except for the value returned by fork()), so the environment of the parent process is exactly the same as the environment of the child. there's no other way to pass environment to a child process... because execve(2) doesn't create a new process. You only load the process' virtual space by loading a new program on it. And this allows you to change the environment, as it happens with the argument list. Think of argc and argv as some way of passing positional parameters to a program, and the environment as some way to pass named parameters to a program. Both are exactly the same kind of things, but ones are seek by position, while the others are accessed by name.
But no new process is created on execve(2) (nor in any of its variants)
Is there a way to start a child process without fork(), using execvp() exclusively?
The pedantic answer to your question is no. The only system call that creates a new process is fork. The system call underlying execvp (called execve) loads a new program into an existing process, which is a different thing.
Some species of Unix have additional system calls besides fork (e.g. vfork, rfork, clone) that create a new process, but they are only small variations on fork itself, and none of them are part of the POSIX standard that specifies the functionality you can count on on anything that calls itself a Unix.
The slightly more helpful answer is that you might be looking for posix_spawn, which is a library routine wrapping fork and exec into a single operation, but I find it more troublesome to use that correctly than to write my own fork+exec subroutine. YMMV.
posix_spawn is the only posix compliant way to create a child process without calling fork directly. I say 'directly' because historically posix_spawn would itself just call fork, or vfork. However, that is no longer the case in GNU/linux. posix_spawn itself may be more efficient than fork, in addition to perhaps being a stronger fit conceptually when code is attempting to run a different executable.
If you aren't worried about portability, you can abandon posix and couple yourself directly to the kernel you are targeting. On linux the system call to create a child process is clone. At the time of this answer the manual page provides documentation for three variants, including the relatively new clone3.
I believe you can take the example from the manual page and add an execvp call to childFunc. I have not tried it yet, though!
Unlike Windows systems, where creating a new process and executing a new process image happen in a single step, Linux and other UNIX-like systems do them as two distinct steps.
The fork function makes an exact duplicate of the calling process and actually returns twice, once to the parent process and once to the child process. The execvp function (and other functions in the exec family) executes a new process image in the same process, overwriting the existing process image.
You can call execvp without calling fork first. If so, that just means the currently running program goes away and is replaced with the given program. However, fork is the way to create a new process.
As user zwol has already explained, execve() does not fork a new process. Rather, it replaces the address space and CPU state of current process,
loads the new address space from the executable filename and starts it from
main() with argument list argv and environment variable list envp.
It keeps pid and open files.
int execve(const char *filename,char *const argv [],char *const envp[]);
filename: name of executable file to run
argv: Command line arguments
envp: environment variable settings (e.g., $PATH, $HOME, etc.)
posix_spawn. But it ignores failures of execvp() -- potentially because implementing this was regarded as too complicated.
What is the usage of execl command?
excel("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127);
Can anyone explain each statement used in execl command?
And why only _exit(127) and not exit(0).
What is 127 number indicating?
execl is one of the several functions (exec*) that let you replace the current code of your process with the one provided by the file (an executable one) specified as the first argument. The whole space of your process is replaced by a fresh one... Other arguments serve as arguments to the command. A process is a kind of system structure controlling execution of some code. exec lets you mutate that code.
In the case exec succeed then the old code is forgotten, you will never be able to get back into it. This is not a function call.
In the case exec fails then execution continues, and in your case a call to _exit is made. _exit is a system function designed to stop execution of the current process, leading to its death. exit is a C-function that does the same at C-level, roughly closing C-streams and calling _exit.
The value provided (127) is used to communicate some information about the termination of this process to the process that launched it (process are launched by the use of fork, a call that clones a process). The value can be any eight bit value, but 0 is used to denote a process that terminated correctly, and any other non 0 value to denote a process that terminated in some abnormal condition.
You can type
man execl
in the terminal for more information on the execl command.
I am trying to write shellcode in assembly. I need to perform a /usr/bin/killall command AND a /usr/bin/wget command. I have both commands running perfectly in shellcode with the execve() syscall. But now I want to combine these 2, but this is not possible because the program exits when the first execve() call is executed. (from the man pages of execve() : execve() does not return on success).
How can I perform 2 execve() calls? Or is there another way to call both /usr/bin/killall and /usr/bin/wget from the same shell code?
Greets and thanks in advance!
When you use the exec-family of functions, the program you call it with is substituted into the current process. So when the first execve-call is made, your entire process image disappears, and thus second call is never made. To get around this you must fork another process before calling execve.
First of all, it is not possible to execute two execve() one after the other. Simply because, by definition, the execve() call will override the memory of the original process with the new one and you will never be able to switch back to the original process again.
The second option that you propose (merging /usr/bin/killall and /usr/bin/wget into the shellcode) is perfectly possible if the killall command is not killing the process executing the shellcode itself. If it is the case, I really need more information about why is this behavior is needed because it seems a bit absurd to me (but I certainly miss the context in which you are running your shellcode).
I have a directory monitoring application which works recursively by launching new processes.
I'd like to know if I'm the "root" process in this tree. I thought about trying to get the name of the caller process and check if it's the same as argv[0].
Is there a smarter way of doing this? Keep in mind, this is a Linux app.
Keep in mind, I don't have much time for this and I'm but a student, so a simple solution would be great.
Thanks for your time.
If you use fork() to create new processes, you can have a local variable initially set at zero that each child sets to 1 immediately after forking. Only the root process would still have it set at zero after a fork.
You could even increase it after each fork, which would let you know how deep in your process tree each process is.
EDIT:
If you cannot use this (e.g. because you do an exec() after fork), you can use any of the common ways that shells use to pass information to the programs that you launch:
Environment variables: call setenv() after fork() but before exec() - or add it in the environment when calling exec().
Use a special command line argument.
Use a special value for argv[0] when doing exec().
Have you the possibility to add an argument meaning "I'm not the root"? That seems the simplest approach.
If you are calling exec, add a special argument, or environment variable called "I_AM_NOT_THE_ROOT" which the child processes get, but the parent does not.
I recently used a command-line argument for this, but env variables might be more convenient.