Enable LD_PRELOAD just for BASh after system startup - c

Is there a way to inject/enable LD_PRELOAD just for new sessions (ie: BASh)?
I have a syntax highlighting library that I want to have automatically enabled (ie: highlight warnings for certain users), and just need it loaded for BASh rather than all processes. If I put it in /etc/ld.so.preload, it's disruptive and causes issues for all the system services and other programs that don't need it running, wrapping system calls (printf and exec mainly).
Is there a simple way to accomplish this?

The easiest solution is probably to replace bash with a shell script that performs the LD_PRELOAD logic, then calls the actual (renamed) bash binary.
That is, move /bin/bash to /bin/bash.original, then create a script /bin/bash with the following contents:
#!/bin/sh
LD_PRELOAD=/path/to/my/library.so
export LD_PRELOAD
exec /bin/bash.original "$#"
You could include logic here (e.g., "is stdout a tty") if you want to only perform the LD_PRELOAD when connected to an interactive session. Trying to perform any sort of terminal manipulation when bash isn't connected to a tty will probably yield weird results.

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.

How do I copy everything from my terminal to a file including the stdout and the prompt using C?

I know how to get the stdout into a file using dup/dup2 system calls, but how do I get the entire output that would be normally shown on my terminal(including the prompt that says my username along with the $ symbol and the current working directory) to a file?
Yes you can, but this may be difficult in many details (depending on your expert level). For the shell to behave normally (I would mean exactly as in a terminal), then it needs to interact with a terminal (special system object). So you need to create a program that behave like a terminal, this what pseudo-terminals devices (/dev) are intended for. Read documentation about this to implement it but roughly, your application should behave like the user so should be connected to the slave side of the pseudo-terminal, and the shell to the master side of the pseudo-terminal. Then you can easily log real inputs made by the user and catch outputs made by the shell.
Can't comment cause of low reputation.
I would say there is no way to do that inside a code in C. Instead, you could use bash for example to redirect everything to a file, and leave the code in C as it is.
In this way you have all the info you want to save: prompt, current directory, call to the program (including flags), and of course the output of the program.
Well, you can do:
-For bash prompt PS1: Echo expanded PS1 (in case you want it expanded, if not there is a simple way to do it just echong PS1)
- For executed command: https://unix.stackexchange.com/questions/169259/how-to-capture-command-line-input-into-logfile-and-execute-it-at-the-same-time
- Standard output and error output: Redirect stderr and stdout in a Bash script
And that's all you want to capture, I think.
Look up the script command in Unix systems. If you want to capture all keyboard and std in/out for a command, use the script executable. If you want to see how it's done, look up the source.

Execute any command-line shell like into execve

In case this is helpful, here's my environment: debian 8, gcc (with std = gnu99).
I am facing the following situation:
In my C program, I get a string (char* via a socket).
This string represents a bash command to execute (like 'ls ls').
This command can be any bash, as it may be complex (pipelines, lists, compound commands, coprocesses, shell function definitions ...).
I can not use system or popen to execute this command, so I use currently execve.
My concern is that I have to "filter" certain command.
For example, for the rm command, I can apply it only on the "/home/test/" directory. All other destinations is prohibited.
So I have to prevent the command "rm -r /" but also "ls ls && rm -r /".
So I have to parse the command line that is given me, to find all the command and apply filters on them.
And that's when I'm begin to be really lost.
The command can be of any complexity, so if I want to make pipelines (execve execute a command at a time) or if I want to find all commands for applying my filters, I'll have to develop parser identical to that of sh.
I do not like creating the wheel again, especially if I make it square.
So I wonder if there is a feature in the C library (or that of gnu) for that.
I have heard of wordexp, but I do not see how manage pipelines, redirection or other (in fact, this does not seem made for this) and i do not see how can I retrieve all the command inside the commande.
I read the man of sh(1) to see if I can use it to "parse" but not execute a command, but so far, I find nothing.
Do I need to code a parser from the beginning?
Thank for your reading, and I apologies for my bad english : it's not my motherlanguage (thanks google translate ...).
Your problem:
I am facing the following situation: In my C program, I get a string
(char* via a socket). This string represents a bash command to execute
(like 'ls ls'). This command can be any bash, as it may be complex
(pipelines, lists, compound commands, coprocesses, shell function
definitions ...).
How do you plan on authenticating who is at the other end of the socket connection?
You need to implement a command parser, with security considerations? Apparently to run commands remotely, as implied by "I get a string (char* via a socket)"?
The real solution:
How to set up SSH without passwords
Your aim
You want to use Linux and OpenSSH to automate your tasks. Therefore
you need an automatic login from host A / user a to Host B / user b.
You don't want to enter any passwords, because you want to call ssh
from a within a shell script.
Seriously.
That's how you solve this problem:
I receive on a socket a string that is a shell command and I have to
execute it. But before execute it, i have to ensure that there is not
a command in conflict with all the rules (like 'rm only inside this
directory, etc etc). For executing the command, I can't use system or
popen (I use execve). The rest is up to me.
Given
And that's when I'm begin to be really lost.
Because what you're being asked to do is implement security features and command parsing. Go look at the amount of code in SSH and bash.
Your OS comes with security features. SSH does authentication.
Don't try to reinvent those. You won't do it well - no one can. Look how long it's taken for bash and SSH to get where they are security-wise. (Hint: it's decades because there's literally decades of history and knowledge that were built into bash and SSH when they were first coded...)

How shell commands execute

I am a newbee and looking for some info.
Thanks in advance.
What is difference between echo "Hello World!" and a c-program which prints "Hello World!" using printf.
How do shell commands get executed. For example if I give ls it lists all the files in the directory. Is there executable binary which is run when we enter ls in shell.
Please let me know if you guys have any links or source to get this clear.
There are two main types of "commands" that the shell can execute. Built-in commands are executed by the shell itself - no new program is started. Simply typing echo in a shell prompt is an example of such a built-in command.
On the other hand, other commands execute external programs (also called binaries) - and ls is an example of this kind of command.
So, if you run echo in a shell, it's executed by the shell itself, but if you write a C program that performs the same action, it wil be run as an external program. As a matter of fact, most Linux systems come with such a binary, located at /bin/echo.
Why does it sometimes make sense to have both a built-in command and a program to accomplish the same task? Built-in commands are faster to execute as there is some cost involved in running an external program. But built-ins have some drawbacks, too: they can't be too complex as this would make the shell big and slow; they can not be upgraded separately from the shell and from each other; finally, there are situations where an external program which is not your shell would like to run an application: it can run external programs but it can't execute shell built-ins directly since it's not the shell. So sometimes it makes sense to have it both ways. Apart from echo, time is another example of this double approach.
The shell is just a user level way of interacting with the operating system, or the kernel. That's one of the reasons it's called a shell. The shell itself (sh, csh, tcsh, ksh, zsh, bash, etc...) is essentially just a binary the operating system executes to allow you to execute other binaries.
It generally gives a lot of other functionality though like built in functions (echo, fg, jobs, etc...), an interpreted language (for x in ..., if then, etc...), command history, and so on...
So, any text entered into the shell (like echo), the binary (or process) interprets and runs the corresponding functions in its code. Built in functions (like echo) don't need to create a new process, but if the text is interpreted as a request to execute a binary (vim, emacs, gcc, test, true, false, etc...) the shell will create a new process for it (unless you prefix it withexec), and execute it.
So, echo "Hello World! just runs code in the shell (process). A printf("Hello World!") would be in seperate binary that the shell would create a new process for (fork), and have the operating system execute (exec).

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.

Resources