/*
 * shell01.c
 * 
 * Copyright 2026 osboxes <osboxes@osboxes>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 * primer intento de shell en foreground
 * input de teclado, fork, exec
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

// prototipo de funciones
char *ingreso();
void ltrim(char *dest,char *origen);
void rtrim(char *dest,char *origen);
void trim(char *dest,char *origen);
int cuentopal(char *origen);
void parsing(char *dest[],int n,char *origen);

int main(int argc, char **argv) {
	char *cmd;
	int salir=0;
	do {
		cmd = ingreso();
		char cmd2[strlen(cmd)+1];
		trim(cmd2,cmd);
		if ( strlen(cmd2) == 0 ) continue;
		if ( strcmp(cmd2,"salir") == 0 ) { salir=1;continue; }
		int np=cuentopal(cmd2)+1;
		char *pcmd[np];
		parsing(pcmd,np,cmd2);
		//creo proceso hijo
		pid_t pid = fork();
		if ( pid == 0 ) {
			int ret = execvp(pcmd[0],pcmd);
			printf("Proceso [%s] no se puede ejecutar! (ret=%d)\n",cmd2,ret);
			free(cmd);
			exit(ret);
		} else {
			wait(0);
		}
		
		
		//int i;
		//for(i=0;i<np;i++) printf("pcmd[%d]=[%s]\n",i,pcmd[i]);
		//printf("cmd2=[%s] tiene %d palabras\n",cmd2,cuentopal(cmd2));
		// ingreso un comando y no salir!
		
		//printf("main(): cmd2=[%s]\n",cmd2);
		//libero memoria
		free(cmd);
	} while(!salir);
	//fin shell
	
	exit(0); //return 0;
}

// implementacion de funciones
char *ingreso() {
	int bloque=64,nbloque=1,n=0;
	int tam=bloque;
	char *p = (char *) malloc(tam);
	if ( p == NULL ) {
		printf("ingreso(): Error en asignacion inicial de memoria!\n");
		return NULL;
	}
	memset(p,0,bloque);
	char *r;
	int salir = 0;
	do {
		//printf("p=[%s] n=%d tam=%d bloque=%d nbloque=%d \n",p,n,tam,bloque,nbloque);
		// si estoy aca es xq asigne bien la memoria inicial
		r = fgets(p+n,bloque,stdin); // stdin = fd 0, stdout = fd 1, stderr = fd 2
		if ( r == NULL ) {
			printf("ingreso(): Error! en retorno fgets()\n");
			return NULL;
		}
		if ( strlen(p+n) >= (bloque-1) ) {
			n+=strlen(p+n);
			// rayos necesito mas memoria!
			nbloque++;
			p = realloc(p,tam+bloque);
			if ( p == NULL ) {
				printf("ingreso(): Error! en re-asignacion de memoria\n");
				return NULL;
			}
			memset(p+tam,0,bloque);
			tam+=bloque;
		} else salir=1;
	} while(!salir);
	p[strlen(p)-1]='\0';
	//printf("p=[%s] n=%d tam=%d bloque=%d nbloque=%d \n",p,n,tam,bloque,nbloque);
	return p;
}

// quita espacios al comienzo 
void ltrim(char *dest,char *origen) {
	char *in = origen;
	char *out = dest;
	while(*in && *in == ' ') in++;
	while(*in) { *out = *in; in++; out++; }
	*out='\0';
}

// quita espacios del final 
void rtrim(char *dest,char *origen) {
	// hola___\0  7
	// hola\0  4
	// ____\0 4
	char *p = origen+strlen(origen)-1;
	while(p > origen && *p == ' ') p--;
	if ( *p != ' ' ) { 
		while(*origen && origen <= p) { *dest = *origen; dest++; origen++; }
	}
	*dest = '\0'; 
}

// elimino espacios delante y atras del string origen
void trim(char *dest,char *origen) {
	char dest1[strlen(origen)+1];
	ltrim(dest1,origen);
	rtrim(dest,dest1);
}

// cuento palabras separadas por uno o mas espacios
// p previamente se hizo trim(p)
int cuentopal(char *p) {
	int n=0;
	while(*p) {
		while(*p && *p != ' ') p++;
		n++;
		while(*p && *p == ' ') p++;
	}
	return n;
}

void parsing(char *dest[],int largo,char *origen) {
	int n=0,i;
	char *p = origen;
	char *po = origen;
	
	while(*p && n < largo) {
		i=0;
		while(*p && *p != ' ') { p++;i++; }
		dest[n]=strndup(po,i);
		n++;
		while(*p && *p == ' ') p++;
		po=p;
	}
	dest[n]=NULL;
}
