home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume10 / pipes.os2 < prev    next >
Text File  |  1990-01-19  |  5KB  |  177 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v10i026: Anonymous Pipes in OS/2
  3. summary: emulation of the bsd unix pipe(2), popen(3), and pclose(3) calls
  4. keywords: pipe, handles, fork, execl, spawn, popen, pclose
  5. organization: Racal InterLan Inc., Boxborough, MA (1-800-LAN-TALK)
  6. From: towfiq@interlan.interlan.com (Mark Mehdi Towfigh)
  7. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  8.  
  9. Posting-number: Volume 10, Issue 26
  10. Submitted-by: towfiq@interlan.interlan.com (Mark Mehdi Towfigh)
  11. Archive-name: pipes.os2
  12.  
  13. Several people in the past have asked about having Unix-like pipe
  14. calls in OS/2.  The following source file, adapted from 4.3 BSD Unix,
  15. uses a #define to give you a pipe(2) call, and contains function
  16. definitions for popen(3) and pclose(3).  Anyone with problems should
  17. send mail to me; they seem to work fine.
  18.  
  19. Mark Towfigh
  20. Racal Interlan, Inc.
  21. ----------------------------------cut-here------------------------------------
  22. /*
  23.  * The following code segment is derived from BSD 4.3 Unix.  See
  24.  * copyright below.  Any bugs, questions, improvements, or problems
  25.  * should be sent to Mark Towfigh (towfiq@interlan.interlan.com).
  26.  *
  27.  * Racal InterLan Inc.
  28.  *
  29.  * Description of the three functions contained in this file, adapted
  30.  * from the BSD 4.3 Manual Pages:
  31.  *
  32.  * SYNOPSIS
  33.  *      pipe(fildes)
  34.  *      int fildes[2];
  35.  * 
  36.  * DESCRIPTION
  37.  *      The pipe call creates an I/O mechanism called a pipe.
  38.  *      The file descriptors returned can be used in read and write
  39.  *      operations.  When the pipe is written using the descriptor
  40.  *      fildes[1] up to 4096 bytes of data are buffered before the
  41.  *      writing process is suspended.  A read using the descriptor
  42.  *      fildes[0] will pick up the data.
  43.  * 
  44.  *      It is assumed that after the pipe has been set up, two (or
  45.  *      more) cooperating processes (created by subsequent spawn
  46.  *      calls) will pass data through the pipe with read and write
  47.  *      calls.
  48.  * 
  49.  *      Read calls on an empty pipe (no buffered data) with only one
  50.  *      end (all write file descriptors closed) returns EOF.
  51.  * 
  52.  * RETURN VALUE
  53.  *      The function value zero is returned if the pipe was created;
  54.  *      -1 if an error occurred.
  55.  * 
  56.  * ERRORS
  57.  *      The pipe call will fail if:
  58.  * 
  59.  *      [EMFILE]       Too many descriptors are active.
  60.  * 
  61.  *      [ENFILE]       The system file table is full.
  62.  * 
  63.  *      [EFAULT]       The fildes buffer is in an invalid area of
  64.  *                     the process's address space.
  65.  * 
  66.  * SYNOPSIS
  67.  * 
  68.  *      FILE *popen(command, type)
  69.  *      char *command, *type;
  70.  * 
  71.  *      pclose(stream)
  72.  *      FILE *stream;
  73.  * 
  74.  * DESCRIPTION
  75.  *      The arguments to popen are pointers to null-terminated
  76.  *      strings containing respectively a command line and an
  77.  *      I/O mode, either "r" for reading or "w" for writing.  It
  78.  *      creates a pipe between the calling process and the command
  79.  *      to be executed.  The value returned is a stream pointer that
  80.  *      can be used (as appropriate) to write to the standard input
  81.  *      of the command or read from its standard output.
  82.  * 
  83.  *      A stream opened by popen should be closed by pclose, which
  84.  *      waits for the associated process to terminate and returns
  85.  *      the exit status of the command.
  86.  * 
  87.  *      Because open files are shared, a type "r" command may be
  88.  *      used as an input filter, and a type "w" as an output filter.
  89.  * 
  90.  * DIAGNOSTICS
  91.  *      Popen returns a null pointer if files or processes cannot be
  92.  *      created.
  93.  *
  94.  *      Pclose returns the exit status of the command.
  95.  */
  96. /*
  97.  * Copyright (c) 1980 Regents of the University of California.
  98.  * All rights reserved.  The Berkeley software License Agreement
  99.  * specifies the terms and conditions for redistribution.
  100.  */
  101.  
  102. #include <stdio.h>
  103. #include <stddef.h>
  104. #include <process.h>
  105. #include <errno.h>
  106.  
  107. #define    INCL_DOS
  108. #include <os2.h>
  109.  
  110. #define    tst(a,b)    (*mode == 'r'? (b) : (a))
  111.  
  112. /*
  113.  * emulate Unix pipe(2) call
  114.  */
  115. #define    pipe(x)        DosMakePipe((PHFILE) &x[0], (PHFILE) &x[1], 4096)
  116.  
  117. #define    RDR    0
  118. #define    WTR    1
  119. static    int    popen_pid[20];
  120.  
  121. FILE *
  122. popen(cmd, mode)
  123. char    *cmd;
  124. char    *mode;
  125. {
  126.     int p[2];
  127.     register myside, hisside, save_stream;
  128.  
  129.     if (pipe(p) < 0)
  130.         return NULL;
  131.     myside = tst(p[WTR], p[RDR]);
  132.     hisside = tst(p[RDR], p[WTR]);
  133.  
  134.     /* set up file descriptors for remote function */
  135.     save_stream = dup(tst(0, 1));        /* don't lose stdin/out! */
  136.     if (dup2(hisside, tst(0, 1)) < 0) {
  137.         perror("dup2");
  138.         return NULL;
  139.     }
  140.     (void) close(hisside);
  141.     
  142.     /*
  143.      * make sure that we can close our side of the pipe, by
  144.      * preventing it from being inherited!
  145.      */
  146.  
  147.     /* set no-inheritance flag */
  148.     DosSetFHandState(myside, OPEN_FLAGS_NOINHERIT);
  149.  
  150.     /* execute the command:  it will inherit our other file descriptors */
  151.     popen_pid[myside] = spawnlp(P_NOWAIT, cmd, cmd, NULL);
  152.  
  153.     /* now restore our previous file descriptors */
  154.     if (dup2(save_stream, tst(0, 1)) < 0) {    /* retrieve stdin/out */
  155.         perror("dup2");
  156.         return NULL;
  157.     }
  158.     (void) close(save_stream);
  159.     return fdopen(myside, mode);        /* return a FILE pointer */
  160. }
  161.  
  162. pclose(ptr)
  163. FILE *ptr;
  164. {
  165.     register f;
  166.     int status;
  167.  
  168.     f = fileno(ptr);
  169.     (void) fclose(ptr);
  170.  
  171.     /* wait for process to terminate */
  172.     cwait(&status, popen_pid[f], WAIT_GRANDCHILD);
  173.  
  174.     return status;
  175. }
  176.  
  177.