DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T r

⟦6be5863ba⟧ TextFile

    Length: 9533 (0x253d)
    Types: TextFile
    Names: »rman.c«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/rman/client/rman.c« 

TextFile

/*
 *  Copyright (c) 1985  Jonathan C. Broome and The Regents of the 
 *  University of California.
 *
 *  This software may be freely redistributed without licensing
 *  provided that this copyright notice remains intact and no profit
 *  is gained through any redistribution.
 *
 *  Please report any bug fixes or modifications to the author at:
 *
 *        broome@ucb-vax.berkeley.edu
 *   or:
 *        ...!ucbvax!broome
 *
 *  The author and the Regents assume no liability for any damages 
 *  or loss of revenue caused directly or indirectly by the use of 
 *  this software.
 */

#ifndef lint
static char *RCSid = "$Header: rman.c,v 1.18 85/08/27 15:19:13 broome Exp $";
#endif

/*
 * $Log:    rman.c,v $
 * Revision 1.18  85/08/27  15:19:13  broome
 * Added copyright/distribution comment.
 * 
 * Revision 1.17  85/08/27  15:04:52  broome
 * 
 * 
 * Revision 1.16  85/08/05  22:14:53  broome
 * Changed method for checking if an arg is a section name --
 * cleaner and more reliable now ...
 * 
 * Also changed local page lookup routine to check for MANPATH 
 * environment variable - list of dirs to search for pages.
 * 
 * Revision 1.15  85/08/04  18:41:20  broome
 * 
 * Revision 1.14  85/08/03  02:36:22  broome
 * Changed to use buffered i/o on temp file, removed error message on 
 * bad options - acts more like the old "man" this way.
 * 
 * Revision 1.13  85/07/31  09:31:28  broome
 * Added "cantconnect" routine so that when EXEC_ON_ERROR is defined, it
 * will fork and execl /usr/ucb/man for each page it needs.  This is
 * obviously only useful for testing purposes!
 * 
 * Revision 1.12  85/07/30  18:51:59  broome
 * Changed to avoid opening host connection until needed.  This way
 * local man pages can be found without needing a remote host.
 * 
 * Revision 1.11  85/07/16  11:10:45  broome
 * Added "-m" option to force use of more, "-" option now disables more,
 * in keeping with the way the old "man" is set up.
 * 
 * Revision 1.10  85/07/13  16:05:57  broome
 * Added fix for setuid version of man.
 * 
 * Revision 1.9  85/07/13  15:57:33  broome
 * Incorporated "pinging" of remote hosts - great speed improvement!
 * 
 * Revision 1.8  85/07/06  16:55:05  broome
 * Ok, *now* it's ready.. Or is it???
 * 
 * Revision 1.7  85/07/04  19:58:21  broome
 * Separated into more logical routines, more error checking,
 * follows the rfc ideas more closely.
 * 
 * Revision 1.6  85/07/03  18:01:55  broome
 * Fixed the '-' option (to force use of "more"), unfortunately breaks
 * being able to specify multiple options in one arg.
 * 
 * Revision 1.5  85/07/03  17:33:30  broome
 * Trying to keep lint happy...
 * 
 * Revision 1.4  85/07/02  21:03:49  broome
 * Getting ready for beta test distribution (Kurt's machines)...
 * Still needs a lot of cleaning in the server, but it works.
 * 
 * Revision 1.3  85/07/02  13:03:28  broome
 * New version, supports the '-k' and '-f' options.
 * 
 * Revision 1.2  85/06/28  12:34:56  broome
 * Added check for output to a tty, cleaned up w.r.t. lint.
 *
 * Revision 1.1  85/06/25  11:22:09  broome
 * Initial revision
 */

#include <sys/file.h>
#include <stdio.h>
#include <signal.h>

#define  eq(a,b)    (strcmp (a,b) == 0)

/*
 *  Known sections. This method makes it easier to update...
 */
static char *sections[] = {
    "1",        "2",
    "3",        "4",
    "5",        "6",
    "7",        "8",
    "cad",      "c",
    "local",    "l",
    "new",      "n",
    "old",      "o",
    "public",   "p",
};
#define NUMSEC (sizeof (sections) / sizeof (char *))

#define MAN     1
#define APROPOS 2
#define WHATIS  3
#define RAW     4
#define MORE    "more"    /* use execlp to find it ... */

int     mode = MAN;
int     use_more = 0;
int     verbose = 0; 
int     connected = 0;
int     interrupt();
int     sigpipe();
char    *prog;
char    *pager;
char    fname[256];
char    *type = (char *) 0;
FILE    *sock_rp;
FILE    *sock_wp;
FILE    *tfp;

main (argc, argv)
int   argc;
char *argv[];
{
    char  *section;
    char  *rindex();
    char  *getenv();
    char  *r;

    if (r = rindex (*argv, '/'))   /* what were we invoked as?? */
        prog = ++r;
    else
        prog = *argv;

    /*
     *  Process the command line.
     */

    if (eq (prog, "apropos"))
        mode = APROPOS;
    else if (eq (prog, "whatis"))
        mode = WHATIS;

    while (*++argv && **argv == '-') {
        switch ((*argv)[1]) {
            case 'a':
            case 'f': mode = APROPOS; break;

            case 'w':
            case 'k': mode = WHATIS; break;

            case 'r': mode = RAW;  break;

            case 't': if (argv[1]) 
                            type = *++argv, argc--;
                      else
                            usage ();
                      break;

            case 'v': verbose = 1; break;

            case 'm':  use_more = 1; break;    /* force use of more */
            case '\0': use_more = -1; break;   /* force *not* use of more */
        }
        argc--;
    }

    if (argc <= 1)
        usage ();

    setlinebuf (stderr);
    signal (SIGHUP,  interrupt);
    signal (SIGINT,  interrupt);
    signal (SIGQUIT, interrupt);
    signal (SIGTERM, interrupt);
    signal (SIGPIPE, sigpipe);

    if (mode == MAN && !use_more)    /* if not forced more and using `man' */
        use_more = isatty (1);

    if (use_more == 1) {             /* set up temp file */
        umask (0);                   /* should we do this when setuid? */
        sprintf (fname, "/tmp/rman.%05d", getpid ());
        if ((tfp = fopen (fname, "w")) == NULL) {
            fprintf (stderr, "%s: cannot create temp file: ", prog);
            perror (fname);
            exit (1);
        }
#ifdef SETUID
        if (!geteuid ())             /* running as root */
            (void) chown (fname, getuid (), -1);
#endif
        if ((pager = getenv ("MANPAGER")) == (char *) 0)  /* use ucb/more ?? */
            if ((pager = getenv("PAGER")) == (char *) 0)
                pager = MORE;
    }

    while (*argv) {
        if (is_section (*argv))
            section = *argv++;
        else
            section = (char *) 0;

        if (section && !*argv) {
            fprintf (stderr, "But what do you want from section %s?\n", section);
            break;
        }
        doit (*argv++, section);
    }

    if (use_more)
        unlink (fname);
    if (connected)
        fprintf (sock_wp, "quit\r\n");
    exit (0);
}


doit (name, sec)
char *name, *sec;
{
    static char *cmd = (char *) 0;

    if (mode == MAN || mode == RAW)            /* check for local pages first */
        if (dolocal (name, sec, mode == RAW))  /* found it locally */
            return;

    /*
     *  Not connected yet, so try to connect to a server.
     */

    if (!connected) {
        if (open_server () == -1) {
            cantconnect (name, sec);
            return;
        } else
            connected = 1;
    }

    if (cmd == (char *) 0)
        switch (mode) {
            case MAN:     cmd = "cat"; break;
            case APROPOS: cmd = "apropos"; break;
            case WHATIS:  cmd = "whatis"; break;
            case RAW:     cmd = "raw"; break;
        }
    fprintf (sock_wp, "%s %s %s\n", cmd, sec, name);  /* ask for a page */
    (void) fflush (sock_wp);

    if (response ())        /* bad response */
        return;

    if (use_more == 1)
        getmore ();
    else
        getcat ();
}


/*
 *  Check to see if `arg' is a valid section name,
 *  return 1 if true, else 0.
 */

is_section (arg)
char *arg;
{
    char *suffixes = "1234567890lnopc";
    char suff;
    int  i, len, arglen;

    arglen = strlen (arg);
    suff = arg[arglen-1];

    /*
     * valid:
     *    exact match - strncmp (a,b,len) == 0  && len == arglen
     *    match for len of a, arglen == len-1, suff in suffixes.
     */

    for (i = 0; i < NUMSEC; i++) {
        len = strlen (sections[i]);
        if (strncmp (arg, sections[i], len))
            continue;
        if (len == arglen)    /* exact match */
            return (1);
        if ((arglen - 1) == len && index (suffixes, suff))    /* subsec */
            return (1);
    }
    return (0);
}


/*
 *  Print a verbose usage message and exit.
 */

usage ()
{
    if (eq (prog, "man") || eq (prog, "rman")) {
        fprintf (stderr, "Usage: man [-r] [-t type] [-v] [ section ] command ...\n");
        fprintf (stderr, "   or: man -k | -w [-m] keyword\n");
        fprintf (stderr, "   or: man -a | -f [-m] file\n");
    } else
        fprintf (stderr, "%s what?\n", prog);
    exit (1);
}


/*
 *  Come here on keyboard interrupt.
 */

interrupt ()
{
    if (use_more)
        (void) unlink (fname);
    exit (1);
}


/*
 *  And come here on sigpipe.
 */

sigpipe ()
{
    fprintf (stderr, "%s: lost connection to remote host.\n", prog);
    if (use_more)
        (void) unlink (fname);
    exit (1);
}


/* 
 *  Try to act intelligently when we can't connect to a server.
 */

/*ARGSUSED*/
cantconnect (name, sec)
char  *name;
char  *sec;
{
#ifdef EXEC_ON_ERROR
    int  pid;

    if (verbose)
        fprintf (stderr, "%s: processing locally.\n", prog);

    if ((pid = fork ()) == -1) {
        perror ("fork");
        return (1);
    } else if (pid == 0) {
        if (sec)
            execl ("/usr/ucb/man", prog, sec, name);
        else
            execl ("/usr/ucb/man", prog, name);
        perror ("execl");
        _exit (1);
    }
    while (wait (0) != pid)
        ;
#else
    fprintf (stderr, "%s: cannot connect to server.\n", prog);
    exit (1);
#endif
}