|
|
1.1 root 1: /*
2:
3: Copyright 1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /* PROC pseudo-filesystem routines */
10:
11: /* basically just to allow 'ls -l X:' to give a list of active processes
12:
13: * some things to note:
14:
15: * process names are given as name.XXX, where 'XXX' is the pid of the
16:
17: * process
18:
19: * process attributes depend on the run queue as follows:
20:
21: * RUNNING: 0x00 (normal)
22:
23: * READY: 0x01 (read-only)
24:
25: * WAIT: 0x20 (archive bit)
26:
27: * IOBOUND: 0x21 (archive bit+read-only)
28:
29: * ZOMBIE: 0x22 (archive+hidden)
30:
31: * TSR: 0x02 (hidden)
32:
33: * STOP: 0x24 (archive bit+system)
34:
35: * the general principle is: inactive processes have the archive bit (0x20)
36:
37: * set, terminated processes have the hidden bit (0x02) set, stopped processes
38:
39: * have the system bit (0x04) set, and the read-only bit is used to
40:
41: * otherwise distinguish states (which is unfortunate, since it would be
42:
43: * nice if this bit corresponded with file permissions).
44:
45: */
46:
47:
48:
49: #include "mint.h"
50:
51:
52:
53:
54:
55: static long proc_root P_((int drv, fcookie *fc));
56:
57: static long proc_lookup P_((fcookie *dir, const char *name, fcookie *fc));
58:
59: static long proc_getxattr P_((fcookie *fc, XATTR *xattr));
60:
61: static long proc_chattr P_((fcookie *fc, int attrib));
62:
63: static long proc_chown P_((fcookie *fc, int uid, int gid));
64:
65: static long proc_chmode P_((fcookie *fc, unsigned mode));
66:
67: static long proc_rmdir P_((fcookie *dir, const char *name));
68:
69: static long proc_remove P_((fcookie *dir, const char *name));
70:
71: static long proc_getname P_((fcookie *root, fcookie *dir, char *pathname));
72:
73: static long proc_rename P_((fcookie *olddir, char *oldname,
74:
75: fcookie *newdir, const char *newname));
76:
77: static long proc_opendir P_((DIR *dirh, int flags));
78:
79: static long proc_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
80:
81: static long proc_rewinddir P_((DIR *dirh));
82:
83: static long proc_closedir P_((DIR *dirh));
84:
85: static long proc_pathconf P_((fcookie *dir, int which));
86:
87: static long proc_dfree P_((fcookie *dir, long *buf));
88:
89: static DEVDRV * proc_getdev P_((fcookie *fc, long *devsp));
90:
91:
92:
93: static long proc_open P_((FILEPTR *f));
94:
95: static long proc_write P_((FILEPTR *f, const char *buf, long bytes));
96:
97: static long proc_read P_((FILEPTR *f, char *buf, long bytes));
98:
99: static long proc_lseek P_((FILEPTR *f, long where, int whence));
100:
101: static long proc_ioctl P_((FILEPTR *f, int mode, void *buf));
102:
103: static long proc_datime P_((FILEPTR *f, short *time, int rwflag));
104:
105: static long proc_close P_((FILEPTR *f, int pid));
106:
107:
108:
109: /* dummy routines from biosfs.c */
110:
111: extern long null_select P_((FILEPTR *f, long p, int mode));
112:
113: extern void null_unselect P_((FILEPTR *f, long p, int mode));
114:
115:
116:
117: static PROC * name2proc P_((const char *name));
118:
119:
120:
121:
122:
123: DEVDRV proc_device = {
124:
125: proc_open, proc_write, proc_read, proc_lseek, proc_ioctl, proc_datime,
126:
127: proc_close, null_select, null_unselect
128:
129: };
130:
131:
132:
133: FILESYS proc_filesys = {
134:
135: (FILESYS *)0,
136:
137: 0,
138:
139: proc_root,
140:
141: proc_lookup, nocreat, proc_getdev, proc_getxattr,
142:
143: proc_chattr, proc_chown, proc_chmode,
144:
145: nomkdir, proc_rmdir, proc_remove, proc_getname, proc_rename,
146:
147: proc_opendir, proc_readdir, proc_rewinddir, proc_closedir,
148:
149: proc_pathconf, proc_dfree,
150:
151: nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,
152:
153: nofscntl, nodskchng
154:
155: };
156:
157:
158:
159: long
160:
161: proc_root(drv, fc)
162:
163: int drv;
164:
165: fcookie *fc;
166:
167: {
168:
169: if (drv == PROCDRV) {
170:
171: fc->fs = &proc_filesys;
172:
173: fc->dev = drv;
174:
175: fc->index = 0L;
176:
177: return 0;
178:
179: }
180:
181: fc->fs = 0;
182:
183: return EINTRN;
184:
185: }
186:
187:
188:
189: static PROC *
190:
191: name2proc(name)
192:
193: const char *name;
194:
195: {
196:
197: const char *pstr;
198:
199: char c;
200:
201: int i;
202:
203:
204:
205: pstr = name;
206:
207: while ( (c = *name++) != 0) {
208:
209: if (c == '.')
210:
211: pstr = name;
212:
213: }
214:
215: if (!isdigit(*pstr) && *pstr != '-')
216:
217: return 0;
218:
219: i = atoi(pstr);
220:
221: if (i == -1)
222:
223: return curproc;
224:
225: else if (i == -2)
226:
227: i = curproc->ppid;
228:
229: return pid2proc(i);
230:
231: }
232:
233:
234:
235: static long
236:
237: proc_lookup(dir, name, fc)
238:
239: fcookie *dir;
240:
241: const char *name;
242:
243: fcookie *fc;
244:
245: {
246:
247: PROC *p;
248:
249:
250:
251: if (dir->index != 0) {
252:
253: DEBUG("proc_lookup: bad directory");
254:
255: return EPTHNF;
256:
257: }
258:
259:
260:
261: /* special case: an empty name in a directory means that directory */
262:
263: /* so does "." */
264:
265: if (!*name || (name[0] == '.' && name[1] == 0)) {
266:
267: *fc = *dir;
268:
269: return 0;
270:
271: }
272:
273:
274:
275: /* another special case: ".." could be a mount point */
276:
277: if (!strcmp(name, "..")) {
278:
279: *fc = *dir;
280:
281: return EMOUNT;
282:
283: }
284:
285:
286:
287: if (!(p = name2proc(name))) {
288:
289: DEBUG("proc_lookup: name not found");
290:
291: return EFILNF;
292:
293: } else {
294:
295: fc->index = (long)p;
296:
297: fc->fs = &proc_filesys;
298:
299: fc->dev = PROC_BASE_DEV | p->pid;
300:
301: }
302:
303: return 0;
304:
305: }
306:
307:
308:
309: static int p_attr[NUM_QUEUES] = { /* attributes corresponding to queues */
310:
311: 0, /* "RUNNING" */
312:
313: 0x01, /* "READY" */
314:
315: 0x20, /* "WAITING" */
316:
317: 0x21, /* "IOBOUND" */
318:
319: 0x22, /* "ZOMBIE" */
320:
321: 0x02, /* "TSR" */
322:
323: 0x24, /* "STOPPED" */
324:
325: 0x21 /* "SELECT" (same as IOBOUND) */
326:
327: };
328:
329:
330:
331: static long
332:
333: proc_getxattr(fc, xattr)
334:
335: fcookie *fc;
336:
337: XATTR *xattr;
338:
339: {
340:
341: PROC *p;
342:
343: extern int proctime, procdate; /* see dosmem.c */
344:
345:
346:
347: xattr->blksize = 1;
348:
349: if (fc->index == 0) {
350:
351: /* the root directory */
352:
353: xattr->index = 0;
354:
355: xattr->dev = PROCDRV;
356:
357: xattr->nlink = 1;
358:
359: xattr->uid = xattr->gid = 0;
360:
361: xattr->size = xattr->nblocks = 0;
362:
363: xattr->mtime = xattr->atime = xattr->ctime = proctime;
364:
365: xattr->mdate = xattr->adate = xattr->cdate = procdate;
366:
367: xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
368:
369: xattr->attr = FA_DIR;
370:
371: return 0;
372:
373: }
374:
375:
376:
377: p = (PROC *)fc->index;
378:
379: xattr->index = p->pid;
380:
381: xattr->dev = PROC_BASE_DEV | p->pid;
382:
383: xattr->nlink = 1;
384:
385: xattr->uid = p->ruid; xattr->gid = p->rgid;
386:
387: xattr->size = xattr->nblocks = memused(p);
388:
389: xattr->mtime = xattr->ctime = xattr->atime = p->starttime;
390:
391: xattr->mdate = xattr->cdate = xattr->adate = p->startdate;
392:
393: xattr->mode = S_IMEM | S_IRUSR | S_IWUSR;
394:
395: xattr->attr = p_attr[p->wait_q];
396:
397: return 0;
398:
399: }
400:
401:
402:
403: static long
404:
405: proc_chattr(fc, attrib)
406:
407: fcookie *fc;
408:
409: int attrib;
410:
411: {
412:
413: return EACCDN;
414:
415: }
416:
417:
418:
419: static long
420:
421: proc_chown(fc, uid, gid)
422:
423: fcookie *fc;
424:
425: int uid, gid;
426:
427: {
428:
429: return EINVFN;
430:
431: }
432:
433:
434:
435: static long
436:
437: proc_chmode(fc, mode)
438:
439: fcookie *fc;
440:
441: unsigned mode;
442:
443: {
444:
445: return EINVFN;
446:
447: }
448:
449:
450:
451: static long
452:
453: proc_rmdir(dir, name)
454:
455: fcookie *dir;
456:
457: const char *name;
458:
459: {
460:
461: return EPTHNF;
462:
463: }
464:
465:
466:
467: static long
468:
469: proc_remove(dir, name)
470:
471: fcookie *dir;
472:
473: const char *name;
474:
475: {
476:
477: PROC *p;
478:
479:
480:
481: if (dir->index != 0)
482:
483: return EPTHNF;
484:
485: p = name2proc(name);
486:
487: if (!p)
488:
489: return EFILNF;
490:
491:
492:
493: post_sig(p, SIGTERM);
494:
495: check_sigs(); /* it might have been us */
496:
497: return 0;
498:
499: }
500:
501:
502:
503: static long
504:
505: proc_getname(root, dir, pathname)
506:
507: fcookie *root, *dir; char *pathname;
508:
509: {
510:
511: PROC *p;
512:
513:
514:
515: if (dir->index == 0)
516:
517: *pathname = 0;
518:
519: else {
520:
521: p = (PROC *)dir->index;
522:
523: ksprintf(pathname, "%s.03d", p->name, p->pid);
524:
525: }
526:
527: return 0;
528:
529: }
530:
531:
532:
533: static long
534:
535: proc_rename(olddir, oldname, newdir, newname)
536:
537: fcookie *olddir;
538:
539: char *oldname;
540:
541: fcookie *newdir;
542:
543: const char *newname;
544:
545: {
546:
547: PROC *p;
548:
549: int i;
550:
551:
552:
553: if (olddir->index != 0 || newdir->index != 0)
554:
555: return EPTHNF;
556:
557: if (!(p = name2proc(oldname)))
558:
559: return EFILNF;
560:
561:
562:
563: oldname = p->name;
564:
565: for (i = 0; i < PNAMSIZ; i++) {
566:
567: if (*newname == 0 || *newname == '.') {
568:
569: *oldname = 0; break;
570:
571: }
572:
573: *oldname++ = *newname++;
574:
575: }
576:
577: return 0;
578:
579: }
580:
581:
582:
583: static long
584:
585: proc_opendir(dirh, flags)
586:
587: DIR *dirh;
588:
589: int flags;
590:
591: {
592:
593: dirh->index = 0;
594:
595: return 0;
596:
597: }
598:
599:
600:
601: static long
602:
603: proc_readdir(dirh, name, namelen, fc)
604:
605: DIR *dirh;
606:
607: char *name;
608:
609: int namelen;
610:
611: fcookie *fc;
612:
613: {
614:
615: int i;
616:
617: int giveindex = (dirh->flags == 0);
618:
619: PROC *p;
620:
621:
622:
623: do {
624:
625: i = dirh->index++;
626:
627: /* BUG: we shouldn't have the magic number "1000" for maximum proc pid */
628:
629: if (i >= 1000) {
630:
631: p = 0;
632:
633: break;
634:
635: }
636:
637: p = pid2proc(i);
638:
639: } while (!p);
640:
641:
642:
643: if (!p)
644:
645: return ENMFIL;
646:
647:
648:
649: fc->index = (long)p;
650:
651: fc->fs = &proc_filesys;
652:
653: fc->dev = PROC_BASE_DEV | p->pid;
654:
655:
656:
657: if (giveindex) {
658:
659: namelen -= sizeof(long);
660:
661: if (namelen <= 0) return ERANGE;
662:
663: *((long *)name) = (long)p->pid;
664:
665: name += sizeof(long);
666:
667: }
668:
669: if (namelen < strlen(p->name) + 5)
670:
671: return ENAMETOOLONG;
672:
673:
674:
675: ksprintf(name, "%s.%03d", p->name, p->pid);
676:
677: return 0;
678:
679: }
680:
681:
682:
683: static long
684:
685: proc_rewinddir(dirh)
686:
687: DIR *dirh;
688:
689: {
690:
691: dirh->index = 0;
692:
693: return 0;
694:
695: }
696:
697:
698:
699: static long
700:
701: proc_closedir(dirh)
702:
703: DIR *dirh;
704:
705: {
706:
707: return 0;
708:
709: }
710:
711: static long
712:
713: proc_pathconf(dir, which)
714:
715: fcookie *dir;
716:
717: int which;
718:
719: {
720:
721: switch(which) {
722:
723: case -1:
724:
725: return DP_MAXREQ;
726:
727: case DP_IOPEN:
728:
729: return UNLIMITED; /* no internal limit on open files */
730:
731: case DP_MAXLINKS:
732:
733: return 1; /* we don't have hard links */
734:
735: case DP_PATHMAX:
736:
737: return PATH_MAX; /* max. path length */
738:
739: case DP_NAMEMAX:
740:
741: return PNAMSIZ; /* max. length of individual name */
742:
743: case DP_ATOMIC:
744:
745: return UNLIMITED; /* all writes are atomic */
746:
747: case DP_TRUNC:
748:
749: return DP_DOSTRUNC; /* file names are truncated to 8.3 */
750:
751: case DP_CASE:
752:
753: return DP_CASEINSENS; /* case preserved, but ignored */
754:
755: default:
756:
757: return EINVFN;
758:
759: }
760:
761: }
762:
763:
764:
765: static long
766:
767: proc_dfree(dir, buf)
768:
769: fcookie *dir;
770:
771: long *buf;
772:
773: {
774:
775: long size;
776:
777: /* "sector" size is the size of the smallest amount of memory that can be
778:
779: allocated. see mem.h for the definition of ROUND
780:
781: */
782:
783: long secsiz = ROUND(1);
784:
785:
786:
787: size = tot_rsize(core, 0) + tot_rsize(alt, 0);
788:
789: *buf++ = size/secsiz; /* number of free clusters */
790:
791: size = tot_rsize(core, 1) + tot_rsize(alt, 1);
792:
793: *buf++ = size/secsiz; /* total number of clusters */
794:
795: *buf++ = secsiz; /* sector size (bytes) */
796:
797: *buf++ = 1; /* cluster size (in sectors) */
798:
799: return 0;
800:
801: }
802:
803:
804:
805: static DEVDRV *
806:
807: proc_getdev(fc, devsp)
808:
809: fcookie *fc;
810:
811: long *devsp;
812:
813: {
814:
815: PROC *p;
816:
817:
818:
819: p = (PROC *)fc->index;
820:
821:
822:
823: *devsp = (long)p;
824:
825: return &proc_device;
826:
827: }
828:
829:
830:
831: /*
832:
833: * PROC device driver
834:
835: */
836:
837:
838:
839: /*
840:
841: * BUG: file locking and the O_SHMODE restrictions are not implemented
842:
843: * for processes
844:
845: */
846:
847:
848:
849: static long
850:
851: proc_open(f)
852:
853: FILEPTR *f;
854:
855: {
856:
857: return 0;
858:
859: }
860:
861:
862:
863: static long
864:
865: proc_write(f, buf, nbytes)
866:
867: FILEPTR *f; const char *buf; long nbytes;
868:
869: {
870:
871: PROC *p;
872:
873: char *where;
874:
875: long bytes_written = 0;
876:
877:
878:
879: p = (PROC *)f->devinfo;
880:
881: where = (char *)f->pos;
882:
883:
884:
885: /* BUG: process read/writes should check for valid addresses */
886:
887:
888:
889: TRACE("proc_write: %ld bytes to %lx", nbytes, where);
890:
891:
892:
893: while (nbytes-- > 0) {
894:
895: *where++ = *buf++;
896:
897: bytes_written++;
898:
899: }
900:
901: f->pos += bytes_written;
902:
903: return bytes_written;
904:
905: }
906:
907:
908:
909: static long
910:
911: proc_read(f, buf, nbytes)
912:
913: FILEPTR *f; char *buf; long nbytes;
914:
915: {
916:
917: PROC *p;
918:
919: char *where;
920:
921: long bytes_read = 0;
922:
923:
924:
925: p = (PROC *)f->devinfo;
926:
927: where = (char *)f->pos;
928:
929:
930:
931: TRACE("proc_read: %ld bytes from %lx", nbytes, where);
932:
933:
934:
935: while (nbytes-- > 0) {
936:
937: *buf++ = *where++;
938:
939: bytes_read++;
940:
941: }
942:
943: f->pos += bytes_read;
944:
945: return bytes_read;
946:
947: }
948:
949:
950:
951: /*
952:
953: * proc_ioctl: currently, the only IOCTL's available are:
954:
955: * PPROCADDR: get address of PROC structure's "interesting" bits
956:
957: * PCTXTSIZE: get the size of the CONTEXT structure
958:
959: * PBASEADDR: get address of process basepage
960:
961: * PSETFLAGS: set the memory allocation flags (e.g. to malloc from fastram)
962:
963: * PGETFLAGS: get the memory allocation flags
964:
965: */
966:
967:
968:
969: static long
970:
971: proc_ioctl(f, mode, buf)
972:
973: FILEPTR *f; int mode; void *buf;
974:
975: {
976:
977: PROC *p;
978:
979:
980:
981: p = (PROC *)f->devinfo;
982:
983: switch(mode) {
984:
985: case PPROCADDR:
986:
987: *((long *)buf) = (long)&p->magic;
988:
989: return 0;
990:
991: case PBASEADDR:
992:
993: *((long *)buf) = (long)p->base;
994:
995: return 0;
996:
997: case PCTXTSIZE:
998:
999: *((long *)buf) = sizeof(CONTEXT);
1000:
1001: return 0;
1002:
1003: case PSETFLAGS:
1004:
1005: /* note: only the low 16 bits are actually used */
1006:
1007: p->memflags = *((long *)buf);
1008:
1009: return 0;
1010:
1011: case PGETFLAGS:
1012:
1013: *((long *)buf) = p->memflags;
1014:
1015: return 0;
1016:
1017: case FIONREAD:
1018:
1019: case FIONWRITE:
1020:
1021: *((long *)buf) = 1L; /* we're always ready for i/o */
1022:
1023: return 0;
1024:
1025: default:
1026:
1027: DEBUG("procfs: bad Fcntl command");
1028:
1029: }
1030:
1031: return EINVFN;
1032:
1033: }
1034:
1035:
1036:
1037: static long
1038:
1039: proc_lseek(f, where, whence)
1040:
1041: FILEPTR *f; long where; int whence;
1042:
1043: {
1044:
1045: switch(whence) {
1046:
1047: case 0:
1048:
1049: f->pos = where;
1050:
1051: break;
1052:
1053: case 1:
1054:
1055: f->pos += where;
1056:
1057: break;
1058:
1059: case 2:
1060:
1061: f->pos = -where;
1062:
1063: break;
1064:
1065: default:
1066:
1067: return EINVFN;
1068:
1069: }
1070:
1071: return f->pos;
1072:
1073: }
1074:
1075:
1076:
1077: static long
1078:
1079: proc_datime(f, timeptr, rwflag)
1080:
1081: FILEPTR *f;
1082:
1083: short *timeptr;
1084:
1085: int rwflag;
1086:
1087: {
1088:
1089: PROC *p;
1090:
1091:
1092:
1093: p = (PROC *)f->devinfo;
1094:
1095: if (rwflag) {
1096:
1097: return EACCDN;
1098:
1099: }
1100:
1101: else {
1102:
1103: *timeptr++ = p->starttime;
1104:
1105: *timeptr++ = p->startdate;
1106:
1107: }
1108:
1109: return 0;
1110:
1111: }
1112:
1113:
1114:
1115: static long
1116:
1117: proc_close(f, pid)
1118:
1119: FILEPTR *f;
1120:
1121: int pid;
1122:
1123: {
1124:
1125: return 0;
1126:
1127: }
1128:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.