Portál AbcLinuxu, 10. května 2025 22:14

Dotaz: Implementace shellove roury v C

tomes.io avatar 8.2.2013 15:19 tomes.io | skóre: 12 | blog: tomesh
Implementace shellove roury v C
Přečteno: 475×
Odpovědět | Admin
Ahoj,

potrebuji poradit s implementaci prikazu
 | 
v C. Kod nize funguje jako rourapro prikazy bez parametru, ale premyslim, jak to udelat, aby roura fungovala obecne, tj. zpracovavala by jako argumenty shellovske prikazy i s jejich pripadnymi parametry.

Kod nize spousti shellovsky prikaz
prikaz1 | prikaz2 dva
jako
./pipe prikaz1 prikaz 2
a ja bych chtel aby to fungovalo napriklad jako:
./pipe prikaz1 -abcde prikaz2 -a -b -c 
Napadaji me jenom same drsne zpusoby jak to vyresit, pomoci ruzneho parsovani, ale tim by se kod stal prilis robustni



int main(int argc,char **argv) {

    int fd[2];

	pipe(fd);
	pid_t childpid;

	pid_t pid = fork();
	
    if (childpid == -1)
    {
        perror("Error forking...");
        exit(1);
    }

	if (pid == -1)  
	   return -1;  

	if (pid == 0)  
	{  
	   close(fd[1]); //close write to pipe, in child
	   dup2(fd[0], STDIN_FILENO); // Replace stdin with the read end of the pipe
	   close(fd[0]); // Don't need another copy of the pipe read end hanging about
	   execlp(argv[2],argv[2],argv[3],NULL);
	}

	else
	{
	   close(fd[0]); //close read from pipe, in parent
	   dup2(fd[1], STDOUT_FILENO); // Replace stdout with the write end of the pipe
	   close(fd[1]); // Don't need another copy of the pipe write end hanging about
	   execlp(argv[1],argv[1],NULL);
	}  
	
	return EXIT_SUCCESS;
}


Řešení dotazu:


Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

Jakub Lucký avatar 8.2.2013 16:26 Jakub Lucký | skóre: 40 | Praha
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
Odpovědět | | Sbalit | Link | Blokovat | Admin
A nechcete to vyřešit tak chytře, jako to vyřešil Bash? Tedy nastavit nějaký delimiter těch příkazů?
./pipe command1 -s -tisicem param etru %DELIMITER% command2 -s -jinym --tisicem par ametru 
If you understand, things are just as they are; if you do not understand, things are just as they are.
9.2.2013 03:21 Sten
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
Odpovědět | | Sbalit | Link | Blokovat | Admin
Tohle nelze jednoduše vyřešit, pokud bude první příkaz třeba cat test a druhý xargs file, nedokážete určit, kde to správně rozdělit (záměrně jsem vybral taková jména, kde každé slovo je zároveň i jméno existujícího programu).

Nejjednodušší řešení je to zauvozovkovat, tedy aby se ten program i s parametry předával jako jeden parametr, a místo execlp použít system:
./pipe "prikaz1 -abcde" "prikaz2 -a -b -c"
9.2.2013 15:58 Logik
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
Druhá možnost je zavést jiný delimiter jako argument (klidně třeba rouru) a spouštět to

./pipe prikaz1 -abcde \| prikaz2 -a -b -c
tomes.io avatar 10.2.2013 22:13 tomes.io | skóre: 12 | blog: tomesh
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
To s tim delimiterem byl dobrej napad, pouzil jsem
@
Vysledny kod vypada takto:


int main(int argc,char *argv[]) {

	if (argc < 2) {
	
		printf("Programme must be run with with arguments and using pipe shell symbol as a delimiter!\n"
			"For example: ./pipe ls -la @ grep -v .c\n");
		exit(1);
	}
        
        int count;
        int fd[2];
        char command1[50];
        char command2[50];
        char arguments1[50];
        char arguments2[50];
        
        strcpy(command1, argv[1]);
        strcpy(arguments1, " ");
        strcpy(arguments2, " ");

        count = 2;
        
        for (; count < argc; count++) {
                        
            if (strcmp(argv[count], "@") == 0) {
                
                break;
            }
            
            strcat(arguments1, argv[count]);
            strcat(arguments1, " ");
        }
        
        arguments1[strlen(arguments1)-1] = '\0';  //removing ending space       
        strcat(command1, arguments1);      
        strcpy(command2, argv[count+1]);
        count += 2;


        for ( ; count < argc; count++) {
            
            strcat(arguments2, argv[count]);
            strcat(arguments2, " ");
        }
        
        arguments1[strlen(arguments2)-1] = '\0'; 
        strcat(command2, arguments2);
                
	pipe(fd);

	pid_t pid = fork();
	
	if (pid == -1)  
	   return -1;  

	if (pid == 0) {
	  
	   close(fd[1]); //close write to pipe, in child
	   dup2(fd[0], STDIN_FILENO); // Replace stdin with the read end of the pipe
	   close(fd[0]); // Don't need another copy of the pipe read end hanging about
           system(command2); 
	}

	else {
	
	   close(fd[0]); //close read from pipe, in parent
	   dup2(fd[1], STDOUT_FILENO); // Replace stdout with the write end of the pipe
	   close(fd[1]); // Don't need another copy of the pipe write end hanging about;
           system(command1); 
	}  
	
	return EXIT_SUCCESS;
}
tomes.io avatar 11.2.2013 14:15 tomes.io | skóre: 12 | blog: tomesh
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
Odpovědět | | Sbalit | Link | Blokovat | Admin
Jeste bych se chtel zeptat, zda by nekdo neporadil, jak stejnou funkcionalitu naimplementovat s
mkfifo()
?
11.2.2013 19:02 jen hádám
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
Místo pipe() tam bude mkfifo a dvakrát open (jednou pro čtení, jednou pro zápis), zbytek stejný, plus v rámci úklidu někde unlink na to fifo (teoreticky je možné hned po těch openech?).
tomes.io avatar 11.2.2013 21:03 tomes.io | skóre: 12 | blog: tomesh
Rozbalit Rozbalit vše Re: Implementace shellove roury v C
Neco takoveho me taky napadlo, ale nedostal jsem se k tomu to dobre usporadat, zatim mam jako hrubou kostru tohle, ale je tam errno pri otevirani souboru
fopen: No such file or directory
DOsavadni kod:
int main(int argc,char *argv[]) {

	if (argc < 2) {
	
		printf("Programme must be run with with arguments and using pipe shell symbol as a delimiter!\n"
			"For example: ./pipe ls -la @ grep -v .c\n");
		exit(1);
	}
        
        int count, fw, fr;
        char command1[50];
        char command2[50];
        char arguments1[50];
        char arguments2[50];
        
        strcpy(command1, argv[1]);
        strcpy(arguments1, " ");
        strcpy(arguments2, " ");

        count = 2;
        
        for (; count < argc; count++) {
                        
            if (strcmp(argv[count], "@") == 0) {
                
                break;
            }
            
            strcat(arguments1, argv[count]);
            strcat(arguments1, " ");
        }
        
        arguments1[strlen(arguments1)-1] = '\0';  //removing ending space       
        strcat(command1, arguments1);      
        strcpy(command2, argv[count+1]);
        count += 2;


        for ( ; count < argc; count++) {
            
            strcat(arguments2, argv[count]);
            strcat(arguments2, " ");
        }
        
        arguments1[strlen(arguments2)-1] = '\0'; 
        strcat(command2, arguments2);
                
        mkfifo(FIFO_FILE, S_IFIFO|0666);

	pid_t pid = fork();
	
	if (pid == -1)  
	   return -1;  

	if (pid == 0) {
	  
	   //close(fifo); //close write to pipe, in child
	   //dup2(fifo, STDIN_FILENO); // Replace stdin with the read end of the pipe
	   //close(fifo); // Don't need another copy of the pipe read end hanging about

            if(fr = fopen(FIFO_FILE, "r") == NULL) {
                perror("fopen");
                exit(1);
            }
            dup2(fr, STDIN_FILENO);
            close(fr);
            
            system(command2); 
	}

	else {
	
	   //close(fifo); //close read from pipe, in parent
	   //dup2(fifo, STDOUT_FILENO); // Replace stdout with the write end of the pipe
	   //close(fifo); // Don't need another copy of the pipe write end hanging about;
            

            if(fw = fopen(FIFO_FILE, "w") == NULL) {
                perror("fopen");
                exit(1);
            }
            dup2(fw, STDOUT_FILENO);
            close(fw);
            system(command1); 
	}  
	
	return EXIT_SUCCESS;
}

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.