what is the difference between chdir(...) and system("cd ...")? - c

Was curious what the difference is in these two lines of code.
chdir ("..");
And
system ("cd ..");
Is there any difference other than call the system library function, which then calls chdir? At least, that's what I assume happens based on what I have found on the internet. Thanks.

The first changes the current working directory of the current process. The second invokes a shell and executes the command in it, which changes its directory; the process's working directory is unchanged. The second is almost never what you want.

Related

Accessing and running /usr/bin programs in C

What is the most efficient method for running programs from the /usr/bin directory in a C program? I am tasking with getting user input, and if the user input matches up with a program in bin, running the respective program.
I had the idea of throwing the names of all the bin's programs in a text file, and using a loop to iterate through each word in the file while comparing the word to the input. However, I figured that might be reinventing the wheel a bit. Are there any streamlined ways to do this?
The "classical" way of invoking a program from an existing process on any of the UNIX-like OS'es is to use one of the exec() functions. When you read about exec() most tutorials will start by explaining another function: fork(). These functions are very commonly used together, but don't get too caught up on that, because they are both useful in their own right.
To answer your question, a fairly efficient way of doing what you're after:
Take the user generated input from whatever your source happens to be
(Optionally, call fork())
Call the execvp() function
What you do here will depend on whether you called fork() in step (2), and what you intend to do (if anything) after performing the task you described.
execvp() will do the legwork for you, by automatically searching on your environment PATH for a filename matching the first argument. If the current environment does not have a PATH set, it will default to /bin:/usr/bin. Since the only way that a call to exec() can yield a return value is when that call failed, you might want to check the value of errno as part of step (4). In the event that the user input didn't match any executable in the environment PATH, errno will be set to ENOENT. Exactly how you do this and what additional steps might be worth taking will depend on whether or not you forked, along with any additional requirements for your program.
I would suggest looking if the name you get from the user matches a file in the /usr/bin directory and if it does use the system function to run this program.
https://linux.die.net/man/3/system
#include <stdlib.h>
int system(const char *command);
i.e
FILE *file;
if (file = fopen(userinput, "r")){
fclose(file);
system(userinput);
}

change terminal directory using c language

i am trying to change the directory of my linux terminal using c language. the thing is i am using threads. i have tried to use chdir() but its not working, n yes chdir() is also a process function.
Actually the thing i am trying to implement is, i am trying to make a multi threaded program which compiles Linux kernel, and that is not possible without specifying directories( i have tried to do it without specifying directories but failed :) )
can anybody help me out with this issue?
Thanks in advance :)
You can't! No process can change the working directory of another. A process can only change its own WD. When you launch an external command such like your C program, then a new process is launched.
The cd command of your shell is an internal one.
It isn't very clear what you are trying to achieve. It appears that somehow you wish to emulate the behaviour of a script (or the make tool) using a C program, that is to say having the C program you wrote launch new processes (using system or perhaps a combination of fork and exec*). If that is the case, then what you actually want is to modify the environment variables of these processes for them to find the files they need. A forked process will inherit the environment of its parent, so all you need is to use getenv, putenv, setenv and unsetenv to retrieve and set the environment variables you want to add, update or remove; or you may use the specific execve, execvpe which let you specify exactly what environment should be available to the new program.
references:
fork system call
exec family of system calls
unix environment

Shellcode: perform 2 execve() calls

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).

Program restart self on update

I checked everywhere so I am hopefully not repeating a question.
I want to add a portable update feature to some C code I am writing. The program may not be in any specific location, and I would prefer to keep it to a single binary (No dynamic library loading)
Then after the update is complete, I want the program to be able to restart (not a loop, actually reload from the HDD)
Is there any way to do this in C on Linux?
If you know where the program is saved on disk, then you can exec() the program:
char args[] = { "/opt/somewhere/bin/program", 0 };
execv(args[0], args);
fprintf(stderr, "Failed to reexecute %s\n", args[0]);
exit(1);
If you don't know where the program is on disk, either use execvp() to search for it on $PATH, or find out. On Linux, use the /proc file system — and /proc/self/exe specifically; it is a symlink to the executable, so you would need to use readlink() to get the value. Beware: readlink() does not null terminate the string it reads.
If you want, you can arrange to pass an argument which indicates to the new process that it is being restarted after update; the bare minimum argument list I provided can be as complex as you need (a list of the files currently open for edit, perhaps, or any other appropriate information and options).
Also, don't forget to clean up before reexecuting — cleanly close any open files, for example. Remember, open file descriptors are inherited by the executed process (unless you mark them for closure on exec with FD_CLOEXEC or O_CLOEXEC), but the new process won't know what they're for unless you tell it (in the argument list) so it won't be able to use them. They'll just be cluttering up the process without helping in the least.
Yes, you need to call the proper exec() function. There might be some complications, it can be troublesome to find the absolute path name. You need to:
Store the current directory in main().
Store the argc and (all) argv[] values from main().
Since calling exec() replaces the current process, that should be all you need to do in order to restart yourself. You might also need to take care to close any opened files, since they might otherwise be "inherited" back to yourself, which is seldom what you want.

how to call system() from a specific directory?

I need my program go to some specific directory then run
system( ... ); there and get me back where I was before. How can I do it?
Just do the cd in your system call:
system("cd wherever; command");
The whole string gets passed to sh(1), so you can do any normal shell things in there. Since it's in a subshell, the working directory of your program won't be changed.
On Linux and Posix systems, the system(3) function is implemented above system calls like fork(2), execve(2), waitpid(2) and others. You could use the chdir(2) syscall to change the current directory. You could use getcwd(2) to retrieve (and memoize) it before changing it. (you could also call getcwd and chdir before system, then restore the original current directory with another chdir).
I suggest reading a good book like Advanced Linux Programming and Advanced Unix Programming, they have several chapters to answer your questions.
Don't expect a forum to explain all this to you. Read books.
Use chdir before calling system. You can even use getcwd before chdir to return to the directory after system.
Go to specific directory with chdir
Run system(...) (as Basile said, if system is taking user-defined variables, make sure to sanitize them)
When the program executes system(..), it will be in the changed directory. After system(...), it will be in the changed directory. When the program exits, it will be in the original directory.

Resources