8

Linux 用の簡単なシェルを作成しました。ctrl+d (eof/-1) が標準入力に入力されるまで、getline() で行ごとに読み取ります。

そのような行コードで標準入力に入る間:

ls -al &
ls -a -l

私のシェルはかなりうまく機能します。

シェルからスクリプトを実行しようとしましたが、うまくいきません。スクリプトを実行すると、シェルが自動的に実行されますが (1 行目)、シェルは他の行を解釈しません。

#!/home/arbuz/Patryk/projekt/a.out
ls -al &
ls -a -l

何が原因でしょうか?私はLinuxの初心者であり、教師はそのすべてについて何も言わなかったと言わざるを得ません。ただの宿題。私はいくつかの調査を行いましたが、それが私が見つけたすべてです。

これが私のシェルのコードです。シェル パスを etc/shells に追加しましたが、まだ機能していません

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>

int main()
{

    ssize_t bufer_size = 0;
    char* line = NULL;
    int line_size;

    while ((line_size = getline(&line, &bufer_size, stdin)) != -1) // while end of file
    {
        char** words_array;
        words_array = (char**)malloc(200 * sizeof(char*));

        int words_count = 0;
        int i;
        int j = 0;
        int words_length = 0;
        char word[100];
        for (i = 0; i < line_size; i++)
        {
            if (line[i] == ' ' || line[i] == '\n')
            {
                words_array[words_count] = (char*)malloc(words_length * sizeof(char));
                int b;
                for (b = 0; b < words_length; b++)
                {
                    words_array[words_count][b] = word[b];
                }
                j = 0;
                words_count++;
                words_length = 0;
            }
            else
            {
                word[j] = line[i];
                j++;
                words_length++;
            }
        }

        bool run_in_background = false;

        if (words_array[words_count - 1][0] == '&')
        {
            run_in_background = true;
            words_array[words_count - 1] = NULL;
        }

        int a = fork();

        if (a == 0) // child process
        {
            execvp(words_array[0], words_array);
        }
        else       // parent process
        {
            if (run_in_background == true)
            {
                printf("\n ---- running in background. \n");
            }
            else
            {
                printf("\n ---- running normal \n");
                wait(NULL);
            }
        }
    }

    return 0;
}
4

2 に答える 2

12

シェルはコマンド ライン引数を受け入れる必要があります。この場合、プログラムは次のように呼び出されます。

/home/arbuz/Patryk/projekt/a.out your_script

main()したがって、次の署名が必要になります。

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

次に、引数を解析します。argc引数の量が含まれます。スクリプトのファイル名は に渡されargv[1]ます。それを ( を使用して) 開き、fopen()の代わりにそこからコマンドを読み取る必要がありますstdin。ファイルが#.

スクリプトが絶対パス (で始まらないパス) なしで呼び出された場合/、ファイル名は現在のディレクトリからの相対パスになります。環境から、または を使用してプログラムで取得できますgetcwd()

于 2012-11-10T13:09:08.673 に答える
6

問題は、シェルが標準入力から読み取るのに対し、she-bang#!によってスクリプトがコマンドライン引数として渡されることです。したがって、シェルは次のように呼び出されます

/home/arbuz/Patryk/projekt/a.out <script>

... コマンドライン引数を無視し、標準入力でコマンドを待ちます。からスクリプトを読む必要がありますargv[1]

于 2012-11-10T13:08:35.807 に答える