home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / shar349.zip / src / pipes.c < prev    next >
C/C++ Source or Header  |  1992-02-22  |  5KB  |  233 lines

  1. /* pipes.c - simple pipes for MS-DOS
  2.    Copyright (C) 1990 Free Software Foundation, Inc.
  3.    Thorsten Ohl <ohl@gnu.ai.mit.edu>, 1990
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 1, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.    $Header: e:/gnu/shar/RCS/pipes.c 0.1 90/09/25 21:34:19 tho Exp $
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdarg.h>
  26. #include <process.h>
  27.  
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include <io.h>
  32. #include <errno.h>
  33.  
  34. #include <gnulib.h>
  35.  
  36. extern char *_pipe_file (int n);
  37. extern int filter_through_command (char *infile, char *outfile,
  38.                    char *command, ...);
  39.  
  40.  
  41. #ifndef DONT_USE_SWAPLIB
  42.  
  43. /* Since the Microsoft C runtime library has a bug in the redirection
  44.    of binary files, it is preferable to use the spawn?? () functions
  45.    from the swaplib, since these don't have this problem.  But the
  46.    swapping is not really needed.  */
  47.  
  48. #include <swaplib.h>
  49.  
  50. /* But we don't need the fancy swaplib actions, so we provide stubs
  51.    to prevent their linkage.  */
  52.  
  53. int swap_smart_p (char *name) { return 0; }
  54. char * swap_invoke_shell (char *cmd, char ***argvp) { return NULL; }
  55. struct swap_respondfile_action *
  56. swap_set_respondfile_actions (void) { return NULL; }
  57.  
  58. #endif /* DONT_USE_SWAPLIB */
  59.  
  60. /* Return the name of a temporary file.
  61.    (This is not restricted to 2 files, just increase NPIPE.)  */
  62.  
  63. #define NPIPE 2
  64. static void cleanup_pipes (void);
  65. static char *pipe_file[NPIPE] = { NULL, NULL };
  66. static char *tmpdir = NULL;
  67. static int tmpdirlen;
  68.  
  69. char *
  70. _pipe_file (int n)
  71. {
  72.   if (n >= NPIPE || n < 0)
  73.     error (1, 0, "no more pipes");
  74.  
  75.   if (!pipe_file[n])
  76.     {
  77.       if (!tmpdir)
  78.     {
  79.       /* Initialize.  */
  80.  
  81.       atexit (cleanup_pipes);
  82.  
  83.       tmpdir = getenv ("TMP");
  84.  
  85.       if (tmpdir)
  86.         {
  87.           tmpdirlen = strlen (tmpdir);
  88.           if (tmpdir[tmpdirlen - 1] == '/'
  89.           || tmpdir[tmpdirlen - 1] == '\\')
  90.         tmpdir[tmpdirlen - 1] = '\0';
  91.         }
  92.       else
  93.         {
  94.           tmpdir = ".";
  95.           tmpdirlen = 1;
  96.         }
  97.     }
  98.  
  99.       pipe_file[n] = (char *) xmalloc (tmpdirlen + 14);
  100.       sprintf (pipe_file[n], "%s/pipe%04x.%03d", tmpdir, getpid (), n);
  101.     }
  102.  
  103.   return pipe_file[n];
  104. }
  105.  
  106.  
  107. /* Clean up after we are done. */
  108.  
  109. void
  110. cleanup_pipes (void)
  111. {
  112.   int i;
  113.  
  114.   for (i = 0; i < NPIPE; i++)
  115.     unlink (pipe_file[i]);
  116. }
  117.  
  118. /* Filter the contents of INFILE through COMMAND (with optional
  119.    arguments) and place the output in OUTFILE.  */
  120.  
  121. #define IN_MODE  (O_RDONLY|O_TEXT)
  122. #define OUT_MODE (O_CREAT|O_TRUNC|O_WRONLY|O_TEXT)
  123. #define OUT_PERM (S_IWRITE|S_IREAD)
  124.  
  125. int
  126. filter_through_command (char *infile, char *outfile, char *command, ...)
  127. {
  128.   int rc;
  129.  
  130.   /* For MS-DOS we know that the stack grows in the right
  131.      direction, so we could just say
  132.  
  133.     swap_spawnvp (command, &command);
  134.  
  135.      but we want to write clean code which doesn't make such
  136.      assumptions.  */
  137.  
  138.   if (command)
  139.     {
  140.       va_list ap;
  141.       char **argv;
  142.       int argc = 1;
  143.       int i;
  144.  
  145.       int our_stdin;
  146.       int our_stdout;
  147.       int child_stdin;
  148.       int child_stdout;
  149.  
  150.  
  151.       /* Count the arguments */
  152.  
  153.       va_start (ap, command);
  154.       while (va_arg (ap, char *))
  155.     argc++;
  156.       va_end (ap);
  157.  
  158.       argv = (char **) xmalloc ((argc + 1) * sizeof (char *));
  159.  
  160.  
  161.       /* Set up the pointers. */
  162.  
  163.       argv[0] = command;
  164.  
  165.       va_start (ap, command);
  166.       for (i = 1; i < argc; i++)
  167.     argv[i] = va_arg (ap, char *);
  168.       va_end (ap);
  169.  
  170.       argv[argc] = NULL;
  171.  
  172.  
  173.       /* Set up our own pipes,
  174.      assuming that the child knows how to setmode ().  */
  175.  
  176.       if (infile)
  177.     if ((our_stdin = dup (0)) < 0
  178.         || (child_stdin = open (infile, IN_MODE)) < 0
  179.         || dup2 (child_stdin, 0) < 0)
  180.       error (1, errno, "can't write to `%s'", command);
  181.  
  182.       if (outfile)
  183.     if ((our_stdout = dup (1)) < 0
  184.         || (child_stdout = open (outfile, OUT_MODE, OUT_PERM)) < 0
  185.         || dup2 (child_stdout, 1) < 0)
  186.       error (1, errno, "can't read from `%s'", command);
  187.  
  188.  
  189.       /* Spawn COMMAND (without intervening shell)  */
  190.  
  191. #ifndef DONT_USE_SWAPLIB
  192.       rc = swap_spawnvp (command, argv);
  193. #else
  194.       rc = spawnvp (P_WAIT, command, argv);
  195. #endif
  196.  
  197.       /* Clean up our pipes.  */
  198.  
  199.       if (infile)
  200.     {
  201.       dup2 (our_stdin, 0);
  202.       close (our_stdin);
  203.       close (child_stdin);
  204.     }
  205.  
  206.       if (outfile)
  207.     {
  208.       dup2 (our_stdout, 1);
  209.       close (our_stdout);
  210.       close (child_stdout);
  211.     }
  212.  
  213.       free (argv);
  214.     }
  215.   else
  216.     {
  217.       /* Invalid arguments.  */
  218.  
  219.       rc = -1;
  220.       errno = EINVAL;
  221.     }
  222.  
  223.   return rc;
  224. }
  225.  
  226. /* 
  227.  * Local Variables:
  228.  * mode:C
  229.  * ChangeLog:ChangeLog
  230.  * compile-command:make
  231.  * End:
  232.  */
  233.