/* wrapexec.c - Wrapper that calls an executor. */ /* Revision: 060820 */ /* ------------------------------------------------------------ */ /* explanation */ /* ------------------------------------------------------------ */ /* 1. Overview. */ /* There's a class of "executor" programs that are used like */ /* this: */ /* */ /* executor-program target-program arg1 arg2 ... */ /* or */ /* executor-program options target-program arg1 arg2 ... */ /* The executor-program runs the specified target-program and */ /* passes arg1 arg2 ... to the target-program as command-line */ /* arguments. Note: If option switches are specified before the */ /* target-program name, they affect the behavior of the execu- */ /* tor, and not the target. */ /* Examples: "Executor" programs of this type include "nice" */ /* and "rlwrap". */ /* "wrapexec.c" is a simple wrapper for "executor"-"target" */ /* program pairs. From the user's point of view, the wrapper */ /* transparently replaces a given target program. When the */ /* wrapper is executed, it uses a given executor program to run */ /* the original target program. */ /* Note: Command-line option switches and/or arguments given to */ /* the wrapper program are passed to the target program. */ /* There's no provision for specifying executor-level option */ /* switches. */ /* ------------------------------------------------------------ */ /* 2. To use this wrapper, proceed as follows: */ /* */ /* a. Rename the target executable to something unique. For */ /* example, you might add the suffix ".bin". */ /* */ /* b. Compile this wrapper program. Define the preprocessor */ /* symbols PATH_EXECUTOR and PATH_TARGET during the procedure. */ /* These symbols should specify absolute pathnames for executa- */ /* bles, with a leading and trailing double quote added in each */ /* case. PATH_EXECUTOR gives the location of the executor exe- */ /* cutable. PATH_TARGET gives the location of the renamed tar- */ /* get executable. */ /* */ /* c. Rename the compiled wrapper executable. You'll probab- */ /* ly want to give it the name that the target executable had */ /* originally. This may or may not be necessary. */ /* */ /* d. Move the wrapper executable to an appropriate direc- */ /* tory. You'll probably want to put it in the same directory */ /* as the renamed target executable. This may or may not be */ /* necessary. */ /* */ /* e. Execute the compiled wrapper. You can specify any opt- */ /* tion switches and/or arguments that are supported by the */ /* original target program. */ /* ------------------------------------------------------------ */ /* 3. Argument-list conventions: */ /* This program passes a modified argument list to the executor */ /* program. The modified list is structured as follows: */ /* */ /* a. The new value of "argv [ZERO]" is equal to the value of */ /* PATH_EXECUTOR [without the leading/trailing quote]. */ /* */ /* b. The new value of "argv [ONE ]" is equal to the value of */ /* PATH_TARGET [without the leading/trailing quote]. */ /* */ /* c. If any arguments were specified on the original command */ /* line, they're passed after "argv [ONE]". */ /* */ /* d. A null entry is passed as the last argument. This termin- */ /* ates the argument list. */ /* ------------------------------------------------------------ */ /* 4. Bugs and restrictions. */ /* The setup procedure described previously involves renaming */ /* the original target-program executable. Therefore, the wrap- */ /* per can't be used with target programs that depend too heav- */ /* ily on their names [i.e., the string values passed in "argv */ /* [ZERO]". */ /* ------------------------------------------------------------ */ /* standard header file(s) */ /* ------------------------------------------------------------ */ #include #include /* ------------------------------------------------------------ */ /* basic definitions */ /* ------------------------------------------------------------ */ #define ZERO 0 #define ONE 1 #define THREE 3 #define NULLCP ((char *) ZERO) /* ------------------------------------------------------------ */ /* main program */ /* ------------------------------------------------------------ */ int main (int argc, char **argv) { int ii; /* Counter */ int OldArrayLen; /* Length of old argument array */ int NewArrayLen; /* Length of new argument array */ char **new_argv; /* New argument array */ /* Get length of old array */ for (ii = ZERO; argv [ii] != NULLCP; ii++) {} OldArrayLen = ii + ONE; /* Get length of new array */ NewArrayLen = OldArrayLen + ONE; if (NewArrayLen < THREE) /* Consistency check */ { fprintf (stderr, "%s\n", "Undetermined internal error"); exit (ONE); } /* Allocate dynamic storage */ new_argv = (char **) malloc (NewArrayLen * sizeof (char **)); /* Safety measure */ if (new_argv == (char **) ZERO) { fprintf (stderr, "%s\n", "Error: Out of memory"); exit (ONE); } /* Set first two entries */ new_argv [ZERO] = PATH_EXECUTOR; new_argv [ONE ] = PATH_TARGET; /* Copy command-line arguments */ for (ii = ONE; ii < OldArrayLen; ii++) { new_argv [ii+ONE] = argv [ii]; } argv = new_argv; /* Replace old argument list */ /* Run the executor program */ execv (PATH_EXECUTOR, argv); return (ZERO); /* This shouldn't be reached */ }