PDA

Visualizza la versione completa : [C] Pipe tra convert e barcode in linux


8bitmagictime
13-08-2009, 11:46
Vorrei eseguire una pipe tra il comando barcode e il comando convert in linux. Ho provato con questo codice: barcode:


if(pbarcode == 0){//sono nel processo figlio per il lancio del comando barcode
close(pb[1]);//Chiudo in lettura
dup2(pb[0],0);
close(pb[0]);
execlp("barcode", "barcode", "-b", codice, "n", "-E", "-e", "ean", "-u", "mm", "-g", "60x25+1+1", NULL);/
}

codice convert:


if(pconvert == 0){//sono nel processo figlio per la conversione del file
close(pb[0]);//Chiudo in scrittura
dup2(pb[1],1);
close(pb[1]);
execlp("convert","convert",nome2,NULL);
}

nome2 è una stringa che contiene il nome del file destinazione.bmp.
Temo non riesca a essere ricevuto il ps creato da barcode. Vedo infatti l'output a video ma non viene elaborato da convert.
Avreste qualche suggerimento da darmi?
Grazie in anticipo.

YuYevon
13-08-2009, 14:08
barcode deve scrivere nella pipe e convert leggere, ma tu stai facendo il contrario



if ( pbarcode == 0 ) {
close(pb[0]); /* Chiudo in lettura */
dup2(pb[1], 1);
close(pb[1]);

execlp("barcode", "barcode", "-b", codice, "n", "-E", "-e", "ean", "-u", "mm", "-g", "60x25+1+1", NULL);
}




if ( pconvert == 0 ) {
close(pb[1]); /* Chiudo in scrittura */
dup2(pb[0], 0);
close(pb[0]);
execlp("convert", "convert", nome2, NULL);
}

8bitmagictime
13-08-2009, 16:36
Grazie!

8bitmagictime
14-08-2009, 10:50
Ho modificato il listato di ieri utilizzando la popen. Ho però un problema strano nella copia del file .ps. Il file viene creato, quindi fino alla riga
fps=fopen(nome1,"w"); tutto dovrebbe essere ok. In seguito non viene copiato alcun carattere nel file .ps e il programma termina dando un errore stack smashing detected. Potreste per favore darmi qualche indicazione su come risolverlo?
Grazie


#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PERM 0777
#define SIZE 100000
main(){
char codice[13]; //il barcode è EAN 13
char nome[15],nome1[15],nome2[15];
char ext1[]=".ps";//Stringa per estensione .ps
char ext2[]=".bmp";//Stringa per estensione .bmp
FILE *pb;//Descrittore di file per la pipe convert | barcode
FILE *fps;//Descrittore del file .ps
char rb[]="barcode -b ";
int n;
pid_t pbarcode,pconvert,pelimina;//pid per il processo che lancia il comando barcode e per quello che lancia convert
printf("\nInserire il codice EAN\n");
scanf("%s", codice);
printf("\nInserire il nome del prodotto\n");
scanf("%s", nome);
strcpy(nome1,nome);
strcpy(nome2,nome);
strcat(nome1,ext1);
strcat(nome2,ext2);
strcat(rb,codice);
strcat(rb," n -E -e ean -u mm -g 60x25+1+1");
if((pb=popen(rb,"r"))==NULL){
printf("Errore popen non riuscita\n");
exit(-2);
}
else{//Sono nel processo padre
if(pconvert=fork() < 0){//crea un processo per lanciare il comando convert
printf("Fork per convert fallita\n");
exit(-3);
}
if(pconvert == 0){//sono nel processo figlio per la conversione del file
fps=fopen(nome1,"w");
while((n=fgetc(pb)) != EOF ){//Copia dalla pipe al file
fputc(n,fps);
}
pclose(pb);
fclose(fps);
}
char nc[]="convert ";//Stringa comando convert
strcat(nc,nome1);
strcat(nc," ");
strcat(nc,nome2);
execl("convert",nc,NULL);
}
waitpid(pconvert,NULL,0);
return 0;
}

YuYevon
14-08-2009, 13:26
Non ho modo di provare quel codice perché non ho barcode, ma vedo comunque alcune cose strane... innanzitutto, tra le ultime righe del programma richiami execl(), che è diversa da execlp(): a quest'ultima non hai bisogno di passare il path completo del comando/programma (il sistema lo ricerca automaticamente nelle directory del tuo PATH, come la "p" del nome della funzione ricorda). La execl() invece necessita del path completo del comando, qundi scrivere solo "convert" non va bene...

Inoltre fai un uso scorretto di popen(): questa funzione non è come una fork(), non devi differenziare tra processo padre e figlio con il costrutto if - then - else... la popen crea un processo eseguendo il comando/programma che le passi, scrive l'output su uno stream di cui restituisce il puntatore come valore di ritorno e chiude subito il processo. Dopo la chiamata popen(), puoi servirti di quello che è stato scritto per compiere altre operazioni.

Questo è un esempio di utilizzo... il programma richiama ls con popen, l'output viene scritto su un file (lsfile) e questo viene poi ordinato da sort. Ho lasciato execl(), specificando però il path completo del comando.



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

int main(void)
{
int byte;
char *output = "lsfile";
FILE *my_pipe, *fp;
pid_t pid;

if( ( my_pipe = popen("ls", "r") ) == NULL ) {
fprintf(stderr, "An error has occurred with popen(): %s\n", strerror(errno));
exit(errno);
}

fp = fopen(output, "w");
if ( fp == NULL ) {
fclose(my_pipe);
fprintf(stderr, "Unable to open %s: %s\n", output, strerror(errno));
exit(errno);
}

while ( ( byte = fgetc(my_pipe) ) != EOF ) /* Copia dalla pipe al file */
fputc(byte ,fp);

fclose(fp);
fclose(my_pipe);

/* la creazione di un nuovo processo per eseguire sort non è necessaria */

pid = fork();
if ( pid < 0 ) {
fprintf(stderr, "An error has occurred with fork(): %s\n", strerror(errno));
exit(errno);
}
if ( pid == 0 ) {
execl("/usr/bin/sort", "sort", output, NULL);
fprintf(stderr, "An error has occurred with execlp(): %s\n", strerror(errno));
exit(errno);
}

waitpid(pid, NULL, 0);

return 0;
}

8bitmagictime
14-08-2009, 16:44
Ti ringrazio per l'esempio. Adesso ho messo a posto la fork di troppo e anche il file .ps adesso è generato correttamente. Mi rimane però un problema. Pur venendo creato correttamente il file nome1 e pur essendo corretta la riga di comando che arriva alla execlp (ho messo una riga di controllo per verificarla)


printf("La riga di comando e' %s \n",nc);
execlp("convert",nc,NULL);

il comando convert anzichè convertirmi il file mi mostra il man, come se gli fossero passati dei parametri sbagliati.
Il listato modificato è questo:


#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PERM 0777
main(){
char codice[13]; //il barcode è EAN 13
char nome[15],nome1[15],nome2[15];
char ext1[]=".ps";//Stringa per estensione .ps
char ext2[]=".bmp";//Stringa per estensione .bmp
FILE *pb;//Descrittore di file per la pipe convert | barcode
FILE *fps;//Descrittore del file .ps
char rb[]="barcode -b ";
int n;
pid_t pbarcode,pconvert,pelimina;//pid per il processo che lancia il comando barcode e per quello che lancia convert
printf("\nInserire il codice EAN\n");
scanf("%s", codice);
printf("\nInserire il nome del prodotto\n");
scanf("%s", nome);
strcpy(nome1,nome);
strcpy(nome2,nome);
strcat(nome1,ext1);
strcat(nome2,ext2);
strcat(rb,codice);
strcat(rb," n -E -e ean -u mm -g 60x25+1+1");
fps=fopen(nome1,"w");
if((pb=popen(rb,"r"))==NULL){
printf("Errore popen non riuscita\n");
exit(-2);
}
while((n=fgetc(pb)) != EOF ){//Copia dalla pipe al file
fputc(n,fps);
}
pclose(pb);
fclose(fps);
//}
char nc[]="convert ";//Stringa comando convert
strcat(nc,nome1);
strcat(nc," ");
strcat(nc,nome2);
printf("La riga di comando e' %s \n",nc);
execlp("convert",nc,NULL);
return 0;
}

Ti prego di scusarmi per il disturbo. E' il primo programma nel quale uso le syscall e probabilmente qualcosa mi sfugge nei meccanismi.
Grazie.

YuYevon
14-08-2009, 17:10
Penso non sia corretto passare a execlp() una stringa che contenga l'intero comando... devi passare gli argomenti separati. Prova con:



execlp("convert", "convert", nome1, nome2, NULL);

8bitmagictime
14-08-2009, 18:31
Grazie mille!
Ho appena provato e in effetti il problema della execlp era proprio quello che mi hai indicato.

8bitmagictime
15-08-2009, 17:13
Scusa se disturbo ancora. Purtroppo ho un altro problema che non riesco a superare. Ho inserito una serie di fork per consentire al processo padre di proseguire oltre il comando convert e lanciare altri due comandi, uno di cancellazione del file .ps e uno di lancio di gimp. Però il programma non va oltre convert. Non so perchè ma non entra nei processi successivi. Allego il listato:


#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PERM 0777
main(){
char codice[13]; //il barcode è EAN 13
char nome[15],nome1[15],nome2[15];
char ext1[]=".ps";//Stringa per estensione .ps
char ext2[]=".jpg";//Stringa per estensione .jpg
FILE *pb;//Descrittore di file per la pipe convert | barcode
FILE *fps;//Descrittore del file .ps
char rb[]="barcode -b ";
int n;//Variabile per la lettura caratteri dalla pipe
char e;//Variabile per controllo uscita finale
pid_t pconvert,pelimina,pmostra;//pid per il processo che cancella il file .ps e per il processo che lancia Gimp
printf("\nInserire il codice EAN\n");
scanf("%s", codice);
printf("\nInserire il nome del prodotto\n");
scanf("%s", nome);
strcpy(nome1,nome);
strcpy(nome2,nome);
strcat(nome1,ext1);
strcat(nome2,ext2);
strcat(rb,codice);
strcat(rb," n -E -e ean -u mm -g 60x25+1+1");
fps=fopen(nome1,"w");
if((pb=popen(rb,"r"))==NULL){
printf("Errore popen non riuscita\n");
exit(-1);
}
while((n=fgetc(pb)) != EOF ){//Copia dalla pipe al file
fputc(n,fps);
}
pclose(pb);
fclose(fps);
if(pconvert=fork() < 0){//crea un processo per lanciare il comando convert e lasciare il processo padre aperto per eseguire i comandi successivi
printf("Fork per conversione file fallita\n");
exit(-2);
}
if(pconvert == 0){//sono nel processo figlio per la conversione del file
execlp("convert","convert",nome1,nome2,NULL);
}
else if(pconvert>0){
printf("Sono uscito da convert\n");
wait(NULL);//sono nel processo padre e aspetto che termini la conversione
if(pelimina=fork() < 0){//crea un processo per lanciare il comando unlink
printf("Fork per cancellazione file fallita\n");
exit(-3);
}
if(pelimina == 0){//sono nel processo figlio per l'eliminazione del file .ps
printf("Sono entrato in elimina\n");
unlink(nome1);
}
else if(pelimina>0){
//Sono nel processo padre che può proseguire indipendentemente dalla cancellazione del file .ps
if(pmostra=fork() < 0){//crea un processo per lanciare gimp
printf("Fork per Gimp fallita\n");
exit(-4);
}
if(pmostra==0){//sono nel processo figlio per il lancio dell'applicazione gimp
execlp("gimp","gimp",nome2,NULL);//lancia l'apertura del nuovo file con Gimp
}
else if(pmostra>0){
printf("Premere il tasto e per chiudere Gimp e uscire\n");
while(e != 'e'){
scanf("%c",&e);
}
kill(pmostra,9);
wait(NULL);//Aspetta la fine di tutti i processi figli
return 0;
}
}
}
}

Grazie in anticipo. Buon ferragosto.

8bitmagictime
16-08-2009, 16:58
Scusate se disturbo ancora. Sono riuscito a superare il problema di cui sopra modificando il codice. Ho il problema però che adesso uscendo dal programma ho un errore di stack smashing detected e segmentation fault. La cosa strana è che l'errore me lo da in uscita dopo che tutte le operazioni sono andate a buon fine. Ringrazio in anticipo per i suggerimenti.


#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PERM 0777
main(){
char codice[13]; //il barcode è EAN 13
char nome[15],nome1[15],nome2[15];
char ext1[]=".ps";//Stringa per estensione .ps
char ext2[]=".jpg";//Stringa per estensione .jpg
FILE *pb;//Descrittore di file per la pipe convert | barcode
FILE *fps;//Descrittore del file .ps
FILE *fjpg;//Descrittore per il test dell'esistenza del file jpg
char rb[]="barcode -b ";
int n;//Variabile per la lettura caratteri dalla pipe
char e;//Variabile per controllo uscita finale
pid_t pconvert,pmostra;//pid per il processo che converte il file .ps e per il processo che lancia Image Viewer
printf("\nInserire il codice EAN\n");
scanf("%s", codice);
printf("\nInserire il nome del prodotto\n");
scanf("%s", nome);
strcpy(nome1,nome);
strcpy(nome2,nome);
strcat(nome1,ext1);
strcat(nome2,ext2);
strcat(rb,codice);
strcat(rb," n -E -e ean -u mm -g 60x25+1+1");
fps=fopen(nome1,"w");
if((pb=popen(rb,"r"))==NULL){
printf("Errore popen non riuscita\n");
exit(-1);
}
while((n=fgetc(pb)) != EOF ){//Copia dalla pipe al file
fputc(n,fps);
}
pclose(pb);
fclose(fps);
pconvert=fork();//crea un processo per lanciare il comando convert e lasciare il processo padre aperto per eseguire i comandi successivi
if(pconvert < 0){
printf("Fork per conversione file fallita\n");
exit(-2);
}
if(pconvert == 0){//sono nel processo figlio per la conversione del file
execlp("convert","convert",nome1,nome2,NULL);
}
if(pconvert>0){
wait(NULL);//sono nel processo padre e aspetto che termini la conversione
unlink(nome1);//Cancello il file .ps
pmostra=fork();//crea un processo per lanciare Image Viewer
if(pmostra < 0){
printf("Fork per Image Viewer fallita\n");
exit(-3);
}
if(pmostra == 0){//sono nel processo figlio per il lancio dell'applicazione gimp
fjpg=fopen(nome2,"rb");
if(fjpg == NULL){
printf("Errore, conversione a jpg non riuscita\n");
exit(-4);
}
execlp("gpicview","gpicview",nome2,NULL);//lancia l'apertura del nuovo file con Image Viewer
}
if(pmostra>0){
printf("Premere il tasto e per chiudere Image Viewer e uscire\n");
while(e != 'e'){
scanf("%c",&e);
}
}
kill(pmostra,SIGTERM);//Termina Image Viewer
}
wait(NULL);//Aspetta la fine di tutti i processi figli
return 0;
}

Loading