I need to override the first argument when I call a binary.
Since it's the program name I have two solutions:
move the binary and call it with its new name; or
create an alias (if the shell allows it).
However, sometimes I need to completly remove the first parameter.
I wrote a simple program in C that does the job:
#include <unistd.h>
int main(int argc, char **argv)
{
return execve(argv[1], NULL, NULL);
}
I there a built-in way to do it with the shell? A solution for bash would be prefered.
You can override it with exec -a, though you can't make it unset.
For example, to run busybox with argv[0] set to ls:
( exec -a ls busybox )
Related
Everytime I create a project (standard command line utility) with Xcode, my
main function starts out looking like this:
int main(int argc, const char * argv[])
What's all this in the parenthesis? Why use this rather than just
int main()?
main receives the number of arguments and the arguments passed to it when you start the program, so you can access it.
argc contains the number of arguments, argv contains pointers to the arguments.
argv[argc] is always a NULL pointer. The arguments usually include the program name itself.
Typically if you run your program like ./myprogram
argc is 1;
argv[0] is the string "./myprogram"
argv[1] is a NULL pointer
If you run your program like ./myprogram /tmp/somefile
argc is 2;
argv[0] is the string "./myprogram"
argv[1] is the string "/tmp/somefile"
argv[2] is a NULL pointer
Although not covered by standards, on Windows and most flavours of Unix and Linux, main can have up to three arguments:
int main(int argc, char *argv[], char *envp[])
The last one is similar to argv (which is an array of strings, as described in other answers, specifying arguments to the program passed on the command line.)
But it contains the environment variables, e.g. PATH or anything else you set in your OS shell. It is null terminated so there is no need to provide a count argument.
These are for using the arguments from the command line -
argc contains the number of arguments on
the command line (including the program name), and argv is the list of
actual arguments (represented as character strings).
These are used to pass command line paramters.
For ex: if you want to pass a file name to your process from outside then
myExe.exe "filename.txt"
the command line "filename.txt" will be stored in argv[], and the number of command line parameter ( the count) will be stored in argc.
main() is a function which actually can take maximum three parameters or no parameters.
The following are the parameters that main() can take is as follows:-
1) int argc : It holds the number of arguments passed (from the command prompt) during the execution of program or you can say it is used ot keep a track of the number of variables passed during the execution of program. It cannot hold the negative value. Eg. If you pass your executable file "./a.out" then that will be considered as a parameter and hence argc value will be 0 i.e 1 value is passed.
2) char *argv[] : it is an array of character pointers which holds the address of the strings(array of characters) that are passed from the command prompt during execution of program. Eg. in above example if you wrote argv[argc] i.e argv[0] in cout then it will give ./a.out as output.
3) char*envp[] : it is also an array of character pointer which is used to hold the address of the environments variables being used in the program. Environment variables are the set of dynamic named value that can affect the way the running process will behave on the computer. For example running process want to store temporary files then it will invoke TEMP environment variables to get a suitable location.
I have written a C program which takes many command line arguments, among which last one can be a *. I have compiled it using mingw-w64 compiler and I am using Microsoft Windows [Version 10.0.19041.508] command prompt.
How to pass a * character as a command-line argument? I have tried many escape sequences like *, ^*, ^^*, !*, \*, /*, "*", and '*', but none of them is working. Only '*' is being passed as it is but I want to pass only * character without any inverted commas. Is there any way to achieve this?
Edit: You can assume MRE to be
int main(int argc, char *argv[])
{
if (*argv[1] == '*')
printf("A asterisk is passed.\n");
}
in RHEL5, the default Ruby's Socket::gethostname returns short hostname without domain name. In RHEL6 it returns the hostname including the domain name.
This is caused by different system hostname functionality in RHEL6 which can be fixed in SH scripts using hostname -s. Is there any Socket::gethostname parameter to fix it in Ruby?
It is possible to fix by parsing the output using regular expression or using system call, e.g. 'hostname -s'.strip, but neither is an easy nor a nice solution.
Could you help?
Thanks
Jan
As you might see in the rubydoc+click-to-toggle-source, gethostname is a simple wrapper to c stdlib.
That said, you might try to compile and execute the below code. As soon as it returns not what you want, you are probably stuck to hostname -s.
#include <unistd.h>
#include <stdio.h>
int main(int, char **) {
char buf[1025];
gethostname(buf, 1024);
printf("%s\n", buf);
}
You could use a regex to return everything up to the first '.'
require 'socket'
hostname = Socket.gethostname[/^[^.]+/]
I like the idea of nemiver, but i can't get this basic function of nemiver to work: redirect standard input to program. so as my program needs file input instead of manual input, it usually takes the form:
./program < list.txt
but apparently, nemiver does not recognize this simple redirection. and thinks "<" and "list.txt" as separate arguments. this frustrates me greatly. is there a solution to this? Thank you guys so much!
If you just want to do a postmortem analysis (and don't need to single-step), you can load a crash-dump (core) file which can be generated under any kind of pipelining/redirection scenario.
( ulimit -c unlimited && ./yourapp <in.txt >out.txt ) || nemiver --load-core=core ./yourapp
This only launches the debugger if a crash or assert occurs.
As a quick-and-dirty solution, you can add something like the following at the beginning of main()...
{
// programmatically redirect stdio
const char * stdin_filename="input.txt", * stdout_filename="output.txt";
assert( dup2(open(stdin_filename ,O_RDONLY),0) != -1 );
assert( dup2(open(stdout_filename,O_WRONLY),1) != -1 );
asm(" int3"); // optional breakpoint -- kills program when not debugging
}
Just make sure that you disable this when not debugging (since presumably you want to use the normal method of redirection in that case).
You also need the following...
#include <unistd.h>
#include <fcntl.h>
In bash shell I can get a full path of a script even if the script is called by source, link, ./..., etc.
These magic bash lines:
#Next lines just find the path of the file.
#Works for all scenarios including:
#when called via multiple soft links.
#when script called by command "source" aka . (dot) operator.
#when arg $0 is modified from caller.
#"./script" "/full/path/to/script" "/some/path/../../another/path/script" "./some/folder/script"
#SCRIPT_PATH is given in full path, no matter how it is called.
#Just make sure you locate this at start of the script.
SCRIPT_PATH="${BASH_SOURCE[0]}";
if [ -h "${SCRIPT_PATH}" ]; then
while [ -h "${SCRIPT_PATH}" ]; do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
pushd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd > /dev/null
How can you get the script path under the same conditions in TCSH shell? What are these 'magic lines'?
P.S. It is not a duplicate of this and similar questions. I'm aware of $0.
IF your csh script is named test.csh, then this will work:
/usr/sbin/lsof +p $$ | \grep -oE /.\*test.csh
I don't use tcsh and do not claim guru status in it, or any other variant of C shell. I also firmly believe that Csh Programming Considered Harmful contains much truth; I use Korn shell or Bash.
However, I can look at manual pages, and I used the man page for tcsh (tcsh 6.17.00 (Astron) 2009-07-10 (x86_64-apple-darwin) on MacOS 10.7.1 Lion).
As far as I can see, there is no analogue to the variable ${BASH_SOURCE[0]} in tcsh, so the starting point for the script fragment in the question is missing. Thus, unless I missed something in the manual, or the manual is incomplete, there is no easy way to achieve the same result in tcsh.
The original script fragment has some problems, too, as noted in comments. If the script is invoked with current directory /home/user1 using the name /usr/local/bin/xyz, but that is a symlink containing ../libexec/someprog/executable, then the code snippet is going to produce the wrong answer (it will likely say /home/user1 because the directory /home/libexec/someprog does not exist).
Also, wrapping the while loop in an if is pointless; the code should simply contain the while loop.
SCRIPT_PATH="${BASH_SOURCE[0]}";
while [ -h "${SCRIPT_PATH}" ]; do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
You should look up the realpath() function; there may even be a command that uses it already available. It certainly is not hard to write a command that does use realpath(). However, as far as I can tell, none of the standard Linux commands wrap the realpath() function, which is a pity as it would help you solve the problem. (The stat and readlink commands do not help, specifically.)
At its simplest, you could write a program that uses realpath() like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
{
int rc = EXIT_SUCCESS;
for (int i = 1; i < argc; i++)
{
char *rn = realpath(argv[i], 0);
if (rn != 0)
{
printf("%s\n", rn);
free(rn);
}
else
{
fprintf(stderr, "%s: failed to resolve the path for %s\n%d: %s\n",
argv[0], argv[i], errno, strerror(errno));
rc = EXIT_FAILURE;
}
}
return(rc);
}
If that program is called realpath, then the Bash script fragment reduces to:
SCRIPT_PATH=$(realpath ${BASH_SOURCE[0]})