
#include "HsmlLang.h"
#include "Cache.h"

char lang[] = "perl";
char file[] = ".pl.html";
char cmd[] = PATH_PERL;
char *args[] = {0, 0, 0};

bool init(void)
{
	args[0] = cmd;
	//args[0] = get_path_from_env();	
}

char *get_path_from_env(void)
{
	//return cmd = getenv("PATH_PERL");
}

void show_config(void)
{
	printf("Perl hsml sublang module\n");
	printf("lang name: %s\nlang file extension: %s\ninterpreter command: %s\n",
		lang, file, cmd);
}

void print_begin(char *buf)
{
		strcat(buf, "print (\"");
}

void print_end(char *buf)
{
	strcat(buf, "\\n\");\n");
}

void print_end_nl(char *buf)
{
	strcat(buf, "\");\n");
}

void code_begin(char *buf){}
	
void code_end(char *buf) {}

void codevar(char *buf, char *p)
{
	strcat(buf, "print (");
	strcat(buf, p+1);
	strcat(buf, ");\n");
}

void exec(char *file, char *buf, char *tmp)
{
	char codefile[PATH_STRING_LEN];
	char outfile[PATH_STRING_LEN];
	int fd;
	int bytes, status;
	
	do {
		bytes = snprintf(codefile, PATH_STRING_LEN, "%s/%s.%d.%d", tmp, file, time(0), rand());
		if(bytes >= PATH_STRING_LEN) {
			printf("Perl source file path too long\n");
			return;
		}
		fd = open(codefile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
	} while(fd == -1 && errno == EEXIST);
	if (fd == -1) printf("Cannot write Perl source to: '%s'\n", codefile);
	else {
		write(fd, buf, strlen(buf));
		close(fd);
		args[1] = codefile;
		
		if(cache && (cacherule == CACHERULE_TIME || cacherule == CACHERULE_NOINPUT && !strcmp("", getenv("ARGS"))))
		{
			do {
				bytes = snprintf(outfile, PATH_STRING_LEN, "%s/%s.%d.%d", tmp, file, time(0), rand());
				if(bytes >= PATH_STRING_LEN) {
					printf("output file path too long\n");
					return;
				}
				fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
			} while(fd == -1 && errno == EEXIST);
			if (fd == -1)
			{
				printf("Cannot write Perl source to: '%s'\n", codefile);
				return;
			}
			if(!fork())
			{
				close(1); dup2(fd,1);
				close(2); dup2(1,2);
				execve(args[0], args, environ);
				printf("Could not exec Perl script\n");
				close(fd);
				unlink(outfile);
				exit(2);
			}
			wait(&status);
			
			if(status == 255)
			{
				printf("Code error in script %s\n", file);
				exit(1);
			}
			
			cache_output_add(outfile, file);
			cache_print(file);
		}
		else {
			if(!fork())
			{
				close(2); dup2(1,2);
				execve(args[0], args, environ);
				exit(1);
			}
			wait(0);
		}
		if(cacherule) cache_exec_add(codefile, file);
		else unlink(codefile);
		exit(0);
	}
}

void cache_exec(char *path, char *tmp)
{
	char full_path[PATH_STRING_LEN];
	char output[PATH_STRING_LEN];
	int fd;
	int bytes;
	
	bytes = snprintf(full_path, PATH_STRING_LEN, "%s/%s/%s", tmp, CACHE_DIR_EXE, path);
	if(bytes >= PATH_STRING_LEN) {
		printf("Perl script file path too long\n");
		return;
	}
	
	args[1] = full_path;
	
	if(cache && (cacherule == CACHERULE_TIME || cacherule == CACHERULE_NOINPUT && !strcmp("", getenv("ARGS"))))
	{
		bytes = snprintf(output, PATH_STRING_LEN, "%s/%s.%d.%d", tmp, path, time(0), rand());
		if(bytes >= PATH_STRING_LEN) {
			printf("HTML output file path too long\n");
			return;
		}
		if(!fork())
		{
			fd = open(output, O_WRONLY | O_CREAT, S_IRUSR);
			if(fd){ close(1); dup2(fd,1);}
			close(2); dup2(1,2);
			execve(args[0], args, environ);
			perror("Could not exec Perl script file\n");
			close(fd);
			unlink(output);
			exit(1);
		}
		wait(0);
		cache_output_add(output, path);
		cache_print(path);
		exit(0);
	}
	else {
		close(2); dup2(1,2);
		execve(args[0], args, environ);
		perror("Could not exec Perl script\n");
		exit(1);
	}
}
