/*
 * $Header: /udir/vixie/src/mail11/d-1.7beta/RCS/decnet-ultrix.c,v 1.5 1991/10/13 02:32:40 vixie Exp $
 * Copyright (c) 1989 Keith Moore
 */
/*
 * These routines maintain a single connection to a DECnet object.
 * This implementation for Ultrix-32 running DECnet-Ultrix.
 */

#include <netdnet/dn.h>
#include "mail11.h"
#include "decnet.h"
#include "debug.h"
#include "defs.h"

static int decnet_in;
static int decnet_out;
extern char *DECNET_RemoteUser;
extern char *DECNET_RemoteNode;
extern char *DECNET_NodeName;
extern char *UNIX_ErrorMessage ();
extern char *getenv ();
extern char *getnodename ();

extern char *getenv P((char *));
extern char *getnodename P(());

FILE *
DECNET_FDOpen_In ()
{
    return fdopen (decnet_in, "r");
}

int
DECNET_Read (buf, size)
char *buf;
{
    int x = read (decnet_in, buf, size);
/*
    DEBUG_DumpBlock ("DECNET_Read", buf, x);
*/
    return x;
}

int
DECNET_Write (buf, size)
char *buf;
{
/*
    DEBUG_DumpBlock ("DECNET_Write", buf, size);
*/
    return write (decnet_out, buf, size);
}

/*
 * return true iff the other end closed the DECnet channel.
 */
int 
DECNET_EOF ()
{
    int x = dnet_eof (decnet_in);
    if (x)
	DEBUG_Print ("DECNET_EOF: T\n");
    return x;
}

/*
 * LOG a DECnet-specific error message for the last error.
 * For now, we do nothing.
 * Eventually this should go to the system logger.
 * (mabye the error should be mailed to postmaster?)
 */
DECNET_Error (message)
char *message;
{
    DEBUG_Print ("DECNET_Error: %s\n", message);
}

/*
 * For now, the DECNET object spawner does the job of accepting the
 * DECnet connection and setting things up.  All we do is initialize
 * some variables.
 *
 * Eventually, we should exchange configuration information with the
 * other DECnet task.
 */
void
DECNET_AcceptConnection (client_config, server_config)
struct mail11_config *client_config, *server_config;
{
    struct accessdata_dn acc_data;
    struct optdata_dn client_data, server_data;
    int client_data_len = sizeof client_data;

    decnet_in = 0;
    decnet_out = 1;

    DECNET_RemoteUser = getenv ("REMUSER");
    DECNET_RemoteNode = getenv ("REMNODE");
    DECNET_NodeName = getnodename ();

    /* get access control information (even though we always accept) */
    setsockopt (decnet_in, DNPROTO_NSP, DSO_CONACCESS, &acc_data,
		sizeof (acc_data));
    
    /* get client config info as optional data */
    getsockopt (decnet_in, DNPROTO_NSP, DSO_CONDATA, &client_data,
		&client_data_len);

    /* copy client config info into a C structure */
    if (client_data.opt_optl > 0)
	GetConfigInfo (client_config, (char *) client_data.opt_data);

    PrintConfigInfo ("client info", client_config);
    if (client_config->iomode & CCSEND)
	server_config->iomode |= CCRECV;
    if ((client_config->iomode & BLKSEND) &&
	(client_config->rfm == RFM_VAR) &&
	(client_config->rat == RAT_CR)
    ) {
	server_config->iomode |= BLKRECV;
	server_config->rfm = RFM_VAR;
	server_config->rat = RAT_CR;
    } else {
	server_config->rfm = client_config->rfm;
	server_config->rat = client_config->rat;
    }

    PrintConfigInfo ("server info", server_config);

    /* convert server config info into network canonical form */
    server_data.opt_optl = 16;
    server_data.opt_status = 0;
    PutConfigInfo ((char *) server_data.opt_data, server_config);

    /* send our configuration data to client */
    setsockopt (decnet_in, DNPROTO_NSP, DSO_CONDATA, &server_data,
		sizeof (server_data));

    /* accept connection */
    setsockopt (decnet_in, DNPROTO_NSP, DSO_CONACCEPT, 0, 0);
}
