home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mint095s / procfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  11.9 KB  |  565 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* PROC pseudo-filesystem routines */
  6. /* basically just to allow 'ls -l X:' to give a list of active processes
  7.  * some things to note:
  8.  * process names are given as name.XXX, where 'XXX' is the pid of the
  9.  *   process
  10.  * process attributes depend on the run queue as follows:
  11.  *   RUNNING:    0x00        (normal)
  12.  *   READY:    0x01        (read-only)
  13.  *   WAIT:    0x20        (archive bit)
  14.  *   IOBOUND:    0x21        (archive bit+read-only)
  15.  *   ZOMBIE:    0x22        (archive+hidden)
  16.  *   TSR:    0x02        (hidden)
  17.  *   STOP:    0x24        (archive bit+system)
  18.  * the general principle is: inactive processes have the archive bit (0x20)
  19.  * set, terminated processes have the hidden bit (0x02) set, stopped processes
  20.  * have the system bit (0x04) set, and the read-only bit is used to
  21.  * otherwise distinguish states (which is unfortunate, since it would be
  22.  * nice if this bit corresponded with file permissions).
  23.  */
  24.  
  25. #include "mint.h"
  26.  
  27.  
  28. static long    proc_root    P_((int drv, fcookie *fc));
  29. static long    proc_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  30. static long    proc_getxattr    P_((fcookie *fc, XATTR *xattr));
  31. static long    proc_chattr    P_((fcookie *fc, int attrib));
  32. static long    proc_chown    P_((fcookie *fc, int uid, int gid));
  33. static long    proc_chmode    P_((fcookie *fc, unsigned mode));
  34. static long    proc_rmdir    P_((fcookie *dir, const char *name));
  35. static long    proc_remove    P_((fcookie *dir, const char *name));
  36. static long    proc_getname    P_((fcookie *root, fcookie *dir, char *pathname));
  37. static long    proc_rename    P_((fcookie *olddir, char *oldname,
  38.                     fcookie *newdir, const char *newname));
  39. static long    proc_opendir    P_((DIR *dirh, int flags));
  40. static long    proc_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  41. static long    proc_rewinddir    P_((DIR *dirh));
  42. static long    proc_closedir    P_((DIR *dirh));
  43. static long    proc_pathconf    P_((fcookie *dir, int which));
  44. static long    proc_dfree    P_((fcookie *dir, long *buf));
  45. static DEVDRV *    proc_getdev    P_((fcookie *fc, long *devsp));
  46.  
  47. static long    proc_open    P_((FILEPTR *f));
  48. static long    proc_write    P_((FILEPTR *f, const char *buf, long bytes));
  49. static long    proc_read    P_((FILEPTR *f, char *buf, long bytes));
  50. static long    proc_lseek    P_((FILEPTR *f, long where, int whence));
  51. static long    proc_ioctl    P_((FILEPTR *f, int mode, void *buf));
  52. static long    proc_datime    P_((FILEPTR *f, short *time, int rwflag));
  53. static long    proc_close    P_((FILEPTR *f, int pid));
  54.  
  55. /* dummy routines from biosfs.c */
  56. extern long    null_select    P_((FILEPTR *f, long p, int mode));
  57. extern void    null_unselect    P_((FILEPTR *f, long p, int mode));
  58.  
  59. static PROC *    name2proc    P_((const char *name));
  60.  
  61.  
  62. DEVDRV proc_device = {
  63.     proc_open, proc_write, proc_read, proc_lseek, proc_ioctl, proc_datime,
  64.     proc_close, null_select, null_unselect
  65. };
  66.  
  67. FILESYS proc_filesys = {
  68.     (FILESYS *)0,
  69.     0,
  70.     proc_root,
  71.     proc_lookup, nocreat, proc_getdev, proc_getxattr,
  72.     proc_chattr, proc_chown, proc_chmode,
  73.     nomkdir, proc_rmdir, proc_remove, proc_getname, proc_rename,
  74.     proc_opendir, proc_readdir, proc_rewinddir, proc_closedir,
  75.     proc_pathconf, proc_dfree,
  76.     nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,
  77.     nofscntl, nodskchng
  78. };
  79.  
  80. long
  81. proc_root(drv, fc)
  82.     int drv;
  83.     fcookie *fc;
  84. {
  85.     if (drv == PROCDRV) {
  86.         fc->fs = &proc_filesys;
  87.         fc->dev = drv;
  88.         fc->index = 0L;
  89.         return 0;
  90.     }
  91.     fc->fs = 0;
  92.     return EINTRN;
  93. }
  94.  
  95. static PROC *
  96. name2proc(name)
  97.     const char *name;
  98. {
  99.     const char *pstr;
  100.     char c;
  101.     int i;
  102.  
  103.     pstr = name;
  104.     while ( (c = *name++) != 0) {
  105.         if (c == '.')
  106.             pstr = name;
  107.     }
  108.     if (!isdigit(*pstr) && *pstr != '-')
  109.         return 0;
  110.     i = atoi(pstr);
  111.     if (i == -1)
  112.         return curproc;
  113.     else if (i == -2)
  114.         i = curproc->ppid;
  115.     return pid2proc(i);
  116. }
  117.  
  118. static long
  119. proc_lookup(dir, name, fc)
  120.     fcookie *dir;
  121.     const char *name;
  122.     fcookie *fc;
  123. {
  124.     PROC *p;
  125.  
  126.     if (dir->index != 0) {
  127.         DEBUG("proc_lookup: bad directory");
  128.         return EPTHNF;
  129.     }
  130.  
  131. /* special case: an empty name in a directory means that directory */
  132. /* so does "." */
  133.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  134.         *fc = *dir;
  135.         return 0;
  136.     }
  137.  
  138. /* another special case: ".." could be a mount point */
  139.     if (!strcmp(name, "..")) {
  140.         *fc = *dir;
  141.         return EMOUNT;
  142.     }
  143.  
  144.     if (!(p = name2proc(name))) {
  145.         DEBUG("proc_lookup: name not found");
  146.         return EFILNF;
  147.     } else {
  148.         fc->index = (long)p;
  149.         fc->fs = &proc_filesys;
  150.         fc->dev = PROC_BASE_DEV | p->pid;
  151.     }
  152.     return 0;
  153. }
  154.  
  155. static int p_attr[NUM_QUEUES] = {    /* attributes corresponding to queues */
  156.     0,            /* "RUNNING" */
  157.     0x01,            /* "READY" */
  158.     0x20,            /* "WAITING" */
  159.     0x21,            /* "IOBOUND" */
  160.     0x22,            /* "ZOMBIE" */
  161.     0x02,            /* "TSR" */
  162.     0x24,            /* "STOPPED" */
  163.     0x21            /* "SELECT" (same as IOBOUND) */
  164. };
  165.  
  166. static long
  167. proc_getxattr(fc, xattr)
  168.     fcookie *fc;
  169.     XATTR *xattr;
  170. {
  171.     PROC *p;
  172.     extern int proctime, procdate;    /* see dosmem.c */
  173.  
  174.     xattr->blksize = 1;
  175.     if (fc->index == 0) {
  176.         /* the root directory */
  177.         xattr->index = 0;
  178.         xattr->dev = PROCDRV;
  179.         xattr->nlink = 1;
  180.         xattr->uid = xattr->gid = 0;
  181.         xattr->size = xattr->nblocks = 0;
  182.         xattr->mtime = xattr->atime = xattr->ctime = proctime;
  183.         xattr->mdate = xattr->adate = xattr->cdate = procdate;
  184.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  185.         xattr->attr = FA_DIR;
  186.         return 0;
  187.     }
  188.  
  189.     p = (PROC *)fc->index;
  190.     xattr->index = p->pid;
  191.     xattr->dev = PROC_BASE_DEV | p->pid;
  192.     xattr->nlink = 1;
  193.     xattr->uid = p->ruid; xattr->gid = p->rgid;
  194.     xattr->size = xattr->nblocks = memused(p);
  195.     xattr->mtime = xattr->ctime = xattr->atime = p->starttime;
  196.     xattr->mdate = xattr->cdate = xattr->adate = p->startdate;
  197.     xattr->mode = S_IMEM | S_IRUSR | S_IWUSR;
  198.     xattr->attr = p_attr[p->wait_q];
  199.     return 0;
  200. }
  201.  
  202. static long
  203. proc_chattr(fc, attrib)
  204.     fcookie *fc;
  205.     int attrib;
  206. {
  207.     return EACCDN;
  208. }
  209.  
  210. static long
  211. proc_chown(fc, uid, gid)
  212.     fcookie *fc;
  213.     int uid, gid;
  214. {
  215.     return EINVFN;
  216. }
  217.  
  218. static long
  219. proc_chmode(fc, mode)
  220.     fcookie *fc;
  221.     unsigned mode;
  222. {
  223.     return EINVFN;
  224. }
  225.  
  226. static long
  227. proc_rmdir(dir, name)
  228.     fcookie *dir;
  229.     const char *name;
  230. {
  231.     return EPTHNF;
  232. }
  233.  
  234. static long
  235. proc_remove(dir, name)
  236.     fcookie *dir;
  237.     const char *name;
  238. {
  239.     PROC *p;
  240.  
  241.     if (dir->index != 0)
  242.         return EPTHNF;
  243.     p = name2proc(name);
  244.     if (!p)
  245.         return EFILNF;
  246.  
  247.     post_sig(p, SIGTERM);
  248.     check_sigs();        /* it might have been us */
  249.     return 0;
  250. }
  251.  
  252. static long
  253. proc_getname(root, dir, pathname)
  254.     fcookie *root, *dir; char *pathname;
  255. {
  256.     PROC *p;
  257.  
  258.     if (dir->index == 0)
  259.         *pathname = 0;
  260.     else {
  261.         p = (PROC *)dir->index;
  262.         ksprintf(pathname, "%s.03d", p->name, p->pid);
  263.     }
  264.     return 0;
  265. }
  266.  
  267. static long
  268. proc_rename(olddir, oldname, newdir, newname)
  269.     fcookie *olddir;
  270.     char *oldname;
  271.     fcookie *newdir;
  272.     const char *newname;
  273. {
  274.     PROC *p;
  275.     int i;
  276.  
  277.     if (olddir->index != 0 || newdir->index != 0)
  278.         return EPTHNF;
  279.     if (!(p = name2proc(oldname)))
  280.         return EFILNF;
  281.  
  282.     oldname = p->name;
  283.     for (i = 0; i < PNAMSIZ; i++) {
  284.         if (*newname == 0 || *newname == '.') {
  285.             *oldname = 0; break;
  286.         }
  287.         *oldname++ = *newname++;
  288.     }
  289.     return 0;
  290. }
  291.  
  292. static long
  293. proc_opendir(dirh, flags)
  294.     DIR *dirh;
  295.     int flags;
  296. {
  297.     dirh->index = 0;
  298.     return 0;
  299. }
  300.  
  301. static long
  302. proc_readdir(dirh, name, namelen, fc)
  303.     DIR *dirh;
  304.     char *name;
  305.     int namelen;
  306.     fcookie *fc;
  307. {
  308.     int i;
  309.     int giveindex = (dirh->flags == 0);
  310.     PROC *p;
  311.  
  312.     do {
  313.         i = dirh->index++;
  314. /* BUG: we shouldn't have the magic number "1000" for maximum proc pid */
  315.         if (i >= 1000) {
  316.             p = 0;
  317.             break;
  318.         }
  319.         p = pid2proc(i);
  320.     } while (!p);
  321.  
  322.     if (!p)
  323.         return ENMFIL;
  324.  
  325.     fc->index = (long)p;
  326.     fc->fs = &proc_filesys;
  327.     fc->dev = PROC_BASE_DEV | p->pid;
  328.  
  329.     if (giveindex) {
  330.         namelen -= sizeof(long);
  331.         if (namelen <= 0) return ERANGE;
  332.         *((long *)name) = (long)p->pid;
  333.         name += sizeof(long);
  334.     }
  335.     if (namelen < strlen(p->name) + 5)
  336.         return ENAMETOOLONG;
  337.  
  338.     ksprintf(name, "%s.%03d", p->name, p->pid);
  339.     return 0;
  340. }
  341.  
  342. static long
  343. proc_rewinddir(dirh)
  344.     DIR *dirh;
  345. {
  346.     dirh->index = 0;
  347.     return 0;
  348. }
  349.  
  350. static long
  351. proc_closedir(dirh)
  352.     DIR *dirh;
  353. {
  354.     return 0;
  355. }
  356. static long
  357. proc_pathconf(dir, which)
  358.     fcookie *dir;
  359.     int which;
  360. {
  361.     switch(which) {
  362.     case -1:
  363.         return DP_MAXREQ;
  364.     case DP_IOPEN:
  365.         return UNLIMITED;    /* no internal limit on open files */
  366.     case DP_MAXLINKS:
  367.         return 1;        /* we don't have hard links */
  368.     case DP_PATHMAX:
  369.         return PATH_MAX;    /* max. path length */
  370.     case DP_NAMEMAX:
  371.         return PNAMSIZ;        /* max. length of individual name */
  372.     case DP_ATOMIC:
  373.         return UNLIMITED;    /* all writes are atomic */
  374.     case DP_TRUNC:
  375.         return DP_DOSTRUNC;    /* file names are truncated to 8.3 */
  376.     case DP_CASE:
  377.         return DP_CASEINSENS;    /* case preserved, but ignored */
  378.     default:
  379.         return EINVFN;
  380.     }
  381. }
  382.  
  383. static long
  384. proc_dfree(dir, buf)
  385.     fcookie *dir;
  386.     long *buf;
  387. {
  388.     long size;
  389. /* "sector" size is the size of the smallest amount of memory that can be
  390.    allocated. see mem.h for the definition of ROUND
  391.  */
  392.     long secsiz = ROUND(1);
  393.  
  394.     size = tot_rsize(core, 0) + tot_rsize(alt, 0);
  395.     *buf++ = size/secsiz;            /* number of free clusters */
  396.     size = tot_rsize(core, 1) + tot_rsize(alt, 1);
  397.     *buf++ = size/secsiz;            /* total number of clusters */
  398.     *buf++ = secsiz;            /* sector size (bytes) */
  399.     *buf++ = 1;                /* cluster size (in sectors) */
  400.     return 0;
  401. }
  402.  
  403. static DEVDRV *
  404. proc_getdev(fc, devsp)
  405.     fcookie *fc;
  406.     long *devsp;
  407. {
  408.     PROC *p;
  409.  
  410.     p = (PROC *)fc->index;
  411.  
  412.     *devsp = (long)p;
  413.     return &proc_device;
  414. }
  415.  
  416. /*
  417.  * PROC device driver
  418.  */
  419.  
  420. /*
  421.  * BUG: file locking and the O_SHMODE restrictions are not implemented
  422.  * for processes
  423.  */
  424.  
  425. static long
  426. proc_open(f)
  427.     FILEPTR *f;
  428. {
  429.     return 0;
  430. }
  431.  
  432. static long
  433. proc_write(f, buf, nbytes)
  434.     FILEPTR *f; const char *buf; long nbytes;
  435. {
  436.     PROC *p;
  437.     char *where;
  438.     long bytes_written = 0;
  439.  
  440.     p = (PROC *)f->devinfo;
  441.     where = (char *)f->pos;
  442.  
  443. /* BUG: process read/writes should check for valid addresses */
  444.  
  445. TRACE("proc_write: %ld bytes to %lx", nbytes, where);
  446.  
  447.     while (nbytes-- > 0) {
  448.         *where++ = *buf++;
  449.         bytes_written++;
  450.     }
  451.     f->pos += bytes_written;
  452.     return bytes_written;
  453. }
  454.  
  455. static long
  456. proc_read(f, buf, nbytes)
  457.     FILEPTR *f; char *buf; long nbytes;
  458. {
  459.     PROC *p;
  460.     char *where;
  461.     long bytes_read = 0;
  462.  
  463.     p = (PROC *)f->devinfo;
  464.     where = (char *)f->pos;
  465.  
  466. TRACE("proc_read: %ld bytes from %lx", nbytes, where);
  467.  
  468.     while (nbytes-- > 0) {
  469.         *buf++ = *where++;
  470.         bytes_read++;
  471.     }
  472.     f->pos += bytes_read;
  473.     return bytes_read;
  474. }
  475.  
  476. /*
  477.  * proc_ioctl: currently, the only IOCTL's available are:
  478.  * PPROCADDR: get address of PROC structure's "interesting" bits
  479.  * PCTXTSIZE: get the size of the CONTEXT structure
  480.  * PBASEADDR: get address of process basepage
  481.  * PSETFLAGS: set the memory allocation flags (e.g. to malloc from fastram)
  482.  * PGETFLAGS: get the memory allocation flags
  483.  */
  484.  
  485. static long
  486. proc_ioctl(f, mode, buf)
  487.     FILEPTR *f; int mode; void *buf;
  488. {
  489.     PROC *p;
  490.  
  491.     p = (PROC *)f->devinfo;
  492.     switch(mode) {
  493.     case PPROCADDR:
  494.         *((long *)buf) = (long)&p->magic;
  495.         return 0;
  496.     case PBASEADDR:
  497.         *((long *)buf) = (long)p->base;
  498.         return 0;
  499.     case PCTXTSIZE:
  500.         *((long *)buf) = sizeof(CONTEXT);
  501.         return 0;
  502.     case PSETFLAGS:
  503.         /* note: only the low 16 bits are actually used */
  504.         p->memflags = *((long *)buf);
  505.         return 0;
  506.     case PGETFLAGS:
  507.         *((long *)buf) = p->memflags;
  508.         return 0;
  509.     case FIONREAD:
  510.     case FIONWRITE:
  511.         *((long *)buf) = 1L;    /* we're always ready for i/o */
  512.         return 0;
  513.     default:
  514.         DEBUG("procfs: bad Fcntl command");
  515.     }
  516.     return EINVFN;
  517. }
  518.  
  519. static long
  520. proc_lseek(f, where, whence)
  521.     FILEPTR *f; long where; int whence;
  522. {
  523.     switch(whence) {
  524.     case 0:
  525.         f->pos = where;
  526.         break;
  527.     case 1:
  528.         f->pos += where;
  529.         break;
  530.     case 2:
  531.         f->pos = -where;
  532.         break;
  533.     default:
  534.         return EINVFN;
  535.     }
  536.     return f->pos;
  537. }
  538.  
  539. static long
  540. proc_datime(f, timeptr, rwflag)
  541.     FILEPTR *f;
  542.     short *timeptr;
  543.     int rwflag;
  544. {
  545.     PROC *p;
  546.  
  547.     p = (PROC *)f->devinfo;
  548.     if (rwflag) {
  549.         return EACCDN;
  550.     }
  551.     else {
  552.         *timeptr++ = p->starttime;
  553.         *timeptr++ = p->startdate;
  554.     }
  555.     return 0;
  556. }
  557.  
  558. static long
  559. proc_close(f, pid)
  560.     FILEPTR *f;
  561.     int pid;
  562. {
  563.     return 0;
  564. }
  565.