Net2/usr/src/contrib/isode/acsap/aetdase.c

Compare this file to the similar file:
Show the results in this format:

/* aetdase.c - DASE-based DSE */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/acsap/RCS/aetdase.c,v 7.6 91/02/22 09:14:28 mrose Interim $";
#endif

/* 
 * $Header: /f/osi/acsap/RCS/aetdase.c,v 7.6 91/02/22 09:14:28 mrose Interim $
 *
 *
 * $Log:	aetdase.c,v $
 * Revision 7.6  91/02/22  09:14:28  mrose
 * Interim 6.8
 * 
 * Revision 7.5  91/01/07  12:39:41  mrose
 * update
 * 
 * Revision 7.4  90/12/23  18:39:01  mrose
 * update
 * 
 * Revision 7.3  90/12/11  10:52:00  mrose
 * lock-and-load
 * 
 * Revision 7.2  90/10/29  18:37:54  mrose
 * updates
 * 
 * Revision 7.1  90/07/09  14:30:48  mrose
 * sync
 * 
 * Revision 7.0  90/07/07  16:11:32  mrose
 * *** empty log message ***
 * 
 */

/*
 *				  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.
 *
 */


/* LINTLIBRARY */

#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include "DASE-types.h"
#include "psap.h"
#include "tsap.h"
#include "dgram.h"
#include "tailor.h"


/*    DATA */

static	int	stayopen = 0;

static	struct TSAPconnect tcs;
static	PS	ps = NULLPS;


static	int	armed = 0;
static	int	interrupted;
static	jmp_buf	intrenv;

SFD	intrser ();


struct element_DASE_1 *read_el ();

/*    LOOKUP */

/* ARGSUSED */

PE	name2value_dase (name, context, ontty, userdn, passwd, real_name)
char   *name,
       *context,
       *userdn,
       *passwd;
int	ontty;
PE     *real_name;
{
    int	    done,
	    err,
	    nfds,
	    vecp;
    fd_set  ifds;
    char   *vec[NVEC + 1];
    PE	    pe = NULLPE,
	    result = NULLPE;
    SFP	    istat;
    register struct type_DASE_Query__REQ *parm = NULL;

    *real_name = NULLPE;

    if (ontty) {
	istat = signal (SIGINT, intrser);
	interrupted = 0;
    }

    if (ps == NULLPS && dase_init () == NOTOK)  {
	if (ontty)
	    (void) signal (SIGINT, istat);

	return NULLPE;
    }
    err = 0;

    if (*name == '@') {
	vec[vecp = 0] = name;
	vecp++;
    }
    else
	if ((vecp = sstr2arg (name, NVEC, vec, ",")) == NOTOK) {
	    PY_advise (NULLCP, "invalid name");
	    goto out;
	}

    if ((parm = (struct type_DASE_Query__REQ *) calloc (1, sizeof *parm))
	    == NULL) {
no_mem: ;
        PY_advise (NULLCP, "name2value_dase: out of memory");
	goto out;
    }
    {
	register char **vp;
	register struct element_DASE_0  *dl,
				       **dp;

	dp = &parm -> name;
	for (vp = vec; vecp > 0; vp++, vecp--) {
	    if ((dl = (struct element_DASE_0 *) calloc (1, sizeof *dl))
		    == NULL)
		goto no_mem;
	    *dp = dl;
	    dp = &dl -> next;

	    if ((dl -> IA5String = str2qb (*vp, strlen (*vp), 1)) == NULL)
		goto no_mem;
	}
    }
    parm -> interactive = ontty ? 1 : 0;
    if ((parm -> envlist = read_el ()) == NULL)
	goto out;
    if ((parm -> context = str2qb (context, strlen (context), 1)) == NULL)
	goto no_mem;
    if (userdn
	    && (parm -> userdn = str2qb (userdn, strlen (userdn), 1)) == NULL)
	goto no_mem;
    if (passwd
	    && (parm -> passwd = str2qb (passwd, strlen (passwd), 1)) == NULL)
	goto no_mem;;

    if (encode_DASE_Query__REQ (&pe, 1, NULL, NULLCP, parm) == NOTOK)
	goto out;

    if ((err = pe2ps (ps, pe)) == NOTOK) {
	PY_advise (NULLCP, "unable to write query [%s]",
		   ps_error (ps -> ps_errno));
	goto out;
    }
    PLOGP (addr_log,DASE_Message, pe, "message", 0);

    FD_ZERO (&ifds);

    nfds = tcs.tc_sd + 1;
    FD_SET (tcs.tc_sd, &ifds);
    
    for (done = 0; !done; ) {
	fd_set	rfds;
	struct type_DASE_Provider__RSP *rsp = NULL;
	PE	in;

	if (!interrupted) {
	    rfds = ifds;		/* struct copy */

	    (void) xselect (nfds, &rfds, NULLFD, NULLFD, NOTOK);
	}
	
	if (interrupted) {
	    PY_advise (NULLCP, "interrupted");
	    break;
	}

	if (!FD_ISSET (tcs.tc_sd, &rfds))
	    continue;

	if ((in = ps2pe (ps)) == NULLPE) {
	    PY_advise (NULLCP, "unable to read response [%s]",
		       ps_error (ps -> ps_errno));
	    err++;
	    break;
	}

	if (decode_DASE_Provider__RSP (in, 1, NULLIP, NULLVP, &rsp) == NOTOK) {
you_lose: ;
	    pe_free (in);
	    if (rsp)
		free_DASE_Provider__RSP (rsp);
	    err++;
	    break;
	}
	PLOGP (addr_log,DASE_Message, in, "message", 1);

	switch (rsp -> offset) {
	    case type_DASE_Provider__RSP_callback:
	        if (!ontty) {
		    PY_advise (NULLCP, "unexpected callback from nameservice");
		    goto you_lose;
		}
		if (dase_callback (rsp -> un.callback) == NOTOK)
		    goto you_lose;
		break;

	    case type_DASE_Provider__RSP_answer:
		{
		    register char *pp,
				  *ep;
		    register struct qbuf *p,
					 *q;
		    register struct type_DASE_Query__RSP *ans
							    = rsp -> un.answer;

		    if ((q = ans -> friendly) && ontty) {
			printf ("[ using ");
			print_qb (q);
			printf (" ]\n");
			(void) fflush (stdout);
		    }
		    *real_name = ans -> name, ans -> name = NULLPE;
		    result = ans -> value, ans -> value = NULLPE;
		    ep = (pp = PY_pepy) + BUFSIZ - 1;
		    if (q = ans -> diagnostic)
			for (p = q -> qb_forw;
			         p != q && pp < ep;
			         pp += p -> qb_len, p = p -> qb_forw)
			    bcopy (p -> qb_data, pp, p -> qb_len);
		    *pp = NULL;

		    done = 1;
		}
	        break;

	    default:
		PY_advise (NULLCP, "unexpected response from nameservice: %d",
			   rsp -> offset);
	        goto you_lose;
	}

	pe_free (in);
	free_DASE_Provider__RSP (rsp);
    }

out: ;
    if (result == NULLPE)
	SLOG (addr_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
    if (parm)
	free_DASE_Query__REQ (parm);
    if (pe)
	pe_free (pe);
    if (ps && (err || !stayopen)) {
	struct TSAPdisconnect tds;

	(void) TDiscRequest (tcs.tc_sd, NULLCP, 0, &tds);
	ps_free (ps);
	ps = NULLPS;
    }

    if (ontty)
	(void) signal (SIGINT, istat);

    return result;
}

/*  */

static int  dase_init () {
    int	    i,
	    nfds;
    fd_set  ifds;
    register struct TSAPaddr *tz;
    register struct TSAPconnect *tc = &tcs;
    struct TSAPdisconnect tds;
    register struct TSAPdisconnect *td = &tds;

    if ((tz = str2taddr (ns_address)) == NULL) {
	PY_advise (NULLCP, "unable to parse nameservice address \"%s\"",
		   ns_address);
out: ;
	SLOG (addr_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
	return NOTOK;
    }

    if ((i = TAsynConnRequest (NULLTA, tz, 0, NULLCP, 0, NULLQOS, tc, td, 1))
	     == NOTOK) {
you_lose: ;
	PY_advise (NULLCP, td -> td_cc > 0
			       ? "unable to connect to nameservice: [%s] %*.*s"
			       : "unable to connect to nameservice: [%s]",
		   TErrString (td -> td_reason),
		   td -> td_cc, td -> td_cc, td -> td_data);
	goto out;
    }

    FD_ZERO (&ifds);

    nfds = tc -> tc_sd + 1;
    FD_SET (tc -> tc_sd, &ifds);

    while (i == CONNECTING_1 || i == CONNECTING_2) {
	fd_set	 mask,
		*rmask,
		*wmask;

	if (!interrupted) {
	    mask = ifds;		/* struct copy */
	    if (i == CONNECTING_2)
		rmask = &mask, wmask = NULLFD;
	    else
		rmask = NULLFD, wmask = &mask;

	    (void) xselect (nfds, rmask, wmask, NULLFD, NOTOK);
	}

	if (interrupted) {
	    PY_advise (NULLCP, "interrupted");
	    goto oops;
	}

	if ((rmask && !FD_ISSET (tc -> tc_sd, rmask))
	        || (wmask && !FD_ISSET (tc -> tc_sd, wmask)))
	    continue;

	if ((i = TAsynRetryRequest (tc -> tc_sd, tc, td)) == NOTOK)
	    goto you_lose;
    }

    if ((ps = ps_alloc (dg_open)) == NULLPS
	    || dg_setup (ps, tc -> tc_sd, MAXDGRAM, ts_read, ts_write, NULLIFP)
		    == NOTOK) {
	if (ps == NULLPS)
	    PY_advise (NULLCP, "ps_alloc: out of memory");
	else {
	    PY_advise (NULLCP, "dg_setup: %s", ps_error (ps -> ps_errno));
	    ps_free (ps);
	    ps = NULL;
	}

oops: ;
	(void) TDiscRequest (tcs.tc_sd, NULLCP, 0, td);
	goto out;
    }

    return OK;
}

/*  */

static int  dase_callback (arg)
register struct type_DASE_Callback__REQ *arg;
{
    register int i,
		 j;
    int	    result;
    register struct element_DASE_3 *choice;
    struct type_DASE_Callback__RSP *rsp = NULL;
    register struct type_DASE_Callback__RSP **rp = &rsp;
    PE	    pe = NULLPE;

    i = 0;
    for (choice = arg -> choices; choice; choice = choice -> next)
	i++;

    if (i > 10) {
	printf ("%d imprecise matches for '", i);
	print_qb (arg -> string);
	printf ("', select fron them [y/n] ? ");
	if (yesno () != OK)
	    goto send_rsp;
    }
    else {
	printf ("Please select from the following %d match%s for '",
		i, i != 1 ? "es" : "");
	print_qb (arg -> string);
	printf ("':\n");
    }

    j = 1;
    for (choice = arg -> choices; choice; choice = choice -> next) {
	register struct type_DASE_Callback__RSP *yes;

	printf ("  ");
	print_qb (choice -> Pair -> friendly);
	printf (" [y/n] ? ");

	switch (yesno ()) {
	    case DONE:
	        goto send_rsp;

	    case NOTOK:
	    default:
		break;

	    case OK:
		if ((yes = (struct type_DASE_Callback__RSP *)
					    calloc (1, sizeof *yes)) == NULL) {
		    PY_advise (NULLCP, "dase_callback: out of memory");
		    result = NOTOK;
		    goto out;
		}
		*rp = yes, rp = &yes -> next;

		yes -> IA5String = choice -> Pair -> complete;
		choice -> Pair -> complete = NULL;
		break;
	}

	if ((j++ % 10) == 0 && choice -> next) {
	    printf ("Continue (%d more) [y/n] ? ", i - j + 1);
	    if (yesno () != OK)
		break;
	}
    }

send_rsp: ;
    if ((result = encode_DASE_Callback__RSP (&pe, 1, NULL, NULLCP, rsp))
	    == NOTOK)
	goto out;
    if ((result = pe2ps (ps, pe)) == NOTOK)
	PY_advise (NULLCP, "unable to write callback [%s]",
		   ps_error (ps -> ps_errno));
    else {
	PLOGP (addr_log,DASE_Message, pe, "message", 0);

	result = OK;
    }

out: ;
    if (rsp)
	free_DASE_Callback__RSP (rsp);
    if (pe)
	pe_free (pe);

    return result;
}

/*  */

static int  yesno () {
    int     x,
            y,
            result;

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

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

	case NOTOK: 
	default: 
	    printf ("\n");
	    armed = 0;
	    return DONE;
    }
    
again: ;
    x = y = getc (stdin);
    while (y != '\n' && y != EOF)
	y = getc (stdin);

    switch (x) {
	case 'y': 
	case '\n':
	    result = OK;
	    break;

	case 'n': 
	    result = NOTOK;
	    break;

	case EOF: 
	    result = DONE;
	    clearerr (stdin);
	    break;

	default: 
	    printf ("Please type 'y' or 'n': ");
	    goto again;
    }

    armed = 0;

    return result;
}


static	print_qb (q)
struct qbuf *q;
{
    register struct qbuf *p;

    for (p = q -> qb_forw; p != q; p = p -> qb_forw)
	printf ("%*.*s", p -> qb_len, p -> qb_len, p -> qb_data);
}

/*  */

static struct element_DASE_1 *read_el () {
    register int   i;
    register char *bp,
		  *cp;
    char    buffer[BUFSIZ],
	    ufnrc[BUFSIZ];
    FILE   *fp;
    struct element_DASE_1 *top;
    register struct element_DASE_1 **etail;
    register struct element_DASE_2 **dtail;

    if (bp = getenv ("UFNRC"))
	(void) strcpy (ufnrc, bp);
    else {
	if ((bp = getenv ("HOME")) == NULL)
	    bp = ".";

	(void) sprintf (ufnrc, "%s/.ufnrc", bp);
    }

    if ((fp = fopen (ufnrc, "r")) == NULL) {
	(void) strcpy (ufnrc, isodefile ("ufnrc", 0));

	if ((fp = fopen (ufnrc, "r")) == NULL) {
	    PY_advise (ufnrc, "unable to read");
	    return NULL;
	}
    }

    top = NULL, etail = &top, dtail = NULL;

    for (i = 0; fgets (bp = buffer, sizeof buffer, fp); i++) {
	register struct element_DASE_2 *dl;

	if (*buffer == '#')
	    continue;
	if (bp = index (buffer, '\n'))
	    *bp = NULL;

	bp = buffer;
	if (*bp == NULL) {
	    dtail = NULL;
	    continue;
	}

	if (!isspace (*bp)) {
	    register char *dp;
	    register struct element_DASE_1 *el;
	    register struct type_DASE_Environment *fl;

	    if ((el = (struct element_DASE_1 *) calloc (1, sizeof *el))
		    == NULL) {
no_mem: ;
		PY_advise (NULLCP, "real_el: out of memory");

out: ;
		for (; top; top = el) {
		    el = top -> next;

		    free_DASE_Environment (top -> Environment);
		    free ((char *) top);
		}
		SLOG (addr_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
		(void) fclose (fp);
		return NULL;
	    }
	    *etail = el;
	    etail = &el -> next;

	    if ((fl = (struct type_DASE_Environment *) calloc (1, sizeof *fl))
		    == NULL)
		goto no_mem;
	    el -> Environment = fl;
	    dtail = &fl -> path;

	    if ((cp = index (bp, ':')) == NULL) {
		PY_advise (NULLCP, "%s: missing ':' at line %d", ufnrc, i);
		goto out;
	    }
	    *cp++ = NULL;

	    if (dp = index (bp, ',')) {
		*dp++ = NULL;

		while (isspace (*dp))
		    dp++;
		fl -> upper = *dp == '+' ? 32767 : atoi (dp);
	    }
	    else
		fl -> upper = 0;

	    fl -> lower = atoi (bp);
	    if (fl -> upper == 0)
		fl -> upper = fl -> lower;

	    bp = cp;
	}
	else
	    if (!dtail) {
		PY_advise (NULLCP, "%s: unexpected blank at start of line %d",
			   ufnrc, i);
		goto out;
	    }

	if ((dl = (struct element_DASE_2 *) calloc (1, sizeof *dl)) == NULL)
	    goto no_mem;
	*dtail = dl;
	dtail = &dl -> next;

	while (isspace (*bp))
	    bp++;
	if ((dl -> IA5String = str2qb (bp, strlen (bp), 1)) == NULL)
	    goto no_mem;
    }

    (void) fclose (fp);

    return top;
}

/*  */

/* ARGSUSED */

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

    if (armed)
	longjmp (intrenv, NOTOK);

    interrupted++;
}

/*  */

set_lookup_dase (flag)
char	flag;
{
    if (!(stayopen = flag) && ps) {
	struct TSAPdisconnect tds;

	(void) TDiscRequest (tcs.tc_sd, NULLCP, 0, &tds);
	ps_free (ps);
	ps = NULLPS;
    }

    acsap_lookup = name2value_dase;
}