1

date、ls などの単純なコマンドを言語 c で解釈できる基本的なシェルを作成しようとしています。

まず、このように PATH 変数を取得して、後で execv() 関数に渡します。

const char *name = "PATH";
char *value;
value = getenv(name)

値を出力すると、次のようになります。

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Ubuntuを実行するためにvirutalboxを使用していることに注意してください。これは、単純な ls コマンドを試すために使用しているコードです。変数行の下のコードでは、ユーザーが書いた実際のコマンドです。この場合は「ls」です。

  pid_t pid, wpid;
  int status;

  pid = fork();
  if (pid == 0) {
      // Child process
      if (execv(value, line) == -1) {
          perror("lsh");
      }
      exit(EXIT_FAILURE);
  }
  else if (pid < 0) {
        // Error forking
        perror("lsh");
  }
  else {
      // Parent process
      do {
          wpid = waitpid(pid, &status, WUNTRACED);
      }
      while (!WIFEXITED(status) && !WIFSIGNALED(status));
    }

そして、私が得る結果はこれです:

lsh: no such file or directory

何か案は?

4

2 に答える 2

5

システム コールは、最初のexecv()引数で指定した名前を実行可能ファイルのファイル名として使用します。PATH ベースの検索は行いません。

つまり、最初の引数として指定する場合、現在のディレクトリに"lsh"実行可能ファイルが存在する必要があります。lsh

PATH ベースの検索が必要な場合は、に置き換えexecv()ますexecvp()。それ以外の場合は、最初の引数でコマンドのパス名 (絶対または相対、ただし絶対の方がより一般的) を指定します。

exec*()関数のいずれかが返された場合、それは失敗していることに注意してください。戻り値をテストする必要はありません。常に -1 になります。

の内容はvalueline次の行に沿っている必要があります。

char *value = "ls";
char *line[] = { "ls", "-l", 0 };

execvp(value, line);

または、より慣習的に:

execvp(line[0], line);

自分で PATH を分析している場合は、PATHline[0]から作成した完全なファイル名を指定する必要がありexecv()ますexecvp()

于 2015-11-19T20:42:29.870 に答える