Annotation of MiNT/doc/fifo.doc, revision 1.1.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.