0

ユーザー指定のターミナルコマンドを実行したいのですが。たとえば、ユーザーがテキストフィールドに入力しkillall "TextEdit"たりsay "Hello world!"、テキストフィールドに入力したりして、そのコマンドを実行したいとします。

NSTaskは、2つの問題があることを除いて、進むべき道です。

最初に:引数。今私はこれをやっています:

NSArray* args = [commandString componentsSeparatedByString: @" "];
[task setArguments: [args subarrayWithRange: NSMakeRange(1, [args count] - 1)]]; // First one is the command name

これはそれを行う方法ですか?まだ問題はないと思いますが、安全とは思えません。これを想像してみてください。ユーザーは書き込みますkillall 'Address Book'が、コマンドは引数として受け取り'AddressますBook'。それはうまくいきません。だから、私は代わりに何をすべきですか?どうすれば引数を安全に解析できますか?

2番目:起動パス。コマンドへの完全なパスではなく、コマンドの名前を記述するだけでよい方がはるかにユーザーフレンドリーです。だから私はそれをサポートしたいのです。つまり、名前だけを持つコマンドのフルパスをプログラムで見つけることを意味します。そのために、私はNSTaskに次のようなカテゴリを作成しました。

+ (NSString*)completePathForExec: (NSString*)exec
{
    NSTask* task = [[NSTask alloc] init];
    NSPipe* pipe = [[NSPipe alloc] init];

    NSArray* args = [NSArray arrayWithObject: exec];
    [task setLaunchPath: @"/usr/bin/which"];
    [task setArguments: args];
    [task setStandardOutput: pipe];
    [task setStandardError: pipe];

    [task launch];    
    [task waitUntilExit];

    NSFileHandle* file = [pipe fileHandleForReading];
    NSString* result = [[NSString alloc] initWithData: [file readDataToEndOfFile] encoding: NSASCIIStringEncoding];

    if ([result length]) {
        if ([result hasSuffix: @"\n"]) { result = [result substringWithRange: NSMakeRange(0, [result length] - 1)]; }

        return result;
    }
    else { return exec; }
}

これはうまくいくようです。/usr/bin/whichただし、このパスが常に機能することをどのように確認できますか?つまり、10.6、10.7、10.8などで動作しますか?シェルコマンドへのパスがシステムバージョンによって変更されたときに問題が発生したと思います。注意しすぎることはありません。

パスが同じままであることが保証されている場合、これは問題ではありません。変更された場合、「パスファインダーへのパス」をどのように知ることができますか?

4

1 に答える 1

3

コマンドライン解析ホイールを再発明しない方がはるかに簡単です。しかし、もちろん、ユーザーが入力した任意のコードを実行するルートをたどるのはセキュリティ上の悪夢です(ユーザーがシステムにアクセスできるため、ターミナルを直接実行できる可能性があります)。

具体的には、NSTaskにコマンドラインオプションを使用してシェルの1つの呼び出しをラップさせ、任意の文字列を実行させます。

sh -c "ls -alF"

shこれにより、すべてのシステムの固定された場所にある起動パスとしてパスを渡すことができます。@"-c"引数は、次の引数をスクリプトとして解析するように指示します。shもちろん、次の引数は、ユーザーが入力したものです。

これにより、ユーザーはパイプを使用することもできます。

于 2012-09-12T16:34:21.687 に答える