home *** CD-ROM | disk | FTP | other *** search
- /* system.c -- UNIX version */
-
- /* Author:
- * Steve Kirkendall
- * 16820 SW Tallac Way
- * Beaverton, OR 97006
- * kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
- */
-
-
- /* This file contains a new version of the system() function and related stuff.
- *
- * Entry points are:
- * system(cmd) - run a single shell command
- * wildcard(names) - expand wildcard characters in filanames
- * filter(m,n,cmd) - run text lines through a filter program
- *
- * This is probably the single least portable file in the program. The code
- * shown here should work correctly if it links at all; it will work on UNIX
- * and any O.S./Compiler combination which adheres to UNIX forking conventions.
- * For DOS, these three functions will have to be reimplemented from scratch.
- */
-
- #include "vi.h"
- extern char **environ;
-
-
- /* This is a new version of the system() function. The only difference
- * between this one and the library one is: this one uses the o_shell option.
- */
-
- #ifndef ARC
-
- int system(cmd)
- char *cmd; /* a command to run */
- {
- int status; /* exit status of the command */
-
- switch (fork())
- {
- case -1: /* error */
- status = -1;
- break;
-
- case 0: /* child */
- execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
- exit(1); /* if we get here, the exec failed */
-
- default: /* parent */
- wait(&status);
- }
-
- return status;
- }
-
- #endif /* ARC */
-
- /* This private function opens a pipe from a filter. It is similar to the
- * system() function above, and to popen(cmd, "r").
- */
- static int rpipe(cmd, in)
- char *cmd; /* the filter command to use */
- int in; /* the fd to use for stdin */
- {
- int r0w1[2];/* the pipe fd's */
-
- /* make the pipe */
- if (pipe(r0w1) < 0)
- {
- return -1; /* pipe failed */
- }
-
- switch (fork())
- {
- case -1: /* error */
- return -1;
-
- case 0: /* child */
- /* close the "read" end of the pipe */
- close(r0w1[0]);
-
- /* redirect stdout to go to the "write" end of the pipe */
- close(1);
- dup(r0w1[1]);
- close(2);
- dup(r0w1[1]);
- close(r0w1[1]);
-
- /* redirect stdin */
- if (in != 0)
- {
- close(0);
- dup(in);
- close(in);
- }
-
- /* exec the shell to run the command */
- execle(o_shell, o_shell, "-c", cmd, (char *)0, environ);
- exit(1); /* if we get here, exec failed */
-
- default: /* parent */
- /* close the "write" end of the pipe */
- close(r0w1[1]);
-
- return r0w1[0];
- }
- }
-
- /* This function closes the pipe opened by rpipe(), and returns 0 for success */
- int rpclose(fd)
- int fd;
- {
- int status;
-
- close(fd);
- wait(&status);
- return status;
- }
-
- /* This function expands wildcards in a filename or filenames. It does this
- * by running the "echo" command on the filenames via the shell; it is assumed
- * that the shell will expand the names for you. If for any reason it can't
- * run echo, then it returns the names unmodified.
- */
- char *wildcard(names)
- char *names;
- {
- int i, j, fd;
-
- /* build the echo command */
- if (names != tmpblk.c)
- {
- /* the names aren't in tmpblk.c, so we can do it the easy way */
- strcpy(tmpblk.c, "echo ");
- strcat(tmpblk.c, names);
- }
- else
- {
- register char *s, *d;
-
- /* the names are already in tmpblk.c, so shift them to make
- * room for the word "echo "
- */
- for (s = names + strlen(names) + 1, d = s + 5; s > names; )
- {
- *--d = *--s;
- }
- strncpy(names, "echo ", 5);
- }
-
- /* run the command & read the resulting names */
- fd = rpipe(tmpblk.c, 0);
- if (fd < 0) return names;
- i = 0;
- do
- {
- j = read(fd, tmpblk.c, BLKSIZE - i);
- i += j;
- } while (j > 0);
-
- /* successful? */
- if (rpclose(fd) == 0 && j == 0 && i < BLKSIZE && i > 0)
- {
- tmpblk.c[i-1] = '\0'; /* "i-1" so we clip off the newline */
- return tmpblk.c;
- }
- else
- {
- return names;
- }
- }
-
- /* This function runs a range of lines through a filter program, and replaces
- * the original text with the filtered version.
- */
- int filter(from, to, cmd)
- MARK from, to; /* the range of lines to filter */
- char *cmd; /* the filter command */
- {
- int scratch; /* fd of the scratch file */
- int fd; /* fd of the pipe from the filter */
- int i;
-
- /* write the lines to a temp file */
- cmd_write(from, to, CMD_BANG, 0, SCRATCHFILE);
-
- /* start the filter program */
- scratch = open(SCRATCHFILE, O_RDONLY);
- if (scratch < 0)
- {
- unlink(SCRATCHFILE);
- return -1;
- }
- fd = rpipe(cmd, scratch);
- if (fd < 0)
- {
- close(scratch);
- unlink(SCRATCHFILE);
- return -1;
- }
-
- ChangeText
- {
- /* delete the original lines. Lines! */
- from &= ~(BLKSIZE - 1);
- to &= ~(BLKSIZE - 1);
- to += BLKSIZE;
- delete(from, to);
-
- /* repeatedly read in new text and add it */
- while ((i = read(fd, tmpblk.c, BLKSIZE)) > 0)
- {
- tmpblk.c[i] = '\0';
- add(from, tmpblk.c);
- for (i = 0; tmpblk.c[i]; i++)
- {
- if (tmpblk.c[i] == '\n')
- {
- from = (from & ~(BLKSIZE - 1)) + BLKSIZE;
- }
- else
- {
- from++;
- }
- }
- }
- }
-
- /* cleanup */
- rpclose(fd);
- close(scratch);
- unlink(SCRATCHFILE);
- return 0;
- }
-