2013-06-13 2 views
1

Я фактически пытаюсь реализовать базовую мини-скорлупу в C. Для этого я сделал fonction, который анализирует, что пользователь вводит в консоли. Я проанализировал его, а затем я хотел бы отправить команду на консоль, используя каналы. Я не понимаю, почему мои трубы не работают. Я проверил разбор и, кажется, все в порядке, у меня есть правильные команды в параметрах фильтрации. Дело в том, что мой код трубы буквально ничего не делает, и я не понимаю, почему. Вот мой код. Спасибо заранее.Трубы, не работающие при использовании мини-раковины

#define READ 0 
#define WRITE 1 

char *cmds[5] = {0}; 

int main() {  
    char *saisie = (char*)malloc(100*sizeof(char*)); 
    char *saisie2 = (char*)malloc(100*sizeof(char*)); 
    gets(saisie); 
    int ncmds = 0; 
    int k = 0; 

    char* token = (char*)malloc(100*sizeof(char*)); 
    char* tofree; 

    if(*(saisie + 0) == '$'){ 
     if(*(saisie + 2) == 'e' && *(saisie + 3) == 'x' && *(saisie + 4) == 'i' || *(saisie + 5) == 't'){ 
      exit(0); 
     } 
     else{ 
      int i; 
      for(i = 0;i<99;i++){ 
       *(saisie2+i) = *(saisie+i+1); 
      }  
      free(saisie); 

      if (saisie2 != NULL) { 
       tofree = saisie2; 

       while ((token = strsep(&saisie2, "|")) != NULL){ 
        cmds[ncmds] = token; 
        ncmds++; 
       } 
       free(tofree);   
      } 
     } 
    } 

    exe(cmds, ncmds); 
    while(wait(NULL) > 0); 
    return 0; 
} 

int exe(char *cmds[], int ncmds){ 
    int fdin, fdout; 
int fds[2]; 
int i; 
int status; 
fdin = 0; 
for(i=0; i < ncmds-1; i++){ 
    pipe(fds); 
    fdout = fds[WRITE]; 

    if(fork() == 0){ 
     if(fdin != 0) { 
      close(0); 
      dup(fdin); 
      close(fdin); 
     } 
     if(fdout != 1) { 
      close(1); 
      dup(fdout); 
      close(fdout); 
     } 
     close(fds[READ]); 
     const char* prog2[] = {cmds[i], "-l", 0}; 
     execvp(cmds[i], prog2); 
     fprintf(stderr, "si esto se ve es un error\n"); 
     exit(1); 
    } 

    if(fdin != 0) 
     close(fdin); 
    if(fdout != 1) 
     close(fdout); 

    fdin = fds[READ]; 
} 

/* Ultimo comando */ 
fdout = 1; 
if(fork() == 0) { 
    if(fdin != 0) { 
     close(0); 
     dup(fdin); 
     close(fdin); 
    } 
    const char* prog2[] = {cmds[i], "-l", 0}; 
    execvp(cmds[i], prog2); 
    close(fds[READ]); 
    exit(1); 
} 

if(fdout!= 1) 
    close(fdout); 
if(fdin != 0) 
    close(fdin); 

    } 
} 
+0

вы должны проверить, 'вилка() <0 'для отказа вилки – leonhart

+2

Никогда не используйте' получает() '. Для любви к '$ DEITY', * никогда не используйте' gets() '*! –

+0

Ну, я использовал некоторую печать, чтобы убедиться, что программа входит в другое состояние и действительно делает это. Проблема, похоже, исходит из неправильной ссылки с дубликом, или закрывается ... – pdilau

ответ

2
int exe(char *cmds[], int ncmds){ 
    int p2c[2];//pipe parent to child 
    int c2p[2];//pipe child to parent 
    int i; 
    int status; 
    int pid; 
    char buf[4096]; 
    memset(buf, 0, 4096); 

    for(i=0; i < ncmds; i++){ 
     pipe(p2c); 
     pipe(c2p); 

     pid = fork(); 
     if(pid < 0) { 
      exit 1; 
     } 
     if(pid == 0){ //in child 
      close(1); 
      dup2(c2p[1],1); // make child write to c2p pipe instead of stdout 
      close(0); 
      dup2(p2c[0],0); // make child read from p2c pipe instead of stdin 
      close(p2c[1]); 
      close(c2p[0]); 
      const char* prog2[] = {cmds[i], "-l", 0}; 
      execvp(cmds[i], prog2); 
      fprintf(stderr, "si esto se ve es un error\n"); 
      exit(1); 
     } 
     //in parent 
     write(p2c[1], buf, strlen(buf)); //write the last output to child 
     close(p2c[1]); 
     close(c2p[1]); 
     memset(buf,0,4096); 
     if(read(c2p[0], buf, 4096) > 0){ //read output from child 
      if(i == ncmds -1){ 
       printf("result:\n"); 
       printf("%s\n", buf); 
      } 
     } 
    } 
} 
+0

Я не совсем понимаю, что должен делать родитель. Я не понимаю, как отправить информацию на консоль. Мне жаль те вопросы, которые могут показаться очень простыми, но я начинаю с C ... – pdilau

+0

@ user2480503 в дочернем процессе, вы сделали fd из 1 (stdout) для канала, поэтому вывод 'execvp (cmds [i], prog2); 'который должен отображаться в консоли, теперь идет в канал (и не будет отображаться на консоли). то в родительском процессе вы должны прочитать вывод из канала и распечатать его на консоли. – leonhart

+0

Так что я предполагаю использовать что-то подобное в родительском: system (fds [READ]). Я понял, что функции семейства exec предполагают выполнение команды так же, как если бы мы выполняли их в консоли. Я понял, что я не читаю вывод трубы в родительском. Должен ли я отправить ссылку, цель которой - отправить инструкцию на консоль на консоль. Я не знаю, объяснил ли я, что я неправильно понял ... – pdilau

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