home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / perl / os2perl / popen.c < prev    next >
C/C++ Source or Header  |  1991-06-16  |  6KB  |  243 lines

  1. /* added real/protect mode branch at runtime and real mode version
  2.  * names changed for perl
  3.  * Kai Uwe Rommel
  4.  */
  5.  
  6. /*
  7. Several people in the past have asked about having Unix-like pipe
  8. calls in OS/2.  The following source file, adapted from 4.3 BSD Unix,
  9. uses a #define to give you a pipe(2) call, and contains function
  10. definitions for popen(3) and pclose(3).  Anyone with problems should
  11. send mail to me; they seem to work fine.
  12.  
  13. Mark Towfigh
  14. Racal Interlan, Inc.
  15. ----------------------------------cut-here------------------------------------
  16. */
  17.  
  18. /*
  19.  * The following code segment is derived from BSD 4.3 Unix.  See
  20.  * copyright below.  Any bugs, questions, improvements, or problems
  21.  * should be sent to Mark Towfigh (towfiq@interlan.interlan.com).
  22.  *
  23.  * Racal InterLan Inc.
  24.  */
  25.  
  26. /*
  27.  * Copyright (c) 1980 Regents of the University of California.
  28.  * All rights reserved.  The Berkeley software License Agreement
  29.  * specifies the terms and conditions for redistribution.
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <io.h>
  35. #include <string.h>
  36. #include <process.h>
  37. #include <errno.h>
  38.  
  39. #define INCL_NOPM
  40. #define    INCL_DOS
  41. #include <os2.h>
  42.  
  43. static FILE *dos_popen(const char *cmd, const char *flags);
  44. static int dos_pclose(FILE *pipe);
  45.  
  46. /*
  47.  * emulate Unix pipe(2) call
  48.  */
  49.  
  50. #define    tst(a,b)    (*mode == 'r'? (b) : (a))
  51. #define READH           0
  52. #define WRITEH          1
  53.  
  54. static  int       popen_pid[20];
  55.  
  56. FILE *mypopen(char *cmd, char *mode)
  57. {
  58.     int p[2];
  59.         register myside, hisside, save_stream;
  60.         char *shell = getenv("COMPSPEC");
  61.  
  62.         if ( shell == NULL )
  63.           shell = "C:\\OS2\\CMD.EXE";
  64.  
  65.         if ( _osmode == DOS_MODE )
  66.           return dos_popen(cmd, mode);
  67.  
  68.         if ( _pipe(p, 4096, 0) )
  69.                 return NULL;
  70.  
  71.         myside = tst(p[WRITEH], p[READH]);
  72.         hisside = tst(p[READH], p[WRITEH]);
  73.  
  74.     /* set up file descriptors for remote function */
  75.     save_stream = dup(tst(0, 1));        /* don't lose stdin/out! */
  76.         if (dup2(hisside, tst(0, 1)) < 0)
  77.         {
  78.         perror("dup2");
  79.         return NULL;
  80.     }
  81.         close(hisside);
  82.  
  83.     /*
  84.      * make sure that we can close our side of the pipe, by
  85.      * preventing it from being inherited!
  86.      */
  87.  
  88.     /* set no-inheritance flag */
  89.     DosSetFHandState(myside, OPEN_FLAGS_NOINHERIT);
  90.  
  91.     /* execute the command:  it will inherit our other file descriptors */
  92.         popen_pid[myside] = spawnlp(P_NOWAIT, shell, shell, "/C", cmd, NULL);
  93.  
  94.     /* now restore our previous file descriptors */
  95.         if (dup2(save_stream, tst(0, 1)) < 0)   /* retrieve stdin/out */
  96.         {
  97.         perror("dup2");
  98.         return NULL;
  99.     }
  100.         close(save_stream);
  101.  
  102.     return fdopen(myside, mode);        /* return a FILE pointer */
  103. }
  104.  
  105. int mypclose(FILE *ptr)
  106. {
  107.     register f;
  108.         int status;
  109.  
  110.         if ( _osmode == DOS_MODE )
  111.           return dos_pclose(ptr);
  112.  
  113.     f = fileno(ptr);
  114.         fclose(ptr);
  115.  
  116.     /* wait for process to terminate */
  117.     cwait(&status, popen_pid[f], WAIT_GRANDCHILD);
  118.  
  119.     return status;
  120. }
  121.  
  122.  
  123. int pipe(int *filedes)
  124. {
  125.   int res;
  126.  
  127.   if ( res = _pipe(filedes, 4096, 0) )
  128.     return res;
  129.  
  130.   DosSetFHandState(filedes[0], OPEN_FLAGS_NOINHERIT);
  131.   DosSetFHandState(filedes[1], OPEN_FLAGS_NOINHERIT);
  132.  
  133.   return 0;
  134. }
  135.  
  136.  
  137. /* this is the MS-DOS version */
  138.  
  139. typedef enum { unopened = 0, reading, writing } pipemode;
  140.  
  141. static struct
  142. {
  143.     char *name;
  144.     char *command;
  145.     pipemode pmode;
  146. }
  147. pipes[_NFILE];
  148.  
  149. static FILE *dos_popen(const char *command, const char *mode)
  150. {
  151.     FILE *current;
  152.     char name[128];
  153.     char *tmp = getenv("TMP");
  154.     int cur;
  155.     pipemode curmode;
  156.  
  157.     /*
  158.     ** decide on mode.
  159.     */
  160.     if(strchr(mode, 'r') != NULL)
  161.         curmode = reading;
  162.     else if(strchr(mode, 'w') != NULL)
  163.         curmode = writing;
  164.     else
  165.         return NULL;
  166.  
  167.     /*
  168.     ** get a name to use.
  169.     */
  170.     strcpy(name, tmp ? tmp : "\\");
  171.     if ( name[strlen(name) - 1] != '\\' )
  172.       strcat(name, "\\");
  173.     strcat(name, "piXXXXXX");
  174.     mktemp(name);
  175.  
  176.     /*
  177.     ** If we're reading, just call system to get a file filled with
  178.     ** output.
  179.     */
  180.     if(curmode == reading)
  181.     {
  182.         char cmd[256];
  183.         sprintf(cmd,"%s > %s", command, name);
  184.         system(cmd);
  185.  
  186.         if((current = fopen(name, mode)) == NULL)
  187.             return NULL;
  188.     }
  189.     else
  190.     {
  191.         if((current = fopen(name, mode)) == NULL)
  192.             return NULL;
  193.     }
  194.  
  195.     cur = fileno(current);
  196.     pipes[cur].name = strdup(name);
  197.     pipes[cur].command = strdup(command);
  198.     pipes[cur].pmode = curmode;
  199.  
  200.     return current;
  201. }
  202.  
  203. static int dos_pclose(FILE * current)
  204. {
  205.     int cur = fileno(current), rval;
  206.     char command[256];
  207.  
  208.     /*
  209.     ** check for an open file.
  210.     */
  211.     if(pipes[cur].pmode == unopened)
  212.         return -1;
  213.  
  214.     if(pipes[cur].pmode == reading)
  215.     {
  216.         /*
  217.         ** input pipes are just files we're done with.
  218.         */
  219.         rval = fclose(current);
  220.         unlink(pipes[cur].name);
  221.     }
  222.     else
  223.     {
  224.         /*
  225.         ** output pipes are temporary files we have
  226.         ** to cram down the throats of programs.
  227.         */
  228.         fclose(current);
  229.         sprintf(command,"%s < %s", pipes[cur].command, pipes[cur].name);
  230.         rval = system(command);
  231.         unlink(pipes[cur].name);
  232.     }
  233.  
  234.     /*
  235.     ** clean up current pipe.
  236.     */
  237.     free(pipes[cur].name);
  238.     free(pipes[cur].command);
  239.     pipes[cur].pmode = unopened;
  240.  
  241.     return rval;
  242. }
  243.