home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mint104s.zoo / mint.src / procfs.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  17KB  |  699 lines

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