2013-09-18 3 views
1
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */ 

/** 
* setup() reads in the next command line, separating it into distinct tokens 
* using whitespace as delimiters. It also sets the args parameter as a 
* null-terminated string. 
*/ 

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

    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 command"); 
    exit(-1);   /* terminate with error code of -1 */ 
    } 

    /* 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("CSE2431Sh->"); 
     fflush(0); 
     setup(inputBuffer, args, &background);  /* get next command */ 

    /* 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. */ 

      /* MY CODE HERE */ 
      pid_t pid; 

     pid = fork(); 

     if(pid == 0) 
     { 
       execvp(args[0],args); 
       /* If execvp returns, it must have failed. */ 

       printf("Fork Failed\n"); 
       exit(0); 
     } 
     else 
     { 
       if(&background == 0) 
       { 
         while(wait(&background) != pid) 
         {/* Do nothing, waiting */} 
       } 
       else 
       { 
         setup(inputBuffer, args, &background); 
       } 
     } 
    } 
} 

Я пытаюсь разблокировать дочерний процесс, чтобы ребенок вызывал execvp() и родительский ожидал в фоновом режиме. Моя ошибка исходит из части ожидания кода с родителем. Все выше, где указано, что мой код здесь указан, и его не следует редактироватьРодительский процесс Ожидание ребенка для завершения в C

+2

Ваш 'if (& background == 0)' всегда будет терпеть неудачу, так как адрес 'background' не' 0'. – lurker

+0

В качестве побочного примечания нет такой вещи, как выход с отрицательным кодом состояния на * nix. Как правило, это значение без знака для наименее 8 бит, которые используются (не уверены, универсально ли это), поэтому выход с -1 будет действительно возвращать 255. – FatalError

+0

Если execv выходит из строя, почему вы печатаете «fork failed» с неправильным потоком? Попробуйте 'perror (" execvp ")'. –

ответ

1

Ваш «Вилка не удалось» сообщение должно быть «Exec не удалось» (вилка работала, ехес Ждут» т). У вас также должен быть отдельный отчет об ошибке «fork failed», но на данный момент этого не хватает. И сообщения об ошибках должны быть записаны в stderr, а не stdout.

Условие wait() цикл должен быть:

int corpse; 
int status; 
while ((corpse = wait(&status)) != -1 && corpse != pid) 
    ; 

Во время отладки, распечатайте информацию из wait() на каждой итерации. Обратите внимание, что waitpid() позволяет подождать, если есть труп для сбора, но вернуться, если нет мертвых детей, которых нужно оплакивать.

Все это имеет значение только после того, как вы столкнулись с предупреждением, которое вы должны были получить от компилятора. Если вы не получаете предупреждения о том, что if (&background == 0) всегда является ложным, вам необходимо установить уровень предупреждения компилятора. Если вы используете GCC, gcc -Wall - хороший старт, лучше - gcc -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes. И исправить предупреждения из компилятора.

+0

Я получаю следующую ошибку из wait (& status) shell.c: В функции âint main() â: shell.c: 100: ошибка: нет соответствующей функции для вызова в âwait :: wait (int *) â /usr /include/bits/waitstatus.h:68: примечание: кандидаты: wait :: wait() /usr/include/bits/waitstatus.h:68: note: wait :: wait (const wait &) – ab91

+0

Ну, (a) вы должны компилироваться с компилятором C, а не с компилятором C++ (или вам следует отложить свой вопрос), и (b) вы должны использовать '#include ' (см. ['wait()' и 'waitpid()' ] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html)). Одним из преимуществ опций '-W * -prototypes' является то, что вы получаете предупреждения, когда у вас нет прототипа в области действия функции до того, как вы его вызовете. –

+0

Моя ошибка с использованием неправильного компилятора. Это привычка. Но приятно позвонить с помощью #include . Исправлено все. Я сделал предположение, что он уже там не проверял. Сейчас все работает. Большая помощь! – ab91

6
if(&background == 0) 
^

Эта линия не имеет большого смысла. Вы сравниваете адрес, когда вы, вероятно, захотите сравнить фактическое сохраненное значение, то есть вы, вероятно, захотите отказаться от &.

В противном случае этот тест никогда не будет так, что это адрес переменной background никогда не будет 0.

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