Hi, everybody. I need help with this: I'm writing a program that reads something like <path [argument1] [argument2] [...][&]> from the standard input and then tries to execute the program 'path' with arguments 'argument1', 'argument2',... This program will be executed in background if the last character of the line is '&' and in foreground other case. The thing is, when I write something like <p a b> I get the message:
*** glibc detected *** free(): invalid next size (normal): 0x0804a018
*** glibc detected *** free(): invalid next size (fast): 0x0804a018
Aborted
When I just write <p> or <p a> it works just fine, but when I try to pass two or more arguments it cracks. My code is the following (if you have any suggestion to improve it, please tell me - and be gentle: I'm not experienced and I use to make the dumbest mistakes :P):
Code:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#define SIZEBUF 1024
typedef enum {FALSE=0, TRUE} bool;
int main(int argc, char* argv[]){
char buffer[SIZEBUF];
char **arguments;
char *path;
int i, currentarg, numargs, bytesread;
pid_t pid;
bool background;
if(setvbuf(stdout, NULL, _IONBF, 0)){
perror("error en setvbuf");
exit(-1);
}
while(1){
printf("\n-------------------------------\n");
printf("------- esperando input -------\n");
printf("-------------------------------\n\n");
//leemos de la entrada estándar
if((bytesread = read(STDOUT_FILENO, buffer, SIZEBUF) - 1) < 0){
perror("error en el read");
exit(-1);
}
//cortamos el buffer por donde corresponda (el '\n')
buffer[bytesread] = '\0';
if(!strcmp(buffer, "exit"))
break;
background = FALSE;
if(buffer[bytesread-1] == '&'){ //comprobamos tiene que ejecutarse en background o no y quitamos el '&' (si lo hay)
background = TRUE;
bytesread--;
buffer[bytesread] = '\0'; //cortamos el buffer por donde corresponda
}
printf("==========%s===========\n\n", background?"background":"foreground");
numargs = 1;
for(i=0; i<bytesread; i++){
if(buffer[i] == ' ') //contamos el número de argumentos para saber cuánta memoria reservar
numargs++;
}
arguments = malloc(numargs+1);
currentarg = 1;
arguments[0] = &(buffer[0]);
for(i=0; i<bytesread; i++){ //creamos el vector de punteros a los argumentos
if(buffer[i] == ' '){
arguments[currentarg] = &(buffer[i+1]);
currentarg++;
buffer[i] = '\0'; //separamos los argumentos por el carácter terminador ('\0')
}
}
path = arguments[0];
arguments[numargs] = NULL;
printf("path: %s\n", path);//quitar
if((pid = fork()) < 0){
perror("error en el fork");
exit(-1);
}else if(pid == 0){ //estamos en el hijo
sleep(1); //ponemos un retraso para ver más claramente los efectos de ejecutarlo en background
if(execv(path, arguments) < 0){ //ejecutamos el otro programa
perror("error en execv");
exit(-1);
}
}else if(!background){//estamos en el padre y queremos ejecutar el hijo en foreground, así que...
wait(NULL); //...esperamos a que termine
} //si queríamos ejecutarlo en background (o si ya ha terminado) seguimos
free(arguments);
}
return 0;
}
Thanks a lot!