home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume10 / pipes.os2 < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  5.4 KB

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