
/* PRI, by Ali T. Ozer (ARPA: ali@score.stanford.edu)
** Written April 1988. Freely distributable.
** 
** Usage: pri <pri> <process>
** 
** Sets the priority of the specified process to pri. These have to be CLI
** processes; pri won't change the prioirity of programs started from the WB.
*/

#include <libraries/dosextens.h>

struct DosLibrary *DosBase, *OpenLibrary();
struct FileHandle *Output();

#define ILLEGALNUM (-9999)  

void Bye (msg) char *msg; {
  struct FileHandle *out;
  if (msg && (out = Output())) Write (out, msg, (long)strlen(msg));
  if (DosBase) CloseLibrary (DosBase);
  exit (msg ? 5 : 0);
}

/* Parse a signed integer. Return ILLEGALNUM on parse error.
*/
int myatoi (str) char *str; {
  int sign = 1, num = 0;
  if (*str == '-') {str++; sign = -1;} else if (*str == '+') str++;
  while (*str) 
    if (*str < '0' || *str > '9') return (ILLEGALNUM);
    else num = num * 10 - '0' + (*str++);
  return (sign * num);
}

main (argc, argv) int argc; char **argv;
{
  int prn, pri;  /* Process number and new desired priority */
  struct RootNode *rn;
  long *lptr;

  if (argc == 0) Bye (NULL);  /* Don't run from Workbench */

  if (((DosBase = OpenLibrary ("dos.library", 0L)) == NULL) ||
      ((rn = (struct RootNode *)DosBase->dl_Root) == NULL) ||
      ((lptr = (long *)((rn->rn_TaskArray) << 2L)) == NULL)) Bye ("DOS?\n");

  /* Now parse the arguments. We need two arguments, first the priority 
  ** (-128..127), and second, the process number (1..Max# of CLIs allowed).
  */

  if (argc != 3) Bye ("Set the priority of CLI process to pri\nUsage: pri <pri> <process>\n");
  if ((pri = myatoi(argv[1])) > 127 || pri < -128) Bye ("Bad priority\n");
  prn = myatoi(argv[2]);

  /* At this stage, lptr points to AmigaDOS's array of CLIs. The first element
  ** in this array is the maximum number of CLIs allowed. Then follows this
  ** many pointers, which, if not NULL, point to CLI processes. (Actually,
  ** they do not point to the process. A process is simply an Amiga 
  ** Task structure, followed by an Amiga MsgPort structure, and then
  ** followed other stuff. These pointers point to the MsgPort structure.
  ** Thus, to get to the task structure (so we can SetTaskPri()), we'll need
  ** to subtract the size of the task structure from the MsgPort pointer.)
  */

  Forbid();
  if ((prn > 0) && ((long)prn <= *lptr) && *(lptr+prn))
    SetTaskPri ((struct Task *)(*(lptr+prn) - sizeof(struct Task)), (long)pri);
    else Bye ("No such process\n");
  Permit();
}
   
