/*
 * kill.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "kernel.h"


const int taskword = 0x4b534154;
int taskhandle = -1;

typedef struct
{
	int handle;
	int taskname;
	int slotsize;
	int tasktype;
} taskblock;

typedef struct
{
	int block_length;
	int sender_handle;
	int my_ref;
	int your_ref;
	int message_code;
} message_header;



void error( int n, char *m )
{
	_kernel_swi_regs r;
	_kernel_oserror e;

	e.errnum = n;
	strcpy (e.errmess, m);

	r.r[0] = (int) &e;
	r.r[1] = 2 | 16;
	r.r[2] = (int) "Suddenly, whilst killing...";
	_kernel_swi( 0x400df, &r, &r );
}
 


void initialise(void)
{
	_kernel_swi_regs r;
	_kernel_oserror *e;

	r.r[0] = 200;
	r.r[1] = taskword;
	r.r[2] = (int) "kill utility task";

	e = _kernel_swi( 0x400c0, &r, &r );

	if (e)
	{
		/* error( e->errnum, e->errmess ); */
	}
	else
	{
		taskhandle = r.r[1];
	}
}


void closedown(void)
{
	_kernel_swi_regs r;

	r.r[0] = taskhandle;
	r.r[1] = taskword;
	if (taskhandle!=-1) { _kernel_swi( 0x400dd, &r, &r ); }
}

int ciscmp(char *a, char *b)
{
	while (!iscntrl(*a))
	{
		if (tolower(*a)!=tolower(*b)) { return 1; }
		a++; b++;
	}

	return (!iscntrl(*b));
}

int cscmp(char *a, char *b)
{
	while (!iscntrl(*a))
	{
		if (*a!=*b) { return 1; }
		a++; b++;
	}

	return (!iscntrl(*b));
}





int task_handle( char *taskname, int casesensitive )
{
	taskblock buffer[256];
	_kernel_swi_regs r;
	int tasksenumd;
	int handle = -1;
	int i;
	char *name;

	r.r[0] = 0;

	while ( r.r[0] != -1 )
	{
		r.r[1] = (int) buffer;
		r.r[2] = 256 * 4 * 4;
		_kernel_swi ( 0x42681, &r, &r );
		tasksenumd = (256*4*4-r.r[2]) / (4*4);
		for ( i=0; i<tasksenumd; i++ )
		{
			name = (char*) buffer[i].taskname;
			if (casesensitive)
			{
				if ( cscmp(taskname,name)==0 )
				{
					handle = buffer[i].handle;
					r.r[0] = -1;
				}
			}
			else
			{
				if ( ciscmp(taskname,name)==0 )
				{
					handle = buffer[i].handle;
					r.r[0] = -1;
				}
			}
		}
	}

	return handle;
}




void killtask( char *name, int csf )
{
	int handle;
	_kernel_swi_regs r;
	_kernel_oserror *e;
	message_header block;

	block.block_length = 20;
	block.sender_handle = taskhandle;
	block.message_code = 0;

	handle = task_handle( name, csf );
	if ( handle!=-1 )
	{
		r.r[0] = 17;
		r.r[1] = (int) &block;
		r.r[2] = handle;
		e = _kernel_swi( 0x400e7, &r, &r );
		if (e)
		{
			error (e->errnum,e->errmess);
			exit(2);
		}
	}
}


int main ( int argc, char *argv[] )
{
	int i;
	int case_sensitive_flag = 1;

	initialise();

	for (i=1; i<argc; i++)
	{
		if ( argv[i][0] == '-' )
		{
			switch ( argv[i][1] )
			{
				case 'i' : case 'I' : case_sensitive_flag = 0; break;
				case 'c' : case 'C' : case_sensitive_flag = 1; break;
				default :
					error ( 0, "bad flag" );
					exit(1);
			}
		}
		else
		{
			killtask(argv[i],case_sensitive_flag);
		}
	}

	closedown();

	return 0;
}
