2016-03-18 42 views
-5
int main(void) { 
    char in[512]; 

    pid_t id; 
    int status, y, x, i = 1; 
    char *f[512]; 
    char *v; 

    while(1) 
    { 
     printf("shell>"); 
     fgets(in,512, stdin); 
     int size = strlen(in);// calculate dim of in execpt null 
     in[size-1] = '\0'; //null at the end because ls\n not executable 
     v = strtok(in, " "); 
     f[0] = v; 
     while (v = strtok(NULL, " ")) { 
      f[i] = v; 
      i++; 
     } 
     f[i] = NULL; 

     y = strcmp(f[0],"exit"); 

     if (y == 0) 
     break; 

     id = fork(); 

     if (id==0) { //child 
      execvp(f[0],f); 
      perror("failure"); 
      exit(1); 
     } 
     else //parent 
     { 
      x=strcmp(f[i-1],"&"); 
      if (x != 0) 
      waitpid(id, &status, 0); 
     } 
    } 
} 

在这段代码中我可以执行shell命令,但是我不能执行command &部分。我怎样才能让execvp在后台执行一个进程?执行后台进程的Shell项目

+4

'if(f [0] ==“exit”)'。使用'=='运算符不能比较C中的字符串。需要使用'strcmp'。 – kaylum

+0

请学习使用编辑框左上角的格式化工具来保持代码/数据/ errorMsgs/etc的格式。祝你好运。 – shellter

+1

这篇文章是不可读的。请记住,如果一行以4个空格开头,Stack Overflow会将其视为代码(并去掉这些空格)。要缩进,只需提供额外的空间。 –

回答

1

阅读Advanced Linux Programming。使用strace(1)现有的程序(特别是shell)了解他们在做什么system calls。查看syscalls(2)的清单并更准确地阅读其中几个文档的文档(请参阅intro(2) ...)。 研究一些现有的free software shell的源代码,如sash & bash

不要忘记系统调用(例如您对fork(2) ...的调用)可能会失败。你应该处理失败,至少喜欢:

id = fork(); 
if (id<0) { perror("fork"); exit(EXIT_FAILURE); }; 

关于结束&的处理,你job control照顾。了解有关process groups的更多信息。

你的计划没有实现globbing或​​,并且不能带参数运行的一些程序(例如命令ls a b应该运行/bin/ls与三个参数"ls""a""b"),因为每个shell应该。见glob(7) & pipe(7)

不要指望我们做你的功课。你可能应该编写一个更大的程序(可能是一千行,几十个函数,几个struct带指针,....),并首先考虑它的设计(这是学习现有的 shell实现将帮助你)。特别要先在一张纸上(或一些白板)列出一套重要的功能和数据结构来实现。

我建议先编写你的shell,以便能够运行简单的命令,如ls a b,实现globbing(所以接受ls *.c)。一旦完成并调试,考虑实施一些内建(特别是cd),作业控制和管道。在所有这些研究的一些现有的外壳的源代码,当然,实现它的主要系统调用。

BTW,编译所有的警告&调试信息(gcc -Wall -Wextra -g)和使用调试器gdb)非常频繁。