how can I set up unix command with C, especially with "system()"? - c

I'm just getting started with C.
What I want to do is issue Unix commands from C, especially with system().But if I have code like this, it can only access files in the same directory.
system("./Test");
But I want to use that code in any directory. Is it possible?

system("/any/other/folder/Test");
calling command via system is like calling command via command line interface so even the path of your command is ../../any/other/folder/Test, you call it with
system("../../any/other/folder/Test");

Just pass an absolute path as parameter
system("/your/folder/Test");

system() forwards its string parameter to the native command line handler - e.g. /bin/sh on Unix or cmd.exe on Windows. You can use whatever command or path those whould take. Of course, such code is not portable.

Related

(LLDB on MacOs Catalina) Shell Expansion Failed

When trying to use the r or run commands in lldb I get an error like this: error: shell expansion failed (reason: invalid JSON). consider launching with 'process launch'.
It works when I just use process launch but I really do not feel like doing that.
Is there any way I could make either an alias or make shell expansions not fail?
The way lldb does shell expansion is to run a little tool called lldb-argdumper (it is in Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources on macOS) with the command arguments that you passed. lldb-argdumper wraps the contents of argv as JSON, and writes that to stdout. lldb then parses the JSON back into args and inserts the args one by oneinto the argc/argv array when it launches the process.
Something in the output is not getting properly wrapped. You can probably see what it is by looking at the output of lldb-argdumper with your arguments. Whatever it is, it's a bug, so if you can reproduce it please file with your example with http://bugs.llvm.org.
(lldb) command alias run-no-shell process launch -X 0 --
will produce an alias that doesn't do shell expansion. You can also put this in your ~/.lldbinit.
I ran into this recently. TL;DR: make sure your shell does not echo anything during initialization. Run <your-shell> -c date to confirm; only the date should be printed.
The problem was that my shell's initialization file was echoing some stuff, which was getting prepended to lldb-argdumper's JSON output. (lldb doesn't run lldb-argdumper directly; it invokes your default shell to run lldb-argdumper.)
Specifically, I use fish as my shell, which does not have separate initialization paths for interactive and non-interactive sessions. (See this issue for discussion of whether this is good.) bash and zsh have separate init files for interactive/non-interactive sessions, which makes avoiding this problem slightly easier.

Executing binary files using exec* in c

I am creating a toy shell. I want to execute a binary file which is either located in the PATH variable or the current directory. This is what I am doing to achieve it:
execl(filePath," -e ",com.arguments,NULL); //e.g of filePath: /home/dino/programs/mywrapper
Now it works fine for some executables like which command. But for commands like tar, a whole bunch of error throws up.
Basically all I want is the execl to execute the executable mentioned in filePath in my shell. How do I do it?
EDIT:
com.arguments is the arguments list. For example in which bash, bash becomes my argument. In tar -zvcf bazinga.tar.gz bazinga/, -zvcf bazinga.tar.gz bazinga/ becomes my arguments etc.
From execl's documentation
The first argument, by convention, should point to the
filename associated with the file being executed.

Using system() function in c

I want to use the system function to get the number of accounts on windows and on linux.
I have no idea where to look. Please just point me in the right direction.
The system() function runs a program. If you know a command line that does what you need, you can use system() to run that command line.
I'm not sure what command-line program would give the number of accounts on Windows. You could get an approximation by looking at the number of home directories. On Windows the home directories are in \Users and on Linux home directories are in `/home'.
The system() function doesn't capture the output of the program. You would then likely need to run a command line that redirects the program output to a file, then open this file and parse the output.
You would probably have an easier time solving this problem using a language like Python. Python programs are very portable and there are some wrappers for system stuff.
Good luck.
I don't know in Linux, but on windows:
NetUserEnum() or NetQueryDisplayInformation() and ofcourse from the Registry here: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
PS: system(const char *command) function call executes the command in the command window/terminal.
I used Google to find the following:
Windows:
http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/8c72b948-d32c-4785-930e-0d6fdf032ecc
Linux:
http://www.linuxforums.org/forum/miscellaneous/29508-list-all-user-accounts-system.html
(search strings: "win32 get user account information", "linux get user account information")
The Linux page gives a command line, so you can put that in your system() call. In Windows though, you don't use system(), you use Win32 API.
For Linux systems you might like to count the number of lines in the file /etc/passwd. This file contains an entry for each user to the system.
To count lines of a text file under Linux the wc command can be used.
Anyway, if you need this info in a C program I propose you take a different approach:
You could open a text file using fopen() and read each line using fgets() until fgets() tells you there are no more lines. Doing so you'll be getting the number of users.

Hooks on terminal. Can I call a method before a command is run in the terminal?

I am wanting to make a terminal app that stores information about files/directories. I want a way to keep the information if the file is moved or renamed.
What I thought I could do is have a function execute before any command is run. I found this:
http://www.twistedmatrix.com/users/glyph/preexec.bash.txt
But I was wondering if this would be a good way to go about it. Or should I do something else?
I would like to call that function from a C program whenever mv is entered I suppose.
If what you're trying to do is attach some sort of metadata to files, there's a much better supported way to do that -- extended attributes.
Another solution might be to use the file's inode number as an index into a database you maintain yourself.
Can you alias the mv command? in .profile or .bashrc
alias mv=/usr/bin/local/mymv
where mymv is a compiled executable that runs your C code function and calls /usr/bin/mv.
precmd and preeexec add some overhead to every bash script that gets run, even if the script never calls mv. The downside to alias is that it requires new code in /usr/local and if scripts or users employ /usr/bin/mv instead of mv it will not do what you want. Generally doing something like this often means there is a better way to handle the problem with some kind of service (daemon) or driver. Plus, what happens if your C code cannot correctly handle interesting input like
mv somefille /dev/null
If you want to run command each time after some command was executed in the terminal, just put the following in ~/.bashrc:
PROMPT_COMMAND="your_command;$PROMPT_COMMAND"
If you want your command to be executed each time before mv is executing, put the following in ~/.bashrc:
alias mv="your_script"
Make sure that your script will execute real mv if needed.
You can use inotify library to track filesystem changes. It's good solution, but once user remove file, it's already gone.
You might be able to make use of the DEBUG trap in Bash.
From man bash:
If a sigspec is DEBUG, the command arg is executed before every
simple command, for command, case command, select command, every
arithmetic for command, and before the first command executes in
a shell function
I found this article when I was forced to work in tcsh and wanted to ensure a specific environemtn variable was present when the user ran a program from a certain folder (without setting that variable globally)
tcsh can do this.
tcsh has special alias, one of which is precmd
This can be used to run a script just before the shell prompt is printed.
e.g. I used set precmd 'bash $HOME/.local/bin/on_cd.sh'
This might be one of the very few useful features in csh.
It is a shame but I don't think the same or similar feature is in bash or other sh derivites (ash, dash etc). Related answer.

What is the purpose of the system() function if I already have access to the system?

If I ran the ssh command and logged into a server, would there be any reason to have code call system() since I can run it myself?
Edit: The code I have would be written in C
system call will execute the program (with parameters) that you want. A system() call invokes a shell. So from inside of a C program, if you want to remove a file, you can invoke system with "rm filename" as argument (this is just a use case - definitely not how you'd like to delete a file from a C program)
You should use system() only when you know what you are doing. If a user input is any part of the argument to the system call, you should make sure you are sanitizing your input lest you are opening yourself to command injections.
An example of a command injections with system call is here
Alternatives to system are popen and obviously fork+exec.

Resources