0

私は現在Cでシェルをプログラミングしていますが、いくつかの問題が発生しています。たとえば、コマンドを「exit」と比較しようとすると、コマンドは書き込みを実行するだけで、gdbによると等しくないように動作します。私はセグメンテーション違反で終わります。誰かが私が何が悪いのかを理解するのを手伝ってくれるなら、私はそれを大いに感謝します。これは私の最初のシェルです!

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <dirent.h>e
#include <sys/types.h>
#include <sys/wait.h>    
#include <signal.h>
#include "sh.h"

int sh( int argc, char **argv, char **envp ){

    char *prompt = calloc(PROMPTMAX, sizeof(char));
    char *commandline = calloc(MAX_CANON, sizeof(char));
    char *command, *arg, *commandpath, *p, *pwd, *owd;
    char **args = calloc(MAXARGS, sizeof(char*));
    int uid, i, status, argsct, go = 1;
    struct passwd *password_entry;
    char *homedir;
    struct pathelement *pathlist;

    uid = getuid();
    password_entry = getpwuid(uid);
    homedir = password_entry->pw_dir; 

    if ( (pwd = getcwd(NULL, PATH_MAX+1)) == NULL ){
    perror("getcwd");
    exit(2);
    }

    owd = calloc(strlen(pwd) + 1, sizeof(char));
    memcpy(owd, pwd, strlen(pwd));
    prompt[0] = ' '; prompt[1] = '\0';

    pathlist = get_path();

    prompt = "[cwd]>";

    while ( go ){
    printf(prompt);

    commandline = fgets(commandline, 100, stdin);
    command = strtok(commandline, " ");

    printf(command);

    if (strcmp(command, "exit")==0){
        exit(0);
    }

    else if (strcmp(command, "which")==0){
    //  which();
    }

    else if (strcmp(command, "where")==0){
    //  where();
    }

    else if (strcmp(command, "cd")==0){
        chdir(argv[0]);
    }

    else if (strcmp(command, "pwd")==0){
        getcwd(pwd, PATH_MAX);
    }

    else if (strcmp(command, "list")==0){
        if (argc == 1){

        }

        else if (argc > 1){

        }
    }

    else if (strcmp(command, "pid")==0){
        getpid();
    }

    else if (strcmp(command, "kill")==0){

    }

    else if (strcmp(command, "prompt")==0){
        prompt = "argv[0] + prompt";
    }

    else if (strcmp(command, "printenv")==0){

    }

    else if (strcmp(command, "alias")==0){

    }

    else if (strcmp(command, "history")==0){

    }   

    else if (strcmp(command, "setenv")==0){

    }

    else{
        fprintf(stderr, "%s: Command not found.\n", args[0]);
    }



}
return 0;

} 

そのほとんどはまだ裸の骨なので、我慢してください。

4

1 に答える 1

4

変更する場合:

printf(command);

の中へ:

printf("<<%s>>\n",command);

これらの文字列のいずれにも一致しない理由がわかります。これは、末尾の改行(a)fgetsを取り除かないためです。

[cwd]>ls
<<ls
>>

つまり、次のコード行が実行されます。

fprintf(stderr, "%s: Command not found.\n", args[0]);

そして、これらすべてのargs[]値を NULL に初期化したのでcalloc、BANG! あなたのコードに行きます(ヌルポインタを逆参照しようとするのは未定義の動作です)。

プロンプト表示、バッファ オーバーフロー保護、長すぎる行の残りの部分の無視、そしてここで最も重要なのは改行の削除を備えた堅牢なユーザー入力ソリューションについては、この回答を参照してください。


(a)余談ですが、ユーザー入力をprintfフォーマット文字列として渡すべきではありません。プロンプトで入力するとどうなるかを推測%s%s%s%s%s%sしてください:-)

そして、あなたの問題とは無関係に、ISO Csizeof(char)常に1 であることを義務付けているため、割り当てステートメントでそれを使用する必要はありません。コードが不必要に詰まるだけです。

于 2012-09-24T03:51:02.930 に答える