Nesting String Manipulations in DOS - string

I know you can use string manipulation in DOS like this:
echo %TIME%
echo %TIME:~0,2%
echo %TIME: =0%
The output of these three commands would be:
8:36:05.60
8
08:36:12.93
I want to know how to combine the second and third lines to get this output:
08
I can't use set to temporarily store a value because I want to use this string in a command line argument.

In pure DOS, you do not have nested statements.
Unless your application (for which the argument is) is a console app, you will not have a console to parse your environment variables (in the run box, try notepad c:\%TIME:~0,2%.txt and see what happens).
If it is a console app, then you would be able to use env vars, but no parsing, which is handled by cmd itself.
So you are bound to launch your app with a cmd.exe or a batch file and you can use all the expressions you need with SETs between.

Related

bash "echo" including ">" in the middle creating file - please explain

When I write:
echo 2*3>5 is a valid inequality
In my bash terminal, a new file named 5 is created in my directory which contains:
2*3 is a valid inequality
I want to know what exactly is going on here and why am I getting this output?
I believe it's obvious that I'm new to Linux!
Thanks
In bash, redirections can occur anywhere in the line (but you shouldn't do it! --- see the bash-hackers tutorial). Bash takes the >5 as a redirection, creates output file 5, and then processes the rest of the arguments. Therefore, echo 2*3 is a valid inequality happens, which gives you the output you see in the output file 5.
What you probably want is
echo "2*3>5 is a valid inequality"
or
echo '2*3>5 is a valid inequality'
(with single-quotes), either of which will give you the message you specify as a printout on the command line. The difference is that, within "", variables (such as $foo) will be filled in, but not within ''.
Edit: The bash man page says that the
redirection operators may precede or appear anywhere within a simple command or may follow a command. Redirections are processed in the order they appear, from left to right.
bash does the output redirection first i.e. >5 is done first and a file named 5 is created (or truncated if it already exists). The resultant file descriptor remains open for the runtime of the echo command.
Then the remaining portion, 2*3 is a valid inequality, runs as the argument to echo and standard output is saved in the (already-open) file 5 eventually.
To get the whole string as the output, use single or double quotes:
echo '2*3>5 is a valid inequality'
This is an example of output redirection. You're instructing the echo statement to, instead of writing to standard out, write to a filename. That filename happens to be "5".
You can avoid that behavior by quoting:
echo "2*3>5 is a valid inequality"

properly using IO redirection to append user input to a file in linux scripting?

I'm just starting to learn linux scripting, and with them user output/inputs. One of the things i need to learn and keep trying to do to no avail is append user input to a file output. Something like
read text > text.dat
or
read text
$text > text.dat
Typically ends up in failure, or the creation of text.dat which ends up empty no matter what is typed in by the user. What am i missing?
The read command, as documented in it's manual file, will take a line of user input and assign it to a variable which you can name as an argument. It will also split the user input and assign it to multiple variables if you pass more than one name. It will do this all in the background without printing any kind of confirmation to the standard out. We also know that the > operator will redirect the standard out of a command to a file descriptor. It is also important to note that unless bash is explicitly told that a line contains multiple commands (by using a semi-colon or similar) it will assume it is all one command with multiple arguments.
So lets have a look at your examples and see what is happening:
read text > text.dat
This will run the read command, which will silently assign the user input to a variable called $text. It will then redirect the output of the command (nothing, as it is silent) to a file called text.dat. End result: an empty text.dat and an unused $text variable.
read text $text > text.dat
Bash will parse this command and first attempt to get the value assigned to the $text variable, at this point it is undefined and so it will be ignored. So it will run the read command, which will silently assign the user input to a variable called $text. It will then redirect the output of the command (nothing, as it is silent) to a file called text.dat. End result: an empty text.dat and an unused $text variable.
So how can we resolve this? The first command is fine, we use read text to allow the user to input a line and have that line assigned to a variable called $text. Then, we need a way to send that variable to standard out so we can redirect it. To do that, we can use the echo command, which we can redirect.
So for example:
read text
echo $text > text.dat
Another thing to note is that the > operator will overwrite the file, to append to it you can use the >> operator.
So to take a user input and append it to a file we have:
read text
echo $text >> text.dat

extract variable's value from script file in Install Anywhere

I am using Install Anywhere 2012 and would like to be able to parse a batch or shell script for a give value and have that value stored in an IA variable. For instance, if I have the following shell file:
MY_VAR1=123
MY_VAR2=a\b\c
ECHO $MY_VAR1
I would like to pass in the path to the file and the variable name (ex. MY_VAR1) and have the result, 123, stored in an IA variable of my choosing (lets say $OUTPUT$). I could achieve this through writing some java custom code but was wondering if there was an alternative approach built into IA that would make this much easier. The variable will not be initialized when I need to figure out its value so essentially just echoing it's value or something similar will not work. Any help would be greatly appreciated!
example in Windows batch:
#echo off &setlocal
for /f "tokens=2delims==" %%a in ('findstr "MY_VAR1" "ShellFile"') do set "output=%%a"
if defined output (echo MY_VAR1: %output%) else echo MY_VAR1 not found!
On Linux/Unix, you could use perl or awk (both are standard utilities in most distros). Python or Ruby are also candidates, but may not be installed on your target system. You could even write your own targeted parser using Lex and Yacc and ship it with your installer. However, for your needs, that's surely overkill.
Here's an example of a possible awk solution in an Execute Script/Batch File Action:
#!/bin/bash
awk '
# Process lines that begin with our variable name,
# preceded by optional spaces or tabs.
/^[ \t]*$TARGET_VARIABLE_NAME$=.+/ {
# Split the current line on "=" into
# an array called result
split($0, result, "=")
value = result[1]
# Look for trailing comments and remove them.
offset = index(value, "#")
if (offset > 0) {
value = substr(value, 1, offset - 1)
}
# Remove any possible leading spaces and quotes.
# Note that the single-quote is escaped. That escape
# is for bash, not for awk. I am doing this from
# memory and do not have access to IA right now.
# you may have to play with the escaping.
gsub(/^[\'" ]*/, "", value)
# Remove any possible trailing spaces and quotes.
# See above regarding the escaped single-quote.
gsub(/[\'" ]*$/, "", value)
# send "value" to stdout
print value
}
' < $SHELL_INPUT_FILE$
The print value line (near the end) sends value to stdout.
In the Execute Script/Batch File Action settings you can designate variables that receive the stdout and stderr streams produced by the script action. By default, the stdout stream is stored in $EXECUTE_STDOUT$. You can change this to a variable name of your choosing.
In the example, above, $TARGET_VARIABLE_NAME$ and $SHELL_INPUT_FILE$ are InstallAnywhere variables that hold the name of the variable to find and the name of the file to parse, respectively. These variables will be replaced by their values before the Action executes.
Assume we have a script called /home/fred/hello.sh, which contains the following code:
#!/bin/bash
WIFE='Wilma'
NEIGHBOR="Barney Rubble"
echo "Hello to $WIFE and $NEIGHBOR from $PWD"
Before the Execute Script/Batch File Action runs, stuff the name of the script file into $SHELL_INPUT_FILE$ (/home/fred/hello.sh). Then set the value of $TARGET_VARIABLE_NAME$ to the variable you wish to find (say, NEIGHBOR). After the action completes, $EXECUTE_STDOUT$ in InstallAnywhere will contain Barney Rubble.
You can build on this idea to parse arbitrarily complex files in an Execute Script/Batch File Action. Just make your awk (or perl/Ruby/Python) script as complex as needed.
NOTE: when scripting Unix shell scripts in InstallAnywhere ALWAYS check the "Do not replace unknown variables" option. If you don't, InstallAnywhere will quietly convert anything that looks vaguely like an InstallAnywhere variable into blanks... It's very annoying.
For a Windows solution, find a standalone Windows version of awk or perl and include it with your installation. Then extend the above solution to work for batch files.
You'd want to create two Execute Script/Batch File Actions, one with a rule for Linux/Unix and one with a rule for Windows. You'd have to install the Windows awk or perl executable before calling this action though. Also, you'd need to fully qualify the path to the awk/perl executable. Finally, the actual script will need to be sensitive to differences in batch syntax versus shell syntax.
Below is an awk script modified to look for batch variable definitions. The pattern changes and you won't have to worry about embedded comments:
$PATH_TO_AWK_EXE$ '
# This pattern looks for optional spaces, the word SET
# with any capitalization, the target variable, more
# optional spaces and the equals sign.
/^[ \t]*[Ss][Ee][Tt][ \t]*$TARGET_VARIABLE_NAME$[ \t]*=.+/ {
# Split the current line on "=" into
# an array called result
split($0, result, "=")
value = result[1]
# No trailing comments in Batch files.
# Remove any possible leading spaces and quotes.
# Note that the single-quote is escaped. That escape
# is for bash, not for awk. I am doing this from
# memory and do not have access to IA right now.
# you may have to play with the escaping.
gsub(/^[\'" ]*/, "", value)
# Remove any possible trailing spaces and quotes.
# See above regarding the escaped single-quote.
gsub(/[\'" ]*$/, "", value)
# send "value" to stdout
print value
}
' < $SHELL_INPUT_FILE$
Above, the IA variable $PATH_TO_AWK_EXE$ points to the location where awk was installed. It would be set as some combination of $USER_INSTALL_FOLDER$, possibly other directory names, and the name of the awk.exe file. $PATH_TO_AWK_EXE$ can later be used to remove the awk executable, if desired.
You can try to get variable from output of script
"Execute Script" -> Store process's stdout in: $EXECUTE_OUTPUT$
Than you can use $EXECUTE_OUTPUT$ as variable after that

arbitrary input from stdin to shell

So I have this existing command that accepts a single argument, but I need something that accepts the argument over stdin instead.
A shell script wrapper like the following works, but as I will be allowing untrusted users to pass arbitrary strings on stdin, I'm wondering if there's potential for someone to execute arbitary commands on the shell.
#!/bin/sh
$CMD "`cat`"
Obviously if $CMD has a vulnerability in the way it processes the argument there's nothing I can do, so I'm concerned stuff like this:
Somehow allow the user to escape the double quotes and pass input into argument #2 of $CMD
Somehow cause another arbitary command to run
The parameter looks fine to me, but the command might be a bit shaky, if it can have a space in it. Also, if you're looking to get just one line from the user then you might prefer this:
#!/bin/bash
read line
exec "$CMD" "$line"
A lot of code would be broken if "$(cmd)" could expand to multiple words.

exec() security

I am trying to add security of GET query to exec function.
If I remove escapeshellarg() function, it work fine. How to fix this issue?
ajax_command.php
<?php
$command = escapeshellarg($_GET['command']);
exec("/usr/bin/php-cli " . $command);
?>
Assume $_GET['command'] value is run.php -n 3
What security check I can also add?
You want escapeshellcmd (escape a whole command, or in your case, sequence of arguments) instead of escapeshellarg (escape just a single argument).
Notice that although you have taken special precautions, this code allows anyone to execute arbitrary commands on your server anyways, by specifying the whole php script in a -r option. Note that php.ini can not be used to restrict this, since the location of it can be overwritten with -c. In short (and with a very small error margin): This code creates a severe security vulnerability.
escapeshellarg returns a quoted value, so if it contains multiple arguments, it won't work, instead looking like a single stringesque argument. You should probably look at splitting the command up into several different parameters, then each can be escaped individually.
It will fail unless there's a file called run.php -n 3. You don't want to escape a single argument, you want to escape a filename and arguments.
This is not the proper way to do this. Have a single PHP script run all your commands for you, everything specified in command line arguments. Escape the arguments and worry about security inside that PHP file.
Or better yet, communicate through a pipe.

Resources