home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1991,1992 Eric R. Smith. All rights reserved.
- */
-
- /* PROC pseudo-filesystem routines */
- /* basically just to allow 'ls -l X:' to give a list of active processes
- * some things to note:
- * process names are given as name.XXX, where 'XXX' is the pid of the
- * process
- * process attributes depend on the run queue as follows:
- * RUNNING: 0x00 (normal)
- * READY: 0x01 (read-only)
- * WAIT: 0x20 (archive bit)
- * IOBOUND: 0x21 (archive bit+read-only)
- * ZOMBIE: 0x22 (archive+hidden)
- * TSR: 0x02 (hidden)
- * STOP: 0x24 (archive bit+system)
- * the general principle is: inactive processes have the archive bit (0x20)
- * set, terminated processes have the hidden bit (0x02) set, stopped processes
- * have the system bit (0x04) set, and the read-only bit is used to
- * otherwise distinguish states (which is unfortunate, since it would be
- * nice if this bit corresponded with file permissions).
- */
-
- #include "mint.h"
-
-
- static long proc_root P_((int drv, fcookie *fc));
- static long proc_lookup P_((fcookie *dir, const char *name, fcookie *fc));
- static long proc_getxattr P_((fcookie *fc, XATTR *xattr));
- static long proc_chattr P_((fcookie *fc, int attrib));
- static long proc_chown P_((fcookie *fc, int uid, int gid));
- static long proc_chmode P_((fcookie *fc, unsigned mode));
- static long proc_rmdir P_((fcookie *dir, const char *name));
- static long proc_remove P_((fcookie *dir, const char *name));
- static long proc_getname P_((fcookie *root, fcookie *dir, char *pathname));
- static long proc_rename P_((fcookie *olddir, char *oldname,
- fcookie *newdir, const char *newname));
- static long proc_opendir P_((DIR *dirh, int flags));
- static long proc_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
- static long proc_rewinddir P_((DIR *dirh));
- static long proc_closedir P_((DIR *dirh));
- static long proc_pathconf P_((fcookie *dir, int which));
- static long proc_dfree P_((fcookie *dir, long *buf));
- static DEVDRV * proc_getdev P_((fcookie *fc, long *devsp));
-
- static long proc_open P_((FILEPTR *f));
- static long proc_write P_((FILEPTR *f, const char *buf, long bytes));
- static long proc_read P_((FILEPTR *f, char *buf, long bytes));
- static long proc_lseek P_((FILEPTR *f, long where, int whence));
- static long proc_ioctl P_((FILEPTR *f, int mode, void *buf));
- static long proc_datime P_((FILEPTR *f, short *time, int rwflag));
- static long proc_close P_((FILEPTR *f, int pid));
-
- /* dummy routines from biosfs.c */
- extern long null_select P_((FILEPTR *f, long p, int mode));
- extern void null_unselect P_((FILEPTR *f, long p, int mode));
-
- static PROC * name2proc P_((const char *name));
-
-
- DEVDRV proc_device = {
- proc_open, proc_write, proc_read, proc_lseek, proc_ioctl, proc_datime,
- proc_close, null_select, null_unselect
- };
-
- FILESYS proc_filesys = {
- (FILESYS *)0,
- 0,
- proc_root,
- proc_lookup, nocreat, proc_getdev, proc_getxattr,
- proc_chattr, proc_chown, proc_chmode,
- nomkdir, proc_rmdir, proc_remove, proc_getname, proc_rename,
- proc_opendir, proc_readdir, proc_rewinddir, proc_closedir,
- proc_pathconf, proc_dfree,
- nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,
- nofscntl, nodskchng
- };
-
- long
- proc_root(drv, fc)
- int drv;
- fcookie *fc;
- {
- if (drv == PROCDRV) {
- fc->fs = &proc_filesys;
- fc->dev = drv;
- fc->index = 0L;
- return 0;
- }
- fc->fs = 0;
- return EINTRN;
- }
-
- static PROC *
- name2proc(name)
- const char *name;
- {
- const char *pstr;
- char c;
- int i;
-
- pstr = name;
- while ( (c = *name++) != 0) {
- if (c == '.')
- pstr = name;
- }
- if (!isdigit(*pstr) && *pstr != '-')
- return 0;
- i = atoi(pstr);
- if (i == -1)
- return curproc;
- else if (i == -2)
- i = curproc->ppid;
- return pid2proc(i);
- }
-
- static long
- proc_lookup(dir, name, fc)
- fcookie *dir;
- const char *name;
- fcookie *fc;
- {
- PROC *p;
-
- if (dir->index != 0) {
- DEBUG("proc_lookup: bad directory");
- return EPTHNF;
- }
-
- /* special case: an empty name in a directory means that directory */
- /* so does "." */
- if (!*name || (name[0] == '.' && name[1] == 0)) {
- *fc = *dir;
- return 0;
- }
-
- /* another special case: ".." could be a mount point */
- if (!strcmp(name, "..")) {
- *fc = *dir;
- return EMOUNT;
- }
-
- if (!(p = name2proc(name))) {
- DEBUG("proc_lookup: name not found");
- return EFILNF;
- } else {
- fc->index = (long)p;
- fc->fs = &proc_filesys;
- fc->dev = PROC_BASE_DEV | p->pid;
- }
- return 0;
- }
-
- static int p_attr[NUM_QUEUES] = { /* attributes corresponding to queues */
- 0, /* "RUNNING" */
- 0x01, /* "READY" */
- 0x20, /* "WAITING" */
- 0x21, /* "IOBOUND" */
- 0x22, /* "ZOMBIE" */
- 0x02, /* "TSR" */
- 0x24, /* "STOPPED" */
- 0x21 /* "SELECT" (same as IOBOUND) */
- };
-
- static long
- proc_getxattr(fc, xattr)
- fcookie *fc;
- XATTR *xattr;
- {
- PROC *p;
- extern int proctime, procdate; /* see dosmem.c */
-
- xattr->blksize = 1;
- if (fc->index == 0) {
- /* the root directory */
- xattr->index = 0;
- xattr->dev = PROCDRV;
- xattr->nlink = 1;
- xattr->uid = xattr->gid = 0;
- xattr->size = xattr->nblocks = 0;
- xattr->mtime = xattr->atime = xattr->ctime = proctime;
- xattr->mdate = xattr->adate = xattr->cdate = procdate;
- xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
- xattr->attr = FA_DIR;
- return 0;
- }
-
- p = (PROC *)fc->index;
- xattr->index = p->pid;
- xattr->dev = PROC_BASE_DEV | p->pid;
- xattr->nlink = 1;
- xattr->uid = p->ruid; xattr->gid = p->rgid;
- xattr->size = xattr->nblocks = memused(p);
- xattr->mtime = xattr->ctime = xattr->atime = p->starttime;
- xattr->mdate = xattr->cdate = xattr->adate = p->startdate;
- xattr->mode = S_IMEM | S_IRUSR | S_IWUSR;
- xattr->attr = p_attr[p->wait_q];
- return 0;
- }
-
- static long
- proc_chattr(fc, attrib)
- fcookie *fc;
- int attrib;
- {
- return EACCDN;
- }
-
- static long
- proc_chown(fc, uid, gid)
- fcookie *fc;
- int uid, gid;
- {
- return EINVFN;
- }
-
- static long
- proc_chmode(fc, mode)
- fcookie *fc;
- unsigned mode;
- {
- return EINVFN;
- }
-
- static long
- proc_rmdir(dir, name)
- fcookie *dir;
- const char *name;
- {
- return EPTHNF;
- }
-
- static long
- proc_remove(dir, name)
- fcookie *dir;
- const char *name;
- {
- PROC *p;
-
- if (dir->index != 0)
- return EPTHNF;
- p = name2proc(name);
- if (!p)
- return EFILNF;
-
- post_sig(p, SIGTERM);
- check_sigs(); /* it might have been us */
- return 0;
- }
-
- static long
- proc_getname(root, dir, pathname)
- fcookie *root, *dir; char *pathname;
- {
- PROC *p;
-
- if (dir->index == 0)
- *pathname = 0;
- else {
- p = (PROC *)dir->index;
- ksprintf(pathname, "%s.03d", p->name, p->pid);
- }
- return 0;
- }
-
- static long
- proc_rename(olddir, oldname, newdir, newname)
- fcookie *olddir;
- char *oldname;
- fcookie *newdir;
- const char *newname;
- {
- PROC *p;
- int i;
-
- if (olddir->index != 0 || newdir->index != 0)
- return EPTHNF;
- if (!(p = name2proc(oldname)))
- return EFILNF;
-
- oldname = p->name;
- for (i = 0; i < PNAMSIZ; i++) {
- if (*newname == 0 || *newname == '.') {
- *oldname = 0; break;
- }
- *oldname++ = *newname++;
- }
- return 0;
- }
-
- static long
- proc_opendir(dirh, flags)
- DIR *dirh;
- int flags;
- {
- dirh->index = 0;
- return 0;
- }
-
- static long
- proc_readdir(dirh, name, namelen, fc)
- DIR *dirh;
- char *name;
- int namelen;
- fcookie *fc;
- {
- int i;
- int giveindex = (dirh->flags == 0);
- PROC *p;
-
- do {
- i = dirh->index++;
- /* BUG: we shouldn't have the magic number "1000" for maximum proc pid */
- if (i >= 1000) {
- p = 0;
- break;
- }
- p = pid2proc(i);
- } while (!p);
-
- if (!p)
- return ENMFIL;
-
- fc->index = (long)p;
- fc->fs = &proc_filesys;
- fc->dev = PROC_BASE_DEV | p->pid;
-
- if (giveindex) {
- namelen -= sizeof(long);
- if (namelen <= 0) return ERANGE;
- *((long *)name) = (long)p->pid;
- name += sizeof(long);
- }
- if (namelen < strlen(p->name) + 5)
- return ENAMETOOLONG;
-
- ksprintf(name, "%s.%03d", p->name, p->pid);
- return 0;
- }
-
- static long
- proc_rewinddir(dirh)
- DIR *dirh;
- {
- dirh->index = 0;
- return 0;
- }
-
- static long
- proc_closedir(dirh)
- DIR *dirh;
- {
- return 0;
- }
- static long
- proc_pathconf(dir, which)
- fcookie *dir;
- int which;
- {
- switch(which) {
- case -1:
- return DP_MAXREQ;
- case DP_IOPEN:
- return UNLIMITED; /* no internal limit on open files */
- case DP_MAXLINKS:
- return 1; /* we don't have hard links */
- case DP_PATHMAX:
- return PATH_MAX; /* max. path length */
- case DP_NAMEMAX:
- return PNAMSIZ; /* max. length of individual name */
- case DP_ATOMIC:
- return UNLIMITED; /* all writes are atomic */
- case DP_TRUNC:
- return DP_DOSTRUNC; /* file names are truncated to 8.3 */
- case DP_CASE:
- return DP_CASEINSENS; /* case preserved, but ignored */
- default:
- return EINVFN;
- }
- }
-
- static long
- proc_dfree(dir, buf)
- fcookie *dir;
- long *buf;
- {
- long size;
- /* "sector" size is the size of the smallest amount of memory that can be
- allocated. see mem.h for the definition of ROUND
- */
- long secsiz = ROUND(1);
-
- size = tot_rsize(core, 0) + tot_rsize(alt, 0);
- *buf++ = size/secsiz; /* number of free clusters */
- size = tot_rsize(core, 1) + tot_rsize(alt, 1);
- *buf++ = size/secsiz; /* total number of clusters */
- *buf++ = secsiz; /* sector size (bytes) */
- *buf++ = 1; /* cluster size (in sectors) */
- return 0;
- }
-
- static DEVDRV *
- proc_getdev(fc, devsp)
- fcookie *fc;
- long *devsp;
- {
- PROC *p;
-
- p = (PROC *)fc->index;
-
- *devsp = (long)p;
- return &proc_device;
- }
-
- /*
- * PROC device driver
- */
-
- /*
- * BUG: file locking and the O_SHMODE restrictions are not implemented
- * for processes
- */
-
- static long
- proc_open(f)
- FILEPTR *f;
- {
- return 0;
- }
-
- static long
- proc_write(f, buf, nbytes)
- FILEPTR *f; const char *buf; long nbytes;
- {
- PROC *p;
- char *where;
- long bytes_written = 0;
-
- p = (PROC *)f->devinfo;
- where = (char *)f->pos;
-
- /* BUG: process read/writes should check for valid addresses */
-
- TRACE("proc_write: %ld bytes to %lx", nbytes, where);
-
- while (nbytes-- > 0) {
- *where++ = *buf++;
- bytes_written++;
- }
- f->pos += bytes_written;
- return bytes_written;
- }
-
- static long
- proc_read(f, buf, nbytes)
- FILEPTR *f; char *buf; long nbytes;
- {
- PROC *p;
- char *where;
- long bytes_read = 0;
-
- p = (PROC *)f->devinfo;
- where = (char *)f->pos;
-
- TRACE("proc_read: %ld bytes from %lx", nbytes, where);
-
- while (nbytes-- > 0) {
- *buf++ = *where++;
- bytes_read++;
- }
- f->pos += bytes_read;
- return bytes_read;
- }
-
- /*
- * proc_ioctl: currently, the only IOCTL's available are:
- * PPROCADDR: get address of PROC structure's "interesting" bits
- * PCTXTSIZE: get the size of the CONTEXT structure
- * PBASEADDR: get address of process basepage
- * PSETFLAGS: set the memory allocation flags (e.g. to malloc from fastram)
- * PGETFLAGS: get the memory allocation flags
- */
-
- static long
- proc_ioctl(f, mode, buf)
- FILEPTR *f; int mode; void *buf;
- {
- PROC *p;
-
- p = (PROC *)f->devinfo;
- switch(mode) {
- case PPROCADDR:
- *((long *)buf) = (long)&p->magic;
- return 0;
- case PBASEADDR:
- *((long *)buf) = (long)p->base;
- return 0;
- case PCTXTSIZE:
- *((long *)buf) = sizeof(CONTEXT);
- return 0;
- case PSETFLAGS:
- /* note: only the low 16 bits are actually used */
- p->memflags = *((long *)buf);
- return 0;
- case PGETFLAGS:
- *((long *)buf) = p->memflags;
- return 0;
- case FIONREAD:
- case FIONWRITE:
- *((long *)buf) = 1L; /* we're always ready for i/o */
- return 0;
- default:
- DEBUG("procfs: bad Fcntl command");
- }
- return EINVFN;
- }
-
- static long
- proc_lseek(f, where, whence)
- FILEPTR *f; long where; int whence;
- {
- switch(whence) {
- case 0:
- f->pos = where;
- break;
- case 1:
- f->pos += where;
- break;
- case 2:
- f->pos = -where;
- break;
- default:
- return EINVFN;
- }
- return f->pos;
- }
-
- static long
- proc_datime(f, timeptr, rwflag)
- FILEPTR *f;
- short *timeptr;
- int rwflag;
- {
- PROC *p;
-
- p = (PROC *)f->devinfo;
- if (rwflag) {
- return EACCDN;
- }
- else {
- *timeptr++ = p->starttime;
- *timeptr++ = p->startdate;
- }
- return 0;
- }
-
- static long
- proc_close(f, pid)
- FILEPTR *f;
- int pid;
- {
- return 0;
- }
-