Reputation:
I'm trying to run BASH commands via a C program, but i'm struggling with the function execv. I don't really know how to write the first parameter of that function. I tried with the strcat function to append the string "/bin/" with the 1st element of the argv tab, which is the command i write when I run my program, but it just doesn't work. I get a "Segmentation fault". Instead of using the strcat function I tried with strdup, but I don't know how to use it right.
Any help would be appreciated. My program is below.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[], char *envp[]){
char *tab[] = {argv[1],NULL};
if(execve(strcat("/bin/",argv[1]), tab, envp)==-1)
{
perror("execve");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Upvotes: 1
Views: 5378
Reputation:
I finally got to find a way to do what I wanted at the first place. Thanks to all of you guys for your help & advices ! Here's the solution !
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[], char *envp[]){
char *tab[] = {argv[1],argv[2],NULL};
char test[20] = "/bin/";
if(execve(strcat(test,argv[1]), tab, envp)==-1)
{
perror("execve");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Upvotes: 0
Reputation: 1
To run a shell command from a C program, you should use system(3).
If you want to get its stdout (or give its stdin, but not both) use popen(3) (don't forget to pclose
such a stream).
The shell used (by system
and popen
) is not exactly bash
but the standard POSIX /bin/sh
(quite similar to bash
with some restrictions).
To build that shell command (but beware of code injections in it) you can use common string functions such as snprintf and asprintf.
Notice that execve(2) does not return when it is successful, and it does not run a command thru a shell, but directly an executable program. Actually Unix shells (such as bash
or /bin/sh
) are using fork(2), execve(2), waitpid(2) very often and are implementing globbing. BTW system
& popen
are also using fork
and execve
on /bin/sh -c
.
strcat("/bin/",argv[1])
is horribly wrong, the first argument to strcat
is the overwritten destination buffer (so cannot be a string literal), and you don't check against buffer overflow.
You might want to code:
char progbuf[80];
int ln = snprintf(progbuf, sizeof(progbuf), "/bin/%s", argv[1]);
and you should check later that ln<(int)sizeof(progbuf)
BTW, your program, when you'll improve it, is not using Bash; it is directly executing some command.
I tried with strdup, but I don't know how to use it right.
Before using any function, you need to carefully read its documentation, for example strdup(3) (or type man strdup
in a terminal).
Upvotes: 1
Reputation: 16540
regarding:
if(execve(strcat("/bin/",argv[1]), tab, envp)==-1)
This will not work ,
Suggest:
#include <stdio.h> // perror()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <sys/types.h>
#include <sys/wait.h> // waitpid()
#include <unistd.h> // fork(), execvp()
#include <string.h> // strlen(), strcpy(), strcat()
int main( int argc, char *argv[], char *env[] )
{
(void)argc;
char *tab[] = { argv[1], NULL };
char string[strlen(argv[1]) + strlen( "/bin/" ) +1 ];
strcpy( string, "/bin/" );
strcat( string, argv[1] );
int status;
pid_t pid = fork();
switch( pid )
{
case -1: // fork failed
perror( "fork failed" );
exit( EXIT_FAILURE );
break;
case 0: // child process
execve( string, tab, env ); // does not return unless an error
perror("execve failed");
exit( EXIT_FAILURE );
break;
default:
waitpid( pid, &status, 0 );
break;
}
}
Caveat: the proposed code just hides the parameter: argc
rather than properly checking it to assure the command line does contain a parameter.
Caveat: the parameter to main: env[]
is not portable and should not be used. Suggest using :
extern char *environ[];
Upvotes: 1
Reputation: 251
Melpomene is right- you can't use strcat
like that. In C, you can't return strings. What you do is pass a memory address (pointer) as the first argument in strcat
, and then strcat
modifies the memory pointed to by it so that it also contains the second argument of strcat
. This is a process you will repeat over and over again in C, so you should understand it. Also, that strcat
doesn't look safe, I bet there is a strcatn
function or something like that.
Upvotes: 0