The execit.c C Program

[return-to Explanation (The execit Programs)] [table of contents] [index]
#ifndef lint
static char *rcsid = "$Id: execit.c,v 1.3 90/02/17 07:18:39 jdpeek Exp $";
#endif

/* execit - run a program; use a different name
 *
 *  Usage: progname [arguments]
 *
 *  Some programs, especially MH programs, check the name they're
 *  invoked with (from their argv[0]) and change the way they work.
 *  The easiest way to do this with system programs is to make a new
 *  link (symbolic or "hard") to the program's executable code, like this:
 *  % ln /usr/local/bin/folder /usr/myhome/bin/folders
 *  Then, you can run "folder" with the name "folders".
 *
 *  The problems with that are:  You can only make hard links (ln) if
 *  you have access to a directory on the same filesystem as the system
 *  executables.  And some systems don't have symbolic links (ln -s).
 *  That's when you need "execit".  This "execit" program lets you
 *  define a table of system commands and the names you want to run them
 *  with.  Then, you make a link to "execit" with the name of the program
 *  you want to run.  It invokes the system program with the name you use.
 *  This way, you get fast execution of a system program with your own name.
 *  And, if you make new hard links to "execit", defining new program names
 *  doesn't take any more filesystem space.
 *
 *  Here's an example of how to set up "execit" so it will run the program
 *  "/usr/local/mh/repl", but make "repl" think its name is "replx":
 *
 *  1) Edit the file "execit.include" and add a new line like this:
 *      "replx", "/usr/local/mh/repl",
 *     (the second string should be where repl is located on your system!)
 *     Be sure to make the line look just like that -- quotes and commas.
 *     This file is read into the xref structure at compile time.
 *
 *  2) Recompile this program, something like this:
 *      % cc -o execit execit.c
 *
 *  3) If there were no errors, make a link to "execit" named "replx":
 *      % ln execit replx
 *     Then, use "ls -li" to be sure previous links to "execit" still exist:
 *      % ls -li execit replx tscan
 *       2379 -rwx------  3 jdpeek  35982 Feb 10 22:14 execit
 *       2379 -rwx------  3 jdpeek  35982 Feb 10 22:14 replx
 *       2379 -rwx------  3 jdpeek  35982 Feb 10 22:14 tscan
 *       ^^^^             ^               ^^^^^^^^^^^^
 *       SAME           SAME                 TODAY'S
 *       i-NUMS      LINK COUNT           DATE AND TIME
 *
 *     (Delete any old links and re-link to the new "execit" with "ln".)
 *
 *  4) Now, assuming the directory is in your shell's search path,
 *     (and, for MH programs, you may want a line in .mh_profile like this:
 *      replx: -switches -go -here
 *     ) you can run "replx" and pass the switch "-query" to it this way:
 *          % replx -query
 *
 *  Placed in the public domain by its author, Jerry Peek, 12 February 1990.
 *  (jdpeek@rodan.acs.syr.edu)  Use at your own risk.  Suggestions welcome!
 */
#include <stdio.h>

/* Table of command name user wants to run as,
 * and full pathname of actual system program to run.
 * Edit the "execit.include" file to add more entries to the structure below;
 * then recompile and re-link this code with the new name.
 */
struct xref {
    char *runas, *torun;
} xrefs[] = {
    "EDIT_ME", "/YOUR/PATH/NAME/HERE",
#include "execit.include"
    "tscan", "/usr/local/mh/scan"
};

main(argc, argv, envp)
int argc;
char **argv, **envp;
{
    char *myname, *p;
    int ret, index, bogus;
    int numcmds = sizeof(xrefs) / sizeof(struct xref);

    /* Get basename of this program by stepping past final '/': */
    myname = p = *argv;
    while (*p)
        if (*p++ == '/')
            myname = p;
    
    /* Find program to run (xrefs[index].torun) from lookup table: */
    bogus = 1;
    for (index = 0; index < numcmds; index++) {
        if (strcmp(myname, xrefs[index].runas) == 0) {
            bogus = 0;  /* found it */
            break;
        }
    }
    if (bogus) {
        fprintf(stderr,
            "%s: Can't run myself!  Fix execit.include and/or run execit.link.\n",
            argv[0]);
        exit(1);
    }

    /* Set fake program name in argv[0], then try to run real program.
     * If exec succeeds, return program's exit status.
     * Otherwise, print errno message and return -1.
     */
    argv[0] = xrefs[index].runas;
    if ((ret = execve(xrefs[index].torun, argv, envp)) != -1)
        exit(ret);
    else {
        perror(xrefs[index].torun);
        exit(-1);
    }
}

[Table of Contents] [Index] [Return to Explanation (The execit Programs)] [The execit.include File] [The execit.link Shell Script] [The execit Makefile]


Last change $Date: 1996/06/06 15:13:41 $

This file is from the third edition of the book MH & xmh: Email for Users & Programmers, ISBN 1-56592-093-7, by Jerry Peek. Copyright © 1991, 1992, 1995 by O'Reilly & Associates, Inc. This file is freely-available; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. For more information, see the file copying.htm.

Suggestions are welcome: Jerry Peek <jpeek@jpeek.com>