2015-12-02 2 views
0

Я хочу реализовать свою собственную оболочку. Я застрял в реализации фонового процесса. На самом деле, я пишу часть кода, но я не уверен, что это работа или нет.Фоновый процесс в оболочке

мой код:

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

#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */ 
    #define HISTORY_SIZE 5 /*keep track of 5 most recent commands*/ 

int cmd_count; /*global to keep track of most recent commands entered*/ 
char history[HISTORY_SIZE][MAX_LINE]; /* global so it can be   accessed  in interrupt handler. */ 


void viewHistory() 
{ 
int i; 

if (cmd_count < 1) 
    printf("No command history to show. \n"); 
else { 
    printf("\n\n"); 
    for (i = (cmd_count >= HISTORY_SIZE) ? cmd_count - HISTORY_SIZE:0; 
     i < cmd_count; i++) 
     printf("%d: %s\n",i+1,history[i%HISTORY_SIZE]); 
} 
//printf("SystemsIIShell->"); 
    } 



    int setup(char inputBuffer[], char *args[],int *background) 
    { 
int length, /* # of characters in the command line */ 
i,  /* loop index for accessing inputBuffer array */ 
start, /* index where beginning of next command parameter is */ 
ct;  /* index of where to place the next parameter into args[] */ 

int temp; 

ct = 0; 

/* read what the user enters on the command line */ 
length = read(STDIN_FILENO, inputBuffer, MAX_LINE); 

start = -1; 
if (length == 0) 
    exit(0);   /* ^d was entered, end of user command stream */ 
if (length < 0){ 
    perror("error reading the command"); 
    exit(-1);   /* terminate with error code of -1 */ 
}else{ 
    inputBuffer[length]='\0'; 
    if(inputBuffer[0]=='r'){ 
     if(inputBuffer[1]=='r'){ 
      if(cmd_count==0){ 
       printf("No recent command can be found in the history. \n"); 
       return 0; 
      } 
      strcpy(inputBuffer,history[(cmd_count)% HISTORY_SIZE]); 
     }else{ 
      temp = atoi(&inputBuffer[1]); 
      if(temp < 1 || temp > cmd_count || temp <= cmd_count -HISTORY_SIZE){ 
       printf("Command number cannot be found. \n"); 
       return 0; 

      } 
      strcpy(inputBuffer,history[(temp-1)%HISTORY_SIZE]); 

     } 
     length = strlen(inputBuffer); 

    } 
    cmd_count++; 
    strcpy(history[(cmd_count-1)%HISTORY_SIZE], inputBuffer); 
    for (i = 0; i < length; i++) { 
     if (inputBuffer[i] == '&') { 
      inputBuffer[i] = '\0'; 
      *background = 1; 
      --length; 
      break; 
     } 

    } 
} 

/* examine every character in the inputBuffer */ 
for (i = 0; i < length; i++) { 
    switch (inputBuffer[i]){ 
     case ' ': 
     case '\t' :    /* argument separators */ 
      if(start != -1){ 
       args[ct] = &inputBuffer[start]; /* set up pointer */ 
       ct++; 
      } 
      inputBuffer[i] = '\0'; /* add a null char; make a C string */ 
      start = -1; 
      break; 

     case '\n':     /* should be the final char examined */ 
      if (start != -1){ 
       args[ct] = &inputBuffer[start]; 
       ct++; 
      } 
      inputBuffer[i] = '\0'; 
      args[ct] = NULL; /* no more arguments to this command */ 
      break; 

     case '&': 
      *background = 1; 
      inputBuffer[i] = '\0'; 
      break; 

     default :    /* some other character */ 
      if (start == -1) 
       start = i; 
    } 
} 
args[ct] = NULL; /* just in case the input line was > 80 */ 
    } 

    int main(void) 
    { 
char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */ 
int background;    /* equals 1 if a command is followed by '&' */ 
char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */ 

while (1){   /* Program terminates normally inside setup */ 
    background = 0; 
    printf("SystemsIIShell->"); 
    fflush(0); 
    setup(inputBuffer, args, &background);  /* get next command */ 

    pid_t child; /* process id for child */ 
    int status; /* status for execvp */ 

    child = fork(); /* create a child process*/ 

    if(child < 0){ /* if the child process didn't return 0, the fork is failed */ 
     printf("Fork failed! \n"); 

    }else if(child==0){ /* child process */ 
     if(inputBuffer[0]=='history' || inputBuffer[0] =='h'){ 
      viewHistory(); 
      return 0; 
     } 
     status = execvp(args[0],args); 
     if(status !=0){ 
      printf("%s: command not found. \n", args[0]); 
     } 

    }else{ /* parent process */ 
     if(background == 0) 
      waitpid(child,&background,0); 

    } 

    /* the steps are: 
    (1) fork a child process using fork() 
    (2) the child process will invoke execvp() 
    (3) if background == 0, the parent will wait, 
    otherwise returns to the setup() function. */ 

}return 0; 

}

я не добавляю весь код, но другие вещи истинны. Я вызываю execv, и он работает. Когда я пишу на консоли:

выходной терминал:

$ gedit ------->it works correctly because it is a foreground 


$ gedit & -----> it opens a gedit file which name is "&" 
$ firefox ---> it works correctly 
$ firefox & ---> it opens a firefox window which url is www.&.com 

Как можно это исправить какие-либо предложения?

редактирование части: https://github.com/iqbalhasnan/CSE2431-System-II/blob/master/lab2/lab2.c -> Я использую этот код в качестве ссылки

+0

Не могли бы вы исправить этот ужасный отступ? – Jens

+0

, нам нужно будет увидеть остальную часть кода. –

+0

Я снова редактирую свой вопрос @ErikNyquist вы можете посмотреть? – esrtr

ответ

2

вы не реализующей фоновых процессов, вы пытаетесь запустить фоновый процесс, используя синтаксис уже реализованной-оболочки на ваш компьютер (но, честно говоря, довольно сложно сказать, что происходит с этим отступом. Это очень плохо. Можете ли вы сделать его читаемым, пожалуйста?). Символ '&' распознается вашей оболочкой, а не execvp. Посмотрите на this similar looking question, который был первым хитом в поиске вашей проблемы.

Смежные вопросы