home *** CD-ROM | disk | FTP | other *** search
- /************************************************************
- *
- * This program was written by me, Mike "Ford" Ditto, and
- * I hereby release it into the public domain in the interest
- * of promoting the development of free, quality software
- * for the hackers and users of the world.
- *
- * Feel free to use, copy, modify, improve, and redistribute
- * this program, but keep in mind the spirit of this
- * contribution; always provide source, and always allow
- * free redistribution (shareware is fine with me). If
- * you use a significant part of this code in a program of
- * yours, I would appreciate being given the appropriate
- * amount of credit.
- * -=] Ford [=-
- *
- ************************************************************/
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <errno.h>
- #include <pwd.h>
- #include <grp.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/tune.h>
- #include <sys/proc.h>
- #include <nlist.h>
-
-
- extern long lseek();
- extern void perror(), exit();
-
-
- void kcopy(), kwrite();
-
- char *progname;
-
- #define tuhiaddr (mysyms[0].n_value)
- #define procaddr (mysyms[1].n_value)
-
- struct nlist mysyms[] =
- {
- { "tuhi", },
- { "proc", },
- { (char *)0, },
- };
-
- char buf[BUFSIZ];
-
- int kmem;
- int myuid;
- int NPROC;
- static struct proc proc;
-
-
- void usage()
- {
- fprintf(stderr,
- "usage: %s [{+-}inc] [=prio] pid ...\n", progname);
- exit(-1);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int status=0;
- int pid, relative, value;
-
- progname = *argv;
-
- setup();
-
- relative = 1;
- value = 5;
-
- while (++argv,--argc)
- switch (argv[0][0])
- {
- case '-':
- if (sscanf(argv[0]+1, "%d", &value) != 1)
- usage();
- relative = 1;
- break;
- case '+':
- if (sscanf(argv[0]+1, "%d", &value) != 1)
- usage();
- value = -value;
- relative = 1;
- break;
- case '=':
- if (sscanf(argv[0]+1, "%d", &value) != 1)
- usage();
- relative = 0;
- break;
- default:
- if (sscanf(argv[0], "%d", &pid) != 1)
- usage();
- status += renice(pid, value, relative);
- }
-
- return status;
- }
-
-
- /* one-time setup of main data structures from the kernel */
- setup()
- {
- struct tunable tune;
-
- if ( (kmem=open("/dev/kmem", O_RDWR)) < 0 )
- {
- sprintf(buf, "%s: can't open /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
-
- if (nlist("/unix", mysyms))
- {
- sprintf(buf, "%s: can't nlist /unix", progname);
- perror(buf);
- exit(1);
- }
-
- myuid = getuid();
- setuid(myuid);
-
- #ifdef DEBUG
- fprintf(stderr, "tuhi: 0x%08lx\n", tuhiaddr);
- #endif DEBUG
- kcopy((char *)&tune, tuhiaddr, (long) sizeof tune);
-
- /* do indirection on the proc address, since it */
- /* is just a pointer in the kernel */
- kcopy((char *)&procaddr, procaddr, (long) sizeof procaddr);
-
- #ifdef DEBUG
- fprintf(stderr, "proc: 0x%08lx\n", procaddr);
- #endif DEBUG
-
- NPROC = tune.nproc;
-
- #ifdef DEBUG
- fprintf(stderr, "NPROC: %d\n", NPROC);
- #endif DEBUG
- }
-
-
- /* copy bytes from kernel address space to this process */
- void kcopy(caddr, kaddr, nbytes)
- char *caddr;
- long kaddr;
- long nbytes;
- {
- if ( lseek(kmem, kaddr, 0)<0L ||
- read(kmem, caddr, (unsigned)nbytes) != nbytes )
- {
- sprintf(buf, "%s: can't read /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
- }
-
-
- /* write bytes from this process' address space to the kernel's */
- void kwrite(kaddr, caddr, nbytes)
- long kaddr;
- char *caddr;
- long nbytes;
- {
- #ifdef DEBUG
- fprintf(stderr, "Writing %ld bytes to kernel address 0x%08lx\n",
- nbytes, kaddr);
- #endif
-
- if ( lseek(kmem, kaddr, 0)<0L ||
- write(kmem, caddr, (unsigned)nbytes) != nbytes )
- {
- sprintf(buf, "%s: can't write /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
- }
-
-
- /* change the nice value of process `pid' based on 'value' and 'relative' */
- renice(pid, value, relative)
- int pid, value, relative;
- {
- register i;
- int tmpnice;
-
- for ( i=0 ; i<NPROC ; ++i )
- {
- kcopy((char *)&proc,
- (long)&((struct proc *)procaddr)[i],
- (long)sizeof proc);
- if ( proc.p_pid == pid )
- {
- #ifdef DEBUG
- fprintf(stderr, "Found it! proc[%d], p_uid is %d\n",
- i, proc.p_uid);
-
- fprintf(stderr, "Old p_nice was %d\n", proc.p_nice);
- #endif DEBUG
-
- tmpnice = proc.p_nice;
-
- if (relative)
- tmpnice += value;
- else
- tmpnice = value;
-
- if (tmpnice >= 40)
- tmpnice = 40;
- if (tmpnice < 0)
- tmpnice = 0;
-
- #ifdef DEBUG
- fprintf(stderr, "New p_nice is %d\n", tmpnice);
- #endif DEBUG
-
- if ( myuid && (myuid != proc.p_uid || tmpnice<proc.p_nice) )
- {
- errno = EACCES;
- sprintf(buf, "%s: can't renice process %d", progname, pid);
- perror(buf);
- return 1;
- }
-
- proc.p_nice = tmpnice;
-
- kwrite((long)&((struct proc *)procaddr)[i]
- + ( ((char *)&proc.p_nice) - (char *)&proc ),
- (char *)&proc.p_nice,
- (long)sizeof proc.p_nice);
- return 0;
- }
- }
-
- fprintf(stderr, "%s: process %d not found.\n", progname, pid);
-
- return 1;
- }
-