home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / attpc.renice / renice.c < prev   
Encoding:
C/C++ Source or Header  |  1988-01-31  |  4.8 KB  |  248 lines

  1. /************************************************************
  2.  *
  3.  * This program was written by me, Mike "Ford" Ditto, and
  4.  * I hereby release it into the public domain in the interest
  5.  * of promoting the development of free, quality software
  6.  * for the hackers and users of the world.
  7.  *
  8.  * Feel free to use, copy, modify, improve, and redistribute
  9.  * this program, but keep in mind the spirit of this
  10.  * contribution; always provide source, and always allow
  11.  * free redistribution (shareware is fine with me).  If
  12.  * you use a significant part of this code in a program of
  13.  * yours, I would appreciate being given the appropriate
  14.  * amount of credit.
  15.  *                -=] Ford [=-
  16.  *
  17.  ************************************************************/
  18.  
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <ctype.h>
  22. #include <errno.h>
  23. #include <pwd.h>
  24. #include <grp.h>
  25. #include <sys/types.h>
  26. #include <sys/param.h>
  27. #include <sys/tune.h>
  28. #include <sys/proc.h>
  29. #include <nlist.h>
  30.  
  31.  
  32. extern long lseek();
  33. extern void perror(), exit();
  34.  
  35.  
  36. void kcopy(), kwrite();
  37.  
  38. char *progname;
  39.  
  40. #define tuhiaddr (mysyms[0].n_value)
  41. #define procaddr (mysyms[1].n_value)
  42.  
  43. struct nlist mysyms[] =
  44. {
  45.     { "tuhi", },
  46.     { "proc", },
  47.     { (char *)0, },
  48. };
  49.  
  50. char buf[BUFSIZ];
  51.  
  52. int kmem;
  53. int myuid;
  54. int NPROC;
  55. static struct proc proc;
  56.  
  57.  
  58. void usage()
  59. {
  60.     fprintf(stderr,
  61.         "usage:    %s [{+-}inc] [=prio] pid ...\n", progname);
  62.     exit(-1);
  63. }
  64.  
  65.  
  66. main(argc, argv)
  67. int argc;
  68. char *argv[];
  69. {
  70.     int status=0;
  71.     int pid, relative, value;
  72.  
  73.     progname = *argv;
  74.  
  75.     setup();
  76.  
  77.     relative = 1;
  78.     value = 5;
  79.  
  80.     while (++argv,--argc)
  81.     switch (argv[0][0])
  82.     {
  83.     case '-':
  84.         if (sscanf(argv[0]+1, "%d", &value) != 1)
  85.         usage();
  86.         relative = 1;
  87.         break;
  88.     case '+':
  89.         if (sscanf(argv[0]+1, "%d", &value) != 1)
  90.         usage();
  91.         value = -value;
  92.         relative = 1;
  93.         break;
  94.     case '=':
  95.         if (sscanf(argv[0]+1, "%d", &value) != 1)
  96.         usage();
  97.         relative = 0;
  98.         break;
  99.     default:
  100.         if (sscanf(argv[0], "%d", &pid) != 1)
  101.         usage();
  102.         status += renice(pid, value, relative);
  103.     }
  104.  
  105.     return status;
  106. }
  107.  
  108.  
  109. /* one-time setup of main data structures from the kernel */
  110. setup()
  111. {
  112.     struct tunable tune;
  113.  
  114.     if ( (kmem=open("/dev/kmem", O_RDWR)) < 0 )
  115.     {
  116.     sprintf(buf, "%s: can't open /dev/kmem", progname);
  117.     perror(buf);
  118.     exit(1);
  119.     }
  120.  
  121.     if (nlist("/unix", mysyms))
  122.     {
  123.     sprintf(buf, "%s: can't nlist /unix", progname);
  124.     perror(buf);
  125.     exit(1);
  126.     }
  127.  
  128.     myuid = getuid();
  129.     setuid(myuid);
  130.  
  131. #ifdef DEBUG
  132.     fprintf(stderr, "tuhi:    0x%08lx\n", tuhiaddr);
  133. #endif DEBUG
  134.     kcopy((char *)&tune, tuhiaddr, (long) sizeof tune);
  135.  
  136.     /* do indirection on the proc address, since it */
  137.     /* is just a pointer in the kernel */
  138.     kcopy((char *)&procaddr, procaddr, (long) sizeof procaddr);
  139.  
  140. #ifdef DEBUG
  141.     fprintf(stderr, "proc:    0x%08lx\n", procaddr);
  142. #endif DEBUG
  143.  
  144.     NPROC = tune.nproc;
  145.  
  146. #ifdef DEBUG
  147.     fprintf(stderr, "NPROC:    %d\n", NPROC);
  148. #endif DEBUG
  149. }
  150.  
  151.  
  152. /* copy bytes from kernel address space to this process */
  153. void kcopy(caddr, kaddr, nbytes)
  154. char *caddr;
  155. long kaddr;
  156. long nbytes;
  157. {
  158.     if ( lseek(kmem, kaddr, 0)<0L ||
  159.     read(kmem, caddr, (unsigned)nbytes) != nbytes )
  160.     {
  161.     sprintf(buf, "%s: can't read /dev/kmem", progname);
  162.     perror(buf);
  163.     exit(1);
  164.     }
  165. }
  166.  
  167.  
  168. /* write bytes from this process' address space to the kernel's */
  169. void kwrite(kaddr, caddr, nbytes)
  170. long kaddr;
  171. char *caddr;
  172. long nbytes;
  173. {
  174. #ifdef DEBUG
  175.     fprintf(stderr, "Writing %ld bytes to kernel address 0x%08lx\n",
  176.         nbytes, kaddr);
  177. #endif
  178.  
  179.     if ( lseek(kmem, kaddr, 0)<0L ||
  180.     write(kmem, caddr, (unsigned)nbytes) != nbytes )
  181.     {
  182.     sprintf(buf, "%s: can't write /dev/kmem", progname);
  183.     perror(buf);
  184.     exit(1);
  185.     }
  186. }
  187.  
  188.  
  189. /* change the nice value of process `pid' based on 'value' and 'relative' */
  190. renice(pid, value, relative)
  191. int pid, value, relative;
  192. {
  193.     register i;
  194.     int tmpnice;
  195.  
  196.     for ( i=0 ; i<NPROC ; ++i )
  197.     {
  198.     kcopy((char *)&proc,
  199.           (long)&((struct proc *)procaddr)[i],
  200.           (long)sizeof proc);
  201.     if ( proc.p_pid == pid )
  202.     {
  203. #ifdef DEBUG
  204.         fprintf(stderr, "Found it!  proc[%d], p_uid is %d\n",
  205.            i, proc.p_uid);
  206.  
  207.         fprintf(stderr, "Old p_nice was %d\n", proc.p_nice);
  208. #endif DEBUG
  209.  
  210.         tmpnice = proc.p_nice;
  211.  
  212.         if (relative)
  213.         tmpnice += value;
  214.         else
  215.         tmpnice = value;
  216.  
  217.         if (tmpnice >= 40)
  218.         tmpnice = 40;
  219.         if (tmpnice < 0)
  220.         tmpnice = 0;
  221.  
  222. #ifdef DEBUG
  223.         fprintf(stderr, "New p_nice is %d\n", tmpnice);
  224. #endif DEBUG
  225.  
  226.         if ( myuid && (myuid != proc.p_uid || tmpnice<proc.p_nice) )
  227.         {
  228.         errno = EACCES;
  229.         sprintf(buf, "%s: can't renice process %d", progname, pid);
  230.         perror(buf);
  231.         return 1;
  232.         }
  233.  
  234.         proc.p_nice = tmpnice;
  235.  
  236.         kwrite((long)&((struct proc *)procaddr)[i]
  237.            + ( ((char *)&proc.p_nice) - (char *)&proc ),
  238.            (char *)&proc.p_nice,
  239.            (long)sizeof proc.p_nice);
  240.         return 0;
  241.     }
  242.     }
  243.  
  244.     fprintf(stderr, "%s: process %d not found.\n", progname, pid);
  245.  
  246.     return 1;
  247. }
  248.