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 m

⟦d68410b6c⟧ TextFile

    Length: 7761 (0x1e51)
    Types: TextFile
    Names: »main.c«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/rman/daemon/main.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: main.c,v 1.9 85/08/27 18:45:47 broome Exp $";
#endif

/*
 * $Log:    main.c,v $
 * Revision 1.9  85/08/27  15:16:47  broome
 * Last cleanup before release.
 * 
 * Revision 1.8  85/08/05  08:53:38  broome
 * Fixed missing argument to error printf ...
 * 
 * Revision 1.7  85/08/04  16:33:06  broome
 * Added new command line options:
 *   -f  -  to specify a configuration file besides the default.
 *   -l  -  sets load cutoff so that we won't answer pings if load is higher.
 *   -p  -  specify alternate port number to listen on.
 * 
 * Revision 1.6  85/07/24  10:38:57  broome
 * 
 * Revision 1.5  85/07/16  11:09:56  broome
 * Tuned the new "ping" stuff a bit.
 * 
 * Revision 1.4  85/07/06  16:55:57  broome
 * Added new ping routines to help improve response times,
 * also makes it easier to cope with dead hosts.
 * 
 * Revision 1.3  85/07/03  17:34:30  broome
 * [ RCS screwed up again! ]
 * 
 * Revision 1.2  85/07/02  21:05:52  broome
 * 
 * Revision 1.1  85/06/25  11:23:38  broome
 * Initial revision
 */

#include "response.h"
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#ifdef SERVICES
#include <netdb.h>
#endif SERVICES

#ifndef STRICT         /* hang up on unknown hosts ??? */
#define STRICT 0
#endif
#ifndef TIMEOUT        /* timeout interval on a connection */
#define TIMEOUT 2
#endif

extern int errno;
char   hostname[32];

main (ac, av)
int  ac;
char **av;
{
#ifdef SERVICES
    struct servent *sp, *getservbyname();
#endif
    char   **argv;
    char   *ctime();
    char   *config_file = CONFIG;
    long   now;
    char   line[128];
    int    argc, len, psock, ssock, new, mask, tty;
    int    reaper(), hup(), timeout();
    int    port = 0;
    int    secure = STRICT;    /* hang up on unidentified hosts??? */
    extern double cutoff;
    struct sockaddr_in sin;

/*
 *  usage: mand [ -s ] [ -f config_file ] [ -p service_port ] [ -l load_cutoff ]
 */

    while (*++av) {
        if (**av != '-')
            usage ();
        switch (*++*av) {
            case 'f': if (*++av)   /* next arg is configuration file */
                        config_file = *av;
                      else
                        usage ();
                      break;
            case 'p': if (*++av)  /* next arg is service port to use */
                        port = htons (atoi (*av));
                      else
                        usage ();
                      break;
            case 'l': if (*++av)  /* next arg is load cutoff point */
                        cutoff = (double) atoi (*av);
                      else
                        usage ();
                      break;
            case 's': secure = !secure;
                      printf ("Secure = O%s\n", secure ? "N" : "FF");
                      break;
            default:  usage ();
        }
    }

    if (port == 0) {
#ifndef SERVICES
        fprintf (stderr, "Have to specify a service port!\n");
        usage ();
#else
        if ((sp = getservbyname ("man", "tcp")) == NULL) {
            fprintf (stderr, "mand: \"man/tcp\": unknown service.\n");
            exit (1);
        }
        port = sp->s_port;
#endif SERVICES
    }

    if ((ssock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
        perror ("socket");
        exit (-1);
    }

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = port;

    if (bind (ssock, (char *)&sin, sizeof (sin)) < 0) {
        perror ("bind");
        exit (-2);
    }

    (void) listen (ssock, 5);

    if ((psock = open_ping (port)) < 0)      /* start up datagram socket */
        exit (1);

    if (fork ())                       /* fork off into background */
        exit (0);
    
    signal (SIGCHLD, reaper);
    signal (SIGPIPE, SIG_IGN);
    signal (SIGHUP,  hup);

    tty = open ("/dev/tty", 0, 0);     /* disassociate from terminal */
    if (tty != -1) {
        ioctl (tty, TIOCNOTTY, (struct sgttyb *)0);
        (void) close (tty);
    } else
        if (setpgrp (0, 0))
            perror ("setpgrp");

    (void) chdir ("/usr/man");
    (void) umask (0);                  /* may not want this when root */
    config (config_file);
    gethostname (hostname, 32);

    for ( ;; ) {
        mask = (1 << psock) | (1 << ssock);
        if (select (20, &mask, 0, 0, 0) <= 0)
            continue;

        if (mask & (1 << psock))           /* `ping' */
            ping ();
        
        if (mask & (1 << ssock)) {
            len = sizeof (sin);
            if ((new = accept (ssock, &sin, &len)) < 0) {
                if (errno != EINTR) {
                    perror ("accept");
                    exit (-1);
                } else
                    continue;
            }
            if (fork ()) {         /* parent */
                close (new);
            } else {               /* child */
                close (ssock);
                close (psock);
                signal (SIGCHLD, SIG_IGN);
                signal (SIGALRM, timeout);
                alarm  (TIMEOUT * 60);   /* close conn after TIMEOUT mins */
                if (new != 0)            /* set up stdin, stdout, stderr */
                    dup2 (new, 0);
                if (new != 1) 
                    dup2 (new, 1);
                if (new != 2) 
                    dup2 (new, 2);

                if (identify (sin) && secure) {
        printf ("%d %s manual server: your host does not have man access\r\n", 
                        ERR_HELLO, hostname);
                    exit (1);
                }

                time (&now);
                printf ("%d %s manual page server ready at %19.19s\r\n",
                        OK_HELLO, hostname, ctime (&now));
                (void) fflush (stdout);
    
                while (gets (line)) {                /* read a line    */
                    argc = parse (line, &argv);      /* parse it       */
                    if (argc == 0)                   /* blank line --- */
                        continue;                    /* just ignore it */
                    funcall (argc, argv);            /* do the command */
                }
                quit();
            }
        }
    }
}


/*
 *  Take care of all the dead children, avoiding zombie processes.
 */

reaper()
{
    union wait status;

    while (wait3 (&status, WNOHANG, 0) > 0)
        ;
}


/*
 *  Bye bye ...
 */

quit ()
{
    long now;

    time (&now);
    printf ("%d %s closing connection at %19.19s\r\n", OK_GOODBYE,
                hostname, ctime (&now));
    exit (0);
}


/*
 *  Exit nicely on SIGHUP.
 */

hup ()
{
    exit (0);
}


/*
 *  Timed out after TIMEOUT minutes --- close down the connection.
 */

timeout ()
{
    printf ("%d %s manual server: connection timed out after %d minutes.\r\n", 
            ERR_TIMEOUT, hostname, TIMEOUT);
    exit (1);
}


/*
 *  Print a usage message and go away.
 */

usage ()
{
    fprintf (stderr, 
    "Usage: mand [ -s ] [ -f config_file ] [ -p port ] [ -l load_cutoff ]\n");
    exit (1);
}