chdir on a file to use execl - c

i'm programming on the command find in c and i'm blocked when i want to use exec on a file.
if it is a repertory it is simple, i just use chdir(path) but on file i have the error not a directory so i can't use exec on it
this is what i have
if (chdir(resultat[i])==-1){
perror("erreur changement de repertoire\n");
exit(1);
}
execl("/bin/ls","ls",(char *)0);
resultat[i] is the path of my file
thanks for your help

(I am not exactly sure what you are trying to do and I do not know what the rest of your code is doing, so this is only a shot in the dark...)
Have you considered passing resultat[i] as an argument to ls? ls will probably do The Right Thing(TM) on it own. I.e. replace the snippet that you supplied with this:
execl("/bin/ls","ls", resultat[i], (char *)0);
I assume that you have already done all the needed work (e.g. fork()) to avoid your application terminating prematurely at the exec() call...

I assume this is Linux (ls is linux only haha), so try using opendir first and see if you get a valid handle, then try to read one file out of it. If you get a valid filename, you can then check if its a file...
http://www.gnu.org/software/libc/manual/html_node/Reading_002fClosing-Directory.html#Reading_002fClosing-Directory

Related

how to completely close the file write before starting another process which uses it?

My program creates a linux shell file, then it call 'popen' to execute it. To my surprise from time to time I am getting the following message: /bin/bash: bad interpreter: Text file busy. So, am looking for a way to solve this problem. Any suggestions?
Here is a skeleton code of what i am doing:
FILE *f = fopen(shFile, "w");
fprintf(f, ...);
...
fclose(f);
FILE *job = popen(shFile, "r");
...
So, both processes run on the same machine, there is no 'nfs' involved, but still the popen process thinks that the file is opened for write, even after i did close. So, some system buffers are not flushed yet.
It looks like sync() works (though it is difficult to tell). However it slows down everything significantly.
When you leave the kernel to determine the interpreter to be used with a script file using a shebang, the kernel must take a similar "lock" on the script file as it does for binaries. (This is a kernel-internal "lock" that you can only observe from userspace. If the file is open for writing by anyone, the lock fails with ETXTBUSY.)
It is trivially to avoid that. You are free to edit script files even when they are being interpreted, if you execute the interpreter instead with the script name as a parameter.
In OP's case, it means executing bash %s, where %s is replaced with the contents of shFile. This also means the file referred to by shFile does not need to be executable; only readable.
If we assume shFile does not contain any ' characters, then in Linux it is sufficient to use
char *jobcmd = NULL;
FILE *job;
if (asprintf(&jobcmd, "bash '%s'", shFile) == -1) {
/* Typically an out of memory error. */
fprintf(stderr, "%s.\n", strerror(errno));
exit(EXIT_FAILURE);
}
errno = ENOMEM;
job = popen(jobcmd, "r");
if (!job) {
fprintf(stderr, "Cannot execute %s: %s.\n", shFile, strerror(errno));
exit(EXIT_FAILURE);
}
free(jobcmd);
jobcmd = NULL;
In general, you should consider a custom routine that constructs the sh shell command needed to execute the desired interpreter with the file name as a parameter, applying any escaping as necessary. (In POSIX sh shells, you can escape single quotes in a single-quoted string using '"'"'.)
If the script is executed only once, a custom replacement for popen()/getline() or fread() or fgetc()/pclose() can be used to write the script to the standard input of the interpreter (here, bash -s), while also retrieving the output of the script into a single array, line per line (perhaps using a callback function?), or character-by-character. This approach has the benefit of the script never being stored on any filesystem.
In general, it is much more common, and definitely recommended, to install the scripts as part of the binary, and supply any specifics to it via command-line parameters (for example, bash /usr/share/yourapp/somescript.bash 'arg1' 'arg2').
In Linux and BSDs, these scripts are usually put somewhere under /usr/lib/yourapp/ or /usr/share/yourapp/.

Catching shell script output in program c

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.

UNIX run program within another program

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.

Executing shell command and reading its output on a C program

I am trying to create a function which takes a shell command as an argument , uses fork to spawn a new process which executes the command. I also want to redirect the standard output of the command so the caller of the function can read it using a FILE* pointer.
static FILE* runCommand(char* command){
int pfd[2];
if(pipe(pfd)<0)
return NULL;
if(pid=fork()==0){ //child
close(pfd[0]);
dup2(pfd[1],1); //redirect output to pipe for writing
execlp(command,(char*)0);
}
close(pfd[1]);
//return a file pointer/descriptor here?
}
I am not sure how to return a file pointer which can be used to read the output of the command. Also is that the correct way to execute a command on the shell?
ps. I read about popen but there is a good reason I can't use it, thus I have to implement this functionality myself.
Thank you
One bug in that code is that you assign to a variable pid that is not declared anywhere. And pid will always be 1 in the parent, because the code as written is equivalent to pid=(fork()==0) rather than (pid=fork())==0.
You should also close pfd[1] after the dup2 call. And for good measure, check for errors from dup2 and execlp.
The answer to your real question is to use fdopen.
Use fdopen to associate an existing file descriptor with a FILE * object. Everything else looks pretty good.

The exec family

I have a project the requires the use of the exec family. My project consist of making an interactive shell. The shell will implement a few basic commands like cd, ls, echo, etc. I have been researching the use of exec, but have not found a useful site. Any suggested links would help.
int ret;
ret = execl ("/bin/ls", "ls", "-1", (char *)0);
How would i get the output of this operation to show on the screen?
doing
int fd = 1;
dup(fd);
close(fd);
gets the output to the screen.
The code you wrote works for me in a simple test program that does nothing else. Remember, when you call execl, the process retains all of the old file handles. So whatever stdout was when you call execl, it will be the same when the new binary is loaded. If you just want the output to go to the terminal, just make sure stdout goes to the terminal.
If you want to do I/O with another program, popen is good for this (as mgb mentioned). It will fork a new process, set up plumbing for you, call some variant of exec, and return a file handle you can use for communication.

Resources