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.
Related
I have a .sh file, say B.sh, that calls goal.c (a Linux C file), and goal.c calls A.sh. The paths of goal.c and A.sh are different.
Upon being called by goal.c, A.sh produces some output which will be seen in the same directory as that of A.sh. But I do not see anything as a problem occurs in goal.c calling A.sh using the system command.
I used as the system ("Pathname of A.sh"), but a warning comes as, system() ignored and I feel the command is not executed.
How do I use the system command in this case?
I have an occasion where a C program invokes a shell script, which in-turn does some copying stuff from the CD mount location to an installation directory.
Now my question is that, is there a straightforward approach to get the absolute path of this C program inside this shell script ?.
I tried a couple of approaches that includes using "$(ps -o comm= $PPID)" from within the script, but nothing did work out till now. I know that I can create a temporary file from the C program which contains its own name (argv[0]) and then make the shell script to read that file, but I don't want to follow that approach here.
Of course, it can be passed as an argument to the script, but I was thinking why the bash built-in macros or something cannot be used here
On linux there is a /proc/self/exe path that points the absolute path of the current executed file. So you can push an environment variable that contains the path before spawning the shell. Something like:
readlink("/proc/self/exe",...,buf);
putenv("MYEXE",buf);
system("thescript");
and accessing the variable in the script:
echo $MYEXE
Before running a foo command you could use which like
fooprog=$(which foo)
to get the full path of the program (scanning your $PATH). For example which ls could give /bin/ls ....
On Linux specifically you could use proc(5).
In your shell process (running bash or some POSIX compliant shell) started by your C program, $PPID give the parent process id, hopefully the pid of the process running your C program.
Then the executable is /proc/$PPID/exe which is a symbolic link. Try for example the ls -l /proc/$PPID/exe command in some terminal.
(notice that you don't run C source files or stricto sensu C programs, you often run some ELF executable which was built by compiling C code)
You might have weird cases (you'll often ignore them, but you might decide to handle them). Someone might move or replace or remove your executable while it is running. Or the parent process (your executable) died prematurely, so the shell process becomes orphan. Or the executable removed itself.
I am trying to not hardcode the name of the input file in my C program. I have all of the other components working when I hardcode the filename. But would like to be able to pass it a string filename.
I am trying to execute compile a file called Matrix.c and name its executable matrix.
So, in terminal, when I get to my working directory.
gcc -g Matrix.c -o matrix
then when I compile
./matrix
It doesn't have a filename passed to it so I am gonna check for that and have the user input a filename to load.
However, when someone passes the filename, should it be passed as:
./matrix filename.txt
or
./matrix < filename.txt
With the latter option, I can't seem to get the name of the argument passed to the function from argv[1] — it's just "(Null)".
I know this is very simplistic question. But am I just completely off my rocker? Is it something to do with me running on OS X El Capitan. I know I've used the '<' convention before.
The issue is how the shell works, mainly. When you use:
./matrix filename.txt
then the program is given two arguments — the program name and the file name. When you use:
./matrix < filename.txt
then the program is given just one argument — the program name — and the shell arranges for its standard input to come from the file (and the file name is not passed to your program).
Either can be made to work; you just have to decide which you want to support. What should happen if the user types ./matrix file1.txt file2.txt file3.txt? One version of conventional behaviour would be to process each file in turn, writing each set of results to standard output. There are plenty of alternative behaviours — most of them have been used by someone at some time or another. Reading from standard input when there is no file name specified is a common mode of operation (think cat and grep and …).
Arguments to a command are in argv[1 .. argc-1].
The redirect from '<' sends the contents of the file to the program's stdin.
A third way to get the filename would be to print "Enter filename: " and then read the string typed by the user.
I'm calling a C executable compiled using Cygwin in MATLAB, using the unix() function. This works fine, and I can see the desired output on the MATLAB command window. However, there is an fprintf() inside the executable that is supposed to create and write to a text file which does not run - no such file is created. The text file is created just fine when I run the executable directly through Cygwin.
I was wondering if I need to grant permissions to the MATLAB file/executable to enable this? How could I go about this?
What path are you using to create the file? It might have been created -- just not where you expected it.
If it's a relative path, you could use getcwd(2) inside your C program to get and print the working directory (or e.g. getpid(2) to get the PID and then do ls -d /proc/<pid>/cwd, which will work on Linux at least). Once you have the working directory, check if the file is somewhere in there.
If it looks like the file really isn't being created, my next step would be to add some error checking to functions and print messages for errors to try to figure out what's going on. strerror(3) and perror(3) might come in handy.
I am writing scripts in tcl for a project I am working on.
I wanted to automate things as much as possible and wanted to not touch the source code of the script as far as possible. I want to run the main script file from a .bat or .job file sort of thing where I pass the command to execute the script along with the arguments.
I have referred to this post on stackoverflow:
How to run tcl script in other tcl script?
And have done pretty much the same thing. However, since my script is naked code rather than a single huge proc, I dont have the "args" parameter to read the arguments I wanted to pass.
For example, if script1.tcl is the main file containing the naked code, I want a file script2.job or script2.bat such that,
<command-to-run-script1.tcl> <mandatory-args> <optional-args>
is the content of the file.
Any suggestions on how I can implement the same?
To run a Tcl script, passing in some arguments, do:
tclsh script1.tcl theFirstArgument theSecondArgument ...
That's how it works in CMD scripts/BAT files on Windows, and in shell scripts on all Unixes. You might want to put quotes around some of the arguments too, but that's just absolute normal running of a program with arguments. (The tclsh might need to be tclsh8.5 or tclsh85 or … well, it depends on how it's installed. And script1.tcl might need to be a full path to the script.)
Inside the script, the arguments (starting at theFirstArgument) will appear in the Tcl list in the global argv variable. Note that this is not args, which is a feature of procedures. There are lots of ways of parsing the list of arguments, but any quoting supplied during the call itself should have been already stripped.
Here's a very simple version:
foreach argument $argv {
puts "Oh, I seem to have a >>$argument<<"
}
You probably need something more elaborate! There's many possibilities though, so be sure to be exact to get more focussed ideas.
If you're calling Tcl from another Tcl script, you need to use exec to do it. On the other hand, you can make things a bit easier for yourself in other ways:
exec [info nameofexecutable] script1.tcl theFirstArgument theSecondArgument ...
The info nameofexecutable command returns the name of the Tcl interpreter program (often tclsh8.5 or wish86 or …)