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 - metrics - download
Index: T s

⟦b247c4bd1⟧ TextFile

    Length: 29386 (0x72ca)
    Types: TextFile
    Names: »snmpi.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/snmp/snmpi.c« 

TextFile

/* snmpi.c - really minimal SNMP initiator */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/snmp/RCS/snmpi.c,v 7.6 90/01/11 18:34:43 mrose Exp $";
#endif

/* 
 * $Header: /f/osi/snmp/RCS/snmpi.c,v 7.6 90/01/11 18:34:43 mrose Exp $
 *
 * Contributed by NYSERNet Inc.  This work was partially supported by the
 * U.S. Defense Advanced Research Projects Agency and the Rome Air Development
 * Center of the U.S. Air Force Systems Command under contract number
 * F30602-88-C-0016.
 *
 *
 * $Log:	snmpi.c,v $
 * Revision 7.6  90/01/11  18:34:43  mrose
 * real-sync
 * 
 * Revision 7.5  89/12/19  17:57:56  mrose
 * touch-up
 * 
 * Revision 7.4  89/12/19  16:18:26  mrose
 * dgram
 * 
 * Revision 7.3  89/12/12  16:13:47  mrose
 * touch-up
 * 
 * Revision 7.2  89/12/11  16:22:33  mrose
 * more clts
 * 
 * Revision 7.1  89/12/01  10:42:18  mrose
 * clts
 * 
 * Revision 7.0  89/11/23  22:23:30  mrose
 * Release 6.0
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <varargs.h>
#include "SNMP-types.h"
#include "objects.h"
#include <sys/ioctl.h>
#include "tailor.h"

#include "dgram.h"
#include "tsap.h"
#ifdef	TCP
#include "internet.h"
#endif
#ifdef	X25
#include "x25.h"
#define	COTS
#endif
#ifdef	TP4
#include "tp4.h"
#if	!defined(CLTS) && !defined(COTS)
#define	COTS
#endif
#endif

/* \f

   DATA */

int	debug = 0;
static	int	verbose = 0;
static	int	watch = 0;

static	char   *myname = "snmp";

static	char  **op = NULLVP;

static	int	ontty;
static	int	armed;
static	jmp_buf	intrenv;
static	int	interrupted;

static	SFP	istat;

SFD	intrser ();


static	PS	ps;
static	char   *community = "public";

static	int	sd;
static	struct TSAPaddr  snmp_ta;

struct type_SNMP_Message *new_message ();


void	adios (), advise ();

/* \f

 */

struct dispatch {
    char   *ds_name;		/* command name */
    IFP	    ds_fnx;		/* dispatch */

    char   *ds_help;		/* help string */
};
struct dispatch *getds ();


int	f_dump ();
int	f_get (), f_get_next (), f_set ();
int	f_help (), f_quit (), f_status ();

static struct dispatch dispatches[] = {
    "dump", f_dump, "dump a portion of the MIB",

    "get", f_get, "perform get operation",

    "help", f_help, "print help information",
    
    "next", f_get_next, "perform powerful get-next operation",

    "quit", f_quit, "terminate program",

    "set", f_set, "perform set operation",

    "status", f_status, "report status",

    NULL
};


static	int	helpwidth;


#ifndef	SYS5
long	random ();
#endif
long	time ();

/* \f

   MAIN */

/* ARGSUSED */

main (argc, argv, envp)
int	argc;
char  **argv,
      **envp;
{
    int	    eof,
	    status,
	    vecp;
    char    buffer[BUFSIZ],
	   *vec[NVEC + 1];

    arginit (argv);

    status = 0;
    if (op) {
	vecp = 0;
	while (*op)
	    vec[vecp++] = *op++;
	vec[vecp] = NULL;

	if (snmploop (vec, NOTOK) == NOTOK)
	    status = 1;

	goto were_out_of_here;
    }

    istat = signal (SIGINT, intrser);
    
    eof = 0;
    for (interrupted = 0;; interrupted = 0) {
	if (getline ("%s> ", buffer) == NOTOK) {
	    if (eof)
		break;

	    eof = 1;
	    continue;
	}
	eof = 0;

	bzero ((char *) vec, sizeof vec);
	if ((vecp = str2vec (buffer, vec)) < 1)
	    continue;

	switch (snmploop (vec, OK)) {
	    case NOTOK:
	        status = 1;
		break;

	   case OK:
	   default:
		continue;

	   case DONE:
		status = 0;
		break;
	}
	break;
    }

    (void) signal (SIGINT, istat);

were_out_of_here: ;
#ifdef	COTS
    if (snmp_ta.ta_addrs -> na_type != NA_TCP) {
	struct TSAPdisconnect tds;

#ifdef	CLTS
	if (snmp_ta.ta_addrs -> na_type != NA_NSAP)
#endif
	    (void) TDiscRequest (sd, NULLCP, 0, &tds);
    }
#endif

    exit (status);		/* NOTREACHED */
}

/* \f

 */

static int  snmploop (vec, error)
char  **vec;
int	error;
{
    register struct dispatch *ds;

    if ((ds = getds (strcmp (*vec, "?") ? *vec : "help")) == NULL)
	return error;
    switch ((*ds -> ds_fnx) (vec)) {
	case NOTOK:
	    return error;

	case OK:
	default:
	    return OK;

	case DONE:
	    return DONE;
    }
}

/* \f

 */

static struct dispatch *getds (name)
char   *name;
{
    register int    longest,
                    nmatches;
    register char  *p,
                   *q;
    char    buffer[BUFSIZ];
    register struct dispatch   *ds,
                               *fs;

    longest = nmatches = 0;
    for (ds = dispatches; p = ds -> ds_name; ds++) {
	for (q = name; *q == *p++; q++)
	    if (*q == NULL)
		return ds;

	if (*q == NULL)
	    if (q - name > longest) {
		longest = q - name;
		nmatches = 1;
		fs = ds;
	    }
	    else
		if (q - name == longest)
		    nmatches++;
    }

    switch (nmatches) {
	case 0: 
	    advise (NULLCP, "unknown operation \"%s\"", name);
	    return NULL;

	case 1: 
	    return fs;

	default: 
	    for (ds = dispatches, p = buffer; q = ds -> ds_name; ds++)
		if (strncmp (q, name, longest) == 0) {
		    (void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q);
		    p += strlen (p);
		}
	    advise (NULLCP, "ambiguous operation, it could be one of:%s",
			buffer);
	    return NULL;
    }
}

/* \f

   OPERATIONS */

static int  f_dump (vec)
char  **vec;
{
    int	    request_id;
    char   *nvec[3];
    OID	    oid;
    PE	    pe;
    struct type_SNMP_Message *msg;
    register struct type_SNMP_PDU *parm;
    register struct type_SNMP_VarBindList *vp;

    if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
	printf ("dump [object]\n");
	printf ("    with no arguments, dump entire MIB\n");
	printf ("    with an argument, dump a portion of the MIB\n");

	return OK;
    }

    nvec[0] = "dump";
    nvec[1] = *vec ? *vec : "mib-2";
    nvec[2] = NULL;

    if ((msg = new_message (type_SNMP_PDUs_get__next__request, nvec)) == NULL)
	return OK;

    request_id = msg -> data -> un.get__response -> request__id = 0;

    if (*vec) {
	if ((oid = oid_cpy (msg -> data -> un.get__next__request ->
			    variable__bindings -> VarBind -> name)) == NULLOID)
	    adios (NULLCP, "out of memory");
    }
    else
	oid = NULLOID;

again: ;
    pe = NULLPE;

    if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) {
	if (watch)
	    (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);

	if (pe2ps (ps, pe) == NOTOK) {
	    advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
	    goto out;
	}
    }
    else
	advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy);

    if (pe)
	pe_free (pe);
    pe = NULLPE;
    
    free_SNMP_Message (msg);
    msg = NULL;

    if ((pe = ps2pe (ps)) == NULLPE) {
	advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
	goto out;
    }

    if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) {
	advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
	goto out;
    }

    if (watch)
	(void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);

    if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
	advise (NULLCP, "unexpected message type %d",
		msg -> data -> offset);
	goto out;
    }

    if ((parm = msg -> data -> un.get__response) -> request__id
	    != request_id) {
	fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n",
		 parm -> request__id, request_id);
	goto out;
    }
	
    if (parm -> error__status != int_SNMP_error__status_noError) {
	if (parm -> error__status != int_SNMP_error__status_noSuchName)
	    fprintf (stderr, "error %d at position %d\n",
		     parm -> error__status, parm -> error__index);
	goto out;
    }

    for (vp = parm -> variable__bindings; vp; vp = vp -> next) {
	caddr_t	 value;
	register OI	oi;
	register OS	os;
	register struct type_SNMP_VarBind *v = vp -> VarBind;
	
	if (oid
	        && (oid -> oid_nelem > v -> name -> oid_nelem
		        || bcmp ((char *) oid -> oid_elements,
				 (char *) v -> name -> oid_elements,
				 oid -> oid_nelem
				 	* sizeof *oid -> oid_elements)))
	    goto out;

	printf ("%s=", oid2ode (vp -> VarBind -> name));
	if ((oi = name2inst (v -> name)) == NULL
	        || (os = oi -> oi_type -> ot_syntax) == NULL
	        || (*os -> os_decode) (&value, v -> value) == NOTOK)
	    vunknown (v -> value);
	else {
	    (*os -> os_print) (value, os);
	    printf ("\n");

	    (*os -> os_free) (value);
	}
    }

    if (pe)
	pe_free (pe);
    msg -> data -> offset = type_SNMP_PDUs_get__next__request;
    request_id = ++parm -> request__id;
    goto again;

 out: ;
    if (oid)
	oid_free (oid);
    if (pe)
	pe_free (pe);
    if (msg)
	free_SNMP_Message (msg);

    return OK;
}

/* \f

 */

static int  f_get (vec)
char  **vec;
{
    (void) process (new_message (type_SNMP_PDUs_get__request, vec));
}

/* \f

 */

static int  f_get_next (vec)
char  **vec;
{
    (void) process (new_message (type_SNMP_PDUs_get__next__request, vec));
}

/* \f

 */

static int  f_set (vec)
char  **vec;
{
    (void) process (new_message (type_SNMP_PDUs_set__request, vec));
}

/* \f

 */

struct type_SNMP_Message *new_message (offset, vec)
int	offset;
char  **vec;
{
    register struct type_SNMP_Message *msg;
    register struct type_SNMP_PDUs *pdu;
    register struct type_SNMP_PDU *parm;
    register struct type_SNMP_VarBindList **vp;

    if ((msg = (struct type_SNMP_Message *) calloc (1, sizeof *msg)) == NULL)
	adios (NULLCP, "out of memory");

    msg -> version = int_SNMP_version_version__1;

    if ((msg -> community = str2qb (community, strlen (community), 1)) == NULL)
	adios (NULLCP, "out of memory");

    if ((pdu = (struct type_SNMP_PDUs *) calloc (1, sizeof *pdu)) == NULL)
	adios (NULLCP, "out of memory");
    msg -> data = pdu;

    pdu -> offset = offset;
    
/* for now, always a PDU... */

    if ((parm = (struct type_SNMP_PDU *) calloc (1, sizeof *parm)) == NULL)
	adios (NULLCP, "out of memory");
    pdu -> un.get__request = parm;

#ifndef	SYS5
    parm -> request__id = ((int) random ()) & 0x7fffffff;
#else
    parm -> request__id = ((int) rand ()) & 0x7fffffff;
#endif

    vp = &parm -> variable__bindings;
    for (vec++; *vec; vec++) {
	register struct type_SNMP_VarBindList *bind;
	register struct type_SNMP_VarBind *v;

	if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind))
	    	    == NULL)
	    adios (NULLCP, "out of memory");
	*vp = bind, vp = &bind -> next;;

	if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL)
	    adios (NULLCP, "out of memory");
	bind -> VarBind = v;

	if (get_ava (v, *vec, offset) == NOTOK) {
	    free_SNMP_Message (msg);
	    return NULL;
	}
    }
    
    return msg;
}

/* \f

 */

static int  get_ava (v, ava, offset)
register struct type_SNMP_VarBind *v;
char   *ava;
int	offset;
{
    int	    result;
    caddr_t value;
    register char *cp;
    register OI	   oi;
    register OT	   ot;
    register OS	   os;
    OID	    oid;

    if (cp = index (ava, '=')) {
	if (offset != type_SNMP_PDUs_set__request)
	    advise (NULLCP, "value unnecessary for get operation");
	*cp++ = NULL;
    }
    else
	if (offset == type_SNMP_PDUs_set__request) {
	    advise (NULLCP, "need variable=value for set operation");
	    return NOTOK;
	}

    if ((oi = text2inst (ava)) == NULL) {
	if (cp || (oid = text2oid (ava)) == NULL) {
	    advise (NULLCP, "unknown variable \"%s\"", ava);
	    return NOTOK;
	}

	ot = NULLOT;
    }
    else
	ot = oi -> oi_type;

    if ((v -> name = oid_cpy (oi ? oi -> oi_name : oid)) == NULLOID)
	adios (NULLCP, "out of memory");

    if (cp == NULL) {
	if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL))
	        == NULLPE)
	adios (NULLCP, "out of memory");
    }
    else {
	if ((os = ot -> ot_syntax) == NULL) {
	    advise (NULLCP, "no syntax defined for object \"%s\"", ava);
	    return NOTOK;
	}

	if ((*os -> os_parse) (&value, cp) == NOTOK) {
	    advise (NULLCP, "invalid value for variable \"%s\": \"%s\"",
		    ava, cp);
	    return NOTOK;
	}
	result = (*os -> os_encode) (value, &v -> value);
	(*os -> os_free) (value);

	if (result == NOTOK) {
	    advise (NULLCP, "encoding error for variable \"%s\"", ava);
	    return NOTOK;
	}	
    }

    if (oi == NULL)
	oid_free (oid);

    return OK;
}

/* \f

 */

static int  process (msg)
struct type_SNMP_Message *msg;
{
    int	    request_id;
    PE	    pe;
    register struct type_SNMP_PDU *parm;
    register struct type_SNMP_VarBindList *vp;

    if (msg == NULL)
	return OK;

    request_id = msg -> data -> un.get__request -> request__id;
    if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) {
	if (watch)
	    (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);

	if (pe2ps (ps, pe) == NOTOK) {
	    advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
	    goto out;
	}
    }
    else
	advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy);

    if (pe)
	pe_free (pe);
    pe = NULLPE;
    
    free_SNMP_Message (msg);
    msg = NULL;

    if ((pe = ps2pe (ps)) == NULLPE) {
	advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
	goto out;
    }

    if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) {
	advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
	goto out;
    }

    if (watch)
	(void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);

    if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
	advise (NULLCP, "unexpected message type %d",
		msg -> data -> offset);
	goto out;
    }

    if ((parm = msg -> data -> un.get__response) -> request__id
	    != request_id) {
	fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n",
		 parm -> request__id, request_id);
	goto out;
    }
	
    if (parm -> error__status != int_SNMP_error__status_noError) {
	fprintf (stderr, "error %d at position %d\n",
		parm -> error__status, parm -> error__index);
	goto out;
    }

    for (vp = parm -> variable__bindings; vp; vp = vp -> next) {
	caddr_t	 value;
	register OI	oi;
	register OS	os;
	register struct type_SNMP_VarBind *v = vp -> VarBind;

	if ((oi = name2inst (v -> name)) == NULL) {
	    advise (NULLCP, "unknown variable \"%s\"", oid2ode (v -> name));
no_dice: ;
	    printf ("%s=", oid2ode (v -> name));
	    vunknown (v -> value);
	    continue;
	}
	if ((os = oi -> oi_type -> ot_syntax) == NULL) {
	    advise (NULLCP, "unknown syntax for object \"%s\"",
		    oi -> oi_type -> ot_text);
	    goto no_dice;
	}
	if ((*os -> os_decode) (&value, v -> value) == NOTOK) {
	    advise (NULLCP, "decode error for variable \"%s\"",
		    oid2ode (v -> name));
	    goto no_dice;
	}

	printf ("%s=", oid2ode (v -> name));
	(*os -> os_print) (value, os);
	printf ("\n");

	(*os -> os_free) (value);
    }

 out: ;
    if (pe)
	pe_free (pe);
    if (msg)
	free_SNMP_Message (msg);

    return OK;
}

/* \f

 */

static int  f_help (vec)
char  **vec;
{
    register int    i,
                    j,
                    w;
    int     columns,
            width,
            lines;
    register struct dispatch   *ds,
                               *es;

    for (es = dispatches; es -> ds_name; es++)
	continue;
    width = helpwidth;

    if (*++vec == NULL) {
	if ((columns = ncols (stdout) / (width = (width + 8) & ~7)) == 0)
	    columns = 1;
	lines = ((es - dispatches) + columns - 1) / columns;

	printf ("Operations:\n");
	for (i = 0; i < lines; i++)
	    for (j = 0; j < columns; j++) {
		ds = dispatches + j * lines + i;
		printf ("%s", ds -> ds_name);
		if (ds + lines >= es) {
		    printf ("\n");
		    break;
		}
		for (w = strlen (ds -> ds_name); w < width; w = (w + 8) & ~7)
		    (void) putchar ('\t');
	    }
	printf ("\n");

	return OK;
    }

    if (strcmp (*vec, "-help") == 0) {
	printf ("help [commands ...]\n");
	printf ("    with no arguments, lists operations which may be invoked\n");
	printf ("    otherwise prints help for each operation given\n");

	return OK;
    }
    
    for (; *vec; vec++)
	if (strcmp (*vec, "?") == 0) {
	    for (ds = dispatches; ds -> ds_name; ds++)
		printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);

	    break;
	}
	else
	    if (ds = getds (*vec))
		printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);

    return OK;
}

/* \f

 */

static int  f_quit (vec)
char  **vec;
{
    if (vec && *++vec != NULL && strcmp (*vec, "-help") == 0) {
	printf ("quit\n");
	printf ("    terminate fred\n");

	return OK;
    }

    return DONE;
}

/* \f

 */

static int  f_status (vec)
char  **vec;
{
    if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
	printf ("status\n");
	printf ("    report status\n");

	return OK;
    }

    printf ("Connected to %s using community \"%s\"\n",
	    taddr2str (&snmp_ta), community);

    return OK;
}

/* \f

   SYNTAX */

static char *ifType[] = {
    "other", "regular1822", "hdh1822", "ddn-x25", "rfc877-x25",
    "ethernet-csmacd", "iso88023-csmacd", "iso88024-tokenBus",
    "iso88025-tokenRing", "iso88026-man", "starLan", "proteon-10Mbit",
    "proteon-80Mbit", "hyperchannel", "fddi", "lapb", "sdlc", "t1-carrier",
     "cept", "basicISDN", "primaryISDN", "propPointToPointSerial",
    "terminalServer-asyncPort", "softwareLoopback", "eon", "ethernet-3Mbit",
    "nsip", "slip"
};

static char *ifStatus[] = {
    "up", "down", "testing"
};

static char *ipForwarding[] = {
    "gateway", "host"
};

static char *ipRouteType[] = {
    "other", "invalid", "direct", "remote"
};

static char *ipRouteProto[] = {
    "other", "local", "netmgmt", "icmp", "egp", "ggp", "hello", "rip", "is-is",
    "es-is", "ciscoIgrp", "bbnSpfIgp", "ospf", "bgp"
};

static char *ipNetToMediaType[] = {
    "other", "invalid", "dynamic", "static"
};

static char *tcpRtoAlgorithm[] = {
    "other", "constant", "rsre", "vanj"
};

static char *tcpConnState[] = {
    "closed", "listen", "synSent", "synReceived", "established", "finWait1",
    "finWait2", "closeWait", "lastAck", "closing", "timewait"
};

static char *egpNeighState[] = {
    "idle", "acquisition", "down", "up", "cease"
};

static char *egpNeighMode[] = {
    "passive", "active"
};

static char *egpNeighEventTrigger[] = {
    "start", "stop"
};

static char *snmpEnableAuthTraps [] = {
    "enabled", "disabled"
};

static char *clnpForwarding[] = {
    "is", "es"
};

static char *clnpRouteType[] = {
    "other", "invalid", "direct", "remote"
};

static char *clnpRouteProto[] = {
    "other", "local", "netmgmt", "", "", "", "", "", "is-is", "es-is",
    "ciscoIgrp", "bbnSpfIgp", "ospf", "bgp"
};


static struct ivar {
    char   *iv_object;

    char  **iv_values;
    int	    iv_nvalue;
} ivars[] = {
    "ifType", ifType,
	sizeof ifType / sizeof ifType[0],
    
    "ifAdminStatus", ifStatus,
	sizeof ifStatus / sizeof ifStatus[0],
    
    "ifOperStatus", ifStatus,
	sizeof ifStatus / sizeof ifStatus[0],

    "ipForwarding", ipForwarding,
	sizeof ipForwarding / sizeof ipForwarding[0],

    "ipRouteType", ipRouteType,
	sizeof ipRouteType / sizeof ipRouteType[0],

    "ipRouteProto", ipRouteProto,
	sizeof ipRouteProto / sizeof ipRouteProto[0],

    "ipNetToMediaType", ipNetToMediaType,
	sizeof ipNetToMediaType / sizeof ipNetToMediaType[0],

    "tcpRtoAlgorithm", tcpRtoAlgorithm,
	sizeof tcpRtoAlgorithm / sizeof tcpRtoAlgorithm[0],

    "tcpConnState", tcpConnState,
	sizeof tcpConnState / sizeof tcpConnState[0],

    "egpNeighState", egpNeighState,
	sizeof egpNeighState / sizeof egpNeighState[0],

    "egpNeighMode", egpNeighMode,
	sizeof egpNeighMode / sizeof egpNeighMode[0],

    "egpNeighEventTrigger", egpNeighEventTrigger,
	sizeof egpNeighEventTrigger / sizeof egpNeighEventTrigger[0],

    "snmpEnableAuthTraps", snmpEnableAuthTraps,
	sizeof snmpEnableAuthTraps / sizeof snmpEnableAuthTraps[0],

    "clnpForwarding", clnpForwarding,
	sizeof clnpForwarding / sizeof clnpForwarding[0],

    "clnpRouteType", clnpRouteType,
	sizeof clnpRouteType / sizeof clnpRouteType[0],

    "clnpRouteProto", clnpRouteProto,
    	sizeof clnpRouteProto / sizeof clnpRouteProto[0],

    NULL
};

/* \f

 */

static int  enum_print (x, os)
integer *x;
OS	os;
{
    int	    i = *x;

    if (i <= 0 || i > os -> os_data2)
	printf ("unknown(%d)", i);
    else
	printf ("%s(%d)", os -> os_data1[i - 1], i);
}

static	moresyntax () {
    register struct ivar *iv;
    register OT	   ot;
    register OS	   os;

    for (iv = ivars; iv -> iv_object; iv++)
	if (ot = text2obj (iv -> iv_object)) {
	    if ((os = ot -> ot_syntax) == NULL) {
		advise (NULLCP, "no syntax defined for object \"%s\"",
			iv -> iv_object);
		continue;
	    }

	    (void) add_syntax (iv -> iv_object, os -> os_encode,
			       os -> os_decode, os -> os_free, os -> os_parse,
			       enum_print);
	    if ((os = text2syn (iv -> iv_object)) == NULL)
		adios (NULLCP, "lost syntax for object \"%s\"",
		       iv -> iv_object);
	    ot -> ot_syntax = os;
	    os -> os_data1 = iv -> iv_values;
	    os -> os_data2 = iv -> iv_nvalue;
	}
	else
	    advise (NULLCP, "no \"%s\" object", iv -> iv_object);
}

/* \f

   MISCELLANY */

static	arginit (vec)
char    **vec;
{
    int	    w;
    register char  *ap,
		   *pp;
    register struct dispatch *ds;
#ifdef	TCP
    int	    port;
    struct sockaddr_in in_socket;
    register struct sockaddr_in *isock = &in_socket;
    register struct hostent *hp;
    register struct servent *sp;
#endif
    register struct TSAPaddr *ta = &snmp_ta,
			     *tz;
    register struct NSAPaddr *na = ta -> ta_addrs;

    if (myname = rindex (*vec, '/'))
	myname++;
    if (myname == NULL || *myname == NULL)
	myname = *vec;

    isodetailor (myname, 1);

    if (ontty = isatty (fileno (stdin)))
	verbose++;

    if ((sp = getservbyname ("snmp", "udp")) == NULL)
	advise (NULLCP, "udp/snmp: unknown service");

    bzero ((char *) ta, sizeof *ta);
#ifdef	TCP
    na -> na_type = NA_TCP;
    na -> na_subnet = ts_comm_tcp_default;
    (void) strncpy (na -> na_domain, getlocalhost (),
		    sizeof na -> na_domain - 1);
    na -> na_port = sp ? sp -> s_port : htons ((u_short) 161);
    na -> na_tset = NA_TSET_UDP;
    ta -> ta_naddr = 1;
#endif

    for (vec++; ap = *vec; vec++) {
	if (*ap == '-') {
	    while (*++ap)
		switch (*ap) {
		    case 'a':		/* e.g., NS+0504030201 */
		        if ((pp = *++vec) == NULL || *pp == '-')
			    adios (NULLCP, "usage: %s -a agent", myname);
#ifdef	TCP
			if (hp = gethostbystring (pp)) {
			    if (na -> na_type != NA_TCP)
				adios (NULLCP, "use -a at most once...");
			    inaddr_copy (hp, isock);
			    (void) strncpy (na -> na_domain,
					    inet_ntoa (isock -> sin_addr),
					    sizeof na -> na_domain - 1);
			}
			else
#endif
			    if ((tz = str2taddr (pp)) && tz -> ta_naddr > 0) {
				*ta = *tz;	/* struct copy */
				if (na -> na_type == NA_TCP) {
				    if (na -> na_port == 0)
					na -> na_port = sp ? sp -> s_port
					               : htons ((u_short) 161);
				    na -> na_tset = NA_TSET_UDP;
				}
			    }
			    else
				adios (NULLCP, "%s: unknown host", pp);
			break;

#ifdef	TCP
		    case 'p':
			if ((pp = *++vec) == NULL
			        || *pp == '-'
			        || (port = atoi (pp)) <= 0)
			    adios (NULLCP, "usage: %s -p portno", myname);
			if (na -> na_type != NA_TCP)
			    adios (NULLCP, "-p not allowed with %s",
				   taddr2str (ta));
			na -> na_port = htons ((u_short) port);
			break;
#endif

		    case 'c':
		        if ((pp = *++vec) == NULL || *pp == '-')
			    adios (NULLCP, "usage: %s -c community", myname);
			community = pp;
			break;

		    case 'd':
		        debug++;
			break;

		    case 'v':
		        verbose++;
			break;

		    case 'w':
		        watch++;
			break;

		    default:
			adios (NULLCP, "unknown switch -%c", *ap);
		}
	    continue;
	}
	if (op == NULL) {
	    op = vec;
	    break;
	}
    }

    helpwidth = 0;
    for (ds = dispatches; ds -> ds_name; ds++)
	if ((w = strlen (ds -> ds_name)) > helpwidth)
	    helpwidth = w;

    if (ta -> ta_naddr == 0)
	adios (NULLCP, "usage: %s -a string", myname);
    switch (na -> na_type) {
	case NA_TCP:
#ifdef	TCP
	    {
		struct sockaddr_in lo_socket;
		register struct sockaddr_in *lsock = &lo_socket;

		bzero ((char *) lsock, sizeof *lsock);
		if ((hp = gethostbystring (pp = getlocalhost ())) == NULL)
		    adios (NULLCP, "%s: unknown host", pp);
		lsock -> sin_family = hp -> h_addrtype;
		inaddr_copy (hp, lsock);
		if ((sd = start_udp_client (lsock, 0, 0, 0)) == NOTOK)
		    adios ("failed", "start_udp_client");

		bzero ((char *) isock, sizeof *isock);
		if ((hp = gethostbystring (na -> na_domain)) == NULL)
		    adios (NULLCP, "%s: unknown host", na -> na_domain);
		isock -> sin_family = hp -> h_addrtype;
		isock -> sin_port = na -> na_port;
		inaddr_copy (hp, isock);

		if (join_udp_server (sd, isock) == NOTOK)
		    adios ("failed", "join_udp_server");

		if ((ps = ps_alloc (dg_open)) == NULLPS
		        || dg_setup (ps, sd, MAXDGRAM, read_udp_socket,
				     write_udp_socket) == NOTOK) {
		    if (ps == NULLPS)
			adios (NULLCP, "ps_alloc: out of memory");
		    else
			adios (NULLCP, "dg_setup: %s",
			       ps_error (ps -> ps_errno));
		}
	    }
	    break;
#else
	    adios (NULLCP, "UDP support not configured");
#endif

	case NA_X25:
#ifdef	X25
	    goto cots;
#else
	    adios (NULLCP, "X.25 support not configured");
#endif
	    
	case NA_NSAP:
#ifdef	CLTS
	    {
		union sockaddr_osi lo_socket;
		register union sockaddr_osi *lsock = &lo_socket;

		bzero ((char *) lsock, sizeof *lsock);
		if ((sd = start_clts_client (lsock, 0, 0, 0)) == NOTOK)
		    adios ("failed", "start_clts_client");

		(void) gen2tp4 (ta, lsock);
		if (join_clts_server (sd, lsock) == NOTOK)
		    adios ("failed", "join_udp_server");

		if ((ps = ps_alloc (dg_open)) == NULLPS
		        || dg_setup (ps, sd, MAXDGRAM, read_clts_socket,
				     write_clts_socket) == NOTOK) {
		    if (ps == NULLPS)
			adios (NULLCP, "ps_alloc: out of memory");
		    else
			adios (NULLCP, "dg_setup: %s",
			       ps_error (ps -> ps_errno));
		}
	    }
	    break;
#else
#ifdef	TP4
	    goto cots;
#else
	    adios (NULLCP, "TP4 support not configured");
#endif
#endif

	default:
	    adios (NULLCP, "unknown network type 0x%x", na -> na_type);
	    /* NOT REACHED */

#ifdef	COTS
cots: ;
	    {
		struct TSAPconnect tcs;
		register struct TSAPconnect *tc = &tcs;
		struct TSAPdisconnect tds;
		register struct TSAPdisconnect *td = &tds;

		if (verbose) {
		    fprintf (stderr, "%s... ", taddr2str (ta));
		    (void) fflush (stderr);
		}
		if (TConnRequest (NULLTA, ta, 0, NULLCP, 0, NULLQOS, tc, td)
		        == NOTOK) {
		    if (verbose)
			fprintf (stderr," failed\n");
		    adios (NULLCP, td -> td_cc > 0
			   		? "T-CONNECT.REQUEST: [%s] %*.*s"
			   		: "T-CONNECT.REQUEST: [%s]",
			   TErrString (td -> td_reason),
			   td -> td_cc, td -> td_cc, td -> td_data);
		}
		fprintf (stderr, "connected\n");

		if ((ps = ps_alloc (dg_open)) == NULLPS
		        || dg_setup (ps, sd = tc -> tc_sd, MAXDGRAM, ts_read,
				     ts_write) == NOTOK) {
		    if (ps == NULLPS)
			adios (NULLCP, "ps_alloc: out of memory");
		    else
			adios (NULLCP, "dg_setup: %s",
			       ps_error (ps -> ps_errno));
		}
	    }
	    break;
#endif
    }

#ifdef	SYS5
    (void) srand ((unsigned int) time ((long *) 0));
#else
    (void) srandom ((int) time ((long *) 0));
#endif

    ps_len_strategy = PS_LEN_LONG;

    if (readobjects () == NOTOK)
	adios (NULLCP, "readobjects: %s", PY_pepy);
    moresyntax ();
}

/* \f

   INTERACTIVE */

static int  getline (prompt, buffer)
char   *prompt,
       *buffer;
{
    register int    i;
    register char  *cp,
                   *ep;
    static int  sticky = 0;

    if (interrupted) {
	interrupted = 0;
	return NOTOK;
    }

    if (sticky) {
	sticky = 0;
	return NOTOK;
    }

    switch (setjmp (intrenv)) {
	case OK:
	    armed++;
	    break;

	case NOTOK:
	    if (ontty)
		printf ("\n");	/* and fall */
	default:
	    armed = 0;
	    return NOTOK;
    }
	
    if (ontty) {
	printf (prompt, myname);
	(void) fflush (stdout);
    }

    for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) {
	if (i == EOF) {
	    if (ontty)
		printf ("\n");
	    clearerr (stdin);
	    if (cp == buffer)
		longjmp (intrenv, DONE);

	    sticky++;
	    break;
	}

	if (cp < ep)
	    *cp++ = i;
    }
    *cp = NULL;

    armed = 0;
    
    return OK;
}

/* \f

 */

/* ARGSUSED */

static	SFD intrser (sig)
int	sig;
{
#ifndef	BSDSIGS
    (void) signal (SIGINT, intrser);
#endif

    if (armed)
	longjmp (intrenv, NOTOK);

    interrupted++;
}

/* \f

 */

#ifndef	TIOCGWINSZ
/* ARGSUSED */
#endif

static int  ncols (fp)
FILE *fp;
{
#ifdef	TIOCGWINSZ
    int	    i;
    struct winsize ws;

    if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &ws) != NOTOK
	    && (i = ws.ws_col) > 0)
	return i;
#endif

    return 80;
}

/* \f

   ERRORS */

#ifndef	lint
void	_advise ();


static void  adios (va_alist)
va_dcl
{
    va_list ap;

    va_start (ap);

    _advise (ap);

    va_end (ap);

    _exit (1);
}
#else
/* VARARGS */

static void  adios (what, fmt)
char   *what,
       *fmt;
{
    adios (what, fmt);
}
#endif


#ifndef	lint
static void  advise (va_alist)
va_dcl
{
    va_list ap;

    va_start (ap);

    _advise (ap);

    va_end (ap);
}


static void  _advise (ap)
va_list	ap;
{
    char    buffer[BUFSIZ];

    asprintf (buffer, ap);

    (void) fflush (stdout);

    fprintf (stderr, "%s: ", myname);
    (void) fputs (buffer, stderr);
    (void) fputc ('\n', stderr);

    (void) fflush (stderr);
}
#else
/* VARARGS */

static void  advise (what, fmt)
char   *what,
       *fmt;
{
    advise (what, fmt);
}
#endif