I have C program ( program.c ) that calls a shell script ( command.sh ).
command.sh returns an output (a password), i need to get this output in my program.c.
using system(command); , i can't get hold of the output.
is there any other way in C to solve my problem?
Not in pure C. You want POSIX. Specifically popen function.
The specification has a nice example, that you can just copy 1:1
http://pubs.opengroup.org/onlinepubs/009604499/functions/popen.html
Sounds like you're afraid to use libraries. Please try and use libraries, they're just as much part of Unix as shell tools.
In pure C (well ... ignoring the contents of the system() call) you can redirect the shell script output to a file, then read that file.
system("whatever > file");
handle = fopen("file", "r");
/* if ok use handle */
fclose(handle);
You can use popen() as suggested above, but note that in this case you have no control over the process you created (e.g. you will not be able to kill it), you also will not know its exit status.
I suggest using classical pipe/fork/exec combination. Then you will know the pid of your child process, so you will be able so send signals, also with pipe() you are able to redirect process standard output, so you can easily read it in your parent process. As example you can see my accepted answer to popen() alternative.
You should open a pipe using popen but this sounds tedious. A C program calling a shell script for a password.
Related
Good morning;
Right now, I'm writing a program which makes a Montecarlo simulation of a physical process and then pipes the data generated to gnuplot to plot a graphical representation. The simulation and plotting work just fine; but I'm interested in printing an error message which informs the user that gnuplot is not installed. In order to manage this, I've tried the following code:
#include <stdio.h>
#include <stdlib.h>
FILE *pipe_gnuplot;
int main()
{
pipe_gnuplot = _popen("gnuplot -persist", "w");
if (pipe_gnuplot==NULL)
{
printf("ERROR. INSTALL gnuplot FIRST!\n");
exit (1);
}
return 0;
}
But, instead of printing my error message, "gnuplot is not recognized as an internal or external command, operable program or batch file" appears (the program runs on Windows). I don't understand what I'm doing wrong. According to _popen documentation, NULL should be returned if the pipe opening fails. Can you help me managing this issue? Thanks in advance and sorry if the question is very basic.
Error handling of popen (or _popen) is difficult.
popen creates a pipe and a process. If this fails, you will get a NULL result, but this occurs only in rare cases. (no more system resources to create a pipe or process or wrong second argument)
popen passes your command line to a shell (UNIX) or to the command processor (Windows). I'm not sure if you would get a NULL result if the system cannot execute the shell or command processor respectively.
The command line will be parsed by the shell or command processor and errors are handled as if you entered the command manually, e.g. resulting in an error message and/or a non-zero exit code.
A successful popen means nothing more than that the system could successfully start the shell or command processor. There is no direct way to check for errors executing the command or to get the exit code of the command.
Generally I would avoid using popen if possible.
If you want to program specifically for Windows, check if you can get better error handling from Windows API functions like CreateProcess.
Otherwise you could wrap your command in a script that checks the result and prints specific messages you can read and parse to distinguish between success and error. (I don't recommend this approach.)
Just to piggy-back on #Bodo's answer, on a POSIX-compatible system you can use wait() to wait for a single child process to return, and obtain its exit status (which would typically be 127 if the command was not found).
Since you are on Windows you have _cwait(), but this does not appear to be compatible with how _popen is implemented, as it requires a handle to the child process, which _popen does not return or give any obvious access to.
Therefore, it seems the best thing to do is to essentially manually re-implemented popen() by creating a pipe manually and spawning the process with one of the spawn[lv][p][e] functions. In fact the docs for _pipe() give an example of how one might do this (although in your case you want to redirect the child process's stdin to the write end of your pipe).
I have not tried writing an example though.
I'm trying to write a shell that will eventually take advantage of concurrency. Right now I've got a working shell parser but I'm having trouble figuring out how to execute commands. I've looked a bit at exec (execvp etc.) and it looks promising but I have some questions.
Can exec handle file input/output redirection? Can I set up pipes using exec?
I'm also wondering about subshells. What should subshells return; the exit status of its last statement? Can subshells be a part of a pipe?
These might seem like really dumb questions but please bear with my inexperience.
Can exec handle file input/output redirection?
No, you do that with open() and dup() or dup2() (and close()).
Can I set up pipes using exec?
No, you do that with pipe(), dup() or dup2() and lots of close() calls.
I'm also wondering about subshells. What should subshells return, the exit status of its last statement?
That's the normal convention, yes.
Can subshells be a part of a pipe?
Yes. In a normal shell, you can write something like:
(cd /some/where; find . -name '*.png') | sed 's/xyz/prq/' > mapped.namelist
If you want to get scared, you could investigate posix_spawn() and its support functions. Search for 'spawn' at the POSIX 2008 site, and be prepared to be scared. I think it is actually easier to do the mapping work ad hoc than to codify it using posix_spawn() and its supporters.
The standard technique for a shell is to use fork-exec. In this model, to execute an application the shell uses fork to create a new process that is a copy of itself, and then uses one of the exec variants to replace its own code, data, etc. with the information specified by an executable file on disk.
The nice thing about this model is that the shell can do a little extra work with file descriptors (which are not thrown away by exec) before it changes out its address space. So to implement redirection, it changes out the file descriptors 0, 1, and 2 (stdin, stdout, and stderr, respectively) to point to another open file, instead of console I/O. You use dup2 to change out the meaning of one of these file descriptors, and then exec to start the new process.
I use fork()/exec()/wait() rather than system() when the command has user input as some of its arguments so the user can't put something like...
&rm -rf /home/* && echo HAHA
... as an argument.
I'm assuming popen is as dangerous as system() because it takes a single string and not a list of strings like the exec family of functions do.
I can only get the return value from the exec functions though. Is there a "safe" version of popen that I can run with user input and process stdout / stderr back in the parent process?
The safe way is to set up the necessary pipes yourself, using straight pipe() calls directly.
That's what popen() does under the hood, but it also invokes the shell in order to run the child process. Skipping that step should make it safer.
I am trying to execute a program from within a C program (inside UNIX).
I have been given an executable ( the program requires a string input during execution and writes that input to another file called sample ) called exec and I want to execute it in program.c, but giving the string input through indirection.
For that I created a file as follows:
% vim input
I wrote the following inside the input file
content
Now in program.c,
#include<unistd.h>
int main()
{
const char* command = "./exec < input";
execvp(command, NULL);
return 0;
}
When I run the program, the content is not entered into the sample file.
But when I run it without indirection, i.e.
const char* command = "./exec";
then it works, and input entered in saved in sample file.
Can someone please tell what am I doing wrong in the indirection syntax.
Thanks.
The syntax you are using is supposed to be interpreted by a shell like bash, csh, ksh, etc.
The system call execvp only expects the path to the executable and a number of arguments, the shell is not invoked there.
To perform redirection in this manner, you'll have to use the dup2(2) system call before calling execvp:
int fd = open("input", O_RDONLY);
/* redirect standard input to the opened file */
dup2(fd, 0);
execvp("/path/to/exec", ...);
Of course, you'll need some additional error checking in a real-world program.
You can't do redirection like that with execvp. Use system() or start getting friendly with dup() and friends. You might google 'implementing redirection'.. you'll likely turn up plenty of examples of how shells (for example) handle this problem.
The exec(3) family of functions does not know anything about input redirection or parsing command lines: it tries to execute exactly the executable you give it. It's trying to search for an executable file with the name "./exec < input", which unsurprisingly does not exist.
One solution would be to use the system(3) function instead of exec. system invokes the user's shell (such as /bin/bash), which is capable of parsing the command line and doing appropriate redirections. But, system() is not as versatile as exec, so it may or may not be suitable for your needs.
The better solution is to do the input redirection yourself. What you need to do us use open(3) to open the file and dup2(3) to duplicate the file descriptor onto file descriptor 0 (standard input), and then exec the executable.
I need to run a script and have access to the default stdin (terminal input) in my program. I could do ./program "script", opening and parsing the script through the program, but I want to make it POSIX style, accepting input from pipes or from redirection.
I mean, since my program is a parser, I could run ./program, type the script and still use stdin (in a scanf, for example). But I'd like to run ./program < script and still be able to use stdin (in a scanf).
My program is a simplified Pascal interpreter, that's why I need to run read(x) and write(x) in my scripts.
Yes, it's homework (the intepreter), but the doubt just popped up in the brainstorming process.
The current controlling terminal can be accessed using /dev/tty, even if stdin has been redirected.
ttyname(0) will return the filename of the current terminal associated with stdin. You can then open that and read from it.
If I understand what you're asking, you're asking for the ability to take in interactive input from a user when using file redirection, like the ./program < script bit above.
I don't believe there's a way to do that. A POSIX system will feed the script in via stdin and that's that. No interaction from the user.
It's also worth noting that you don't have to do anything special to realize that. Just treat stdin like you normally would. You don't have to think about whether it's coming in interactively or from a file, which is really quite nice.