->back to toppage

課題内容-levelX-

自分で、今までにない、新しいレベルを作り、実装し、評価せよ。
例えば、関数を実装する。引数呼びだしを定義するには、局所変数を実現する必要がある。RPCなどと組み合わせて、 分散shellを実装するなどが考えられる。rloginを実装するには、pty に関する処理が必要になる。


cdコマンドの実装

cshでは,cdコマンドは組み込みコマンドである.よって,execveでは実行できない.これを実装してみた. cdの実装には,chdirシステムコールを利用する.以下に構文規則を示す.
構文規則 (shell.y)
top : expr { 
        command($1);
        free_node($1);
    }
    ;


expr: 
~省略~
|   cmd            {$$ = new_node('w',$1->value,NULL,NULL);}
|   cmd {arg_count=0;} file
                   {$$ = new_node('w',$1->value,$3,NULL);} // cd
~省略~
 

cdの構文規則は上のようになる.cmd(cd)の引数は,file一つか,ないものとなる.
以下にcdが実行される関数commandを示す.
関数command() (shell.y)
void
command(d)
node *d;
{
 ~省略~

  case 2:              // cd
    if( d->left != NULL ){                 // 引数があれば
      if( d->left->value[0]== '~' ){       // '~'の展開
        homelen = strlen(getenv("HOME"));
        filelen = strlen(d->left->value);

      // チルダを消す(上書きする)ので,終端文字のために要素数を+1しなくて良い
        path = (char *)calloc(homelen+filelen,sizeof(char));
        if(path == NULL){
          perror(path);
        }

        strcpy(path,getenv("HOME"));
        // d->left->value+1 で'~'より後の文字列を連結
        strncat(path,d->left->value+1,filelen); 

        if (chdir(path) == -1){
          perror(path);
        }
        free(path);
      }else if( chdir(d->left->value) == -1){
        perror(d->left->value);
      }
    }else{                                 // 引数がなければhomeに移動
      if( chdir(getenv("HOME") ) == -1){
        perror(getenv("HOME"));
      }
    }
    break;

 ~省略~
}

d->leftがNULLということは,引数がないということである.このときは,else文が実行され, getenv関数で環境変数HOMEを取得して,HOMEに移動するようにしている.d->leftがNULLじゃ ない場合は,引数にディレクトリ名がきているはずなので,そのディレクトリに移動するようにして いる.また,引数の先頭がチルダなら,チルダをHOMEに展開する.


実行結果

cdの実行結果
[nw0409:unixlab2/leoinfo4/ch_dir] j04009% ./my-shell
j04009 % pwd
/Users/j04009/Documents/u-ryukyu/2006-Kouki/unixlab2/leoinfo4/ch_dir
j04009 % cd ../
j04009 % pwd
/Users/j04009/Documents/u-ryukyu/2006-Kouki/unixlab2/leoinfo4
j04009 % ls -l
total 152
-rw-r--r--    1 j04009  j04009     93 Jan 14 17:35 Makefile
drwxr-xr-x   16 j04009  j04009    544 Jan 16 02:40 ch_dir
drwxr-xr-x   14 j04009  j04009    476 Jan 14 20:08 levelX
-rwxr-xr-x    1 j04009  j04009  34680 Jan 14 17:36 my-shell
-rw-r--r--    1 j04009  j04009  21644 Jan 14 17:36 shell.c
-rwxrwxrwx    1 j04009  j04009  10436 Jan 14 00:25 shell.y
drwxr-xr-x    7 j04009  j04009    238 Jan 16 02:42 tex
j04009 % cd shell.c
shell.c: Not a directory
j04009 % cd
j04009 % pwd
/Users/j04009
j04009 % cd Documents/u-ryukyu/2006-Kouki/unixlab2/leoinfo4/ch_dir
j04009 % pwd
/Users/j04009/Documents/u-ryukyu/2006-Kouki/unixlab2/leoinfo4/ch_dir
j04009 % cd ~/
j04009 % pwd
/Users/j04009
j04009 % exit

ディレクトリの移動ができていることが確認できる.引数がディレクトリでない場合も,ちゃんと エラーが出ている.また,チルダを使ったディレクトリの移動もできていることが確認できる.


<-previous problem    go to top