home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 317b.lha / RCS_Sources / rsbx.lib / popen.c < prev    next >
C/C++ Source or Header  |  1989-12-05  |  6KB  |  305 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. #include <dos.h>
  5. #include <ios1.h>
  6. #include <fcntl.h>
  7. #include <libraries/dosextens.h>
  8. #include <exec/lists.h>
  9. #include <exec/nodes.h>
  10. #include <rsbx/ChildTasking.h>
  11.  
  12.  
  13. struct pstruct {
  14.     struct MinNode node;
  15.     FILE    *fptr1;
  16.     struct ChildNode *child;
  17.     };
  18.  
  19. static struct MinList PList = { 0 };
  20.  
  21.  
  22. FILE *popenl(char *args, ...);
  23. FILE *popenv(char **args, char *mode);
  24. int pclose(FILE *fptr);
  25. static char *mktemp(char *template);
  26.  
  27.  
  28.  
  29. /****** rsbx.lib/popenl() ****************************************************
  30. *
  31. *   NAME
  32. *    popenl -- Initiate I/O to or from a command.
  33. *
  34. *   SYNOPSIS
  35. *    pipe = popenl(arg0, ..., argn, NULL, mode)
  36. *
  37. *    FILE *popenl(char *, char *, ...);
  38. *
  39. *   FUNCTION
  40. *    Creates a stream between the calling process and the stdin or stdout
  41. *        streams of the command it executes. Mode should be "r" to read
  42. *        the stdout stream of the command, or "w" to write to the stdin
  43. *        stream of the command. 
  44. *
  45. *   INPUTS
  46. *    arg0          - Name of file to execute.
  47. *       ...           - Other command line arguments needed by the file to be
  48. *                    executed.
  49. *    NULL          - Zero.
  50. *    mode          _ I/O mode string.
  51. *
  52. *   RESULT
  53. *    pipe          - File pointer to use to read or write to the command
  54. *                    with.
  55. *
  56. *   NOTES
  57. *    A stream opened by popenl() should be closed by pclose().
  58. *
  59. *   SEE ALSO
  60. *    popenv(), pclose().
  61. *
  62. *   BUGS
  63. *    This function does not create a complete CLI enviroment for the child
  64. *        process. Use of this function with a command that expects a BCPL
  65. *        environment will crash the system. The Unix function 'popen' takes
  66. *        as arguments a command string which it passes to the shell, and a
  67. *        mode string.
  68. *
  69. ******************************************************************************
  70. *
  71. */
  72.  
  73. FILE *popenl(char *args, ...)
  74.     {
  75.     char **nullarg;
  76.  
  77.     for(nullarg = (char **)(&args); *nullarg != 0; nullarg++);
  78.  
  79.     return(popenv(&args, *(nullarg+1)));
  80.     }
  81.  
  82.  
  83. /****** rsbx.lib/popenv() ****************************************************
  84. *
  85. *   NAME
  86. *    popenv -- Initiate I/O to or from a command.
  87. *
  88. *   SYNOPSIS
  89. *    pipe = popenv(argv, mode)
  90. *
  91. *    FILE *popenv(char **, char *);
  92. *
  93. *   FUNCTION
  94. *    Creates a stream between the calling process and the stdin or stdout
  95. *        streams of the command it executes. Mode should be "r" to read
  96. *        the stdout stream of the command, or "w" to write to the stdin
  97. *        stream of the command. 
  98. *
  99. *   INPUTS
  100. *    argv          - An array of pointer to the argument strings for the
  101. *                    command. The last pointer must be followed by a 0
  102. *                    pointer. The first pointer, argv[0], is the name of
  103. *                    file to execute.
  104. *    mode          _ I/O mode string.
  105. *
  106. *   RESULT
  107. *    pipe          - File pointer to use to read or write to the command
  108. *                    with.
  109. *
  110. *   NOTES
  111. *    A stream opened by popenv() should be closed by pclose().
  112. *
  113. *   SEE ALSO
  114. *    popenl(), pclose().
  115. *
  116. *   BUGS
  117. *    This function does not create a complete CLI enviroment for the child
  118. *        process. Use of this function with a command that expects a BCPL
  119. *        environment will crash the system. The Unix function 'popen' takes
  120. *        as arguments a command string which it passes to the shell, and a
  121. *        mode string.
  122. *
  123. ******************************************************************************
  124. *
  125. */
  126.  
  127. FILE *popenv(char **args, char *mode)
  128.     {
  129.     struct LAUNCHENV env = { 0,0,0,0,0,0,0 };
  130.     static char tempname[] = "pipe:popen.XXXX.XXXXXXXX";
  131.     char *pname;
  132.     char redir[64];
  133.     struct pstruct *poptr;
  134.     char *mode1;
  135.     int mode2;
  136.     int f2;
  137.  
  138.     if (!PList.mlh_Head)
  139.         {
  140.         NewList(&PList);
  141.         }
  142.  
  143.     if ((strcmp(mode,"r") != 0) && (strcmp(mode,"w") != 0))
  144.         {
  145.         fprintf(stderr,"popen: bad mode!\n");
  146.         return(NULL);
  147.         }
  148.  
  149.     if (*mode == 'r')
  150.         {
  151.         mode1 = "r";
  152.         mode2 = MODE_NEWFILE;
  153.         }
  154.     else
  155.         {
  156.         mode1 = "w";
  157.         mode2 = MODE_OLDFILE;
  158.         }
  159.  
  160.     strcpy(redir,tempname);
  161.  
  162.     if (!(poptr = (struct pstruct *)malloc(sizeof(struct pstruct))))
  163.         {
  164.         fprintf(stderr,"popen: Out of memory!\n");
  165.         return(NULL);
  166.         }
  167.  
  168.     if (!(pname = mktemp(redir)))
  169.         {
  170.         fprintf(stderr,"popen: Unable to find an available pipe.\n");
  171.         free(poptr);
  172.         return(NULL);
  173.         }
  174.  
  175.     if (!(poptr->fptr1 = fopen(pname, mode1)))
  176.         {
  177.         fprintf(stderr,"popen: Unable to open pipe end 1 file %s mode %s\n", pname, m
  178. de);
  179.         free(poptr);
  180.         return(NULL);
  181.         }
  182.  
  183.     if (!(f2 = Open(pname, mode2)))
  184.         {
  185.         fprintf(stderr,"popen: Unable to open pipe end 2 file %s mode %s\n", pname, m
  186. de);
  187.         fclose(poptr->fptr1);
  188.         free(poptr);
  189.         return(NULL);
  190.         }
  191.  
  192.     env.priority = ((struct Task *)FindTask(NULL))->tc_Node.ln_Pri;
  193.     if (*mode == 'r')
  194.         {
  195.         env.std_out = f2;
  196.         }
  197.     else
  198.         {
  199.         env.std_in = f2;
  200.         }
  201.     env.le_fh1 = f2;
  202.  
  203.     if (!(poptr->child = LaunchChildv(&env, *args, args)))
  204.         {
  205.         fprintf(stderr,"popen: Fork failed\n");
  206.         Close(f2);
  207.         fclose(poptr->fptr1);
  208.         free(poptr);
  209.         return(NULL);
  210.         }
  211.  
  212.     AddTail(&PList, poptr);
  213.  
  214.     return(poptr->fptr1);
  215.     }
  216.  
  217.  
  218. /****** rsbx.lib/pclose() ****************************************************
  219. *
  220. *   NAME
  221. *    pclose -- Closes pipe opened by popenl() or by popenv().
  222. *
  223. *   SYNOPSIS
  224. *    status = pclose(pipe)
  225. *
  226. *    int pclose(FILE *);
  227. *
  228. *   FUNCTION
  229. *    Waits for the command associated with the pipe to exit, closes the
  230. *        stream, and returns the return code from the command.
  231. *
  232. *   INPUTS
  233. *    pipe          - Stream pointer returned by a call to popenl() or to
  234. *                    popenv().
  235. *
  236. *   RESULT
  237. *    status        - The return code from the command executed, or -1 if
  238. *                    pipe wasn't opened by popenl() or by popenv().
  239. *
  240. *   NOTES
  241. *
  242. *   SEE ALSO
  243. *    popenl(), popenv().
  244. *
  245. *   BUGS
  246. *    None known.
  247. *
  248. ******************************************************************************
  249. *
  250. */
  251.  
  252. int pclose(FILE *fptr)
  253.     {
  254.     long status;
  255.     struct pstruct *poptr;
  256.  
  257.     for (poptr = (struct pstruct *)PList.mlh_Head;
  258.         poptr->node.mln_Succ;
  259.         poptr = (struct pstruct *)poptr->node.mln_Succ)
  260.         {
  261.         if (poptr->fptr1 == fptr)
  262.             {
  263.             Remove(poptr);
  264.             fclose(poptr->fptr1);
  265.             if (!WaitChild(poptr->child, &status))
  266.                 {
  267.                 status = -1;
  268.                 }
  269.             free(poptr);
  270.             return(status);
  271.             }
  272.         }
  273.  
  274.     return -1;
  275.     }
  276.  
  277. static unsigned short Generation = 0;
  278.  
  279. static char *hex = "0123456789abcdef";
  280.  
  281. static char *mktemp(char *template)
  282.     {
  283.     char *cp;
  284.     unsigned long val;
  285.  
  286.     cp = template;
  287.     cp += strlen(template);
  288.  
  289.     val = (unsigned long) FindTask(0L);
  290.     while (*--cp == 'X')
  291.         {
  292.         *cp = hex[val%16];
  293.         val /= 16;
  294.         }
  295.  
  296.     val = Generation++;
  297.     while (*--cp == 'X')
  298.         {
  299.         *cp = hex[val%16];
  300.         val /= 16;
  301.         }
  302.  
  303.     return template;
  304.     }
  305.