2010-10-14 18 views
5

में पाइप को कार्यान्वित करना मूल रूप से मैंने मानक पॉज़िक्स कमांड का उपयोग करके एक खोल बनाया है, मैं भी पाइपिंग को लागू करने में सक्षम होना चाहता हूं। अभी यह सही ढंग से आदेशों को संभालता है, और & के साथ पृष्ठभूमि प्रसंस्करण कर सकता है। लेकिन मुझे उपयोग करके पाइप करने में सक्षम होना चाहिए और >> साथ ही साथ। उदाहरण के लिए कुछ ऐसा: बिल्ली फ़ाइल 1 फ़ाइल 2 >> फ़ाइल 3 बिल्ली फ़ाइल 1 फ़ाइल 2 | अधिक अधिक फ़ाइल 1 | grep सामानएक सी खोल (यूनिक्स)

यहां वर्तमान में कोड है। मैं भी "सिस्टम" कॉल से बचना चाहता हूं। मुझे पता है कि यू को डुप्ली 2 का उपयोग करने की ज़रूरत है, लेकिन जिस तरह से मैंने अपना कोड किया है, वह थोड़ा अजीब है, इसलिए मुझे उम्मीद है कि अगर कोई मुझे बता सकता है कि क्या इस कोड में पाइप लागू करना संभव है? धन्यवाद! मुझे पता है कि dup2 का उपयोग किया जाता है, लेकिन मैं भी def def। कार्यान्वित करने के तरीके में भ्रमित >> के रूप में अच्छी तरह से |

#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

आप सिस्टम कॉल से बचने की कोशिश क्यों कर रहे थे? पोर्टेबिलिटी? आप यथासंभव POSIX निर्दिष्ट सिस्टम कॉल से चिपके रह सकते हैं। इसके अलावा, आपका खोल सी और सी ++ का एक अजीब मिश्रण है। – nategoose

उत्तर

5

आप अपने खोल से पाइप और उत्पादन पुनर्निर्देशन लागू करने में सक्षम होना चाहिए, लेकिन कुछ बातें मैंने देखा हैं:

  • इनपुट पढ़ने, पार्स करने के लिए आपका कोड, और उत्पादन एक साथ मिश्रित कर रहे हैं, आप कर सकते हैं इस कार्यक्षमता को अलग करना चाहते हैं।
  • strtok खोल आदेशों के लिए एक पार्सर के रूप में बहुत अच्छी तरह से काम नहीं करेगा। यह बहुत ही सरल कमांड के लिए काम करेगा, लेकिन आप एक बेहतर पार्सर बनाने या खोजने में लग सकते हैं। echo "hello world" जैसे कमांड आपके वर्तमान पार्सिंग विधि के साथ समस्याग्रस्त हो जाएगा।
  • आप अपने पार्स किए गए आदेशों को रखने के लिए एक सरल संरचना बनाना चाहते हैं।

    #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); 
        } 
    } 
    

    इस परियोजना के साथ गुड लक:

यहाँ कुछ स्यूडोकोड पाने के लिए आप शुरू कर दिया है!

5

पाइप और रीडायरेक्शन वास्तव में अलग हैं। पुनर्निर्देशन को लागू करने के लिए (जैसे >>) आपको वास्तव में dup2 का उपयोग करना होगा। सबसे पहले, इच्छित झंडे के साथ वांछित फ़ाइल खोलें (>> के लिए वे O_WRONLY|O_CREAT|O_APPEND होंगे)। दूसरा, dup2 का उपयोग करके, इस नए खुले एफडी की एक प्रतिलिपि बनाएं (फाइल डिस्क्रिप्टर 1)। अंत में, बंद नया खोला एफडी।

पाइप बनाने के लिए, आपको pipe syscall की आवश्यकता होगी। इसके मैनपेज को पढ़ें, इसमें उदाहरण कोड है। फिर आपको pipe द्वारा लौटाए गए फ़ाइल डिस्क्रिप्टर को क्रमशः एक प्रक्रिया और stdout के लिए stdin होने के लिए dup2 की आवश्यकता होगी।

+0

क्या आपको लगता है कि मैंने अपना खोल किस तरह से किया है, यह "संभव" होगा या क्या मुझे अपना खोल फिर से डिजाइन करना चाहिए? –

संबंधित मुद्दे