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