home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume3 / xenix-fuser / fuser.c.sco < prev    next >
Encoding:
Text File  |  1989-02-03  |  8.8 KB  |  398 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 <pwd.h>
  23. #include <sys/types.h>
  24. #include <sys/param.h>
  25. #include <sys/sysmacros.h>
  26. #include <sys/stat.h>
  27. #include <sys/inode.h>
  28. #include <sys/file.h>
  29. #include <sys/seg.h>
  30. #include <sys/page.h>
  31. #include <sys/text.h>
  32. #include <sys/proc.h>
  33. #include <sys/signal.h>
  34. #include <sys/dir.h>
  35. #include <sys/user.h>
  36. #include <sys/var.h>
  37.  
  38. extern char *sbrk();
  39. extern long lseek();
  40. extern void perror(), exit();
  41. extern struct passwd *getpwuid();
  42. extern char *malloc();
  43.  
  44.  
  45. char *progname;
  46.  
  47. #define inodeaddr (mysyms[0].xl_value)
  48. #define fileaddr (mysyms[1].xl_value)
  49. #define procaddr (mysyms[2].xl_value)
  50. #define varaddr (mysyms[3].xl_value)
  51.  
  52. struct xlist mysyms[] =
  53. {
  54.     { 0,0,0,"_inode" },
  55.     { 0,0,0,"_file" },
  56.     { 0,0,0,"_proc" },
  57.     { 0,0,0,"_v" },
  58.     { 0,0,0,(char *)0 }
  59. };
  60.  
  61. char buf[BUFSIZ];
  62.  
  63. int kmem, mem, swap, kflag, uflag;
  64. int NINODE, NFILE, NPROC;
  65.  
  66. struct inode *inodep;
  67. struct file *filep;
  68. struct proc *procp;
  69. struct var *var;
  70.  
  71.  
  72. /* main program for fuser(1M), a program which lists */
  73. /* processes that are using the given file(s) */
  74. main(argc, argv)
  75. int argc;
  76. char *argv[];
  77. {
  78.     int status=0;
  79.  
  80.     progname = *argv;
  81.  
  82.     setup();
  83.  
  84.     while (++argv,--argc)
  85.     if ((*argv)[0]=='-')
  86.     {
  87.         register char c, *i;
  88.  
  89.         kflag=uflag=0;
  90.  
  91.         i = *argv+1;
  92.         while (c= *i++) switch(c)
  93.         {
  94.         case 'k':
  95.         ++kflag;
  96.         break;
  97.         case 'u':
  98.         ++uflag;
  99.         break;
  100.         default:
  101.         fprintf(stderr, "%s: bad flag `-%c'\n", progname, c);
  102.         fprintf(stderr,
  103.             "Usage: %s [-ku] files [[-] [-ku] files]\n",
  104.             progname);
  105.         return -1;
  106.         }
  107.     }
  108.     else {
  109.         printf ("%s: ", *argv);
  110.         status += fuser(*argv);
  111.         putchar ('\n');
  112.     }
  113.     return status;
  114. }
  115.  
  116.  
  117. /* a fast, zeroizing, memory allocator for things */
  118. /* that will never need to be freed */
  119. char *myalloc(nbytes)
  120. long nbytes;
  121. {
  122.     register char *ptr;
  123.  
  124.     ptr = malloc((unsigned) nbytes);
  125.     if (! ptr)
  126.     {
  127.     sprintf(buf, "%s: no memory!", progname);
  128.     perror(buf);
  129.     exit(1);
  130.     }
  131.     memset (ptr, 0, nbytes);
  132.  
  133.     return ptr;
  134. }
  135.  
  136.  
  137. /* one-time setup of main data structures from the kernel */
  138. setup()
  139. {
  140.     if ( (kmem=open("/dev/kmem", O_RDONLY)) < 0 )
  141.     {
  142.     sprintf(buf, "%s: can't open /dev/kmem", progname);
  143.     perror(buf);
  144.     exit(1);
  145.     }
  146.  
  147.     if ( (mem=open("/dev/mem", O_RDONLY)) < 0 )
  148.     {
  149.     sprintf(buf, "%s: can't open /dev/mem", progname);
  150.     perror(buf);
  151.     exit(1);
  152.     }
  153.  
  154.     if ( (swap=open("/dev/swap", O_RDONLY)) < 0 )
  155.     {
  156.     sprintf(buf, "%s: can't open /dev/swap", progname);
  157.     perror(buf);
  158.     exit(1);
  159.     }
  160.  
  161.     if (xlist("/xenix", mysyms))
  162.     {
  163.     sprintf(buf, "%s: can't xlist /xenix", progname);
  164.     perror(buf);
  165.     exit(1);
  166.     }
  167.  
  168.     setuid(getuid());
  169.  
  170. #ifdef DEBUG
  171.     fprintf(stderr, "inode:    0x%08lx\n", inodeaddr);
  172.     fprintf(stderr, "file:    0x%08lx\n", fileaddr);
  173.     fprintf(stderr, "proc:    0x%08lx\n", procaddr);
  174.     fprintf(stderr, "var:       0x%08lx\n", varaddr);
  175. #endif DEBUG
  176.  
  177.     var = (struct var *)myalloc((long) sizeof (struct var));
  178.     kcopy((char *)var, varaddr, (long) sizeof (struct var));
  179.  
  180.     NINODE = var->v_inode;
  181.     NFILE = var->v_file;
  182.     NPROC = var->v_proc;
  183.  
  184. #ifdef DEBUG
  185.     fprintf(stderr, "NOFILE:    %d\n", NOFILE);
  186.     fprintf(stderr, "NINODE:    %d\n", NINODE);
  187.     fprintf(stderr, "NFILE:    %d\n", NFILE);
  188.     fprintf(stderr, "NPROC:    %d\n", NPROC);
  189. #endif DEBUG
  190.  
  191.     inodep = (struct inode *)myalloc((long) sizeof (struct inode) * NINODE);
  192.     filep = (struct file *)myalloc((long) sizeof (struct file) * NFILE);
  193.     procp = (struct proc *)myalloc((long) sizeof (struct proc) * NPROC);
  194.  
  195.     kcopy((char *)inodep, inodeaddr, (long) sizeof (struct inode) * NINODE);
  196.     kcopy((char *)filep, fileaddr, (long) sizeof (struct file) * NFILE);
  197.     kcopy((char *)procp, procaddr, (long) sizeof (struct proc) * NPROC);
  198. }
  199.  
  200.  
  201. /* copy bytes from physical address space to this process */
  202. pcopy(caddr, paddr, nbytes)
  203. char *caddr;
  204. long paddr;
  205. long nbytes;
  206. {
  207.     if ( lseek(mem, paddr, 0)<0L ||
  208.     read(mem, caddr, (unsigned)nbytes) != nbytes )
  209.     {
  210.     sprintf(buf, "%s: can't read /dev/mem", progname);
  211.     perror(buf);
  212.     exit(1);
  213.     }
  214. }
  215.  
  216.  
  217. /* copy bytes from kernel address space to this process */
  218. kcopy(caddr, kaddr, nbytes)
  219. char *caddr;
  220. long kaddr;
  221. long nbytes;
  222. {
  223.     if ( lseek(kmem, kaddr, 0)<0L ||
  224.     read(kmem, caddr, (unsigned)nbytes) != nbytes )
  225.     {
  226.     sprintf(buf, "%s: can't read /dev/kmem", progname);
  227.     perror(buf);
  228.     exit(1);
  229.     }
  230. }
  231.  
  232. findu (proc, slot, user)
  233. struct    proc    *proc;
  234. int    slot;
  235. struct    user    *user;
  236. {
  237.     long    swapaddr;
  238.     int    i;
  239.  
  240.     if ((proc->p_flag & (SSWAP|SSPART)) || ! (proc->p_flag & SLOAD)) {
  241.         swapaddr = proc->p_addr[0].te_frameno * NBPC;
  242.         lseek (swap, swapaddr, 0);
  243.         if (read (swap, user, sizeof *user) < 0)
  244.             return (0);
  245.     } else {
  246.         lseek (mem, proc->p_addr[0].te_frameno * NBPC, 0);
  247.         if (read (mem, user, sizeof *user) < 0)
  248.             return (0);
  249.     }
  250.     if ((user->u_procp - (struct proc *) procaddr) == slot)
  251.         return (1);
  252.     else
  253.         return (0);
  254. }
  255. /* Return a pointer to a local copy of the user structure */
  256. /* for process number `procidx'.  Returns NULL if procidx */
  257. /* refers to an invalid (not-in-use or otherwise) slot. */
  258. struct user *getuser(procidx)
  259. int procidx;
  260. {
  261.     static struct user **users;
  262.     struct file **ofile;
  263.     long upage;
  264.  
  265. #ifdef    DEBUG
  266.     fprintf (stderr, "Looking for upage for proc %d\n", procidx);
  267. #endif
  268.     if (!procp[procidx].p_stat ||
  269.     procp[procidx].p_stat == SIDL ||
  270.     procp[procidx].p_stat == SZOMB)
  271.     return 0;
  272.  
  273.     if (!users)
  274.     users = (struct user **)myalloc((long) sizeof (struct user *) * NPROC);
  275.  
  276.     if (!users[procidx])
  277.     {
  278.     /* allocate and copy in the user structure */
  279.     users[procidx] = (struct user *)myalloc((long) sizeof (struct user));
  280.     if (! findu (&procp[procidx], procidx, users[procidx]))
  281.         return 0;
  282.     }
  283.     return users[procidx];
  284. }
  285.  
  286.  
  287. /* find all users of the file `name' */
  288. fuser(name)
  289. char *name;
  290. {
  291.     register i;
  292.     int filesys;
  293.     struct stat Stat;
  294.  
  295.     if (stat(name, &Stat))
  296.     {
  297.     sprintf(buf, "%s: can't stat %s", progname, name);
  298.     perror(buf);
  299.     return 1;
  300.     }
  301.  
  302.     /* see if we are looking for a whole filesystem */
  303.     filesys = ((Stat.st_mode & S_IFMT) == S_IFBLK);
  304.  
  305. #ifdef DEBUG
  306.     if (filesys)
  307.     fprintf(stderr, "looking for files on dev=%d,%d\n",
  308.         bmajor(Stat.st_rdev), minor(Stat.st_rdev));
  309.     else
  310.     fprintf(stderr, "looking for dev=%d,%d, ino=%d\n",
  311.         bmajor(Stat.st_dev), minor(Stat.st_dev), Stat.st_ino);
  312. #endif DEBUG
  313.  
  314.     for ( i=0 ; i<NINODE ; ++i )
  315.     {
  316.     if ( inodep[i].i_count &&
  317.          ((filesys && (inodep[i].i_dev == Stat.st_rdev))
  318.          || (inodep[i].i_dev == Stat.st_dev &&
  319.             inodep[i].i_number == Stat.st_ino)) )
  320.     {
  321. #ifdef DEBUG
  322.         fprintf(stderr, "Found it!  inodep[%d], i_size is %ld\n",
  323.            i, inodep[i].i_size);
  324. #endif DEBUG
  325.  
  326.         iuser((struct inode *)inodeaddr + i);
  327.     }
  328.     }
  329.  
  330.     return 0;
  331. }
  332.  
  333.  
  334. #define CHECK(kaddr, type) if (kaddr==kinode) { if (++flag==1) printf(" %d", procp[i].p_pid); if (type) putchar(type); }
  335.  
  336. /* find all users of the inode at kernel address `kinode' */
  337. iuser(kinode)
  338. struct inode *kinode;
  339. {
  340.     register int i, j;
  341.     int flag;
  342.     struct user *user;
  343.     struct passwd *pwd;
  344.     struct text text;
  345.  
  346. #ifdef DEBUG
  347.     fprintf(stderr, "Looking for users of inode at kernel address 0x%08lx\n",
  348.         kinode);
  349. #endif DEBUG
  350.  
  351.     for ( i=0 ; i<NPROC ; ++i )
  352.     if (user = getuser(i))
  353.     {
  354. #ifdef DEBUG
  355.         fprintf(stderr, "%03d: pid=%5d addr[0]=%05x addr[1]=%05x\n",
  356.             i, procp[i].p_pid, procp[i].p_addr[0], procp[i].p_addr[1]);
  357. #endif DEBUG
  358.  
  359. #ifdef DEBUG
  360.         fprintf(stderr, "    user = 0x%08lx\n", user);
  361. #endif DEBUG
  362.  
  363.         fflush(stderr);
  364.         flag=0;
  365.         if (procp[i].p_textp) {
  366.         kcopy((char *)&text, procp[i].p_textp, (long) sizeof (struct text));
  367.         CHECK(text.x_iptr, 't');
  368.         }
  369.  
  370.         CHECK(user->u_cdir, 'c');
  371.         CHECK(user->u_rdir, 'r');
  372.         CHECK(user->u_pdir, 'p');
  373.  
  374.         for ( j=0 ; !flag && j<NOFILE ; ++j )
  375.         if (user->u_ofile[j])
  376.             CHECK(filep[user->u_ofile[j]-(struct file *)fileaddr].f_inode, 0);
  377.         fflush(stdout);
  378.  
  379.         if (flag)
  380.         {
  381.         if (uflag)
  382.         {
  383.             if ( (pwd=getpwuid((int)procp[i].p_uid)) )
  384.             fprintf(stderr, "(%s)", pwd->pw_name);
  385.             else
  386.             fprintf(stderr, "(%d)", procp[i].p_uid);
  387.         }
  388.         if (kflag && procp[i].p_pid)
  389.             if (kill(procp[i].p_pid, SIGKILL))
  390.             {
  391.             sprintf(buf, "%s: can't kill process %d",
  392.                 progname, procp[i].p_pid);
  393.             perror(buf);
  394.             }
  395.         }
  396.     }
  397. }
  398.