2010-10-14 14 views
5

Básicamente, he creado un caparazón usando comandos POSIX estándar, también quiero poder implementar tuberías. En este momento, maneja los comandos correctamente y puede procesar el fondo con &. Pero necesito poder usar tuberías | y >> también. Por ejemplo algo como esto: cat file1 file2 >> file3 cat file1 file2 | más más archivo1 | grep stuffImplementando tuberías en un caparazón C (Unix)

Aquí está el código que tengo actualmente. También quiero EVITAR llamadas al "SISTEMA". Sé que necesito usar dup2, pero la forma en que hice mi código es un poco extraña, así que espero que alguien me diga si es factible implementar tuberías en este código. ¡Gracias! Sé que se usa dup2, pero también soy def. confundido sobre cómo implementar >> tan BIEN como |

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

using namespace std; 


void Execute(char* command[],bool BG) 
{ 
//Int Status is Used Purely for the waitpid, fork() is set up like normal. 
    int status; 
    pid_t pid = fork(); 


    switch(pid) 
    { 
     case 0: 
      execvp(command[0], command); 

      if(execvp(command[0], command) == -1) 
      { 
       cout << "Command Not Found" << endl; 
       exit(0); 
      } 

      default: 
      if(BG == 0) 
      { 
        waitpid(pid, &status, 0); 
//Debug    cout << "DEBUG:Child Finished" << endl; 
      } 


    } 

} 


bool ParseArg(char* prompt, char* command[], char Readin[],bool BG) 
{ 

    fprintf(stderr, "myshell>"); 
     cin.getline(Readin,50); 
    prompt = strtok(Readin, " "); 
    int i = 0; 

    while(prompt != NULL) 
    { 
     command[i] = prompt; 
     if(strcmp(command[i], "&") == 0){ 
//Debug  cout << "& found"; 
     command[i] = NULL; 
     return true; 
    } 
//Debug  cout << command[i] << " "; 
     i++; 
     prompt = strtok(NULL, " "); 

    } 
    return false; 
} 

void Clean(char* command[]) 
{ 
//Clean Array 
     for(int a=0; a < 50; a++) 
     { 
      command[a] = NULL; 
     } 
} 



int main() 
{ 
    char* prompt; 
    char* command[50]; 
    char Readin[50]; 
    bool BG = false; 



    while(command[0] != NULL) 
    { 

     Clean(command); 
     BG = ParseArg(prompt, command, Readin, BG); 
     if(strcmp(command[0], "exit") == 0 || strcmp(command[0], "quit") == 0) 
     { 
      break; 
     } 

    else 
    { 
      Execute(command,BG); 
    } 

    } 

    return 1; 

} 
+3

¿Por qué intentabas evitar las llamadas al sistema? ¿Portabilidad? Puede quedarse con las llamadas al sistema especificadas POSIX tanto como sea posible. Además, tu caparazón es una extraña mezcla de C y C++. – nategoose

Respuesta

5

Usted debe ser capaz de implementar las tuberías y redirección de la salida con su cáscara, pero hay algunas cosas que noté:

  • Su código para la lectura de entrada, análisis y de salida se mezclan entre sí, es posible quiero separar esta funcionalidad
  • strtok no funcionará muy bien como un analizador para comandos de shell. Funcionará para comandos muy simples, pero es posible que desee buscar crear o encontrar un analizador mejor. Un comando como echo "hello world" será problemático con su método de análisis actual.
  • Es posible que desee crear una estructura simple para mantener sus comandos analizados.

Aquí es un poco de pseudocódigo para empezar:

#define MAX_LINE 10000 
#define MAX_COMMANDS 100 
#define MAX_ARGS 100 

// Struct to contain parsed input 
struct command 
{ 
    // Change these with IO redirection 
    FILE *input; // Should default to STDIN 
    FILE *output; // Should default to STDOUT 

    int num_commands; 
    int num_args[MAX_COMMANDS]; // Number of args for each command 
    char* command_list[MAX_COMMANDS]; // Contains the programs to be run 
    char* args_list[MAX_COMMANDS][MAX_ARGS]; // The args for each command 
    boolean background_task; 
    boolean append; 
} 

int main() 
{ 
    char input[MAX_LINE]; 

    while (1) 
    { 
     struct command cmd; 

     print_prompt(); 
     read_input(input); 
     parse_input(input, &cmd); 
     execute(&cmd); 
    } 
} 

Buena suerte con este proyecto!

5

Las tuberías y las redirecciones son diferentes, en realidad. Para implementar una redirección (como >>), tiene que usar dup2 de hecho. Primero, abra el archivo deseado con los indicadores apropiados (para >> serán O_WRONLY|O_CREAT|O_APPEND). En segundo lugar, usando dup2, haga de stdout (descriptor de archivo 1) una copia de este fd recién abierto. Finalmente, cierre el fd recién abierto.

Para crear una tubería, necesitará un pipe syscall. Lea su página de manual, contiene código de ejemplo. Entonces también necesitará dup2 para hacer que los descriptores de archivos devueltos por pipe sean stdin para un proceso y stdout para otro, respectivamente.

+0

¿Crees que con la forma en que hice mi caparazón será "posible" o debería rediseñar mi caparazón? –

Cuestiones relacionadas