





























#include <stdio.h>
#include <pwd.h>
#include <errno.h>
#include <ctype.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/file.h>
#include "except.h"
#include "proc.h"
#include "debug.h"
#include "expr.h"
#include "sched.h"
#include "trace.h"

#ifdef NDBM
#include <ndbm.h>
#else NDBM
#include "ndbm_fake.h"
#endif NDBM

static char *_FileName_ = __FILE__;		/* Used by EXCEPT (see except.h)     */

#define STAR	-1

DBM		*Q, *OpenJobQueue();

char	*param();
char	*MyName;
char	*Spool;
XDR		*xdr_Init();

PROC_ID	List[2000];
int		N_Elem;
char	*UserName;
int		All;

int		PrioAdjustment;
int		NewPriority;
int		PrioritySet;
int		AdjustmentSet;

#define MIN_PRIO -20
#define MAX_PRIO 20

usage()
{
	fprintf( stderr, "Usage: %s [{+|-}priority ] [-p priority] [ -a ] [user] [ cluster[.proc] ... ]\n",
																MyName );
	exit( 1 );
}

main( argc, argv)
int		argc;
char	*argv[];
{
	char	queue_name[MAXPATHLEN];
	char	*arg;
	int		gather_all(), gather_user();
	int		change_prio();
	int		i;
	int		prio_adj;

	MyName = argv[0];

	config( MyName, (CONTEXT *)0 );
	init_params();

	if( argc < 2 ) {
		usage();
	}

	PrioritySet = 0;
	AdjustmentSet = 0;

	for( argv++; arg = *argv; argv++ ) {
		if( arg[0] == '-' && arg[1] == 'a' ) {
			All = 1;
		} else if( (arg[0] == '-' || arg[0] == '+') && isdigit(arg[1]) ) {
			PrioAdjustment = compute_adj(arg);
			AdjustmentSet = TRUE;
		} else if( arg[0] == '-' && arg[1] == 'p' ) {
			argv++;
			NewPriority = atoi(*argv);
			PrioritySet = TRUE;
		} else if( isdigit(arg[0]) ) {
			add_to_list( arg );
		} else {
			UserName = arg;
		}
	}

	if( PrioritySet == FALSE && AdjustmentSet == FALSE ) {
		fprintf( stderr, 
			"You must specify a new priority or priority adjustment.\n");
		usage();
		exit(1);
	}

	if( PrioritySet && (NewPriority < MIN_PRIO) || (NewPriority > MAX_PRIO) ) {
		fprintf( stderr, 
			"Invalid priority specified.  Must be between %d and %d.\n", 
			MIN_PRIO, MAX_PRIO );
		exit(1);
	}

		/* Open job queue */
	(void)sprintf( queue_name, "%s/job_queue", Spool );
	if( (Q=OpenJobQueue(queue_name,O_RDWR,0)) == NULL ) {
		EXCEPT( "OpenJobQueue(%s)", queue_name );
	}

	LockJobQueue( Q, WRITER );

	if( All ) {
		ScanJobQueue( Q, gather_all );
	}

	if( UserName ) {
		ScanJobQueue( Q, gather_user );
	}

	for( i=0; i<N_Elem; i++ ) {
		if( check_permission(List[i].cluster) == FALSE ) {
			continue;
		}

		if( List[i].proc == STAR ) {
			ScanCluster( Q, List[i].cluster, change_prio );
		} else {
			change_prio_proc( &List[i] );
		}
	}

	exit( 0 );
}

set_new_prio( proc )
PROC *proc;
{
	if( AdjustmentSet == TRUE && PrioritySet == FALSE ) {
		proc->prio += PrioAdjustment;
		if( proc->prio > MAX_PRIO )
			proc->prio = MAX_PRIO;
		else if( proc->prio < MIN_PRIO )
			proc->prio = MIN_PRIO;
	} else {
		proc->prio = NewPriority;
	}
}

/*
** Change prio for a particular process.
*/
change_prio_proc( pid )
PROC_ID	*pid;
{
    PROC	proc;

    proc.id.cluster = pid->cluster;
    proc.id.proc = pid->proc;

    if( FetchProc(Q,&proc) != 0 ) {
		printf( "Process %d.%d doesn't exist\n",
	       proc.id.cluster, proc.id.proc );
		return -1;
    }

	set_new_prio( &proc );

    if( StoreProc(Q,&proc) != 0 ) {
		EXCEPT( "Can't store process struct %d.%d\n",
	       proc.id.cluster, proc.id.proc );
    }

    return 0;
}

compute_adj( arg )
char *arg;
{
	char *ptr;
	int val;
	
	ptr = arg+1;

	val = atoi(ptr);

	if( *arg == '-' ) {
		return( -val );
	} else {
		return( val );
	}
}

SetSyscalls( foo )
int		foo;
{
	return foo;
}

add_to_list( arg )
char	*arg;
{
	char	*p, *index();
	int		cluster, proc;

	if( p=index(arg,'.') ) {
		cluster = atoi( arg );
		proc = atoi( ++p );
	} else {
		cluster = atoi( arg );
		proc = STAR;
	}

	if( cluster < 1 || proc < STAR )
		usage();

	List[N_Elem].cluster = cluster;
	List[N_Elem].proc = proc;
	N_Elem += 1;
}

change_prio( proc )
PROC *proc;
{
	set_new_prio( proc );

	if( StoreProc( Q, proc ) < 0) {
		EXCEPT( "change_prio: couldn't StoreProc, proc id = %d.%d\n",
			proc->id.cluster, proc->id.proc);
	}
}

gather_all( proc )
PROC	*proc;
{
	List[N_Elem].cluster = proc->id.cluster;
	List[N_Elem].proc = proc->id.proc;
	N_Elem += 1;
}

gather_user( proc )
PROC	*proc;
{
	if( strcmp(proc->owner,UserName) == MATCH ) {
		List[N_Elem].cluster = proc->id.cluster;
		List[N_Elem].proc = proc->id.proc;
		N_Elem += 1;
	}
}

check_permission( cluster )
int		cluster;
{
	PROC	proc;
	struct passwd	*pwd, *getpwuid();
	int		uid;

	proc.id.cluster = cluster;
	proc.id.proc = 0;

	if( FetchProc(Q,&proc) != 0 ) {
		printf( "Cluster %d: Doesn't Exist\n", cluster );
		return FALSE;
	}

	uid = getuid();

	if( uid == 0 )
		return TRUE;

	if( (pwd=getpwuid(uid)) == NULL ) {
		EXCEPT( "Can't find password entry for user %d\n", uid );
	}

	if( strcmp(pwd->pw_name,proc.owner) == MATCH ) {
		return TRUE;
	} else {
		printf( "Cluster %d: Permission Denied\n", cluster );
		return FALSE;
	}
}

init_params()
{
	Spool = param("SPOOL");
	if( Spool == NULL ) {
		EXCEPT( "SPOOL not specified in config file\n" );
	}
}
