|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.5 ! root 5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /* DOS file handling routines */
14:
15:
16:
17: #include "mint.h"
18:
19:
20:
21: static long do_dup P_((int,int));
22:
23: static void unselectme P_((PROC *));
24:
25:
26:
27: /*
28:
29: * first, some utility routines
30:
31: */
32:
33:
34:
35: FILEPTR *
36:
37: do_open(name, rwmode, attr, x)
38:
39: const char *name; /* file name */
40:
41: int rwmode; /* file access mode */
42:
43: int attr; /* TOS attributes for created files (if applicable) */
44:
45: XATTR *x; /* filled in with attributes of opened file */
46:
47: {
48:
49: struct tty *tty;
50:
51: fcookie dir, fc;
52:
53: long devsp;
54:
55: FILEPTR *f;
56:
57: DEVDRV *dev;
58:
59: long r;
60:
61: XATTR xattr;
62:
63: unsigned perm;
64:
65: int creating;
66:
1.1.1.4 root 67: char temp1[PATH_MAX];
68:
1.1.1.3 root 69: extern FILESYS proc_filesys;
70:
1.1 root 71:
72:
73: /* for special BIOS "fake" devices */
74:
75: extern DEVDRV fakedev;
76:
77:
78:
1.1.1.2 root 79: TRACE(("do_open(%s)", name));
1.1 root 80:
81:
82:
83: /*
84:
85: * first step: get a cookie for the directory
86:
87: */
88:
89:
90:
91: r = path2cookie(name, temp1, &dir);
92:
93: if (r) {
94:
1.1.1.2 root 95: mint_errno = (int)r;
1.1 root 96:
1.1.1.2 root 97: DEBUG(("do_open(%s): error %ld", name, r));
1.1 root 98:
99: return NULL;
100:
101: }
102:
103:
104:
105: /*
106:
107: * second step: try to locate the file itself
108:
109: */
110:
111: r = relpath2cookie(&dir, temp1, follow_links, &fc, 0);
112:
113:
114:
115: /*
116:
117: * file found: this is an error if (O_CREAT|O_EXCL) are set
118:
119: */
120:
1.1.1.3 root 121:
122:
1.1 root 123: if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
124:
1.1.1.2 root 125: DEBUG(("do_open(%s): file already exists",name));
1.1 root 126:
127: mint_errno = EACCDN;
128:
1.1.1.3 root 129: release_cookie(&fc);
130:
131: release_cookie(&dir);
132:
1.1 root 133: return NULL;
134:
135: }
136:
137: /*
138:
139: * file not found: maybe we should create it
140:
1.1.1.3 root 141: * note that if r != 0, the fc cookie is invalid (so we don't need to
142:
143: * release it)
144:
1.1 root 145: */
146:
147: if (r == EFILNF && (rwmode & O_CREAT)) {
148:
149: /* check first for write permission in the directory */
150:
151: r = (*dir.fs->getxattr)(&dir, &xattr);
152:
153: if (r == 0) {
154:
155: if (denyaccess(&xattr, S_IWOTH))
156:
157: r = EACCDN;
158:
159: }
160:
161: if (r) {
162:
1.1.1.2 root 163: DEBUG(("do_open(%s): couldn't get "
1.1 root 164:
1.1.1.2 root 165: "write permission on directory",name));
1.1 root 166:
1.1.1.2 root 167: mint_errno = (int)r;
1.1 root 168:
1.1.1.3 root 169: release_cookie(&dir);
170:
1.1 root 171: return NULL;
172:
173: }
174:
175: r = (*dir.fs->creat)(&dir, temp1,
176:
177: (S_IFREG|DEFAULT_MODE) & (~curproc->umask), attr, &fc);
178:
179: if (r) {
180:
1.1.1.2 root 181: DEBUG(("do_open(%s): error %ld while creating file",
1.1 root 182:
1.1.1.2 root 183: name, r));
1.1 root 184:
1.1.1.2 root 185: mint_errno = (int)r;
1.1 root 186:
1.1.1.3 root 187: release_cookie(&dir);
188:
1.1 root 189: return NULL;
190:
191: }
192:
193: creating = 1;
194:
195: } else if (r) {
196:
1.1.1.2 root 197: DEBUG(("do_open(%s): error %ld while searching for file",
1.1 root 198:
1.1.1.2 root 199: name, r));
1.1 root 200:
1.1.1.2 root 201: mint_errno = (int)r;
1.1 root 202:
1.1.1.3 root 203: release_cookie(&dir);
204:
1.1 root 205: return NULL;
206:
207: } else {
208:
209: creating = 0;
210:
211: }
212:
213:
214:
215: /*
216:
217: * check now for permission to actually access the file
218:
219: */
220:
221: r = (*fc.fs->getxattr)(&fc, &xattr);
222:
223: if (r) {
224:
1.1.1.2 root 225: DEBUG(("do_open(%s): couldn't get file attributes",name));
1.1 root 226:
1.1.1.2 root 227: mint_errno = (int)r;
1.1 root 228:
1.1.1.3 root 229: release_cookie(&dir);
230:
231: release_cookie(&fc);
232:
1.1 root 233: return NULL;
234:
235: }
236:
237: /*
238:
239: * we don't do directories
240:
241: */
242:
243: if ( (xattr.mode & S_IFMT) == S_IFDIR ) {
244:
1.1.1.2 root 245: DEBUG(("do_open(%s): file is a directory",name));
1.1 root 246:
1.1.1.3 root 247: release_cookie(&dir);
248:
249: release_cookie(&fc);
250:
1.1 root 251: mint_errno = EFILNF;
252:
253: return NULL;
254:
255: }
256:
257:
258:
259: switch (rwmode & O_RWMODE) {
260:
261: case O_WRONLY:
262:
263: perm = S_IWOTH;
264:
265: break;
266:
267: case O_RDWR:
268:
269: perm = S_IROTH|S_IWOTH;
270:
271: break;
272:
273: case O_EXEC:
274:
275: perm = (fc.fs->fsflags & FS_NOXBIT) ? S_IROTH : S_IXOTH;
276:
277: break;
278:
279: case O_RDONLY:
280:
281: perm = S_IROTH;
282:
283: break;
284:
285: default:
286:
287: perm = 0;
288:
289: ALERT("do_open: bad file access mode: %x", rwmode);
290:
291: }
292:
293: if (!creating && denyaccess(&xattr, perm)) {
294:
1.1.1.2 root 295: DEBUG(("do_open(%s): access to file denied",name));
1.1 root 296:
1.1.1.3 root 297: release_cookie(&dir);
298:
299: release_cookie(&fc);
300:
1.1 root 301: mint_errno = EACCDN;
302:
303: return NULL;
304:
305: }
306:
307:
308:
309: /*
310:
311: * an extra check for write access -- even the superuser shouldn't
312:
313: * write to files with the FA_RDONLY attribute bit set (unless,
314:
1.1.1.3 root 315: * we just created the file, or unless the file is on the proc
316:
317: * file system and hence FA_RDONLY has a different meaning)
1.1 root 318:
319: */
320:
1.1.1.3 root 321: if ( !creating && (xattr.attr & FA_RDONLY) && fc.fs != &proc_filesys) {
1.1 root 322:
323: if ( (rwmode & O_RWMODE) == O_RDWR ||
324:
325: (rwmode & O_RWMODE) == O_WRONLY ) {
326:
1.1.1.2 root 327: DEBUG(("do_open(%s): can't write a read-only file",
1.1 root 328:
1.1.1.2 root 329: name));
1.1 root 330:
1.1.1.3 root 331: release_cookie(&dir);
332:
333: release_cookie(&fc);
334:
1.1 root 335: mint_errno = EACCDN;
336:
337: return NULL;
338:
339: }
340:
341: }
342:
343:
344:
345: /*
346:
347: * if writing to a setuid or setgid file, clear those bits
348:
349: */
350:
351: if ( (perm & S_IWOTH) && (xattr.mode & (S_ISUID|S_ISGID)) ) {
352:
353: xattr.mode &= ~(S_ISUID|S_ISGID);
354:
355: (*fc.fs->chmode)(&fc, (xattr.mode & ~S_IFMT));
356:
357: }
358:
359: /*
360:
361: * If the caller asked for the attributes of the opened file, copy them over.
362:
363: */
364:
365: if (x) *x = xattr;
366:
367:
368:
369: /*
370:
371: * So far, so good. Let's get the device driver now, and try to
372:
373: * actually open the file.
374:
375: */
376:
377: dev = (*fc.fs->getdev)(&fc, &devsp);
378:
379: if (!dev) {
380:
1.1.1.2 root 381: mint_errno = (int)devsp;
1.1 root 382:
1.1.1.2 root 383: DEBUG(("do_open(%s): device driver not found",name));
1.1 root 384:
1.1.1.3 root 385: release_cookie(&dir);
386:
387: release_cookie(&fc);
388:
1.1 root 389: return NULL;
390:
391: }
392:
393:
394:
395: if (dev == &fakedev) { /* fake BIOS devices */
396:
397: f = curproc->handle[devsp];
398:
399: if (!f) {
400:
401: mint_errno = EIHNDL;
402:
403: return 0;
404:
405: }
406:
407: f->links++;
408:
1.1.1.3 root 409: release_cookie(&dir);
410:
411: release_cookie(&fc);
412:
1.1 root 413: return f;
414:
415: }
416:
1.1.1.2 root 417: if (0 == (f = new_fileptr())) {
1.1 root 418:
1.1.1.3 root 419: release_cookie(&dir);
420:
421: release_cookie(&fc);
422:
1.1 root 423: mint_errno = ENSMEM;
424:
425: return NULL;
426:
427: }
428:
429: f->links = 1;
430:
431: f->flags = rwmode;
432:
433: f->pos = 0;
434:
435: f->devinfo = devsp;
436:
437: f->fc = fc;
438:
439: f->dev = dev;
440:
1.1.1.3 root 441: release_cookie(&dir);
442:
1.1 root 443:
444:
445: r = (*dev->open)(f);
446:
447: if (r < 0) {
448:
1.1.1.2 root 449: DEBUG(("do_open(%s): device open failed with error %ld",
1.1 root 450:
1.1.1.2 root 451: name, r));
1.1 root 452:
1.1.1.2 root 453: mint_errno = (int)r;
1.1 root 454:
455: f->links = 0;
456:
1.1.1.3 root 457: release_cookie(&fc);
458:
1.1 root 459: dispose_fileptr(f);
460:
461: return NULL;
462:
463: }
464:
465:
466:
467: /* special code for opening a tty */
468:
469: if (is_terminal(f)) {
470:
471: extern struct tty default_tty; /* in tty.c */
472:
473:
474:
475: tty = (struct tty *)f->devinfo;
476:
477: if (tty->use_cnt == 0) { /* first open for this device? */
478:
479: *tty = default_tty;
480:
481: }
482:
483: tty->use_cnt++;
484:
485: }
486:
487: return f;
488:
489: }
490:
491:
492:
493: /*
494:
495: * helper function for do_close: this closes the indicated file pointer which
496:
497: * is assumed to be associated with process p. The extra parameter is necessary
498:
499: * because f_midipipe mucks with file pointers of other processes, so
500:
501: * sometimes p != curproc.
502:
503: *
504:
505: * Note that the function changedrv() in filesys.c can call this routine.
506:
507: * in that case, f->dev will be 0 to represent an invalid device, and
508:
509: * we cannot call the device close routine.
510:
511: */
512:
513:
514:
515: long
516:
517: do_pclose(p, f)
518:
519: PROC *p;
520:
521: FILEPTR *f;
522:
523: {
524:
525: long r = 0;
526:
527:
528:
529: if (!f) return EIHNDL;
530:
531:
532:
533: /* if this file is "select'd" by this process, unselect it
534:
1.1.1.2 root 535: * (this is just in case we were killed by a signal)
1.1 root 536:
537: */
538:
539:
540:
541: /* BUG? Feature? If media change is detected while we're doing the select,
542:
543: * we'll never unselect (since f->dev is set to NULL by changedrv())
544:
545: */
546:
547: if (f->dev) {
548:
549: (*f->dev->unselect)(f, (long)p, O_RDONLY);
550:
551: (*f->dev->unselect)(f, (long)p, O_WRONLY);
552:
553: }
554:
555:
556:
557: f->links--;
558:
559:
560:
561: /* TTY manipulation must be done *before* calling the device close routine,
562:
563: * since afterwards the TTY structure may no longer exist
564:
565: */
566:
567: if (is_terminal(f) && f->links <= 0) {
568:
569: struct tty *tty = (struct tty *)f->devinfo;
570:
571: tty->use_cnt--;
572:
1.1.1.3 root 573: if (tty->use_cnt <= 0)
574:
575: tty->pgrp = 0;
576:
1.1 root 577: if (tty->use_cnt <= 0 && tty->xkey) {
578:
579: kfree(tty->xkey);
580:
581: tty->xkey = 0;
582:
583: }
584:
585: }
586:
587:
588:
589: if (f->dev) {
590:
591: r = (*f->dev->close)(f, p->pid);
592:
593: if (r) {
594:
1.1.1.2 root 595: DEBUG(("close: device close failed"));
1.1 root 596:
597: }
598:
599: }
600:
601: if (f->links <= 0) {
602:
1.1.1.3 root 603: release_cookie(&f->fc);
604:
1.1 root 605: dispose_fileptr(f);
606:
607: }
608:
609: return r;
610:
611: }
612:
613:
614:
615: long
616:
617: do_close(f)
618:
619: FILEPTR *f;
620:
621: {
622:
623: return do_pclose(curproc, f);
624:
625: }
626:
627:
628:
1.1.1.2 root 629: long ARGS_ON_STACK
1.1 root 630:
631: f_open(name, mode)
632:
633: const char *name;
634:
635: int mode;
636:
637: {
638:
639: int i;
640:
641: FILEPTR *f;
642:
643: PROC *proc;
644:
645:
646:
1.1.1.2 root 647: TRACE(("Fopen(%s, %x)", name, mode));
1.1 root 648:
649: #if O_GLOBAL
650:
651: if (mode & O_GLOBAL) {
652:
653: /* oh, boy! user wants us to open a global handle! */
654:
655: proc = rootproc;
656:
657: }
658:
659: else
660:
661: #endif
662:
663: proc = curproc;
664:
665:
666:
667: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
668:
669: if (!proc->handle[i])
670:
671: goto found_for_open;
672:
673: }
674:
1.1.1.2 root 675: DEBUG(("Fopen(%s): process out of handles",name));
1.1 root 676:
677: return ENHNDL; /* no more handles */
678:
679:
680:
681: found_for_open:
682:
683: mode &= O_USER; /* make sure the mode is legal */
684:
685:
686:
687: /* note: file mode 3 is reserved for the kernel; for users, transmogrify it
688:
689: * into O_RDWR (mode 2)
690:
691: */
692:
693: if ( (mode & O_RWMODE) == O_EXEC ) {
694:
695: mode = (mode & ~O_RWMODE) | O_RDWR;
696:
697: }
698:
699:
700:
1.1.1.5 ! root 701: proc->handle[i] = (FILEPTR *)1; /* reserve this handle */
1.1 root 702:
1.1.1.5 ! root 703: f = do_open(name, mode, 0, (XATTR *)0);
1.1 root 704:
1.1.1.5 ! root 705: proc->handle[i] = (FILEPTR *)0;
1.1 root 706:
707:
708:
709: if (!f) {
710:
711: return mint_errno;
712:
713: }
714:
715: proc->handle[i] = f;
716:
717: /* default is to close non-standard files on exec */
718:
719: proc->fdflags[i] = FD_CLOEXEC;
720:
721:
722:
723: #if O_GLOBAL
724:
725: if (proc != curproc) {
726:
727: /* we just opened a global handle */
728:
729: i += 100;
730:
731: }
732:
733: #endif
734:
735:
736:
1.1.1.2 root 737: TRACE(("Fopen: returning %d", i));
1.1 root 738:
739: return i;
740:
741: }
742:
743:
744:
1.1.1.2 root 745: long ARGS_ON_STACK
1.1 root 746:
747: f_create(name, attrib)
748:
749: const char *name;
750:
751: int attrib;
752:
753: {
754:
755: fcookie dir;
756:
757: int i;
758:
759: FILEPTR *f;
760:
761: long r;
762:
763: PROC *proc;
764:
765: int offset = 0;
766:
1.1.1.4 root 767: char temp1[PATH_MAX];
768:
1.1 root 769:
770:
1.1.1.2 root 771: TRACE(("Fcreate(%s, %x)", name, attrib));
1.1 root 772:
773: #if O_GLOBAL
774:
775: if (attrib & O_GLOBAL) {
776:
777: proc = rootproc;
778:
779: offset = 100;
780:
781: attrib &= ~O_GLOBAL;
782:
783: }
784:
785: else
786:
787: #endif
788:
789: proc = curproc;
790:
791:
792:
793: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
794:
795: if (!proc->handle[i])
796:
797: goto found_for_create;
798:
799: }
800:
1.1.1.2 root 801: DEBUG(("Fcreate(%s): process out of handles",name));
1.1 root 802:
803: return ENHNDL; /* no more handles */
804:
805:
806:
807: found_for_create:
808:
809: if (attrib == FA_LABEL) {
810:
811: r = path2cookie(name, temp1, &dir);
812:
813: if (r) return r;
814:
815: r = (*dir.fs->writelabel)(&dir, temp1);
816:
1.1.1.3 root 817: release_cookie(&dir);
818:
1.1 root 819: if (r) return r;
820:
821: /*
822:
823: * just in case the caller tries to do something with this handle,
824:
825: * make it point to u:\dev\null
826:
827: */
828:
829: f = do_open("u:\\dev\\null", O_RDWR|O_CREAT|O_TRUNC, 0,
830:
831: (XATTR *)0);
832:
833: proc->handle[i] = f;
834:
1.1.1.4 root 835: proc->fdflags[i] = FD_CLOEXEC;
836:
1.1 root 837: return i+offset;
838:
839: }
840:
841: if (attrib & (FA_LABEL|FA_DIR)) {
842:
1.1.1.2 root 843: DEBUG(("Fcreate(%s,%x): illegal attributes",name,attrib));
1.1 root 844:
845: return EACCDN;
846:
847: }
848:
849:
850:
1.1.1.5 ! root 851: proc->handle[i] = (FILEPTR *)1; /* reserve this handle */
! 852:
1.1 root 853: f = do_open(name, O_RDWR|O_CREAT|O_TRUNC, attrib, (XATTR *)0);
854:
1.1.1.5 ! root 855: proc->handle[i] = (FILEPTR *)0;
! 856:
1.1 root 857:
858:
859: if (!f) {
860:
1.1.1.2 root 861: DEBUG(("Fcreate(%s) failed, error %d", name, mint_errno));
1.1 root 862:
863: return mint_errno;
864:
865: }
866:
867: proc->handle[i] = f;
868:
1.1.1.4 root 869: proc->fdflags[i] = FD_CLOEXEC;
870:
1.1 root 871: i += offset;
872:
1.1.1.2 root 873: TRACE(("Fcreate: returning %d", i));
1.1 root 874:
875: return i;
876:
877: }
878:
879:
880:
1.1.1.2 root 881: long ARGS_ON_STACK
1.1 root 882:
883: f_close(fh)
884:
885: int fh;
886:
887: {
888:
889: FILEPTR *f;
890:
891: long r;
892:
893: PROC *proc;
894:
895:
896:
1.1.1.2 root 897: TRACE(("Fclose: %d", fh));
1.1 root 898:
899: #if O_GLOBAL
900:
901: if (fh >= 100) {
902:
903: fh -= 100;
904:
905: proc = rootproc;
906:
907: }
908:
909: else
910:
911: #endif
912:
913: proc = curproc;
914:
915:
916:
1.1.1.2 root 917: if (fh < 0 || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 918:
919: return EIHNDL;
920:
921: }
922:
1.1.1.3 root 923: r = do_pclose(proc, f);
1.1 root 924:
925:
926:
927: /* standard handles should be restored to default values */
928:
929: /* do this for TOS domain only! */
930:
931: if (proc->domain == DOM_TOS) {
932:
933: if (fh == 0 || fh == 1)
934:
935: f = proc->handle[-1];
936:
937: else if (fh == 2 || fh == 3)
938:
939: f = proc->handle[-fh];
940:
941: else
942:
943: f = 0;
944:
945: } else
946:
947: f = 0;
948:
949:
950:
1.1.1.4 root 951: if (f) {
952:
953: f->links++;
954:
955: proc->fdflags[fh] = 0;
956:
957: }
1.1 root 958:
959: proc->handle[fh] = f;
960:
961: return r;
962:
963: }
964:
965:
966:
1.1.1.2 root 967: long ARGS_ON_STACK
1.1 root 968:
969: f_read(fh, count, buf)
970:
971: int fh;
972:
973: long count;
974:
975: char *buf;
976:
977: {
978:
979: FILEPTR *f;
980:
981:
982:
983: PROC *proc;
984:
985:
986:
987: #if O_GLOBAL
988:
989: if (fh >= 100) {
990:
991: fh -= 100;
992:
993: proc = rootproc;
994:
995: }
996:
997: else
998:
999: #endif
1000:
1001: proc = curproc;
1002:
1003:
1004:
1.1.1.2 root 1005: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1006:
1.1.1.2 root 1007: DEBUG(("Fread: invalid handle: %d", fh));
1.1 root 1008:
1009: return EIHNDL;
1010:
1011: }
1012:
1013: if ( (f->flags & O_RWMODE) == O_WRONLY ) {
1014:
1.1.1.2 root 1015: DEBUG(("Fread: read on a write-only handle"));
1.1 root 1016:
1017: return EACCDN;
1018:
1019: }
1020:
1021: if (is_terminal(f))
1022:
1023: return tty_read(f, buf, count);
1024:
1025:
1026:
1.1.1.3 root 1027: TRACELOW(("Fread: %ld bytes from handle %d to %lx", count, fh, buf));
1.1 root 1028:
1029: return (*f->dev->read)(f, buf, count);
1030:
1031: }
1032:
1033:
1034:
1.1.1.2 root 1035: long ARGS_ON_STACK
1.1 root 1036:
1037: f_write(fh, count, buf)
1038:
1039: int fh;
1040:
1041: long count;
1042:
1043: const char *buf;
1044:
1045: {
1046:
1047: FILEPTR *f;
1048:
1049: PROC *proc;
1050:
1051: long r;
1052:
1053:
1054:
1055: #if O_GLOBAL
1056:
1057: if (fh >= 100) {
1058:
1059: fh -= 100;
1060:
1061: proc = rootproc;
1062:
1063: }
1064:
1065: else
1066:
1067: #endif
1068:
1069: proc = curproc;
1070:
1071:
1072:
1.1.1.2 root 1073: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1074:
1.1.1.2 root 1075: DEBUG(("Fwrite: bad handle: %d", fh));
1.1 root 1076:
1077: return EIHNDL;
1078:
1079: }
1080:
1081: if ( (f->flags & O_RWMODE) == O_RDONLY ) {
1082:
1.1.1.2 root 1083: DEBUG(("Fwrite: write on a read-only handle"));
1.1 root 1084:
1085: return EACCDN;
1086:
1087: }
1088:
1089: if (is_terminal(f))
1090:
1091: return tty_write(f, buf, count);
1092:
1093:
1094:
1095: /* it would be faster to do this in the device driver, but this
1096:
1097: * way the drivers are easier to write
1098:
1099: */
1100:
1.1.1.3 root 1101: if (f->flags & O_APPEND) {
1.1 root 1102:
1103: r = (*f->dev->lseek)(f, 0L, SEEK_END);
1104:
1.1.1.3 root 1105: /* ignore errors from unseekable files (e.g. pipes) */
1106:
1107: if (r == EACCDN)
1108:
1109: r = 0;
1110:
1111: } else
1.1 root 1112:
1113: r = 0;
1114:
1115: if (r >= 0) {
1116:
1.1.1.3 root 1117: TRACELOW(("Fwrite: %ld bytes to handle %d", count, fh));
1.1 root 1118:
1119: r = (*f->dev->write)(f, buf, count);
1120:
1121: }
1122:
1123: if (r < 0) {
1124:
1.1.1.2 root 1125: DEBUG(("Fwrite: error %ld", r));
1.1 root 1126:
1127: }
1128:
1129: return r;
1130:
1131: }
1132:
1133:
1134:
1.1.1.2 root 1135: long ARGS_ON_STACK
1.1 root 1136:
1137: f_seek(place, fh, how)
1138:
1139: long place;
1140:
1141: int fh;
1142:
1143: int how;
1144:
1145: {
1146:
1147: FILEPTR *f;
1148:
1149: PROC *proc;
1150:
1151:
1152:
1.1.1.2 root 1153: TRACE(("Fseek(%ld, %d) on handle %d", place, how, fh));
1.1 root 1154:
1155: #if O_GLOBAL
1156:
1157: if (fh >= 100) {
1158:
1159: fh -= 100;
1160:
1161: proc = rootproc;
1162:
1163: }
1164:
1165: else
1166:
1167: #endif
1168:
1169: proc = curproc;
1170:
1171:
1172:
1.1.1.2 root 1173: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1174:
1.1.1.2 root 1175: DEBUG(("Fseek: bad handle: %d", fh));
1.1 root 1176:
1177: return EIHNDL;
1178:
1179: }
1180:
1181: if (is_terminal(f)) {
1182:
1183: return 0;
1184:
1185: }
1186:
1187: return (*f->dev->lseek)(f, place, how);
1188:
1189: }
1190:
1191:
1192:
1193: /* duplicate file pointer fh; returns a new file pointer >= min, if
1194:
1195: one exists, or ENHNDL if not. called by f_dup and f_cntl
1196:
1197: */
1198:
1199:
1200:
1201: static long do_dup(fh, min)
1202:
1203: int fh, min;
1204:
1205: {
1206:
1207: FILEPTR *f;
1208:
1209: int i;
1210:
1211: PROC *proc;
1212:
1213:
1214:
1215: for (i = min; i < MAX_OPEN; i++) {
1216:
1217: if (!curproc->handle[i])
1218:
1219: goto found;
1220:
1221: }
1222:
1223: return ENHNDL; /* no more handles */
1224:
1225: found:
1226:
1227: #if O_GLOBAL
1228:
1229: if (fh >= 100) {
1230:
1231: fh -= 100;
1232:
1233: proc = rootproc;
1234:
1235: } else
1236:
1237: #endif
1238:
1239: proc = curproc;
1240:
1241:
1242:
1.1.1.2 root 1243: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh]))
1.1 root 1244:
1245: return EIHNDL;
1246:
1247:
1248:
1249: curproc->handle[i] = f;
1250:
1251:
1252:
1253: /* set default file descriptor flags */
1254:
1255: if (i >= 0) {
1256:
1257: if (i >= MIN_OPEN)
1258:
1259: curproc->fdflags[i] = FD_CLOEXEC;
1260:
1261: else
1262:
1263: curproc->fdflags[i] = 0;
1264:
1265: }
1266:
1267: f->links++;
1268:
1269: return i;
1270:
1271: }
1272:
1273:
1274:
1.1.1.2 root 1275: long ARGS_ON_STACK
1.1 root 1276:
1277: f_dup(fh)
1278:
1279: int fh;
1280:
1281: {
1282:
1283: long r;
1284:
1285: r = do_dup(fh, MIN_OPEN);
1286:
1.1.1.2 root 1287: TRACE(("Fdup(%d) -> %ld", fh, r));
1.1 root 1288:
1289: return r;
1290:
1291: }
1292:
1293:
1294:
1.1.1.2 root 1295: long ARGS_ON_STACK
1.1 root 1296:
1297: f_force(newh, oldh)
1298:
1299: int newh;
1300:
1301: int oldh;
1302:
1303: {
1304:
1305: FILEPTR *f;
1306:
1307: PROC *proc;
1308:
1309:
1310:
1.1.1.2 root 1311: TRACE(("Fforce(%d, %d)", newh, oldh));
1.1 root 1312:
1313:
1314:
1315: #if O_GLOBAL
1316:
1317: if (oldh >= 100) {
1318:
1319: oldh -= 100;
1320:
1321: proc = rootproc;
1322:
1323: } else
1324:
1325: #endif
1326:
1327: proc = curproc;
1328:
1329:
1330:
1331: if (oldh < MIN_HANDLE || oldh >= MAX_OPEN ||
1332:
1.1.1.2 root 1333: 0 == (f = proc->handle[oldh])) {
1.1 root 1334:
1.1.1.2 root 1335: DEBUG(("Fforce: old handle invalid"));
1.1 root 1336:
1337: return EIHNDL;
1338:
1339: }
1340:
1341:
1342:
1343: if (newh < MIN_HANDLE || newh >= MAX_OPEN) {
1344:
1.1.1.2 root 1345: DEBUG(("Fforce: new handle out of range"));
1.1 root 1346:
1347: return EIHNDL;
1348:
1349: }
1350:
1351:
1352:
1353: (void)do_close(curproc->handle[newh]);
1354:
1355: curproc->handle[newh] = f;
1356:
1.1.1.4 root 1357: /* set default file descriptor flags */
1358:
1359: if (newh >= 0)
1360:
1361: curproc->fdflags[newh] = (newh >= MIN_OPEN) ? FD_CLOEXEC : 0;
1362:
1.1 root 1363: f->links++;
1364:
1365: /*
1366:
1367: * special: for a tty, if this is becoming a control terminal and the
1368:
1369: * tty doesn't have a pgrp yet, make it have the pgrp of the process
1370:
1371: * doing the Fforce
1372:
1373: */
1374:
1375: if (is_terminal(f) && newh == -1) {
1376:
1377: struct tty *tty = (struct tty *)f->devinfo;
1378:
1379:
1380:
1381: if (!tty->pgrp)
1382:
1383: tty->pgrp = curproc->pgrp;
1384:
1385: }
1386:
1.1.1.4 root 1387: return 0;
1.1 root 1388:
1389: }
1390:
1391:
1392:
1.1.1.2 root 1393: long ARGS_ON_STACK
1.1 root 1394:
1395: f_datime(timeptr, fh, rwflag)
1396:
1397: short *timeptr;
1398:
1399: int fh;
1400:
1401: int rwflag;
1402:
1403: {
1404:
1405: FILEPTR *f;
1406:
1407: PROC *proc;
1408:
1409:
1410:
1.1.1.2 root 1411: TRACE(("Fdatime(%d)", fh));
1.1 root 1412:
1413: #if O_GLOBAL
1414:
1415: if (fh >= 100) {
1416:
1417: fh -= 100;
1418:
1419: proc = rootproc;
1420:
1421: }
1422:
1423: else
1424:
1425: #endif
1426:
1427: proc = curproc;
1428:
1429:
1430:
1.1.1.2 root 1431: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1432:
1.1.1.2 root 1433: DEBUG(("Fdatime: invalid handle"));
1.1 root 1434:
1435: return EIHNDL;
1436:
1437: }
1438:
1439:
1440:
1441: /* some programs use Fdatime to test for TTY devices */
1442:
1443: if (is_terminal(f))
1444:
1445: return EACCDN;
1446:
1447:
1448:
1449: return (*f->dev->datime)(f, timeptr, rwflag);
1450:
1451: }
1452:
1453:
1454:
1.1.1.2 root 1455: long ARGS_ON_STACK
1.1 root 1456:
1457: f_lock(fh, mode, start, length)
1458:
1459: int fh, mode;
1460:
1461: long start, length;
1462:
1463: {
1464:
1465: FILEPTR *f;
1466:
1467: struct flock lock;
1468:
1469: PROC *proc;
1470:
1471:
1472:
1473: #if O_GLOBAL
1474:
1475: if (fh >= 100) {
1476:
1477: fh -= 100;
1478:
1479: proc = rootproc;
1480:
1481: }
1482:
1483: else
1484:
1485: #endif
1486:
1487: proc = curproc;
1488:
1489:
1490:
1.1.1.2 root 1491: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1492:
1.1.1.2 root 1493: DEBUG(("Flock: invalid handle"));
1.1 root 1494:
1495: return EIHNDL;
1496:
1497: }
1498:
1.1.1.2 root 1499: TRACE(("Flock(%d,%d,%ld,%ld)", fh, mode, start, length));
1.1 root 1500:
1501: lock.l_whence = SEEK_SET;
1502:
1503: lock.l_start = start;
1504:
1505: lock.l_len = length;
1506:
1507:
1508:
1509: if (mode == 0) /* create a lock */
1510:
1511: lock.l_type = F_WRLCK;
1512:
1513: else if (mode == 1) /* unlock region */
1514:
1515: lock.l_type = F_UNLCK;
1516:
1517: else
1518:
1519: return EINVFN;
1520:
1521:
1522:
1523: return (*f->dev->ioctl)(f, F_SETLK, &lock);
1524:
1525: }
1526:
1527:
1528:
1529: /*
1530:
1531: * extensions to GEMDOS:
1532:
1533: */
1534:
1535:
1536:
1537: /*
1538:
1539: * Fpipe(int *handles): opens a pipe. if successful, returns 0, and
1540:
1541: * sets handles[0] to a file descriptor for the read end of the pipe
1542:
1543: * and handles[1] to one for the write end.
1544:
1545: */
1546:
1547:
1548:
1.1.1.2 root 1549: long ARGS_ON_STACK
1.1 root 1550:
1551: f_pipe(usrh)
1552:
1553: short *usrh;
1554:
1555: {
1556:
1557: FILEPTR *in, *out;
1558:
1559: static int pipeno = 0;
1560:
1561: int i, j;
1562:
1563: char pipename[32]; /* MAGIC: 32 >= strlen "u:\pipe\sys$pipe.000\0" */
1564:
1565:
1566:
1.1.1.2 root 1567: TRACE(("Fpipe"));
1.1 root 1568:
1569:
1570:
1571: /* BUG: more than 999 open pipes hangs the system */
1572:
1573: do {
1574:
1575: ksprintf(pipename, "u:\\pipe\\sys$pipe.%03d", pipeno);
1576:
1577: pipeno++; if (pipeno > 999) pipeno = 0;
1578:
1.1.1.2 root 1579: out = do_open(pipename, O_WRONLY|O_CREAT|O_EXCL, FA_RDONLY|FA_HIDDEN|FA_CHANGED,
1580:
1581: (XATTR *)0);
1.1 root 1582:
1583: /* read-only attribute means unidirectional fifo */
1584:
1585: /* hidden attribute means check for broken pipes */
1586:
1.1.1.2 root 1587: /* changed attribute means act like Unix fifos */
1588:
1.1 root 1589: } while (out == 0 && mint_errno == EACCDN);
1590:
1591:
1592:
1593: if (!out) {
1594:
1.1.1.2 root 1595: DEBUG(("Fpipe: error %d", mint_errno));
1.1 root 1596:
1597: return mint_errno;
1598:
1599: }
1600:
1601:
1602:
1603: in = do_open(pipename, O_RDONLY, 0, (XATTR *)0);
1604:
1605: if (!in) {
1606:
1.1.1.2 root 1607: DEBUG(("Fpipe: in side of pipe not opened (error %d)",
1.1 root 1608:
1.1.1.2 root 1609: mint_errno));
1.1 root 1610:
1611: (void)do_close(out);
1612:
1613: return mint_errno;
1614:
1615: }
1616:
1617:
1618:
1619: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
1620:
1621: if (curproc->handle[i] == 0)
1622:
1623: break;
1624:
1625: }
1626:
1627:
1628:
1629: for (j = i+1; j < MAX_OPEN; j++) {
1630:
1631: if (curproc->handle[j] == 0)
1632:
1633: break;
1634:
1635: }
1636:
1637:
1638:
1639: if (j >= MAX_OPEN) {
1640:
1.1.1.2 root 1641: DEBUG(("Fpipe: not enough handles left"));
1.1 root 1642:
1643: (void) do_close(in);
1644:
1645: (void) do_close(out);
1646:
1647: return ENHNDL;
1648:
1649: }
1650:
1651: curproc->handle[i] = in; curproc->handle[j] = out;
1652:
1653: /* leave pipes open across Pexec */
1654:
1655: curproc->fdflags[i] = 0;
1656:
1657: curproc->fdflags[j] = 0;
1658:
1659:
1660:
1661: usrh[0] = i;
1662:
1663: usrh[1] = j;
1664:
1.1.1.2 root 1665: TRACE(("Fpipe: returning 0: input %d output %d",i,j));
1.1 root 1666:
1667: return 0;
1668:
1669: }
1670:
1671:
1672:
1673: /*
1674:
1675: * f_cntl: a combination "ioctl" and "fcntl". Some functions are
1676:
1677: * handled here, if they apply to the file descriptors directly
1678:
1679: * (e.g. F_DUPFD) or if they're easily translated into file system
1680:
1681: * functions (e.g. FSTAT). Others are passed on to the device driver
1682:
1683: * via dev->ioctl.
1684:
1685: */
1686:
1687:
1688:
1.1.1.2 root 1689: long ARGS_ON_STACK
1.1 root 1690:
1691: f_cntl(fh, arg, cmd)
1692:
1693: int fh;
1694:
1695: long arg;
1696:
1697: int cmd;
1698:
1699: {
1700:
1701: FILEPTR *f;
1702:
1703: PROC *proc;
1704:
1705: struct flock *fl;
1706:
1707: long r;
1708:
1709:
1710:
1.1.1.2 root 1711: TRACE(("Fcntl(%d, cmd=0x%x)", fh, cmd));
1.1 root 1712:
1713: #if O_GLOBAL
1714:
1715: if (fh >= 100) {
1716:
1717: fh -= 100;
1718:
1719: proc = rootproc;
1720:
1721: }
1722:
1723: else
1724:
1725: #endif
1726:
1727: proc = curproc;
1728:
1729:
1730:
1731: if (fh < MIN_HANDLE || fh >= MAX_OPEN) {
1732:
1.1.1.2 root 1733: DEBUG(("Fcntl: bad file handle"));
1.1 root 1734:
1735: return EIHNDL;
1736:
1737: }
1738:
1739:
1740:
1741: if (cmd == F_DUPFD) {
1742:
1743: #if O_GLOBAL
1744:
1745: if (proc != curproc) fh += 100;
1746:
1747: #endif
1748:
1749: return do_dup(fh, (int)arg);
1750:
1751: }
1752:
1753:
1754:
1755: f = proc->handle[fh];
1756:
1757: if (!f) return EIHNDL;
1758:
1759:
1760:
1761: switch(cmd) {
1762:
1763: case F_GETFD:
1764:
1.1.1.2 root 1765: TRACE(("Fcntl F_GETFD"));
1.1 root 1766:
1767: if (fh < 0) return EIHNDL;
1768:
1769: return proc->fdflags[fh];
1770:
1771: case F_SETFD:
1772:
1.1.1.2 root 1773: TRACE(("Fcntl F_SETFD"));
1.1 root 1774:
1775: if (fh < 0) return EIHNDL;
1776:
1777: proc->fdflags[fh] = arg;
1778:
1779: return 0;
1780:
1781: case F_GETFL:
1782:
1.1.1.2 root 1783: TRACE(("Fcntl F_GETFL"));
1.1 root 1784:
1785: return f->flags & O_USER;
1786:
1787: case F_SETFL:
1788:
1.1.1.2 root 1789: TRACE(("Fcntl F_SETFL"));
1.1 root 1790:
1791: arg &= O_USER; /* make sure only user bits set */
1792:
1.1.1.3 root 1793: #if 0
1794:
1.1 root 1795: /* COMPATIBILITY WITH OLD VERSIONS ONLY */
1796:
1797: /* THIS CODE WILL GO AWAY. REALLY! */
1798:
1799: if (arg & 4) {
1800:
1801: arg |= O_NDELAY;
1802:
1803: arg &= ~4;
1804:
1805: }
1806:
1.1.1.3 root 1807: #endif
1808:
1.1 root 1809:
1810:
1811: /* make sure the file access and sharing modes are not changed */
1812:
1813: arg &= ~(O_RWMODE|O_SHMODE);
1814:
1815: arg |= f->flags & (O_RWMODE|O_SHMODE);
1816:
1817: f->flags &= ~O_USER; /* set user bits to arg */
1818:
1819: f->flags |= arg;
1820:
1821: return 0;
1822:
1823: case FSTAT:
1824:
1825: return (*f->fc.fs->getxattr)(&f->fc, (XATTR *)arg);
1826:
1827: case F_SETLK:
1828:
1.1.1.2 root 1829: case F_SETLKW:
1830:
1.1 root 1831: /* make sure that the file was opened with appropriate permissions */
1832:
1833: fl = (struct flock *)arg;
1834:
1835: if (fl->l_type == F_RDLCK) {
1836:
1837: if ( (f->flags & O_RWMODE) == O_WRONLY )
1838:
1839: return EACCDN;
1840:
1841: } else {
1842:
1843: if ( (f->flags & O_RWMODE) == O_RDONLY )
1844:
1845: return EACCDN;
1846:
1847: }
1848:
1849: /* fall through to device ioctl */
1850:
1851: default:
1852:
1.1.1.2 root 1853: TRACE(("Fcntl mode %x: calling ioctl",cmd));
1.1 root 1854:
1855: r = (*f->dev->ioctl)(f, cmd, (void *)arg);
1856:
1857: if (r == EINVFN && is_terminal(f)) {
1858:
1859: r = tty_ioctl(f, cmd, (void *)arg);
1860:
1861: }
1862:
1863: return r;
1864:
1865: }
1866:
1867: }
1868:
1869:
1870:
1871: /*
1872:
1873: * fselect(timeout, rfd, wfd, xfd)
1874:
1875: * timeout is an (unsigned) 16 bit integer giving the maximum number
1876:
1877: * of milliseconds to wait; rfd, wfd, and xfd are pointers to 32 bit
1878:
1879: * integers containing bitmasks that describe which file descriptors
1880:
1881: * we're interested in. These masks are changed to represent which
1882:
1883: * file descriptors actually have data waiting (rfd), are ready to
1884:
1885: * output (wfd), or have exceptional conditions (xfd -- currently
1886:
1887: * ignored). If timeout is 0, fselect blocks until some file descriptor
1888:
1889: * is ready; otherwise, it waits only "timeout" milliseconds.
1890:
1891: * Return value: number of file descriptors that are available for
1892:
1893: * reading/writing; or a negative error number.
1894:
1895: */
1896:
1897:
1898:
1899: /* helper function for time outs */
1900:
1901: static void
1902:
1903: unselectme(p)
1904:
1905: PROC *p;
1906:
1907: {
1908:
1909: wakeselect((long)p);
1910:
1911: }
1912:
1913:
1914:
1.1.1.2 root 1915: long ARGS_ON_STACK
1.1 root 1916:
1917: f_select(timeout, rfdp, wfdp, xfdp)
1918:
1919: unsigned timeout;
1920:
1921: long *rfdp, *wfdp, *xfdp;
1922:
1923: {
1924:
1925: long rfd, wfd;
1926:
1927: long mask, bytes;
1928:
1929: int i, count;
1930:
1931: FILEPTR *f;
1932:
1933: PROC *p;
1934:
1935: TIMEOUT *t;
1936:
1.1.1.3 root 1937: short sr;
1938:
1.1 root 1939:
1940:
1.1.1.3 root 1941: if (xfdp)
1942:
1943: *xfdp = 0;
1.1.1.2 root 1944:
1945:
1946:
1.1 root 1947: if (rfdp) {
1948:
1949: rfd = *rfdp; *rfdp = 0;
1950:
1951: }
1952:
1953: else
1954:
1955: rfd = 0;
1956:
1957: if (wfdp) {
1958:
1959: wfd = *wfdp; *wfdp = 0;
1960:
1961: }
1962:
1963: else
1964:
1965: wfd = 0;
1966:
1967:
1968:
1.1.1.2 root 1969: TRACE(("Fselect(%u, %lx, %lx)", timeout, rfd, wfd));
1.1 root 1970:
1971: p = curproc; /* help the optimizer out */
1972:
1973:
1974:
1975: /* first, validate the masks */
1976:
1977: mask = 1L;
1978:
1979: for (i = 0; i < MAX_OPEN; i++) {
1980:
1981: if ( ((rfd & mask) || (wfd & mask)) && !(p->handle[i]) ) {
1982:
1.1.1.4 root 1983: DEBUG(("Fselect: invalid handle: %d", i));
1.1 root 1984:
1985: return EIHNDL;
1986:
1987: }
1988:
1989: mask = mask << 1L;
1990:
1991: }
1992:
1993:
1994:
1995: /* now, loop through the file descriptors, setting up the select process */
1996:
1997: /* NOTE: wakeselect will set p->wait_cond to 0 if data arrives during the
1998:
1999: * selection
2000:
2001: * Also note: because of the validation above, we may assume that the
2002:
2003: * file handles are valid here. However, this assumption may no longer
2004:
2005: * be true after we've gone to sleep, since a signal handler may have
2006:
2007: * closed one of the handles.
2008:
2009: */
2010:
2011:
2012:
2013: mask = 1L;
2014:
2015: count = 0;
2016:
1.1.1.2 root 2017: curproc->wait_cond = (long)wakeselect; /* flag */
1.1 root 2018:
2019:
2020:
2021: for (i = 0; i < MAX_OPEN; i++) {
2022:
2023: if (rfd & mask) {
2024:
2025: f = p->handle[i];
2026:
1.1.1.5 ! root 2027: if ((*f->dev->select)(f, (long)p, O_RDONLY) == 1) {
1.1 root 2028:
2029: count++;
2030:
2031: *rfdp |= mask;
2032:
2033: }
2034:
2035: }
2036:
2037: if (wfd & mask) {
2038:
2039: f = p->handle[i];
2040:
1.1.1.5 ! root 2041: if ((*f->dev->select)(f, (long)p, O_WRONLY) == 1) {
1.1 root 2042:
2043: count++;
2044:
2045: *wfdp |= mask;
2046:
2047: }
2048:
2049: }
2050:
2051: mask = mask << 1L;
2052:
2053: }
2054:
2055:
2056:
2057: if (count == 0) {
2058:
2059: /* OK, now let's set a timeout */
2060:
2061:
2062:
2063: if (timeout) {
2064:
2065: t = addtimeout((long)timeout, unselectme);
2066:
2067: } else {
2068:
2069: t = 0;
2070:
2071: }
2072:
2073:
2074:
1.1.1.3 root 2075: sr = spl7();
2076:
2077:
2078:
1.1 root 2079: /* curproc->wait_cond changes when data arrives or the timeout happens */
2080:
1.1.1.2 root 2081: while (curproc->wait_cond == (long)wakeselect) {
1.1 root 2082:
1.1.1.2 root 2083: TRACE(("sleeping in Fselect"));
1.1 root 2084:
1.1.1.2 root 2085: sleep(SELECT_Q, (long)wakeselect);
1.1 root 2086:
2087: }
2088:
1.1.1.3 root 2089: spl(sr);
2090:
1.1 root 2091:
2092:
2093: /* we can cancel the time out now (if it hasn't already happened) */
2094:
2095: if (t) canceltimeout(t);
2096:
2097:
2098:
2099: /* OK, let's see what data arrived (if any) */
2100:
2101: mask = 1L;
2102:
2103: for (i = 0; i < MAX_OPEN; i++) {
2104:
2105: if (rfd & mask) {
2106:
2107: f = p->handle[i];
2108:
2109: if (f) {
2110:
2111: bytes = 1L;
2112:
2113: (void)(*f->dev->ioctl)(f, FIONREAD,&bytes);
2114:
2115: if (bytes > 0) {
2116:
2117: *rfdp |= mask;
2118:
2119: count++;
2120:
2121: }
2122:
2123: }
2124:
2125: }
2126:
2127: if (wfd & mask) {
2128:
2129: f = p->handle[i];
2130:
2131: if (f) {
2132:
2133: bytes = 1L;
2134:
2135: (void)(*f->dev->ioctl)(f, FIONWRITE,&bytes);
2136:
2137: if (bytes > 0) {
2138:
2139: *wfdp |= mask;
2140:
2141: count++;
2142:
2143: }
2144:
2145: }
2146:
2147: }
2148:
2149: mask = mask << 1L;
2150:
2151: }
2152:
2153: }
2154:
2155:
2156:
2157: /* at this point, we either have data or a time out */
2158:
2159: /* cancel all the selects */
2160:
2161: mask = 1L;
2162:
2163:
2164:
2165: for (i = 0; i < MAX_OPEN; i++) {
2166:
2167: if (rfd & mask) {
2168:
2169: f = p->handle[i];
2170:
2171: if (f)
2172:
2173: (*f->dev->unselect)(f, (long)p, O_RDONLY);
2174:
2175: }
2176:
2177: if (wfd & mask) {
2178:
2179: f = p->handle[i];
2180:
2181: if (f)
2182:
2183: (*f->dev->unselect)(f, (long)p, O_WRONLY);
2184:
2185: }
2186:
2187: mask = mask << 1L;
2188:
2189: }
2190:
2191:
2192:
1.1.1.2 root 2193: TRACE(("Fselect: returning %d", count));
1.1 root 2194:
2195: return count;
2196:
2197: }
2198:
2199:
2200:
2201:
2202:
2203: /*
2204:
2205: * GEMDOS extension: Fmidipipe
2206:
2207: * Fmidipipe(pid, in, out) manipultes the MIDI file handles (handles -4 and -5)
2208:
2209: * of process "pid" so that they now point to the files with handles "in" and
2210:
2211: * "out" in the calling process
2212:
2213: */
2214:
2215:
2216:
1.1.1.2 root 2217: long ARGS_ON_STACK
1.1 root 2218:
2219: f_midipipe(pid, in, out)
2220:
2221: int pid, in, out;
2222:
2223: {
2224:
2225: PROC *p;
2226:
2227: FILEPTR *fin, *fout;
2228:
2229:
2230:
2231: /* first, find the process */
2232:
2233:
2234:
2235: if (pid == 0)
2236:
2237: p = curproc;
2238:
2239: else {
2240:
2241: p = pid2proc(pid);
2242:
2243: if (!p)
2244:
2245: return EFILNF;
2246:
2247: }
2248:
2249:
2250:
2251: /* next, validate the input and output file handles */
2252:
1.1.1.2 root 2253: if (in < MIN_HANDLE || in >= MAX_OPEN || (0==(fin = curproc->handle[in])))
1.1 root 2254:
2255: return EIHNDL;
2256:
2257: if ( (fin->flags & O_RWMODE) == O_WRONLY ) {
2258:
1.1.1.2 root 2259: DEBUG(("Fmidipipe: input side is write only"));
1.1 root 2260:
2261: return EACCDN;
2262:
2263: }
2264:
1.1.1.2 root 2265: if (out < MIN_HANDLE || out >= MAX_OPEN || (0==(fout = curproc->handle[out])))
1.1 root 2266:
2267: return EIHNDL;
2268:
2269: if ( (fout->flags & O_RWMODE) == O_RDONLY ) {
2270:
1.1.1.2 root 2271: DEBUG(("Fmidipipe: output side is read only"));
1.1 root 2272:
2273: return EACCDN;
2274:
2275: }
2276:
2277:
2278:
2279: /* OK, duplicate the handles and put them in the new process */
2280:
2281: fin->links++; fout->links++;
2282:
2283: (void)do_pclose(p, p->midiin);
2284:
2285: (void)do_pclose(p, p->midiout);
2286:
2287: p->midiin = fin; p->midiout = fout;
2288:
2289: return 0;
2290:
2291: }
2292:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.