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 <pwd.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/sysmacros.h>
- #include <sys/stat.h>
- #include <sys/tune.h>
- #include <sys/inode.h>
- #include <sys/file.h>
- #include <sys/user.h>
- #include <sys/proc.h>
- #include <sys/signal.h>
- #include <a.out.h>
-
- /* get rid of meaningless NOFILE from param.h */
- #ifdef NOFILE
- #undef NOFILE
- #endif
-
- extern char *sbrk();
- extern long lseek();
- extern void perror(), exit();
- extern struct passwd *getpwuid();
-
-
- char *progname;
-
- #define tuhiaddr (mysyms[0].n_value)
- #define inodeaddr (mysyms[1].n_value)
- #define fileaddr (mysyms[2].n_value)
- #define procaddr (mysyms[3].n_value)
- #define nofileaddr (mysyms[4].n_value)
-
- struct nlist mysyms[] =
- {
- { "tuhi", },
- { "inode", },
- { "file", },
- { "proc", },
- { "nofile", },
- { (char *)0, },
- };
-
- char buf[BUFSIZ];
-
- int kmem, mem, kflag, uflag;
- int NINODE, NFILE, NPROC, NOFILE;
-
- struct inode *inode;
- struct file *file;
- struct proc *proc;
-
-
- /* main program for fuser(1M), a program which lists */
- /* processes that are using the given file(s) */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int status=0;
-
- progname = *argv;
-
- setup();
-
- while (++argv,--argc)
- if ((*argv)[0]=='-')
- {
- register char c, *i;
-
- kflag=uflag=0;
-
- i = *argv+1;
- while (c= *i++) switch(c)
- {
- case 'k':
- ++kflag;
- break;
- case 'u':
- ++uflag;
- break;
- default:
- fprintf(stderr, "%s: bad flag `-%c'\n", progname, c);
- fprintf(stderr,
- "Usage: %s [-ku] files [[-] [-ku] files]\n",
- progname);
- return -1;
- }
- }
- else
- status += fuser(*argv);
-
- return status;
- }
-
-
- /* a fast, zeroizing, memory allocator for things */
- /* that will never need to be freed */
- char *myalloc(nbytes)
- long nbytes;
- {
- register char *ptr = sbrk((int)nbytes);
-
- if ((long)ptr < 0L)
- {
- sprintf(buf, "%s: no memory!", progname);
- perror(buf);
- exit(1);
- }
-
- return ptr;
- }
-
-
- /* one-time setup of main data structures from the kernel */
- setup()
- {
- struct tunable tune;
-
- if ( (kmem=open("/dev/kmem", O_RDONLY)) < 0 )
- {
- sprintf(buf, "%s: can't open /dev/kmem", progname);
- perror(buf);
- exit(1);
- }
-
- if ( (mem=open("/dev/mem", O_RDONLY)) < 0 )
- {
- sprintf(buf, "%s: can't open /dev/mem", progname);
- perror(buf);
- exit(1);
- }
-
- if (nlist("/unix", mysyms))
- {
- sprintf(buf, "%s: can't nlist /unix", progname);
- perror(buf);
- exit(1);
- }
-
- setuid(getuid());
-
- kcopy((char *)&NOFILE, nofileaddr, (long) sizeof NOFILE);
-
- #ifdef DEBUG
- fprintf(stderr, "tuhi: 0x%08lx\n", tuhiaddr);
- #endif DEBUG
- kcopy((char *)&tune, tuhiaddr, (long) sizeof tune);
-
- /* do indirection on these addresses, since they */
- /* are just pointers in the kernel */
- kcopy((char *)&inodeaddr, inodeaddr, (long) sizeof inodeaddr);
- kcopy((char *)&fileaddr, fileaddr, (long) sizeof fileaddr);
- kcopy((char *)&procaddr, procaddr, (long) sizeof procaddr);
-
- #ifdef DEBUG
- fprintf(stderr, "inode: 0x%08lx\n", inodeaddr);
- fprintf(stderr, "file: 0x%08lx\n", fileaddr);
- fprintf(stderr, "proc: 0x%08lx\n", procaddr);
- #endif DEBUG
-
- NINODE = tune.ninode;
- NFILE = tune.nfile;
- NPROC = tune.nproc;
-
- #ifdef DEBUG
- fprintf(stderr, "NOFILE: %d\n", NOFILE);
- fprintf(stderr, "NINODE: %d\n", NINODE);
- fprintf(stderr, "NFILE: %d\n", NFILE);
- fprintf(stderr, "NPROC: %d\n", NPROC);
- #endif DEBUG
-
- inode = (struct inode *)myalloc((long) sizeof (struct inode) * NINODE);
- file = (struct file *)myalloc((long) sizeof (struct file) * NFILE);
- proc = (struct proc *)myalloc((long) sizeof (struct proc) * NPROC);
-
- kcopy((char *)inode, inodeaddr, (long) sizeof (struct inode) * NINODE);
- kcopy((char *)file, fileaddr, (long) sizeof (struct file) * NFILE);
- kcopy((char *)proc, procaddr, (long) sizeof (struct proc) * NPROC);
- }
-
-
- /* copy bytes from physical address space to this process */
- pcopy(caddr, paddr, nbytes)
- char *caddr;
- long paddr;
- long nbytes;
- {
- if ( lseek(mem, paddr, 0)<0L ||
- read(mem, caddr, (unsigned)nbytes) != nbytes )
- {
- sprintf(buf, "%s: can't read /dev/mem", progname);
- perror(buf);
- exit(1);
- }
- }
-
-
- /* copy bytes from kernel address space to this process */
- 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);
- }
- }
-
-
- /* Return a pointer to a local copy of the user structure */
- /* for process number `procidx'. Returns NULL if procidx */
- /* refers to an invalid (not-in-use or otherwise) slot. */
- struct user *getuser(procidx)
- int procidx;
- {
- static struct user **users;
- struct file **ofile;
- long upage;
-
- if (!proc[procidx].p_stat ||
- proc[procidx].p_stat == SIDL ||
- proc[procidx].p_stat == SZOMB)
- return 0;
-
- if (!(proc[procidx].p_flag & SLOAD))
- {
- /* can't handle swapped process yet */
- fprintf(stderr, "%s: can't handle swapped process %d (flag=%05x)\n",
- progname, proc[procidx].p_pid, proc[procidx].p_flag);
- return 0;
- }
-
- if (!users)
- users = (struct user **)myalloc((long) sizeof (struct user *) * NPROC);
-
- if (!users[procidx])
- {
- upage = (long)ctob(proc[procidx].p_addr[0]);
-
- /* allocate and copy in the user structure */
- users[procidx] = (struct user *)myalloc((long) sizeof (struct user));
- pcopy((char *)(users[procidx]),
- upage + U_OFFSET,
- (long) sizeof (struct user));
-
- /* allocate and copy in the list of file pointers */
- ofile = (struct file **)myalloc((long) sizeof (struct file *) * NOFILE);
- pcopy((char *)ofile,
- upage+(long)(users[procidx]->u_ofile)-VPG_BASE,
- (long) sizeof (struct file *) * NOFILE);
- users[procidx]->u_ofile = ofile;
- }
-
- return users[procidx];
- }
-
-
- /* find all users of the file `name' */
- fuser(name)
- char *name;
- {
- register i;
- int filesys;
- struct stat Stat;
-
- if (stat(name, &Stat))
- {
- sprintf(buf, "%s: can't stat %s", progname, name);
- perror(buf);
- return 1;
- }
-
- /* see if we are looking for a whole filesystem */
- filesys = ((Stat.st_mode&S_IFMT) == S_IFBLK);
-
- #ifdef DEBUG
- if (filesys)
- fprintf(stderr, "looking for files on dev=%d,%d\n",
- bmajor(Stat.st_rdev), minor(Stat.st_rdev));
- else
- fprintf(stderr, "looking for dev=%d,%d, ino=%d\n",
- bmajor(Stat.st_dev), minor(Stat.st_dev), Stat.st_ino);
- #endif DEBUG
-
- for ( i=0 ; i<NINODE ; ++i )
- {
- if ( inode[i].i_count &&
- (filesys
- ? (brdev(inode[i].i_dev) == Stat.st_rdev)
- : (brdev(inode[i].i_dev) == Stat.st_dev &&
- inode[i].i_number == Stat.st_ino)) )
- {
- #ifdef DEBUG
- fprintf(stderr, "Found it! inode[%d], i_size is %ld\n",
- i, inode[i].i_size);
- #endif DEBUG
-
- iuser((struct inode *)inodeaddr + i);
- }
- }
-
- putchar('\n');
-
- return 0;
- }
-
-
- #define CHECK(kaddr, type) if (kaddr==kinode) { if (++flag==1) printf(" %d", proc[i].p_pid); if (type) putchar(type); }
-
- /* find all users of the inode at kernel address `kinode' */
- iuser(kinode)
- struct inode *kinode;
- {
- register int i, j;
- int flag;
- struct user *user;
- struct passwd *pwd;
-
- #ifdef DEBUG
- fprintf(stderr, "Looking for users of inode at kernel address 0x%08lx\n",
- kinode);
- #endif DEBUG
-
- for ( i=0 ; i<NPROC ; ++i )
- if (user = getuser(i))
- {
- #ifdef DEBUG
- fprintf(stderr, "%03d: pid=%5d addr[0]=%05x addr[1]=%05x swaddr=%05x\n",
- i, proc[i].p_pid, proc[i].p_addr[0], proc[i].p_addr[1],
- proc[i].p_swaddr);
- #endif DEBUG
-
- #ifdef DEBUG
- fprintf(stderr, " user = 0x%08lx\n", user);
- fprintf(stderr, " user->u_ofile = 0x%08lx\n", user->u_ofile);
- #endif DEBUG
-
- fflush(stderr);
- flag=0;
- CHECK(user->u_cdir, 'c');
- CHECK(user->u_rdir, 'r');
- CHECK(user->u_pdir, 'p');
- for ( j=0 ; !flag && j<NOFILE ; ++j )
- if (user->u_ofile[j])
- CHECK(file[user->u_ofile[j]-(struct file *)fileaddr].f_inode, 0);
- fflush(stdout);
-
- if (flag)
- {
- if (uflag)
- {
- if ( (pwd=getpwuid((int)proc[i].p_uid)) )
- fprintf(stderr, "(%s)", pwd->pw_name);
- else
- fprintf(stderr, "(%d)", proc[i].p_uid);
- }
- if (kflag && proc[i].p_pid)
- if (kill(proc[i].p_pid, SIGKILL))
- {
- sprintf(buf, "%s: can't kill process %d",
- progname, proc[i].p_pid);
- perror(buf);
- }
- }
- }
- }
-