/*

  rt.c

  Runs process on realtime priority.

  $Id$

  */

# include <stdio.h>
# include <sched.h>
# include <unistd.h>
# include <stdlib.h>
# include <errno.h>

void Usage( void )
{
	fprintf( stderr,
			 "Usage: rt [options] command\n"
			 "\n"
			 "Recognized options are:\n"
			 "\t-r   Use SCHED_RR scheduling policy (default);\n"
			 "\t-f   Use SCHED_FIFO scheduling policy;\n"
			 "\t-p N Set priority level N. If N<0, set priority level\n"
			 "\t      to sched_get_priority_min(POLICY)-N.\n"
			 "\t      Default is (sched_get_priority_max()+sched_get_priority_min())/2;\n"
			 "\t--   End of options;\n"
			 "\t-v   Be verbose;\n"
			 "\t-h   This help screen.\n"
		);
}

main( int argc, char *argv[] )
{
   struct sched_param param;
   int opt, policy = SCHED_RR, priority = 0, verbose = 0;
   char **argv_;
   int i;

   if ( argc == 1 ) {
      Usage();
      return 1;
   }

   for (i=1;i<argc;i++)
     {
	if (!strncmp(argv[i],"-",1))
	  {
	     if (argv[1][i]=='f') 
	       {
		  policy = SCHED_FIFO;
	       }
	     else if (argv[1][i]=='r')
	       {
		  policy = SCHED_RR;
	       }
	     else if (argv[1][i]=='p')
	       {
		  priority = atoi(argv[i++]);
	       }
	     else if (argv[1][i]=='v')
	       {
		  verbose = 1;
	       }
	     else
	       {
		  Usage();
		  return 1;
	       }
	  }
	else
	  {
	     optind=i;
	     i=argc;
	     break;
	  }
     }
   
   if ( optind >= argc ) 
     {
	Usage();
	return 1;
     }
   
   
     {
	int prio_min = sched_get_priority_min( policy );
	int prio_max = sched_get_priority_max( policy );
	if ( priority == 0 )
	  priority = ( prio_min + prio_max ) / 2;
	else {
	   if ( priority < 0 )
	     priority = prio_min - priority;
	   if ( priority < prio_min || priority > prio_max ) {
	      fprintf( stderr, "Bad priority value, should be %d..%d\n",
		      prio_min, prio_max );
	      return 1;
	   }
	}
     }
   
   param.sched_priority = priority;
   
   if ( verbose )
     fprintf( stderr, "Starting %s with policy %s, priority %d.\n",
	     argv[ optind ], policy == SCHED_RR ? "SCHED_RR" :
	     "SCHED_FIFO", priority );
   
   if ( sched_setscheduler( getpid(), policy, &param ) ) {
      perror( "sched_setscheduler" );
		return 1;
   }
   argv_=(char **)malloc(2+argc-optind);
   argv_[1+argc-optind]=NULL;
   for (i=0;i<1+argc-optind;i++)
     argv_[i]=argv[i+optind];
   setuid(getuid());
   execvp( argv[ optind ], argv_ );
   fprintf( stderr, "Can't exec %s: %s\n", argv[ optind ],
	   sys_errlist[ errno ] );
   return 1;
}


