4

私はubuntuでUNIXミニシェルを書いていますが、この時点で組み込みコマンドを追加しようとしています。組み込みコマンドでない場合はフォークしてから子が実行しますが、組み込みコマンドの場合は現在のプロセスで実行します。

したがって、ファイルが存在するかどうかを確認する方法が必要です(ファイルが存在する場合は組み込みコマンドではありません)が、execvpは環境PATH変数を使用してファイルを自動的に検索するため、事前に手動で確認する方法がわかりません。

では、名前を指定するだけで、引数をテストして組み込みコマンドかどうかを確認する方法を知っていますか?

みんなありがとう。

4

4 に答える 4

3

私はトムの答えをテストしました

それには多くの問題が含まれていました。ここでそれらを修正し、テスト プログラムを提供しました。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

int is_file(const char* path) {
    struct stat buf;
    stat(path, &buf);
    return S_ISREG(buf.st_mode);
}

/*
 * returns non-zero if the file is a file in the system path, and executable
 */
int is_executable_in_path(char *name)
{
    char *path = getenv("PATH");
    char *item = NULL;
    int found  = 0;

    if (!path) 
        return 0;
    path = strdup(path);

    char real_path[4096]; // or PATH_MAX or something smarter
    for (item = strtok(path, ":"); (!found) && item; item = strtok(NULL, ":"))
    {
        sprintf(real_path, "%s/%s", item, name);
        // printf("Testing %s\n", real_path);
        if ( is_file(real_path) && !(
               access(real_path, F_OK) 
            || access(real_path, X_OK))) // check if the file exists and is executable
        {
            found = 1;
        }
    }

    free(path);
    return found;
}

int main()
{
    if (is_executable_in_path("."))
        puts(". is executable");
    if (is_executable_in_path("echo"))
        puts("echo is executable");
}

ノート

  1. 戻り値のテストaccessが逆になった
  2. 2 番目の strtok 呼び出しの区切り文字が間違っていました
  3. strtok はpath引数を変更しました。私のサンプルはコピーを使用しています
  4. 連結されたパス区切り文字が適切であることを保証するものは何もありませんでした。real_path
  5. 一致したファイルが実際にファイルであるかどうかのチェックはありませんでした (ディレクトリも「実行可能」になる可能性があります)。.これは、外部バイナリとして認識されるなどの奇妙なことにつながります
于 2012-10-07T00:52:40.847 に答える
1

できることは、特定のディレクトリへのパスを変更してから、#include<dirent.h>ヘッダーファイルとそのreaddir関数を使用scandirしてディレクトリまたは構造をウォークスルーしstat、ファイルがディレクトリに存在するかどうかを確認することです。

于 2012-10-07T00:53:51.893 に答える
1

:PATH ディレクトリを反復処理し、PATH の各エントリに対して (おそらくstrtokを使用して PATH を分割する必要があります)、各パスの最後に呼び出されたコマンドの名前を連結します。このパスを作成したら、ファイルが存在するかどうか、およびaccessを使用して実行可能かどうかを確認します。

int is_built_in(char *path, char *name)
{
  char *item = strtok(path, ":");

  do {
    char real_path[4096] = strcat(item, name); // you would normally alloc exactly the size needed but lets stick to it for the sake of the example
    if (!access(real_path, F_OK) && !access(real_path, X_OK)) // check if the file exists and is executable
      return 0;
  } while ((item = strtok(NULL, ":")) != NULL);
  return 1;
}
于 2012-10-07T00:21:40.433 に答える
1

を呼び出すにテストするのはなぜexecvpですか? それは間違ったアプローチです。呼び出すだけexecvpで、プログラムが存在しないかどうかがわかります。

于 2012-10-07T03:40:05.380 に答える