/*
 * C P R I :	This allows you to muck around with the priorities of 
 *		running AmigaDOS processes.
 */

#include	<stdio.h>
#include	<ctype.h>
#include	<libraries/dos.h>
#include	<libraries/dosextens.h>
#include	<exec/tasks.h>

/* Externs */
extern struct DosLibrary *DOSBase;	/* dos library base pointer */
extern struct FileLock	 *Output();	/* get output file handle */
extern	short		 SetTaskPri();	/* sets priority for specified task */

/* Globals */
static struct FileLock	 *OutLock;	/* used by WSTR define */

/* Defines */

/* Use AmigaDOS i/o to keep executable size down */
#define WSTR(s)		 (void)Write(OutLock, s, (long)strlen(s))

/* Casting conveniences */
#define ROOTNODE	((struct RootNode *)DOSBase->dl_Root)

main(argc, argv)
int	argc;
char	**argv;
{
	void		usage();
	char		*pris = argv[1];
	int		sign  = 1;
	long		pri, atol();
	struct Task 	*tcb;
	unsigned long   *tt, procnum;
	struct   Task	*task;
	UBYTE		*port;

	OutLock = Output();
					
	if (argc != 3) usage();

	/* Handle any leading + or - sign */
	if (*pris == '+') {
		pris++;
	} else if (*pris == '-') {
		pris++;
		sign = -1;
	}
	
	/* What's left must be a digit string */
	if (*pris == '\0' || (!isdigstr(pris)) ) usage();
	
	pri = atol(pris) * sign;		/* got the priority */

	/* Bound check the priority */
	if (pri	< -128 || pri > 127) {
		WSTR("Bad priority: range is -128 to 127\n");
		exit(20);
	}
	
	/* The second parameter should be a CLI procnum */
	if ( !isdigstr(argv[2]) ) usage();
	
	procnum = atol(argv[2]);
	tt = (unsigned long *)(BADDR(ROOTNODE->rn_TaskArray));

	/* Validate with range check */
	if (procnum > tt[0] || tt[procnum] == 0L) {
		WSTR("Invalid process number\n");
		exit(20);
	}

	Forbid();	/* task mustn't go away while we fiddle with it */
	port = (UBYTE *)tt[procnum];
	tcb = (struct Task *)(port - sizeof(struct Task));

	/* Now we have a task, let's set its priority */
	(void)SetTaskPri(tcb, pri);	
	Permit();
}

void
usage()
{
	WSTR("usage: cpri [+/-]priority CLI-process-number\n");
	exit(20);
}

isdigstr(s)
char	*s;
{
	register char	*p;
	
	for(p =s ; *p != '\0'; p++)
		if (!isdigit(*p) )
			return 0;
	return 1;
}
