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