home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- subject: v10i026: Anonymous Pipes in OS/2
- summary: emulation of the bsd unix pipe(2), popen(3), and pclose(3) calls
- keywords: pipe, handles, fork, execl, spawn, popen, pclose
- organization: Racal InterLan Inc., Boxborough, MA (1-800-LAN-TALK)
- From: towfiq@interlan.interlan.com (Mark Mehdi Towfigh)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 10, Issue 26
- Submitted-by: towfiq@interlan.interlan.com (Mark Mehdi Towfigh)
- Archive-name: pipes.os2
-
- Several people in the past have asked about having Unix-like pipe
- calls in OS/2. The following source file, adapted from 4.3 BSD Unix,
- uses a #define to give you a pipe(2) call, and contains function
- definitions for popen(3) and pclose(3). Anyone with problems should
- send mail to me; they seem to work fine.
-
- Mark Towfigh
- Racal Interlan, Inc.
- ----------------------------------cut-here------------------------------------
- /*
- * The following code segment is derived from BSD 4.3 Unix. See
- * copyright below. Any bugs, questions, improvements, or problems
- * should be sent to Mark Towfigh (towfiq@interlan.interlan.com).
- *
- * Racal InterLan Inc.
- *
- * Description of the three functions contained in this file, adapted
- * from the BSD 4.3 Manual Pages:
- *
- * SYNOPSIS
- * pipe(fildes)
- * int fildes[2];
- *
- * DESCRIPTION
- * The pipe call creates an I/O mechanism called a pipe.
- * The file descriptors returned can be used in read and write
- * operations. When the pipe is written using the descriptor
- * fildes[1] up to 4096 bytes of data are buffered before the
- * writing process is suspended. A read using the descriptor
- * fildes[0] will pick up the data.
- *
- * It is assumed that after the pipe has been set up, two (or
- * more) cooperating processes (created by subsequent spawn
- * calls) will pass data through the pipe with read and write
- * calls.
- *
- * Read calls on an empty pipe (no buffered data) with only one
- * end (all write file descriptors closed) returns EOF.
- *
- * RETURN VALUE
- * The function value zero is returned if the pipe was created;
- * -1 if an error occurred.
- *
- * ERRORS
- * The pipe call will fail if:
- *
- * [EMFILE] Too many descriptors are active.
- *
- * [ENFILE] The system file table is full.
- *
- * [EFAULT] The fildes buffer is in an invalid area of
- * the process's address space.
- *
- * SYNOPSIS
- *
- * FILE *popen(command, type)
- * char *command, *type;
- *
- * pclose(stream)
- * FILE *stream;
- *
- * DESCRIPTION
- * The arguments to popen are pointers to null-terminated
- * strings containing respectively a command line and an
- * I/O mode, either "r" for reading or "w" for writing. It
- * creates a pipe between the calling process and the command
- * to be executed. The value returned is a stream pointer that
- * can be used (as appropriate) to write to the standard input
- * of the command or read from its standard output.
- *
- * A stream opened by popen should be closed by pclose, which
- * waits for the associated process to terminate and returns
- * the exit status of the command.
- *
- * Because open files are shared, a type "r" command may be
- * used as an input filter, and a type "w" as an output filter.
- *
- * DIAGNOSTICS
- * Popen returns a null pointer if files or processes cannot be
- * created.
- *
- * Pclose returns the exit status of the command.
- */
- /*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- */
-
- #include <stdio.h>
- #include <stddef.h>
- #include <process.h>
- #include <errno.h>
-
- #define INCL_DOS
- #include <os2.h>
-
- #define tst(a,b) (*mode == 'r'? (b) : (a))
-
- /*
- * emulate Unix pipe(2) call
- */
- #define pipe(x) DosMakePipe((PHFILE) &x[0], (PHFILE) &x[1], 4096)
-
- #define RDR 0
- #define WTR 1
- static int popen_pid[20];
-
- FILE *
- popen(cmd, mode)
- char *cmd;
- char *mode;
- {
- int p[2];
- register myside, hisside, save_stream;
-
- if (pipe(p) < 0)
- return NULL;
- myside = tst(p[WTR], p[RDR]);
- hisside = tst(p[RDR], p[WTR]);
-
- /* set up file descriptors for remote function */
- save_stream = dup(tst(0, 1)); /* don't lose stdin/out! */
- if (dup2(hisside, tst(0, 1)) < 0) {
- perror("dup2");
- return NULL;
- }
- (void) close(hisside);
-
- /*
- * make sure that we can close our side of the pipe, by
- * preventing it from being inherited!
- */
-
- /* set no-inheritance flag */
- DosSetFHandState(myside, OPEN_FLAGS_NOINHERIT);
-
- /* execute the command: it will inherit our other file descriptors */
- popen_pid[myside] = spawnlp(P_NOWAIT, cmd, cmd, NULL);
-
- /* now restore our previous file descriptors */
- if (dup2(save_stream, tst(0, 1)) < 0) { /* retrieve stdin/out */
- perror("dup2");
- return NULL;
- }
- (void) close(save_stream);
- return fdopen(myside, mode); /* return a FILE pointer */
- }
-
- pclose(ptr)
- FILE *ptr;
- {
- register f;
- int status;
-
- f = fileno(ptr);
- (void) fclose(ptr);
-
- /* wait for process to terminate */
- cwait(&status, popen_pid[f], WAIT_GRANDCHILD);
-
- return status;
- }
-
-