home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / rcs567s.zip / rcs / src / ms / spawnvpq.c < prev    next >
C/C++ Source or Header  |  1994-04-06  |  2KB  |  119 lines

  1. /* spawnvpq for MS-DOS and OS/2 */
  2.  
  3. /* by Paul Eggert and Frank Whaley */
  4.  
  5.     /* $Id: spawnvpq.c,v 1.5 1992/02/17 23:02:20 eggert Exp $ */
  6.  
  7. #if !defined(__EMX__) || defined(__MSDOS__)
  8.  
  9. #include <errno.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sys/types.h>
  13.  
  14. /*
  15. * Most MS-DOS and OS/2 versions of spawnvp do not
  16. * properly handle arguments with embedded blanks,
  17. * so spawnvpq works around the bug by quoting arguments itself.
  18. * The quoting regime, bizarre as it sounds, is as follows:
  19. *
  20. *    If an argument contains N (>=0) backslashes followed by '"',
  21. *    precede the '"' with an additional N+1 backslashes.
  22. *
  23. *    Surround an argument with '"' if it contains space or tab.
  24. *
  25. *    If an argument contains space or tab and ends with N backslashes,
  26. *    append an additional N backslashes.
  27. */
  28.     int
  29. spawnvpq(int mode, char const *path, char * const *argv)
  30. {
  31.     char *a, **argw, **aw, *b, *buf;
  32.     char * const *av;
  33.     size_t argsize = 0, argvsize;
  34.  
  35.     for (av = argv;  (a = *av++);  ) {
  36.         size_t backslashrun = 0, quotesize = 0;
  37.         char *p = a;
  38.         for (;;) {
  39.             switch (*p++) {
  40.                 case '\t': case ' ':
  41.                     quotesize = 2;
  42.                     /* fall into */
  43.                 case '"':
  44.                     argsize += backslashrun + 1;
  45.                     /* fall into */
  46.                 default:
  47.                     backslashrun = 0;
  48.                     continue;
  49.  
  50.                 case '\\':
  51.                     backslashrun++;
  52.                     continue;
  53.  
  54.                 case 0:
  55.                     if (quotesize)
  56.                         argsize += backslashrun;
  57.                     break;
  58.             }
  59.             break;
  60.         }
  61.         argsize += p - a + quotesize;
  62.     }
  63.  
  64.     argvsize = (av-argv) * sizeof(char*);
  65.     if (!(buf  =  malloc(argvsize + argsize))) {
  66.         errno = E2BIG;
  67.         return -1;
  68.     }
  69.     aw = argw = (char**)buf;
  70.     b = buf + argvsize;
  71.  
  72.     for (av = argv;  (a = *av++);  ) {
  73.         char c;
  74.         int contains_white = strchr(a, ' ') || strchr(a, '\t');
  75.         size_t backslashrun = 0;
  76.         char *p = a;
  77.         *aw++ = b;
  78.         if (contains_white)
  79.             *b++ = '"';
  80.         for (;  ;  *b++ = c) {
  81.             switch ((c = *p++)) {
  82.                 case '\\':
  83.                     backslashrun++;
  84.                     continue;
  85.  
  86.                 case '"':
  87.                     backslashrun++;
  88.                     memset(b, '\\', backslashrun);
  89.                     b += backslashrun;
  90.                     /* fall into */
  91.                 default:
  92.                     backslashrun = 0;
  93.                     continue;
  94.  
  95.                 case 0:
  96.                     break;
  97.             }
  98.             break;
  99.         }
  100.         if (contains_white) {
  101.             memset(b, '\\', backslashrun);
  102.             b += backslashrun;
  103.             *b++ = '"';
  104.         }
  105.         *b++ = 0;
  106.     }
  107.     *aw = 0;
  108.  
  109.     {
  110.         int r = spawnvp(mode, path, argw);
  111.         int e = errno;
  112.         free(buf);
  113.         errno = e;
  114.         return r;
  115.     }
  116. }
  117.  
  118. #endif
  119.