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;
}
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).
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[];
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.
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.