2017-05-14 2 views
0

cでexeclp()に関する質問があります。Cプログラムでのexeclp()の使用

#include <stdio.h> 
#include <unistd.h> 
#include <sys/unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 
#include <stdlib.h> 
#include <limits.h> 
#include <signal.h> 

void INThandler(int); 

int main(int argc, char* argv[]) { 

    struct passwd *pwd; 
    char *lgn; 
    char *cwd; 
    char buff[PATH_MAX + 1]; 
    char s1[10], s2[10]; 

    /*Um den Namen zu bekommen*/ 
    lgn = getlogin(); 
    pwd = getpwnam(lgn); 

    /*Um den Hostnamen zu bekommen*/ 
    char hostname[128]; 
    gethostname(hostname, sizeof hostname); 

    /*Um das Arbeitsverzeichnis zu bekommen*/ 
    cwd = getcwd(buff, PATH_MAX + 1); 
    if((cwd!=NULL)&& hostname!=NULL && ((lgn=getlogin())!=NULL || 
(pwd!=NULL))) 
    { 
     signal(SIGINT, INThandler); 
     while(1) 
     { 
      printf("%[email protected]%s %s$", pwd->pw_name, hostname, cwd); 
      if(scanf("%s %s",s1, s2)<1) 
      return 1; 
      printf("Befehl: %s\nArgument: %s\n",s1,s2); 
      execlp(s1, s1, NULL); 
      printf("Zhopa"); 
      return 1; 
     } 

    } 
    return 0; 
} 

void INThandler(int sig) { 
    char c; 

    signal(sig, SIG_IGN); 
    printf("Wollen Sie Program Verlassen? [y/n]"); 

    c = getchar(); 
    if(c == 'y' || c=='Y') 
    exit(0); 
    else 
    signal(SIGINT, INThandler); 
    getchar(); 
} 

それは、ユーザー名@ホスト名のフォルダ$を印刷し、それはのexeclpでそれを起動する必要があり、その後(引数の「ls -al」 としてLinuxのコマンドを取る必要があります。

私は、次のプログラムの開発を持っています)、それは私が思うように動作しません。

私はこのコマンドに関するすべての記事を読んでいますが、私はまだそれを使用する方法を理解していないと思います。

私は誰かの助けに感謝します。

+2

*「それは私が考えるべきではない」とは*正確に何を意味するのでしょうか? - execlp *はプロセスイメージを置き換えることに注意してください。あなたのプログラムには決して戻りません。私が理解する限り、http://stackoverflow.com/questions/16206961/c-program-exits-on-executing-execlp-function –

+0

を見てください。もしexeclp()の文字列s1、s2(つまり、 execlp(s1、s2、NULL)、s1 = "ls"、s2 = "-al")なら、ls -al – Natalya

+0

を実行する必要がありますか? – Natalya

答えて

1

fork()で新しいプロセスを作成し、新しいプロセス(子プロセス)でexeclpを使用しました。ここにサンプルコードがあります。それはすべてのエラーを処理しないと、それは私が理解してきたものだから、それだけで正確に1パラメータを指定してコマンドを使用して動作します(例えば。ls -all

#include <stdio.h> 
#include <unistd.h> 
#include <sys/unistd.h> 
#include <sys/wait.h> /*Lib for waitpid*/ 
#include <sys/types.h> 
#include <pwd.h> 
#include <stdlib.h> 
#include <limits.h> 
#include <signal.h> 

void INThandler(int); 

int main(int argc, char* argv[]) { 

    int pid = 0; /*PROCESS ID*/ 
    struct passwd *pwd; 
    char *lgn; 
    char *cwd; 
    char buff[PATH_MAX + 1]; 
    char s1[10], s2[10]; 

    /*Um den Namen zu bekommen*/ 
    lgn = getlogin(); 
    pwd = getpwnam(lgn); 

    /*Um den Hostnamen zu bekommen*/ 
    char hostname[128]; 
    gethostname(hostname, sizeof hostname); 

    /*Um das Arbeitsverzeichnis zu bekommen*/ 
    cwd = getcwd(buff, PATH_MAX + 1); 
    if((cwd!=NULL)&& hostname!=NULL && ((lgn=getlogin())!=NULL || 
(pwd!=NULL))) 
    { 
     signal(SIGINT, INThandler); 
     while(1) 
     { 
      printf("%[email protected]%s %s$", pwd->pw_name, hostname, cwd); 
      if(scanf("%s %s",s1, s2)<1) 
      return 1; 
      printf("Befehl: %s\nArgument: %s\n",s1,s2); 
      pid = fork(); 
      if(pid == 0){ /*Child*/ 
      execlp(s1, s1, s2,(char*) NULL); 
      }else if(pid > 0){ /*Father*/ 
      /*father waiting for the child*/ 
      waitpid(pid,NULL,0); 
      } 
      printf("Zhopa"); 
     } 

    } 
    return 0; 
} 

void INThandler(int sig) { 
    char c; 

    signal(sig, SIG_IGN); 
    printf("Wollen Sie Program Verlassen? [y/n]"); 

    c = getchar(); 
    if(c == 'y' || c=='Y') 
    exit(0); 
    else 
    signal(SIGINT, INThandler); 
    getchar(); 
} 
1

あなたのシグナルハンドラが未定義の動作を呼び出します。

シグナルハンドラ内からのみ非同期シグナルセーフ機能を呼び出すことができます。 Per the POSIX standard:シグナルハンドラは、次の表に記載されている機能 の1よりも、この標準の他に定義された任意の 関数を呼び出す場合

... 行動は...定義されていません。

次の表は、 async-signal-safeである一連の関数を定義しています。したがって、アプリケーションはシグナル捕捉関数から の制限なしに呼び出すことができます。 ...

[非同期シグナル安全関数のテーブル]

任意の機能上の表に信号に対して安全でないかもしれません。 ...

このシグナルハンドラ

void INThandler(int sig) { 
    char c; 

    signal(sig, SIG_IGN); 
    printf("Wollen Sie Program Verlassen? [y/n]"); 

    c = getchar(); 
    if(c == 'y' || c=='Y') 
    exit(0); 
    else 
    signal(SIGINT, INThandler); 
    getchar(); 
} 

は、その中に複数の非非同期シグナルセーフの機能があります。

  • printf()
  • getchar()
  • exit()

これらの関数をシグナルハンドラ内から安全に呼び出すことはできません。

コードを指定すると、にプロセスがブロックされているときに、この信号ハンドラが呼び出される可能性が高い場所は、stdinからの読み取りを試みます。おそらく何らかのロックやミューテックスが関係する可能性があります。しかし、あなたのシグナルハンドラは、getchar()を呼び出して、stdinからの読み取りを試みます。これは、ロックされているか、または不確定な状態になっている可能性があります。メインスレッドがscanf()でブロックされている場合、信号ハンドラ内のgetchar()への非同期呼び出しによって、stdinに使用される内部構造がデッドロックまたは破損する可能性があります。

関連する問題