2012-02-18 94 views
2

对于我的操作系统类,我有一个应用程序,该应用程序是构建到以前的作业上的。不幸的是,我以前的项目不能正常工作,除了我不知道我需要从哪里开始下一个项目。下面的代码假设模仿一个简单的UNIX/Linux shell,其中包含一些无法使用execvp执行的命令:通过&符号操作符进行后台处理,'jobs'shell命令:列出所有活动子进程的pid即不是已经终止的那些),“僵尸”进程的“收获”以及'cd'shell命令:更改shell的工作目录。UNIX中执行的命令C

我相信,除了“jobs”命令和“cd”命令之外的所有东西都可以工作,但我不确定为什么这两个都不是。

下一个任务是添加一些I/O重定向在 “mysh $ CMD ARG1 ARG2 ARGN> file.out” 我不知道在哪里,甚至真正开始的形式...

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <strings.h> 
#include <unistd.h> 
#include <wait.h> 
#include <signal.h> 
#include <sys/types.h> 

int main(int argc, char **argv) { 
    char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr; 
    int jobs[100]; 
    int jobList = 0; 
    int background; 
    ssize_t rBytes; 
    int aCount; 
    pid_t pid; 
    int status; 
    while(!feof(stdin)) { 
     pid = waitpid(-1, &status, WNOHANG); 
     if (pid > 0) 
     printf("waitpid reaped child pid %d\n", pid); 
     write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27); 
     rBytes = read(0, bBuffer, BUFSIZ-1); 
     if(rBytes == -1) { 
     perror("read"); 
     exit(1); 
    } 

    bBuffer[rBytes-1] = '\0'; 
    if(!strcasecmp(bBuffer, "exit")){ 
     exit(0); 
    } 

    sPtr = bBuffer; 
    aCount = 0; 
    do { 
     aPtr = strsep(&sPtr, " "); 
     pArgs[aCount++] = aPtr; 
    } while(aPtr); 
     background = (strcmp(pArgs[aCount-2], "&") == 0); 
     if (background) 
     pArgs[aCount-2] = NULL; 

     if (strlen(pArgs[0]) > 1) { 
      pid = fork(); 
      if (pid == -1) { 
       perror("fork"); 
       exit(1); 
      } else if (pid == 0) { 
       jobs[jobList] = pid; 
       jobList++; 

       if(!strcasecmp(pArgs[0], "jobs")){           
        for(int i; i<jobList; i++) { 
         if(kill(jobs[i],0)==0){ 
          printf(jobs[i]);  
         } 
         printf("these are jobs\n"); 
         exit(1); 
        } 
        if(!strcasecmp(pArgs[0], "cd")){ 
         int ret; 
         if (!pArgs[1]) 
          strcpy(bBuffer, "pwd"); 
         ret = chdir(pArgs[1]); 
         strcpy(bBuffer, "pwd"); 
         exit(1); 
        }         
        fclose(stdin); 
        fopen("/dev/null", "r"); 
        execvp(pArgs[0], pArgs); 
        exit(1); 
       } else if (!background) { 
        pid = waitpid(pid, &status, 0); 
        if (pid > 0) 
         printf("waitpid reaped child pid %d\n", pid); 
       } 
     } 
    } 
    return 0; 
} 
+1

请记住'chdir'不会影响父进程或兄弟进程。此外,一些'退出'看起来被放置在可疑的位置... – 2012-02-18 07:57:04

+0

@pst我明白你现在说的话,但我不知道如何处理chdir然后...任何建议? – 2012-02-19 01:29:30

+0

['while(!feof(file))'总是出错](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong)。 – 2015-04-07 04:25:34

回答

2

首先,您需要解析您的线路并检测是否需要重定向到文件。所以我们假设你使用strsep或其他什么,你会发现输出是file.out或输入来自file.in

此时您想要使用dup/dup2重定向输出。例如,重定向STDOUT

int 
do_redirect(int fileno, const char *name) 
{ 
    int newfd; 

    switch (fileno) { 
    case STDOUT_FILENO: 
     newfd = open(name, O_WRONLY | O_CREAT, S_IRUSR | S_IRUSR); 
     break; 
    } 
    if (newfd == -1) { 
     perror("open"); 
     return -1; 
    } 

    return dup2(fileno, newfd); 
} 
/* ... */ 


pid = fork(); 
do_redirect(STDOUT_FILENO, name); 

注意事项:

  • 我没有测试的代码 - 甚至都不编译
  • 我没有做太多的错误检查 - 你应该(我为open的方式)
  • 你需要实现自己的
  • 注意我是如何用一个单独的函数STDIN_FILENO重定向,您main是方式大,因为它是
  • 你的代码有类似7级缩进 - 曾听说过arrow code
0

由于这是作业,我不会直接给你代码。

dupdup2freopen是很好看的输入/输出重定向。

fork用于启动并发进程(符号)

您使用waitpid收获子进程在正确的轨道上。