/*
 * This code is part of Screws project.
 * Copylefted by pancake@phreaker.net at 2003
 */

#include "Lang.h"

/*
 * Languages MUST have needed parameters to read script from standard input
 * (finished with a '\0')
 */
#ifndef PATH_PERL
#error Perl path is not defined
#endif
#ifndef PATH_PYTHON
#error Python path is not defined
#endif
#ifndef PATH_SH
#error Sh path is not defined
#endif

char *langs[4][4] = {
    {"perl",	PATH_PERL,		"-",	NULL},
    {"python",	PATH_PYTHON,		"-",	NULL},
    {"sh",	PATH_SH,		NULL,	NULL},
    {NULL,	NULL,			NULL,	NULL}
};

bool
parsetoLang (ssblock, res)
    _cblock_t *ssblock;
    bool res;
{
    cblock_t *sblock=(cblock_t*)ssblock;
    group_t *gr;
    int in[2], status;
#if 0
    int out[2];
#endif
    lang_t lang;
    cblock_t *bl;
    char endcb='\0';
    int wrote, aux, clen;
    char *cstrt;

    if (!blockExecutable(sblock))
	return ignore;

    if (pipe(in)<0) {
	printf("Internal error while executing script (pipe).");
	return ignore;
    }
#if 0
    if (pipe(out)<0) {
	printf("Internal error while executing script (pipe).");
	return ignore;
    }
#endif
    switch (fork()) {
	case -1: /* error */
	    printf("Internal error while executing script (fork).");
	    return ignore;
	case 0:  /* at least! my creation! (aka son) */
	    close( in[1]);
#if 0
	    close(out[0]);
	    if (dup2(out[1],1)<0) { /* stdout */
		printf("Internal error while executing script (dup).");
		exit(1);
	    }
	    if (dup2(out[1],2)<0) { /* stderr */
		printf("Internal error while executing script (dup).");
		exit(2);
	    }
	    close(out[1]);
#endif
	    if (dup2( in[0],0)<0) { /* stdin */
		printf("Internal error while executing script (dup).");
		exit(3);
	    }
	    close( in[0]);

	    if (res!=false) { /* must ignore output(redirecting to /dev/null) */
		int fd=open("/dev/null",0);
		if (fd<0) {
		    printf("Internal error while executing script (open).");
		    exit(4);
		}
		if (dup2(fd,1)<0) {
		    printf("Internal error while executing script (dup).");
		    exit(5);
		}
	    }
	    if (dup2(1,2)<0) { /* stderr redirected to stdout */
		printf("Internal error while executing script (dup).");
		exit(6);
	    }

	    lang=blockLang(sblock);
	    if (lang==CUSTOM)
		langs[lang][LANG_PATH]=blockSLang(sblock)+1;
	    
	    execve( langs[lang][LANG_PATH],
		    &langs[lang][LANG_PATH],
		    environ );

	    printf("\n\nexecve: %s | ",langs[lang][LANG_PATH]);
	    fflush(stdout);
	    perror("perror");
	    printf("Internal error while executing script (execve).\n\n");
	    exit(4);
    }

    /* the father returns on scene */
    close( in[0]);
#if 0
    close(out[1]);
#endif
    
    gr=blockGroup(sblock);
    for (bl=groupBlockFirst(gr,sblock); bl!=NULL; bl=groupBlockNext(gr,sblock)) {
	if (!(blockExecutable(bl) && bl!=sblock)) {
	    blockCodeParms(bl,&cstrt,&clen);
	    for (wrote=aux=0; wrote < clen; wrote+=aux) {
		aux=write(in[1],cstrt+wrote,clen-wrote);
		if (aux < 0) {
		    printf("Internal error while executing script (write).");
		    return ignore;
		}
	    }
	}
    }
    write(in[1],&endcb,sizeof(char));
    close(in[1]);
    /* Child now has all of its script */

    if (wait(&status)<0) {
	printf("Internal error while executing script (wait).");
	return ignore;
    }

    if (blockExitV(sblock)!=script)
	return blockExitV(sblock);
    else
	return WEXITSTATUS(status)==0?false:true;
}

/*
 * Returns the lang_t of a string representing one
 * (must be defined or custom (!), otherwise returns an error)
 */
lang_t
slangTolang_t (slang)
    char *slang;
{
    lang_t res;

    if (slang[0]=='!')
	return CUSTOM;

    for (res=0; res!=CUSTOM; res++) 
	if ( ! strncmp( langs[res][LANG_NAME],
			slang,
			strlen(langs[res][LANG_NAME])) )
	    return res;

    return DEFAULT_LANG;
    return bError;
}

