Annotation of MiNT/doc/fifo.doc, revision 1.1

1.1     ! root        1: Using Fifo's:
        !             2: 
        !             3: 
        !             4: 
        !             5: Fifo's (first-in first-out pipes) are actually very easy to
        !             6: 
        !             7: use. Here are a couple of things to keep in mind:
        !             8: 
        !             9: 
        !            10: 
        !            11: (1) The server program (the one that's going to be listening
        !            12: 
        !            13:     for requests from clients) should create the fifo with
        !            14: 
        !            15:     Fcreate(). The file descriptor returned from Fcreate is
        !            16: 
        !            17:     the "server" descriptor; descriptors returned by Fopen will
        !            18: 
        !            19:     be "client" descriptors. Data written to the server descriptor
        !            20: 
        !            21:     can be read by client descriptors, and vice-versa.
        !            22: 
        !            23: (2) Fifos are by default bidirectional. You can create a single
        !            24: 
        !            25:     directional fifo by creating the fifo "read only"; in this case,
        !            26: 
        !            27:     only the server descriptor can be written to, and only client
        !            28: 
        !            29:     descriptors can be read from.
        !            30: 
        !            31: (3) Be careful not to mix data up; if two clients are trying to
        !            32: 
        !            33:     read from the same fifo at the same time, they each may read
        !            34: 
        !            35:     data intended for the other. The easiest way to avoid this is
        !            36: 
        !            37:     by having every client lock the fifo before accessing it,
        !            38: 
        !            39:     and unlock the fifo when finished. It's also possible (if you're
        !            40: 
        !            41:     careful) to use the fact that all writes of <1024 bytes are atomic
        !            42: 
        !            43:     (i.e. take place in one "chunk") to avoid interleaving of data;
        !            44: 
        !            45:     but locks are probably safer.
        !            46: 
        !            47: 
        !            48: 
        !            49: The flags to the Fcreate() system call used to create the fifo can
        !            50: 
        !            51: be used to control the way the fifo works. For most applications,
        !            52: 
        !            53: the flags should probably be 0, i.e. the call should look like
        !            54: 
        !            55:    serverfd = Fcreate("U:\\PIPE\\FIFO", 0);
        !            56: 
        !            57: but for some specialized applications it may be useful to use one
        !            58: 
        !            59: or more of the following flags (they may be or'd together:
        !            60: 
        !            61: 
        !            62: 
        !            63: FA_RDONLY: Make the fifo unidirectional; the server fd will be write
        !            64: 
        !            65:     only, and the client fd read only.
        !            66: 
        !            67: FA_HIDDEN: Make reads from the fifo return "end of file" if no other
        !            68: 
        !            69:     process has the fifo open for writing. This is normally not desired
        !            70: 
        !            71:     for server processes, since the server's read will often occur
        !            72: 
        !            73:     when nobody has the fifo open, and should wait until some client
        !            74: 
        !            75:     does want to use the fifo.
        !            76: 
        !            77: FA_SYSTEM: Make the fifo a "pseudo-terminal". This type of fifo behaves
        !            78: 
        !            79:     just like a terminal, and most of the terminal control Fcntl calls
        !            80: 
        !            81:     can operate on it. Also, data can be passed through the fifo in long
        !            82: 
        !            83:     words rather than in bytes, if the Fputchar() system call is used.
        !            84: 
        !            85:     This allows the server program to pass the extended BIOS information
        !            86: 
        !            87:     (such as the shift key status and scan code) to be returned by Bconin()
        !            88: 
        !            89:     calls on the client side of the pipe. The 'extra' 3 bytes of the longword
        !            90: 
        !            91:     could also be used for other out of band data as well.
        !            92: 
        !            93: FA_CHANGED: Make the fifo return from an Fread() call as soon as any data are
        !            94: 
        !            95:     available (just like a terminal). This isn't necessary if the FA_SYSTEM
        !            96: 
        !            97:     bit is set (since pseudo-terminals already act like terminals), but is
        !            98: 
        !            99:     useful for making ordinary fifo's emulate Unix pipe semantics.
        !           100: 
        !           101: 
        !           102: 
        !           103: Here is a sample pair of applications. The server program ("fortserv.c")
        !           104: 
        !           105: creates a fifo and listens on it for requests. When it receives a
        !           106: 
        !           107: request, it writes a cute saying (a "fortune cookie") back to the fifo.
        !           108: 
        !           109: The client program ("fortune.c") opens the fifo, writes a request,
        !           110: 
        !           111: reads the response, and prints the result on the terminal. These are
        !           112: 
        !           113: very simple minded applications, but it should give you an idea of
        !           114: 
        !           115: the flavour of how to use fifos for interprocess communication.
        !           116: 
        !           117: -------------------------- fortserv.c -------------------------
        !           118: 
        !           119: /* fortune server: send cookies to clients */
        !           120: 
        !           121: /* illustrates server side use of fifos */
        !           122: 
        !           123: 
        !           124: 
        !           125: /*
        !           126: 
        !           127:  * This program opens a fifo ("U:\PIPE\FORTUNE")
        !           128: 
        !           129:  * and listens to requests on that fifo. When it
        !           130: 
        !           131:  * gets a request (consisting of a single '?'
        !           132: 
        !           133:  * character) it writes back as a reply a 1 byte
        !           134: 
        !           135:  * "length" followed by a randomly selected saying.
        !           136: 
        !           137:  * BUGS:
        !           138: 
        !           139:  *   - maximum of 255 characters for a fortune
        !           140: 
        !           141:  *   - the fortunes aren't particularly interesting
        !           142: 
        !           143:  */
        !           144: 
        !           145: 
        !           146: 
        !           147: #ifdef __GNUC__
        !           148: 
        !           149: #include <minimal.h>
        !           150: 
        !           151: #endif
        !           152: 
        !           153: #include <osbind.h>
        !           154: 
        !           155: #include <mintbind.h>
        !           156: 
        !           157: #include <string.h>
        !           158: 
        !           159: 
        !           160: 
        !           161: #define FIFONAME "U:\\PIPE\\FORTUNE"
        !           162: 
        !           163: #define MAXSIZE 255
        !           164: 
        !           165: 
        !           166: 
        !           167: /* witty (?) sayings */
        !           168: 
        !           169: 
        !           170: 
        !           171: char * sayings[] = {
        !           172: 
        !           173: "Core fault -- program dumped.",
        !           174: 
        !           175: "Don't worry, be happy!",
        !           176: 
        !           177: "Help! I'm trapped in a fortune cookie factory!",
        !           178: 
        !           179: "\"Home is where you wear-a your hat.\"",
        !           180: 
        !           181: "I want a cookie.",
        !           182: 
        !           183: "MS-DOS: just say \"no\".",
        !           184: 
        !           185: "Never play leapfrog with a unicorn.",
        !           186: 
        !           187: "No matter where you go, there you are.",
        !           188: 
        !           189: "Sorry, I'm out of short, pithy sayings today.\r\nTry again later.",
        !           190: 
        !           191: "They say that playing NetHack is like walking into a death trap.",
        !           192: 
        !           193: "Vision hazy, try again later.",
        !           194: 
        !           195: "What? You expected something funny?",
        !           196: 
        !           197: "Why is it that UFO's always seem to visit idiots?",
        !           198: 
        !           199: "Your puny intellect is no match for our superior weapons.",
        !           200: 
        !           201: };
        !           202: 
        !           203: #define NUMSAYINGS (sizeof(sayings) / sizeof(char *))
        !           204: 
        !           205: 
        !           206: 
        !           207: /* file descriptor for the fortune fifo */
        !           208: 
        !           209: int fd;
        !           210: 
        !           211: 
        !           212: 
        !           213: 
        !           214: 
        !           215: /* send a witty saying out through the fifo */
        !           216: 
        !           217: 
        !           218: 
        !           219: void
        !           220: 
        !           221: send_saying()
        !           222: 
        !           223: {
        !           224: 
        !           225:        int i;
        !           226: 
        !           227:        char *s;
        !           228: 
        !           229:        char tmpbuf[MAXSIZE+1];
        !           230: 
        !           231: 
        !           232: 
        !           233: /* pick a saying at random */
        !           234: 
        !           235:        i = ((unsigned)Random() >> 1) % NUMSAYINGS;
        !           236: 
        !           237:        s = sayings[i];
        !           238: 
        !           239: 
        !           240: 
        !           241: /* construct the message to send */
        !           242: 
        !           243:        i = (int)strlen(s);
        !           244: 
        !           245:        tmpbuf[0] = i;
        !           246: 
        !           247:        strcpy(tmpbuf+1,s);
        !           248: 
        !           249: 
        !           250: 
        !           251: /* we really should check for an error */
        !           252: 
        !           253:        (void)Fwrite(fd, (long)i+1, tmpbuf);
        !           254: 
        !           255: }
        !           256: 
        !           257: 
        !           258: 
        !           259: /* main function: create the fifo, then sit around
        !           260: 
        !           261:  * listening for requests
        !           262: 
        !           263:  */
        !           264: 
        !           265: 
        !           266: 
        !           267: int
        !           268: 
        !           269: main(argc, argv, envp)
        !           270: 
        !           271:        int argc;
        !           272: 
        !           273:        char **argv, **envp;
        !           274: 
        !           275: {
        !           276: 
        !           277:        char c;
        !           278: 
        !           279:        long r;
        !           280: 
        !           281: 
        !           282: 
        !           283:        fd = Fcreate(FIFONAME, 0);
        !           284: 
        !           285:        if (fd < 0) {
        !           286: 
        !           287:                Cconws("Couldn't create ");
        !           288: 
        !           289:                Cconws(FIFONAME);
        !           290: 
        !           291:                Cconws("!\r\n");
        !           292: 
        !           293:                Pterm(1);
        !           294: 
        !           295:        }
        !           296: 
        !           297: 
        !           298: 
        !           299:        for(;;) {
        !           300: 
        !           301:                r = Fread(fd, 1L, &c);
        !           302: 
        !           303:                if (r != 1) {   /* read error?? */
        !           304: 
        !           305:                        break;
        !           306: 
        !           307:                }
        !           308: 
        !           309:                if (c == '?') { /* request for saying */
        !           310: 
        !           311:                        send_saying();
        !           312: 
        !           313:                }
        !           314: 
        !           315:        /* could have other requests here */
        !           316: 
        !           317:        }
        !           318: 
        !           319:        return 0;
        !           320: 
        !           321: }
        !           322: 
        !           323: ------------------------ fortune.c ----------------------
        !           324: 
        !           325: /* fortune client: get a fortune cookie from
        !           326: 
        !           327:  * the fortune server
        !           328: 
        !           329:  */
        !           330: 
        !           331: 
        !           332: 
        !           333: /* illustrates client side use of fifos */
        !           334: 
        !           335: 
        !           336: 
        !           337: #ifdef __GNUC__
        !           338: 
        !           339: #include <minimal.h>
        !           340: 
        !           341: #endif
        !           342: 
        !           343: #include <osbind.h>
        !           344: 
        !           345: #include <mintbind.h>
        !           346: 
        !           347: 
        !           348: 
        !           349: #define FIFONAME "U:\\PIPE\\FORTUNE"
        !           350: 
        !           351: #define BUFSIZ 256
        !           352: 
        !           353: #define F_SETLKW 7
        !           354: 
        !           355: 
        !           356: 
        !           357: struct flock {
        !           358: 
        !           359:        short l_type;                   /* type of lock */
        !           360: 
        !           361: #define F_RDLCK                0
        !           362: 
        !           363: #define F_WRLCK                1
        !           364: 
        !           365: #define F_UNLCK                3
        !           366: 
        !           367:        short l_whence;                 /* SEEK_SET, SEEK_CUR, SEEK_END */
        !           368: 
        !           369:        long l_start;                   /* start of locked region */
        !           370: 
        !           371:        long l_len;                     /* length of locked region */
        !           372: 
        !           373:        short l_pid;                    /* pid of locking process
        !           374: 
        !           375:                                                (F_GETLK only) */
        !           376: 
        !           377: };
        !           378: 
        !           379: 
        !           380: 
        !           381: int
        !           382: 
        !           383: main(argc, argv, envp)
        !           384: 
        !           385:        int argc;
        !           386: 
        !           387:        char **argv, **envp;
        !           388: 
        !           389: {
        !           390: 
        !           391:        int fd;
        !           392: 
        !           393:        char buf[BUFSIZ];
        !           394: 
        !           395:        unsigned char len;
        !           396: 
        !           397:        struct flock lock;
        !           398: 
        !           399:        long r;
        !           400: 
        !           401: 
        !           402: 
        !           403: /* open the fifo */
        !           404: 
        !           405:        fd = Fopen(FIFONAME, 2);
        !           406: 
        !           407:        if (fd < 0) {
        !           408: 
        !           409:                Cconws("Couldn't open ");
        !           410: 
        !           411:                Cconws(FIFONAME);
        !           412: 
        !           413:                Cconws("!\r\n");
        !           414: 
        !           415:                Pterm(1);
        !           416: 
        !           417:        }
        !           418: 
        !           419: 
        !           420: 
        !           421: /* get a lock; this makes sure that two fortune
        !           422: 
        !           423:  * programs don't try to send requests and read
        !           424: 
        !           425:  * replys at the same time
        !           426: 
        !           427:  */
        !           428: 
        !           429: 
        !           430: 
        !           431:        lock.l_type = F_WRLCK;
        !           432: 
        !           433: 
        !           434: 
        !           435: /* lock the whole file -- only thing that makes sense
        !           436: 
        !           437:  * for a fifo
        !           438: 
        !           439:  */
        !           440: 
        !           441:        lock.l_whence = 0;
        !           442: 
        !           443:        lock.l_start = lock.l_len = 0L;
        !           444: 
        !           445: 
        !           446: 
        !           447:        r = Fcntl(fd, &lock, F_SETLKW);
        !           448: 
        !           449:        if (r != 0) {
        !           450: 
        !           451:                Cconws("Couldn't get a lock!\r\n");
        !           452: 
        !           453:                Pterm(r);
        !           454: 
        !           455:        }
        !           456: 
        !           457: 
        !           458: 
        !           459: /* write the request */
        !           460: 
        !           461:        Fwrite(fd, 1L, "?");
        !           462: 
        !           463: /* wait for a reply */
        !           464: 
        !           465: /* the fortune server writes a 1 byte length, followed by
        !           466: 
        !           467:  * the fortune itself
        !           468: 
        !           469:  */
        !           470: 
        !           471:        r = Fread(fd, 1L, &len);
        !           472: 
        !           473:        if (r != 1L || len != Fread(fd, (long)len, buf)) {
        !           474: 
        !           475:                Cconws("Error reading fortune!\r\n");
        !           476: 
        !           477:                Pterm(1);
        !           478: 
        !           479:        }
        !           480: 
        !           481:        buf[len] = 0;
        !           482: 
        !           483: 
        !           484: 
        !           485: /* unlock the fifo */
        !           486: 
        !           487: 
        !           488: 
        !           489:        lock.l_type = F_UNLCK;
        !           490: 
        !           491:        (void) Fcntl(fd, &lock, F_SETLKW);
        !           492: 
        !           493: 
        !           494: 
        !           495:        Fclose(fd);
        !           496: 
        !           497: 
        !           498: 
        !           499: /* now write the fortune to the screen */
        !           500: 
        !           501:        Cconws(buf);
        !           502: 
        !           503:        Cconws("\r\n");
        !           504: 
        !           505: 
        !           506: 
        !           507:        return 0;
        !           508: 
        !           509: }
        !           510: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.