home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / elvis / Source / c / system < prev    next >
Encoding:
Text File  |  1990-03-09  |  4.8 KB  |  235 lines

  1. /* system.c  -- UNIX version */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    16820 SW Tallac Way
  6.  *    Beaverton, OR 97006
  7.  *    kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
  8.  */
  9.  
  10.  
  11. /* This file contains a new version of the system() function and related stuff.
  12.  *
  13.  * Entry points are:
  14.  *    system(cmd)    - run a single shell command
  15.  *    wildcard(names)    - expand wildcard characters in filanames
  16.  *    filter(m,n,cmd)    - run text lines through a filter program
  17.  *
  18.  * This is probably the single least portable file in the program.  The code
  19.  * shown here should work correctly if it links at all; it will work on UNIX
  20.  * and any O.S./Compiler combination which adheres to UNIX forking conventions.
  21.  * For DOS, these three functions will have to be reimplemented from scratch.
  22.  */
  23.  
  24. #include "vi.h"
  25. extern char    **environ;
  26.  
  27.  
  28. /* This is a new version of the system() function.  The only difference
  29.  * between this one and the library one is: this one uses the o_shell option.
  30.  */
  31.  
  32. #ifndef ARC
  33.  
  34. int system(cmd)
  35.     char    *cmd;    /* a command to run */
  36. {
  37.     int    status;    /* exit status of the command */
  38.  
  39.     switch (fork())
  40.     {
  41.       case -1:                        /* error */
  42.         status = -1;
  43.         break;
  44.  
  45.       case 0:                        /* child */
  46.         execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
  47.         exit(1); /* if we get here, the exec failed */
  48.  
  49.       default:                        /* parent */
  50.         wait(&status);
  51.     }
  52.  
  53.     return status;
  54. }
  55.  
  56. #endif /* ARC */
  57.  
  58. /* This private function opens a pipe from a filter.  It is similar to the
  59.  * system() function above, and to popen(cmd, "r").
  60.  */
  61. static int rpipe(cmd, in)
  62.     char    *cmd;    /* the filter command to use */
  63.     int    in;    /* the fd to use for stdin */
  64. {
  65.     int    r0w1[2];/* the pipe fd's */
  66.  
  67.     /* make the pipe */
  68.     if (pipe(r0w1) < 0)
  69.     {
  70.         return -1;    /* pipe failed */
  71.     }
  72.  
  73.     switch (fork())
  74.     {
  75.       case -1:                        /* error */
  76.         return -1;
  77.  
  78.       case 0:                        /* child */
  79.         /* close the "read" end of the pipe */
  80.         close(r0w1[0]);
  81.  
  82.         /* redirect stdout to go to the "write" end of the pipe */
  83.         close(1);
  84.         dup(r0w1[1]);
  85.         close(2);
  86.         dup(r0w1[1]);
  87.         close(r0w1[1]);
  88.  
  89.         /* redirect stdin */
  90.         if (in != 0)
  91.         {
  92.             close(0);
  93.             dup(in);
  94.             close(in);
  95.         }
  96.  
  97.         /* exec the shell to run the command */
  98.         execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
  99.         exit(1); /* if we get here, exec failed */
  100.  
  101.       default:                        /* parent */
  102.         /* close the "write" end of the pipe */    
  103.         close(r0w1[1]);
  104.  
  105.         return r0w1[0];
  106.     }
  107. }
  108.  
  109. /* This function closes the pipe opened by rpipe(), and returns 0 for success */
  110. int rpclose(fd)
  111.     int    fd;
  112. {
  113.     int    status;
  114.  
  115.     close(fd);
  116.     wait(&status);
  117.     return status;
  118. }
  119.  
  120. /* This function expands wildcards in a filename or filenames.  It does this
  121.  * by running the "echo" command on the filenames via the shell; it is assumed
  122.  * that the shell will expand the names for you.  If for any reason it can't
  123.  * run echo, then it returns the names unmodified.
  124.  */
  125. char *wildcard(names)
  126.     char    *names;
  127. {
  128.     int    i, j, fd;
  129.  
  130.     /* build the echo command */
  131.     if (names != tmpblk.c)
  132.     {
  133.         /* the names aren't in tmpblk.c, so we can do it the easy way */
  134.         strcpy(tmpblk.c, "echo ");
  135.         strcat(tmpblk.c, names);
  136.     }
  137.     else
  138.     {
  139.         register char *s, *d;
  140.  
  141.         /* the names are already in tmpblk.c, so shift them to make
  142.          * room for the word "echo "
  143.          */
  144.         for (s = names + strlen(names) + 1, d = s + 5; s > names; )
  145.         {
  146.             *--d = *--s;
  147.         }
  148.         strncpy(names, "echo ", 5);
  149.     }
  150.  
  151.     /* run the command & read the resulting names */
  152.     fd = rpipe(tmpblk.c, 0);
  153.     if (fd < 0) return names;
  154.     i = 0;
  155.     do
  156.     {
  157.         j = read(fd, tmpblk.c, BLKSIZE - i);
  158.         i += j;
  159.     } while (j > 0);
  160.  
  161.     /* successful? */
  162.     if (rpclose(fd) == 0 && j == 0 && i < BLKSIZE && i > 0)
  163.     {
  164.         tmpblk.c[i-1] = '\0'; /* "i-1" so we clip off the newline */
  165.         return tmpblk.c;
  166.     }
  167.     else
  168.     {
  169.         return names;
  170.     }
  171. }
  172.  
  173. /* This function runs a range of lines through a filter program, and replaces
  174.  * the original text with the filtered version.
  175.  */
  176. int filter(from, to, cmd)
  177.     MARK    from, to;    /* the range of lines to filter */
  178.     char    *cmd;        /* the filter command */
  179. {
  180.     int    scratch;    /* fd of the scratch file */
  181.     int    fd;        /* fd of the pipe from the filter */
  182.     int    i;
  183.  
  184.     /* write the lines to a temp file */
  185.     cmd_write(from, to, CMD_BANG, 0, SCRATCHFILE);
  186.  
  187.     /* start the filter program */
  188.     scratch = open(SCRATCHFILE, O_RDONLY);
  189.     if (scratch < 0)
  190.     {
  191.         unlink(SCRATCHFILE);
  192.         return -1;
  193.     }
  194.     fd = rpipe(cmd, scratch);
  195.     if (fd < 0)
  196.     {
  197.         close(scratch);
  198.         unlink(SCRATCHFILE);
  199.         return -1;
  200.     }
  201.  
  202.     ChangeText
  203.     {
  204.         /* delete the original lines.  Lines!  */
  205.         from &= ~(BLKSIZE - 1);
  206.         to &= ~(BLKSIZE - 1);
  207.         to += BLKSIZE;
  208.         delete(from, to);
  209.  
  210.         /* repeatedly read in new text and add it */
  211.         while ((i = read(fd, tmpblk.c, BLKSIZE)) > 0)
  212.         {
  213.             tmpblk.c[i] = '\0';
  214.             add(from, tmpblk.c);
  215.             for (i = 0; tmpblk.c[i]; i++)
  216.             {
  217.                 if (tmpblk.c[i] == '\n')
  218.                 {
  219.                     from = (from & ~(BLKSIZE - 1)) + BLKSIZE;
  220.                 }
  221.                 else
  222.                 {
  223.                     from++;
  224.                 }
  225.             }
  226.         }
  227.     }
  228.  
  229.     /* cleanup */
  230.     rpclose(fd);
  231.     close(scratch);
  232.     unlink(SCRATCHFILE);
  233.     return 0;
  234. }
  235.