0

私は C で UNIX ミニシェルを書いていて、コマンド展開を追加している段階です。これが意味することは、コマンドを他のコマンドにネストできるということです。たとえば、次のようになります。

$> echo hello $(echo world! ... $(echo and stuff))
hello world! ... and stuff

私はそれがほとんど機能していると思いますが、展開された文字列の末尾を正しくマークしていません。たとえば、次の場合です。

$> echo a $(echo b $(echo c))
a b c
$> echo d $(echo e)
d e c

私が頼んだわけではありませんが、c が出力されるのを見てください。これが私のコードです:

msh.c - http://pastebin.com/sd6DZYwB expand.c - http://pastebin.com/uLqvFGPw

もっとコードがありますが、たくさんあります。これらは、現時点で問題を抱えている部分です。私がこれを行っている基本的な方法をお伝えしようと思います。

Main は msh.c にあります。ここでは、コマンドラインまたはシェルファイルから入力行を取得し、プロセスライン (char *line, int outFD, int waitFlag) を呼び出します。ここで、line は取得した行、outFD は出力ファイルのファイル記述子であり、waitFlag はフォークする場合に待機する必要があるかどうかを示します。これを main から呼び出すときは、次のようにします。

processline (buffer, 1, 1);

processline では、新しい行を割り当てます。

char expanded_line[EXPANDEDLEN];

次に、expand.c で expand を呼び出します。

expand(line, expanded_line, EXPANDEDLEN);

expand では、$( が見つかるまで文字列を line から Expanded_line に文字どおりにコピーし、次を呼び出します。

static int expCmdOutput(char *orig, char *new, int *oldl_ind, int *newl_ind)

orig は行、new は展開された行です。oldl_ind と newl_ind は、それぞれ行と展開された行の現在の位置です。次に、パイプを使用して processline を再帰的に呼び出し、ネストされたコマンドを渡します (たとえば、"echo a $(echo b)" がある場合は、processline "echo b" を渡します)。

これは私が混乱するところです.expandが呼び出されるたびに、EXPANDEDLEN longの新しいメモリチャンクが割り当てられますか? もしそうなら、これは悪いことです (非常にネストされたコマンドライン入力の場合)。expand では、展開された文字列の最後に null 文字を挿入します。なぜそれを超えて印刷されるのですか?

さらにコードや説明が必要な場合は、お尋ねください。第二に、大量のコードがあるため、コードをペーストビンに入れました。私の経験では、コードでいくつかのページを埋めると、人々はそれを気に入りません。

4

1 に答える 1

1

あなたの問題はにありますexpCmdOutput。すでにお気づきのように、を使用して子プロセスの出力を読み取るときに、NULで終了する文字列を取得することはありませんread。あなたがしたいのは、次のようなものを追加して、文字列を手動で終了することです

    buf[bytes_read] = '\0';

read29行目(expand.c)への呼び出し後。NUL用のスペースが必要な場合はBUF_SIZE - 1、もちろん、最大バイトまでしか読み取ることができません。

ただし、後で行うループ全体を再考する必要があります。

    /* READ OUTPUT OF COMMAND FROM READ END OF PIPE, THEN CLOSE READ END */
    bytes_read = read(fd[0],buf,BUF_SIZE);
    while(bytes_read > 0)
    {
            bytes_read = read(fd[0], buf, BUF_SIZE);
            if (bytes_read == -1) perror("read");
    }
    close(fd[0]);

コマンドの出力がBUF_SIZEよりも長い場合は、単にもう一度読み取り、読み取っbufた出力を上書きします。ここで本当に必要なのは、メモリを割り当てて、を使用してstrcat(または効率を上げるために文字列の最後へのポインタを保持することによって)最後に追加することです。

于 2012-11-19T10:37:04.650 に答える