2017-10-08 35 views
1

私はCプログラム経由でBASHコマンドを実行しようとしていますが、私はexecv関数で苦労しています。私は実際にその関数の最初のパラメータを書く方法を知らない。私はstrcat関数を使って文字列 "/ bin /"をargvタブの最初の要素に追加しようとしました。これはプログラムを実行するときに書き込むコマンドですが、動作しません。私は「セグメンテーション違反」を取得します。 strcat関数を使う代わりにstrdupを使ってみましたが、それを正しく使う方法はわかりません。Cプログラム経由でBASHコマンドを実行

ご協力いただければ幸いです。私のプログラムは以下の通りです。

#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; 
} 
+2

基本的に、Cで2つの文字列を連結する方法を尋ねているだけですか?あなたはCチュートリアルを読もうとしましたか? – melpomene

+0

私はどのように連結するかを尋ねていませんが、これが連結についてのものであれば、関数strcatは十分であるはずです。しかし、そうではありません。だから私はプログラムを動作させるためにexecv関数を使う別の方法について助けを求めている。 – TheScientist

+4

それがあなたが求めているものでなければ、あなたが求めるべきものです。明らかに、 'strcat'が何をするのか、あるいはC文字列がどのように動作するのか理解していません。 ( 'strcat'の最初の引数として文字列リテラルを渡すことは決して意味がありません) – melpomene

答えて

0

メルポメンはstrcatのように使用できません。 Cでは、文字列を返すことはできません。あなたが行うのは、strcatの最初の引数としてメモリアドレス(ポインタ)を渡し、次にstrcatという2番目の引数も含むようにstrcatが指すメモリを変更します。これはCで何度も何度も繰り返すプロセスなので、理解しておく必要があります。また、strcatは安全ではありません。私はそこにstrcatnのような機能があると思います。

+1

'strncat'がありますが、' n'引数は何バ​​イトターゲットバッファの大きさではなく、第2引数から(多くとも)読み込みます。 – melpomene

+0

LOL stdlibはそれを正しく取得しません。 –

1

Cプログラムからシェルコマンドを実行するには、system(3)を使用する必要があります。 stdoutを取得したい場合(あるいはその両方を取得するのではなく)、popen(3)を使用します(pcloseそのようなストリームを忘れないでください)。

systempopenで)使用するシェルは正確にbashではなく、標準のPOSIX /bin/sh(いくつかの制限がbashと非常に似ています)。

シェルコマンドを作成するには(code injectionsに注意してください)、snprintfasprintfのような一般的な文字列関数を使用できます。

execve(2)は、成功した場合には返されず、シェルを介してコマンドを実行するのではなく、実行可能プログラムを直接実行することに注意してください。実際にUnix shells(例えば、bashまたは/bin/sh)は、fork(2),execve(2),waitpid(2)を頻繁に使用しており、globbingを実装しています。 BTW system & popenforkexecve/bin/sh -cに使用しています。

strcat("/bin/",argv[1])

strcatへの最初の引数は(そうリテラル文字列にすることはできません)上書きされた宛先バッファである、とあなたがbuffer overflowに対してチェックしていない、恐ろしく間違っています。

あなたはコードが必要になる場合があります

char progbuf[80]; 
int ln = snprintf(progbuf, sizeof(progbuf), "/bin/%s", argv[1]); 

、あなたはBTW ln<(int)sizeof(progbuf)

、あなたはそれを改善するだろうあなたのプログラムが、バッシュを使用していないことを後で確認する必要があります。いくつかのコマンドを直接実行しています。


私はのstrdupを試みたが、私は右のそれを使用する方法がわかりません。

は、任意の関数を使用する前に、慎重に例 strdup(3)ためのマニュアルを読み(または端末に man strdupを入力)する必要があります。

1

if(execve(strcat("/bin/",argv[1]), tab, envp)==-1) 

これは動作しません、

  1. リテラル "/ binに/" 読み出し専用メモリであるので、保持するのに十分な大きさのcharバッファを必要とする(変更することはできません文字列 'と同様の完全な文字列[100] = "/ binに/";

が提案:

#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; 
    } 

} 

注意:提案されたコードは、コマンドラインにパラメータが含まれていることを確認するために正しくチェックするのではなく、パラメータ:argcを隠すだけです。

注意:メインへのパラメータ:env[]は移植性がなく、使用しないでください。提案する:

extern char *environ[]; 
0

私は最終的に私が最初にしたいことをする方法を見つける必要がありました。あなたのお役に立ってくれてありがとう&アドバイス!ここに解決策があります!

#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; 
} 
関連する問題