-1

私は単純なシェルを作成するタスクを与えてきましたが、いくつかの非常に基本的な機能を取得することができましたが、環境の取得と設定を求めているステージの 1 つでした。タスクの詳細です。

ステージ 4: パスの取得と設定 – 10 点

元のパスを保持

これが必要な理由は、シェルの終了時にパスを元のパスに復元したいからです。シェルの環境 (つまり、上記の setenv() 関数) に加えた変更は、シェル自体だけでなく、後で同じ端末から実行される他のプログラムにも影響するため、これは重要です。このため、終了時の状態に戻すことをお勧めします。

元のパスを維持するには、単一の文字列で十分です。

パスの保存は、シェルの起動時に最初に実行する必要があります。

パスの出力と変更 - 組み込みコマンド

C プログラムからは、getenv() 関数を使用して環境にアクセスでき、setenv() 関数を使用して環境を変更できます。setenv() のマニュアル ページを見ると、それがどのように機能するか (つまり、必要なパラメーターと戻り値) と、それを使用するために含める必要があることがわかります。

getpath – システム パスを表示 & setpath – システム パスを設定

これら 2 つのコマンドは、環境パラメーター PATH に関するものです。1 つ目はその値を取得して出力するだけですが、2 つ目はパス (コロンで区切られたディレクトリのリストの文字列) をパラメーターとして取り、それを PATH の値にします。この目的のために、それぞれ getenv() と setenv() を使用できます。

復元パス

PATH 環境パラメータを元の値 (つまり、シェルの起動時に保存した値) に変更するだけです。

パスを復元することは、シェルが終了する前に行う最後のことです。

ステージ 4: テスト

まず、ステージ 3 で実行したすべてのテストが引き続き機能することを確認します。ただし、パスを変更しているため、外部プログラムの実行に影響することに注意してください。

追加機能を確認するには、まずパスの保存と復元が機能することを確認する必要があります。ここでの良い考えは、シェルの実行の開始時にパスを保存するときにパスを出力し、最後に終了するときに再度出力することです。どちらの場合も、印刷されたパスはまったく同じでなければなりません!

その後、 getpath が呼び出されたときに現在のパスを出力することを確認する必要があります。これは元のパスと同じである必要があります。

次に、setpath のテストに集中する必要があります。まず、パスを新しい値に設定し、getpath がそれを出力することをテストします。次に、パスの変更が外部コマンドの実行に実際にどのように影響するかを確認します (たとえば、パスを '.' のみに設定して 'ls' を試すか、シェル自体など)。

これは私のコードです:

/* S.NO:201148541 Simple Shell Example
Completed upto Stage 3 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define BUFFER_SIZE 1<<16
#define ARR_SIZE 1<<16

void parse_args(char *buffer, char** args, 
                size_t args_size, size_t *nargs)
{
    char *buf_args[args_size]; 
    char **cp;
    char *wbuf;
    size_t i, j;

    wbuf=buffer;
    buf_args[0]=buffer; 
    args[0] =buffer;

    for(cp=buf_args; (*cp=strsep(&wbuf, " \n\t")) != NULL ;){
        if ((*cp != '\0') && (++cp >= &buf_args[args_size]))
            break;
    }

    for (j=i=0; buf_args[i]!=NULL; i++){
        if(strlen(buf_args[i])>0)
            args[j++]=buf_args[i];
    }

    *nargs=j;
    args[j]=NULL;
}


int main(int argc, char *argv[], char *envp[]){
    char buffer[BUFFER_SIZE];
    char *args[ARR_SIZE];
    int *ret_status;
    size_t nargs;
    pid_t pid;

    char curDir[100];


    while(1){
        getcwd(curDir, 100);
        printf("%s->", curDir);
        fgets(buffer, BUFFER_SIZE, stdin);
        parse_args(buffer, args, ARR_SIZE, &nargs); 

        if (nargs==0) continue;
         if(strcmp(args[0], "cd") == 0){
            chdir(args[1]);

        }
        else if (!strcmp(args[0], "exit" )) exit(0);       
        pid = fork();
        if (pid){
            pid = wait(ret_status);
            printf("finished\n", pid);
        }
         else {

            if( execvp(args[0], args)) {
                puts(strerror(errno));
                exit(127);
            }
        }
        }
    }



    return 0;
}

私は本当に途方に暮れており、どんなガイダンスも役に立ちます。

4

1 に答える 1

1

あなたの以前のステップが何であるかがわからないことを考えると、アドバイスに従います

次に、setpath のテストに集中する必要があります。最初に、パスを新しい値に設定し、getpath がそれを出力することをテストします。次に、パスの変更が外部コマンドの実行に実際にどのように影響するかを確認します (たとえば、パスを '.' のみに設定して 'ls' を試すか、シェル自体など)。

あなたはこのようにすることができます...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *path, *old, *tobeSet;
    path = malloc(1024);
    path = getenv("PATH");
    old = malloc(strlen(path));
    tobeSet = malloc(10); // just to be safe
    strcpy(tobeSet,".");
    if(setenv("PATH",tobeSet,1)!=0)
    {
        printf("Couldn't set path\n");
        return 0;
    }
    printf("\nPATH::\t%s\n",path);
    printf("\n\nNewPath::\t%s\n",tobeSet);
    if(setenv("PATH",path,1)!=0)
    {
        printf("Couldn't restore path\n");
        return 0;
    }
    printf("\n\nOld path ::\t%s\n",path);
    free(path);
    free(old);
    free(tobeSet);
    return 0;
}
于 2013-04-23T11:34:15.530 に答える