用C语言制作自己的外壳

用C语言制作自己的外壳,c,shell,operating-system,posix,C,Shell,Operating System,Posix,我正试图用C语言编写自己的shell,但在使用strtok时遇到了问题。我使用它来正确地解析输入中的命令和参数,但是我无法让它解析路径(它当前是segfults)。一旦正确解析了路径,我就应该能够相应地对每个片段和fork进程调用execlp。如有任何见解,将不胜感激,代码如下。如果你认为我可以做得更好,也可以随意评论风格选择 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include

我正试图用C语言编写自己的shell,但在使用strtok时遇到了问题。我使用它来正确地解析输入中的命令和参数,但是我无法让它解析路径(它当前是segfults)。一旦正确解析了路径,我就应该能够相应地对每个片段和fork进程调用execlp。如有任何见解,将不胜感激,代码如下。如果你认为我可以做得更好,也可以随意评论风格选择

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

void parse(char *, char *);
void process(char *, char *, int);

int main(int argc, char *argv[]) {
  char *command;
  char *path;
  char buffer[1024];
  command = (char *)malloc(sizeof(char));
  path = (char *)malloc(sizeof(char));
  int loop = 1;
  while(loop == 1){
    path = getenv("MYPATH");
    if(path == NULL)
      path = "/bin#.";
    printf("($MYPATH is %s)\n", path);

    printf("myshell$ ");
    command = fgets(buffer, 1024, stdin);
    printf("Buffer: %s", buffer);
    printf("Command: %s", command);

    if(strcmp(command,"exit\n") == 0 || strcmp(command, "quit\n") == 0){
      loop = 0;
      printf("Program Terminated\n");
    }
    parse(command, path);
  }
  return 0;
}

void parse(char *command, char *path){
  char *argv;
  int argNum = 0;
  argv = strtok(command, " ");
  while(argv != NULL){
    printf("%s %d\n", argv, argNum);
    argv = strtok (NULL, " ");
    argNum++;
    }
  printf("Calling...\n");
  process(argv, path, argNum);
  printf("Called\n");
}

void process(char *argv, char *path, int argNum){
  char *pathPiece;
  int pathNum = 0;
  pathPiece = strtok(path, "#");
  while(pathPiece != NULL){
    printf("%s %d\n", pathPiece, pathNum);
    pathPiece = strtok(NULL, "#");
    pathNum++;
  }
}
#包括
#包括
#包括
#包括
void解析(char*,char*);
无效进程(char*,char*,int);
int main(int argc,char*argv[]){
char*命令;
字符*路径;
字符缓冲区[1024];
command=(char*)malloc(sizeof(char));
path=(char*)malloc(sizeof(char));
int循环=1;
while(循环==1){
path=getenv(“MYPATH”);
if(路径==NULL)
path=“/bin#.”;
printf(“($MYPATH是%s)\n”,路径);
printf(“myshell$”);
命令=fgets(缓冲区,1024,标准输入);
printf(“缓冲区:%s”,缓冲区);
printf(“命令:%s”,命令);
如果(strcmp(命令,“退出”\n”)==0 | | strcmp(命令,“退出”\n”)==0){
循环=0;
printf(“程序终止\n”);
}
解析(命令、路径);
}
返回0;
}
void解析(char*命令,char*路径){
char*argv;
int argNum=0;
argv=strtok(命令“”);
while(argv!=NULL){
printf(“%s%d\n”,argv,argNum);
argv=strtok(空,“”);
argNum++;
}
printf(“呼叫…\n”);
进程(argv,path,argNum);
printf(“称为\n”);
}
无效进程(char*argv、char*path、int argNum){
字符*路径块;
int-pathNum=0;
pathPiece=strtok(路径“#”);
while(路径!=NULL){
printf(“%s%d\n”,路径段,路径编号);
pathPiece=strtok(空,“#”);
pathNum++;
}
}

您正在将path设置为指向只读内存位置,当
strtok
尝试标记它时(即在其中某处写入空字符),对其调用
strtok
可能是导致问题的原因

您可能需要以下内容:

char path[1024];
并调用strcpy,如:

strcpy(path, getenv("MYPATH"));


我强烈建议您仔细阅读C中的字符串处理。

您正在设置指向只读内存位置的路径,并且在其上调用
strtok
可能是当
strtok
尝试对其进行标记(即在其内部某处写入空字符)时出现问题的原因

您可能需要以下内容:

char path[1024];
并调用strcpy,如:

strcpy(path, getenv("MYPATH"));


我强烈建议您仔细阅读C中的字符串处理。

以下内容不会达到预期效果

path = "/bin#.";
试试strcpy(路径,“/bin#”。”取而代之

正如larsmans所说,修复malloc,以便为命令大小分配足够的字节


另外,如果您严格编译的是C,那么在您所处的位置声明
循环
整数时,应该会出现编译错误。

以下操作不会产生预期效果

path = "/bin#.";
试试strcpy(路径,“/bin#”。”取而代之

正如larsmans所说,修复malloc,以便为命令大小分配足够的字节


另外,如果您严格编译的是C,那么在您所在的位置声明
循环
整数时,您应该有一个编译错误。

当它出现故障时,您向它提供了什么输入?。它隐藏了像这样的错误。当它出现故障时,你给它提供了什么输入?。它隐藏了这些错误。谢谢,我应该注意到(有时我的C++潜入,我对C是新的)。我认为新的C标准现在允许你在执行代码后声明整数,但我可能错了。@fossuser:是的,现代C确实允许在可执行代码后声明变量。然而,我们中的许多程序员忘记了这一点,因为我们必须维护史前编译器编写的代码。谢谢,我应该注意到(有时我的C++潜入,而我对C是新的)。我认为新的C标准现在允许你在执行代码后声明整数,但我可能错了。@fossuser:是的,现代C确实允许在可执行代码后声明变量。不过,我们许多C程序员都忘记了这一点,因为我们必须维护用史前编译器编写的代码。谢谢,帮了大忙。我知道字符串函数,虽然有时我的C++潜入(我是C的新手),我很难看到错误。谢谢,帮助很大。我知道字符串函数,虽然有时我的C++潜入(我是C的新手),但我很难看到错误。