/* panteltje uirc internet relay chat client */
/*    Copyright (C) 1996  <Panteltje>
/* email: pante@pi.net
/* snail mail: PO BOX 61  SINT ANNA  9076ZP HOLLAND

    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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "uirc.h"

extern fd_set readfs;

struct execs
	{
	char *text;
	FILE *filefd;
	char *arguments;
	char *nick;
	char *mode;
	time_t timer;
	struct execs *nxtentr;
	};
static struct execs *execstab[1];


struct execs *lookup_execs_text(char *text)
{
struct execs *pa;

/*pa points to next entry*/
for(pa = execstab[0]; pa != 0; pa = pa -> nxtentr)
	{
	if(strcmp(pa -> text, text) == 0) return(pa);/* found it */
	}
return(0);/*not found*/
}


struct execs *install_execs_text(char *text)
{
struct execs *pa, *lookup_execs_text();
char *strsave();
char *malloc();

pa = lookup_execs_text(text);

if(!pa)	/* not found */
	{
	pa = (struct execs *)malloc(sizeof(*pa));
	if(!pa) return(0);
	pa -> text = strsave(text);
	if(! pa -> text) return(0);
	pa -> nxtentr = execstab[0];
	execstab[0] = pa;
	return(pa);
	}
return(0);
}


int delete_execs_text(char *text)
{
struct execs *pa, *pprev;/* pa points to next entry */
int i;
char temp[80];

pa = execstab[0];
i = 0;
if(! pa)return(0);/* no entry */
while(1)/* for all structures */
	{
	if(strcmp(pa -> text, text) == 0)
		{
		if(i == 0)/* first entry */
			{
			execstab[0] = pa -> nxtentr;
			}
		else/* not first one */
			{
			pprev -> nxtentr = pa -> nxtentr;
			}
		free(pa -> text);/* free name */
		free(pa -> arguments);
		free(pa -> mode);
		free(pa -> nick);
		free(pa);/* free structure */
		return(1);
		}/* end found */
	pprev = pa;/* save this pointer */
	pa = pa -> nxtentr;
	if(! pa) return(0);/* end of chain of structures */
	i++;
	}/* end while all structures */ 
return(0);/* not found */
}/* end function delete_dcc_nick */


int read_line_from_stream(FILE *stream, char *contents)
{
int c, i;

for(i = 0; i < 512; i++)
	{
	c = getc(stream);
	if(c == EOF)
		{
		contents[i] = 0;/* EOF marker */
		return(EOF);
		}
	if(c == '\n')
		{
		contents[i] = 0;/* EOF marker */
		return(1);/* end of line */
		}
	contents[i] = c;
	}
return(1);/* line overflow */
}


int write_data (FILE *stream)
{
int i;
for (i = 0; i < 100; i++)
fprintf (stream, "%d\n", i);
if (ferror (stream))
	{
	fprintf (stderr, "Output to stream failed.\n");
	exit (EXIT_FAILURE);
	}
}


int read_data(FILE *stream)
{
int c;

while(1)
	{
	c = getc(stream);
	if(c == EOF) break;
	fprintf(stdout, "%c", c);
	}
}


do_exec(char *text, int socketfd)
{
char temp[512];
char temp2[512];
char arguments[512];
int a, i;
char arg0[512], arg1[512], arg2[512];
char uarg0[512];     
struct execs *pa;
extern char *strsave();

/* set arguments empty */
arg0[0] = 0;
arg1[0] = 0;
arg2[0] = 0;

/* parse the user text */
sscanf(text, "%s %s %s", arg0, arg1, arg2);

/* if the first field is an flag extract the command and argunments */

/* convert arg0 to upper case in uarg0 */
for(i = 0; i < 40; i++)
	{
	uarg0[i] = toupper(arg0[i]);
	if(arg0[i] == 0) break;/* string terminator */
	}

/* mode select */
if(uarg0[0] != '-')/* just plain command with arguments */
	{
	sprintf(arguments, "%s", text);
	}
else
	{
	sprintf(arguments, "%s", strstr(text, arg2) );
	}

pa = install_execs_text(text);
if(! pa)
	{
	sprintf(temp, "do_exec:  Cannot install %s", text);
	to_screen(temp, "");
	return(0);
	}
pa -> arguments = strsave(arguments);
if(! pa -> arguments)
	{
	sprintf(temp, "do_exec:  Cannot install arguments %s", arguments);
	to_screen(temp, "");
	delete_execs_text(text);
	return(0);
	}
pa -> nick = strsave(arg1);
if(! pa -> nick)
	{
	sprintf(temp, "do_exec:  Cannot install nick %s", arg1);
	to_screen(temp, "");
	delete_execs_text(text);
	return(0);
	}
pa -> mode = strsave(uarg0);
if(! pa -> mode)
	{
	sprintf(temp, "do_exec:  Cannot install mode %s", uarg0);
	to_screen(temp, "");
	delete_execs_text(text);
	return(0);
	}
pa -> filefd = popen(arguments, "r");
if( !pa -> filefd)
	{
	sprintf(temp, "Cannot run %s", text);
	to_screen(temp,"");
	delete_execs_text(text);
	return(1);
	}
pa -> timer = time(0);
return(1);
}/* end function do_exec */


int set_all_exec_filedescriptors()
{
struct execs *pa;

for(pa = execstab[0]; pa != 0; pa = pa -> nxtentr)
	{
	FD_SET(fileno(pa -> filefd), &readfs);
	}

return(1);
}


int exec_read_write_all_data(int socketfd)
{
int a;
char temp[512];
char temp2[512];
char nick[80];
struct execs *pa;
extern long exec_delay;

for(pa = execstab[0]; pa != 0; pa = pa -> nxtentr)
	{
	/* if not local screen use flood prevention delay setting */
	if(strcmp(pa -> mode, "-MSG") == 0)
		{
		if(time(0) - pa -> timer < exec_delay) break;
		}

	/* read ONE line from the process */
	a = read_line_from_stream(pa -> filefd, temp);	

	/* check for end of file */
	if(a == EOF)
		{
		FD_CLR(fileno(pa -> filefd), &readfs);
		pclose(pa -> filefd);

		/* delete structure */
		delete_execs_text(pa -> text);	
		return(1);
		}
	
	if(pa -> mode[0] != '-')/* local screen only */
		{
		/* echo show what is send */
		to_screen(temp, "");
		}
	else if(strcmp(pa -> mode, "-MSG") == 0)/* to nick or channel */
		{
		/* send to server */
		sprintf(temp2, "PRIVMSG %s :%s\n", pa -> nick, temp);

		if(! send_to_server(socketfd, temp2) )
			{
			to_screen("do_exec: SEND TO SERVER RETURNED 0" ,"");
			return(0);
			}

		/* echo show what is send */
		to_screen(temp, "");

		/* reset timer */
		pa -> timer = time(0);
		}/* end if -msg */
	else if(strcmp(pa -> mode, "-IN") == 0)
		{
		}
	else if(strcmp(pa -> mode, "-OUT") == 0)
		{
		}	
	}/* end for all structures */
return(1);
}
